OLD | NEW |
(Empty) | |
| 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 |
| 8 #ifndef SkAnalyticEdge_DEFINED |
| 9 #define SkAnalyticEdge_DEFINED |
| 10 |
| 11 #include "SkEdge.h" |
| 12 |
| 13 inline SkFixed SkFixedMul_lowprec(SkFixed a, SkFixed b) { |
| 14 SkASSERT(((int64_t)a >> 8) * (b >> 8) <= SK_MaxS32); |
| 15 return (a >> 8) * (b >> 8); |
| 16 } |
| 17 |
| 18 struct SkAnalyticEdge { |
| 19 // Similar to SkEdge, the conic edges will be converted to quadratic edges |
| 20 enum Type { |
| 21 kLine_Type, |
| 22 kQuad_Type, |
| 23 kCubic_Type |
| 24 }; |
| 25 |
| 26 SkAnalyticEdge* fNext; |
| 27 SkAnalyticEdge* fPrev; |
| 28 |
| 29 SkFixed fX; |
| 30 SkFixed fDX; |
| 31 SkFixed fUpperX; // The x value when y = fUpperY |
| 32 SkFixed fY; // The current y |
| 33 SkFixed fUpperY; // The upper bound of y (our edge is from y = fUpper
Y to y = fLowerY) |
| 34 SkFixed fLowerY; // The lower bound of y (our edge is from y = fUpper
Y to y = fLowerY) |
| 35 SkFixed fDY; // abs(1/fDX); may be SK_MaxS32 when fDX is close to
0. |
| 36 // fDY is only used for blitting trapezoids. |
| 37 |
| 38 int8_t fCurveCount; // only used by kQuad(+) and kCubic(-) |
| 39 uint8_t fCurveShift; // appled to all Dx/DDx/DDDx except for fCubicDShift
exception |
| 40 uint8_t fCubicDShift; // applied to fCDx and fCDy only in cubic |
| 41 int8_t fWinding; // 1 or -1 |
| 42 |
| 43 static const int kDefaultAccuracy = 2; // default accuracy for snapping |
| 44 |
| 45 static inline SkFixed snapY(SkFixed y, int accuracy = kDefaultAccuracy) { |
| 46 return SkFixedRoundToFixed(y << accuracy) >> accuracy; |
| 47 } |
| 48 |
| 49 // Update fX, fY of this edge so fY = y |
| 50 inline void goY(SkFixed y) { |
| 51 if (y == fY + SK_Fixed1) { |
| 52 fX = fX + fDX; |
| 53 fY = y; |
| 54 } else if (y != fY) { |
| 55 // Drop lower digits as our alpha only has 8 bits |
| 56 // (fDX and y - fUpperY may be greater than SK_Fixed1) |
| 57 fX = fUpperX + SkFixedMul_lowprec(fDX, y - fUpperY); |
| 58 fY = y; |
| 59 } |
| 60 } |
| 61 |
| 62 inline bool setLine(const SkPoint& p0, const SkPoint& p1, const SkIRect* cli
p = nullptr); |
| 63 inline bool updateLine(SkFixed ax, SkFixed ay, SkFixed bx, SkFixed by, SkFix
ed slope); |
| 64 void chopLineWithClip(const SkIRect& clip); |
| 65 |
| 66 inline bool intersectsClip(const SkIRect& clip) const { |
| 67 SkASSERT(SkFixedFloorToInt(fUpperY) < clip.fBottom); |
| 68 return SkFixedCeilToInt(fLowerY) > clip.fTop; |
| 69 } |
| 70 |
| 71 #ifdef SK_DEBUG |
| 72 void dump() const { |
| 73 SkDebugf("edge: upperY:%d lowerY:%d y:%g x:%g dx:%g w:%d\n", |
| 74 fUpperY, fLowerY, SkFixedToFloat(fY), SkFixedToFloat(fX), |
| 75 SkFixedToFloat(fDX), fWinding); |
| 76 } |
| 77 |
| 78 void validate() const { |
| 79 SkASSERT(fPrev && fNext); |
| 80 SkASSERT(fPrev->fNext == this); |
| 81 SkASSERT(fNext->fPrev == this); |
| 82 |
| 83 SkASSERT(fUpperY < fLowerY); |
| 84 SkASSERT(SkAbs32(fWinding) == 1); |
| 85 } |
| 86 #endif |
| 87 }; |
| 88 |
| 89 struct SkAnalyticQuadraticEdge : public SkAnalyticEdge { |
| 90 SkQuadraticEdge fQEdge; |
| 91 |
| 92 // snap y to integer points in the middle of the curve to accelerate AAA pat
h filling |
| 93 SkFixed fSnappedX, fSnappedY; |
| 94 |
| 95 bool setQuadratic(const SkPoint pts[3]); |
| 96 bool updateQuadratic(); |
| 97 }; |
| 98 |
| 99 struct SkAnalyticCubicEdge : public SkAnalyticEdge { |
| 100 SkCubicEdge fCEdge; |
| 101 |
| 102 bool setCubic(const SkPoint pts[4]); |
| 103 bool updateCubic(); |
| 104 }; |
| 105 |
| 106 bool SkAnalyticEdge::setLine(const SkPoint& p0, const SkPoint& p1, const SkIRect
* clip) { |
| 107 // We must set X/Y using the same way (times 4, to FDot6, then to Fixed) as
Quads/Cubics. |
| 108 // Otherwise the order of the edge might be wrong due to precision limit. |
| 109 SkFixed x0 = SkFDot6ToFixed(SkScalarToFDot6(p0.fX * 4)) >> 2; |
| 110 SkFixed y0 = snapY(SkFDot6ToFixed(SkScalarToFDot6(p0.fY * 4)) >> 2); |
| 111 SkFixed x1 = SkFDot6ToFixed(SkScalarToFDot6(p1.fX * 4)) >> 2; |
| 112 SkFixed y1 = snapY(SkFDot6ToFixed(SkScalarToFDot6(p1.fY * 4)) >> 2); |
| 113 |
| 114 // are we a zero-height line? |
| 115 if (y0 == y1) { |
| 116 return false; |
| 117 } |
| 118 |
| 119 int top = SkFixedFloorToInt(y0); |
| 120 int bot = SkFixedCeilToInt(y1); |
| 121 |
| 122 // are we completely above or below the clip? |
| 123 if (clip && (top >= clip->fBottom || bot <= clip->fTop)) { |
| 124 return false; |
| 125 } |
| 126 |
| 127 int winding = 1; |
| 128 |
| 129 if (y0 > y1) { |
| 130 SkTSwap(x0, x1); |
| 131 SkTSwap(y0, y1); |
| 132 winding = -1; |
| 133 } |
| 134 |
| 135 SkFixed slope = SkFixedDiv(x1 - x0, y1 - y0); |
| 136 |
| 137 fX = x0; |
| 138 fDX = slope; |
| 139 fUpperX = x0; |
| 140 fY = y0; |
| 141 fUpperY = y0; |
| 142 fLowerY = y1; |
| 143 fDY = x1 != x0 ? SkAbs32(SkFixedDiv(y1 - y0, x1 - x0)) : SK_MaxS32; |
| 144 fCurveCount = 0; |
| 145 fWinding = SkToS8(winding); |
| 146 fCurveShift = 0; |
| 147 |
| 148 if (clip) { |
| 149 this->chopLineWithClip(*clip); |
| 150 } |
| 151 return true; |
| 152 } |
| 153 |
| 154 #endif |
OLD | NEW |