SkEdge.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /*
  2. * Copyright 2006 The Android Open Source Project
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #ifndef SkEdge_DEFINED
  8. #define SkEdge_DEFINED
  9. #include "include/core/SkMath.h"
  10. #include "include/core/SkRect.h"
  11. #include "include/private/SkTo.h"
  12. #include "src/core/SkFDot6.h"
  13. #include <utility>
  14. // This correctly favors the lower-pixel when y0 is on a 1/2 pixel boundary
  15. #define SkEdge_Compute_DY(top, y0) (SkLeftShift(top, 6) + 32 - (y0))
  16. struct SkEdge {
  17. enum Type {
  18. kLine_Type,
  19. kQuad_Type,
  20. kCubic_Type
  21. };
  22. SkEdge* fNext;
  23. SkEdge* fPrev;
  24. SkFixed fX;
  25. SkFixed fDX;
  26. int32_t fFirstY;
  27. int32_t fLastY;
  28. int8_t fCurveCount; // only used by kQuad(+) and kCubic(-)
  29. uint8_t fCurveShift; // appled to all Dx/DDx/DDDx except for fCubicDShift exception
  30. uint8_t fCubicDShift; // applied to fCDx and fCDy only in cubic
  31. int8_t fWinding; // 1 or -1
  32. int setLine(const SkPoint& p0, const SkPoint& p1, const SkIRect* clip, int shiftUp);
  33. // call this version if you know you don't have a clip
  34. inline int setLine(const SkPoint& p0, const SkPoint& p1, int shiftUp);
  35. inline int updateLine(SkFixed ax, SkFixed ay, SkFixed bx, SkFixed by);
  36. void chopLineWithClip(const SkIRect& clip);
  37. inline bool intersectsClip(const SkIRect& clip) const {
  38. SkASSERT(fFirstY < clip.fBottom);
  39. return fLastY >= clip.fTop;
  40. }
  41. #ifdef SK_DEBUG
  42. void dump() const {
  43. SkDebugf("edge: firstY:%d lastY:%d x:%g dx:%g w:%d\n", fFirstY, fLastY, SkFixedToFloat(fX), SkFixedToFloat(fDX), fWinding);
  44. }
  45. void validate() const {
  46. SkASSERT(fPrev && fNext);
  47. SkASSERT(fPrev->fNext == this);
  48. SkASSERT(fNext->fPrev == this);
  49. SkASSERT(fFirstY <= fLastY);
  50. SkASSERT(SkAbs32(fWinding) == 1);
  51. }
  52. #endif
  53. };
  54. struct SkQuadraticEdge : public SkEdge {
  55. SkFixed fQx, fQy;
  56. SkFixed fQDx, fQDy;
  57. SkFixed fQDDx, fQDDy;
  58. SkFixed fQLastX, fQLastY;
  59. bool setQuadraticWithoutUpdate(const SkPoint pts[3], int shiftUp);
  60. int setQuadratic(const SkPoint pts[3], int shiftUp);
  61. int updateQuadratic();
  62. };
  63. struct SkCubicEdge : public SkEdge {
  64. SkFixed fCx, fCy;
  65. SkFixed fCDx, fCDy;
  66. SkFixed fCDDx, fCDDy;
  67. SkFixed fCDDDx, fCDDDy;
  68. SkFixed fCLastX, fCLastY;
  69. bool setCubicWithoutUpdate(const SkPoint pts[4], int shiftUp, bool sortY = true);
  70. int setCubic(const SkPoint pts[4], int shiftUp);
  71. int updateCubic();
  72. };
  73. int SkEdge::setLine(const SkPoint& p0, const SkPoint& p1, int shift) {
  74. SkFDot6 x0, y0, x1, y1;
  75. {
  76. #ifdef SK_RASTERIZE_EVEN_ROUNDING
  77. x0 = SkScalarRoundToFDot6(p0.fX, shift);
  78. y0 = SkScalarRoundToFDot6(p0.fY, shift);
  79. x1 = SkScalarRoundToFDot6(p1.fX, shift);
  80. y1 = SkScalarRoundToFDot6(p1.fY, shift);
  81. #else
  82. float scale = float(1 << (shift + 6));
  83. x0 = int(p0.fX * scale);
  84. y0 = int(p0.fY * scale);
  85. x1 = int(p1.fX * scale);
  86. y1 = int(p1.fY * scale);
  87. #endif
  88. }
  89. int winding = 1;
  90. if (y0 > y1) {
  91. using std::swap;
  92. swap(x0, x1);
  93. swap(y0, y1);
  94. winding = -1;
  95. }
  96. int top = SkFDot6Round(y0);
  97. int bot = SkFDot6Round(y1);
  98. // are we a zero-height line?
  99. if (top == bot) {
  100. return 0;
  101. }
  102. SkFixed slope = SkFDot6Div(x1 - x0, y1 - y0);
  103. const SkFDot6 dy = SkEdge_Compute_DY(top, y0);
  104. fX = SkFDot6ToFixed(x0 + SkFixedMul(slope, dy)); // + SK_Fixed1/2
  105. fDX = slope;
  106. fFirstY = top;
  107. fLastY = bot - 1;
  108. fCurveCount = 0;
  109. fWinding = SkToS8(winding);
  110. fCurveShift = 0;
  111. return 1;
  112. }
  113. #endif