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 |