Index: src/core/SkEdge.h |
diff --git a/src/core/SkEdge.h b/src/core/SkEdge.h |
index 11669b4f7fb4056f0309022294a0bc8dc625fd1b..eedec5e33d806acb23a22070dcb49bf50b204534 100644 |
--- a/src/core/SkEdge.h |
+++ b/src/core/SkEdge.h |
@@ -130,5 +130,150 @@ int SkEdge::setLine(const SkPoint& p0, const SkPoint& p1, int shift) { |
return 1; |
} |
+//////////////Analytic Edges//////////////////////////////// |
+ |
+struct SkAnalyticEdge { |
+ // Similar to SkEdge, the conic edges will be converted to quadratic edges |
+ enum Type { |
+ kLine_Type, |
+ kQuad_Type, |
+ kCubic_Type |
+ }; |
+ |
+ SkAnalyticEdge* fNext; |
+ SkAnalyticEdge* fPrev; |
+ |
+ SkFixed fX; |
+ SkFixed fDX; |
+ SkFixed fUpperX; // The x value when y = fUpperY |
+ SkFixed fY; // The current y |
+ SkFixed fUpperY; // The upper bound of y (our edge is from y = fUpperY to y = fLowerY) |
+ SkFixed fLowerY; // The lower bound of y (our edge is from y = fUpperY to y = fLowerY) |
+ SkFixed fDY; // abs(1/fDX); may be SK_MaxS32 when fDX is close to 0. |
+ // fDY is only used for blitting trapezoids. |
+ |
+ int8_t fCurveCount; // only used by kQuad(+) and kCubic(-) |
+ uint8_t fCurveShift; // appled to all Dx/DDx/DDDx except for fCubicDShift exception |
+ uint8_t fCubicDShift; // applied to fCDx and fCDy only in cubic |
+ int8_t fWinding; // 1 or -1 |
+ |
+ static const int kDefaultAccuracy = 4; // default accuracy for snapping |
+ |
+ static inline SkFixed snapY(SkFixed y, int accuracy = kDefaultAccuracy) { |
+ // We do ceiling to ensure that y is increasing |
+ return SkFixedCeilToFixed(y << accuracy) >> accuracy; |
+ } |
+ |
+ // Update fX, fY of this edge so fY = y |
+ inline void goY(SkFixed y) { |
+ if (y == fY + SK_Fixed1) { |
+ fX = fX + fDX; |
+ fY = y; |
+ } else if (y != fY) { |
+ // Drop lower digits as our alpha only has 8 bits |
+ // (fDX and y - fUpperY may be greater than SK_Fixed1) |
+ fX = fUpperX + SkFixedMul_lowprec(fDX, y - fUpperY); |
+ fY = y; |
+ } |
+ } |
+ |
+ inline bool setLine(const SkPoint& p0, const SkPoint& p1, const SkIRect* clip = nullptr); |
+ inline bool updateLine(SkFixed ax, SkFixed ay, SkFixed bx, SkFixed by, SkFixed slope); |
+ void chopLineWithClip(const SkIRect& clip); |
+ |
+ inline bool intersectsClip(const SkIRect& clip) const { |
+ SkASSERT(SkFixedFloorToInt(fUpperY) < clip.fBottom); |
+ return SkFixedCeilToInt(fLowerY) > clip.fTop; |
+ } |
+ |
+#ifdef SK_DEBUG |
+ void dump() const { |
+ SkDebugf("edge: upperY:%d lowerY:%d y:%g x:%g dx:%g w:%d\n", |
+ fUpperY, fLowerY, SkFixedToFloat(fY), SkFixedToFloat(fX), |
+ SkFixedToFloat(fDX), fWinding); |
+ } |
+ |
+ void validate() const { |
+ SkASSERT(fPrev && fNext); |
+ SkASSERT(fPrev->fNext == this); |
+ SkASSERT(fNext->fPrev == this); |
+ |
+ SkASSERT(fUpperY < fLowerY); |
+ SkASSERT(SkAbs32(fWinding) == 1); |
+ } |
+#endif |
+}; |
+ |
+struct SkAnalyticQuadraticEdge : public SkAnalyticEdge { |
+ SkFixed fQx, fQy; |
+ SkFixed fQDx, fQDy; |
+ SkFixed fQDDx, fQDDy; |
+ SkFixed fQLastX, fQLastY; |
+ |
+ // snap y to integer points in the middle of the curve to accelerate AAA path filling |
+ SkFixed fSnappedX, fSnappedY; |
+ |
+ int setQuadratic(const SkPoint pts[3]); |
+ int updateQuadratic(); |
+}; |
+ |
+struct SkAnalyticCubicEdge : public SkAnalyticEdge { |
+ SkFixed fCx, fCy; |
+ SkFixed fCDx, fCDy; |
+ SkFixed fCDDx, fCDDy; |
+ SkFixed fCDDDx, fCDDDy; |
+ SkFixed fCLastX, fCLastY; |
+ |
+ int setCubic(const SkPoint pts[4]); |
+ int updateCubic(); |
+}; |
+ |
+bool SkAnalyticEdge::setLine(const SkPoint& p0, const SkPoint& p1, const SkIRect* clip) { |
+ SkFixed x0 = SkScalarToFixed(p0.fX); |
+ SkFixed y0 = snapY(SkScalarToFixed(p0.fY)); |
+ SkFixed x1 = SkScalarToFixed(p1.fX); |
+ SkFixed y1 = snapY(SkScalarToFixed(p1.fY)); |
+ |
+ // are we a zero-height line? |
+ if (y0 == y1) { |
+ return false; |
+ } |
+ |
+ int top = SkFixedFloorToInt(y0); |
+ int bot = SkFixedCeilToInt(y1); |
+ |
+ // are we completely above or below the clip? |
+ if (clip && (top >= clip->fBottom || bot <= clip->fTop)) { |
+ return false; |
+ } |
+ |
+ int winding = 1; |
+ |
+ if (y0 > y1) { |
+ SkTSwap(x0, x1); |
+ SkTSwap(y0, y1); |
+ winding = -1; |
+ } |
+ |
+ SkFixed slope = SkFixedDiv(x1 - x0, y1 - y0); |
+ |
+ fX = x0; |
+ fDX = slope; |
+ fUpperX = x0; |
+ fY = y0; |
+ fUpperY = y0; |
+ fLowerY = y1; |
+ fDY = x1 != x0 ? SkAbs32(SkFixedDiv(y1 - y0, x1 - x0)) : SK_MaxS32; |
+ fCurveCount = 0; |
+ fWinding = SkToS8(winding); |
+ fCurveShift = 0; |
+ |
+ if (clip) { |
+ this->chopLineWithClip(*clip); |
+ } |
+ return true; |
+} |
+ |
+//////////////////////////////////////////////////////////// |
#endif |