Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: src/core/SkAnalyticEdge.cpp

Issue 2221103002: Analytic AntiAlias for Convex Shapes (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Declare flag in SkCommonFlags.h for iOS build Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/core/SkAnalyticEdge.h ('k') | src/core/SkBlitter.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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
9 #include "SkAnalyticEdge.h"
10 #include "SkFDot6.h"
11 #include "SkMathPriv.h"
12 #include "SkAAAConstants.h"
13
14 class QuickFDot6Inverse {
15 private:
16 static constexpr const SkFDot6* table = gFDot6INVERSE + kInverseTableSize;
17 public:
18 inline static SkFixed Lookup(SkFDot6 x) {
19 SkASSERT(SkAbs32(x) < kInverseTableSize);
20 return table[x];
21 }
22 };
23
24 static inline SkFixed quickSkFDot6Div(SkFDot6 a, SkFDot6 b) {
25 if (SkAbs32(b) < kInverseTableSize) {
26 SkASSERT((int64_t)a * QuickFDot6Inverse::Lookup(b) <= SK_MaxS32);
27 SkFixed ourAnswer = (a * QuickFDot6Inverse::Lookup(b)) >> 6;
28 #ifdef SK_DEBUG
29 SkFixed directAnswer = SkFDot6Div(a, b);
30 SkASSERT(
31 (directAnswer == 0 && ourAnswer == 0) ||
32 SkFixedDiv(SkAbs32(directAnswer - ourAnswer), SkAbs32(directAnswer)) <= 1 << 10
33 );
34 #endif
35 return ourAnswer;
36 } else {
37 return SkFDot6Div(a, b);
38 }
39 }
40
41 // This will become a bottleneck for small ovals rendering if we call SkFixedDiv twice here.
42 // Therefore, we'll let the outter function compute the slope once and send in t he value.
43 // Moreover, we'll compute fDY by quickly lookup the inverse table (if possible) .
44 bool SkAnalyticEdge::updateLine(SkFixed x0, SkFixed y0, SkFixed x1, SkFixed y1, SkFixed slope) {
45 // Since we send in the slope, we can no longer snap y inside this function.
46 // If we don't send in the slope, or we do some more sophisticated snapping, this function
47 // could be a performance bottleneck.
48 SkASSERT(fWinding == 1 || fWinding == -1);
49 SkASSERT(fCurveCount != 0);
50
51 SkASSERT(y0 <= y1);
52
53 SkFDot6 dx = SkFixedToFDot6(x1 - x0);
54 SkFDot6 dy = SkFixedToFDot6(y1 - y0);
55
56 // are we a zero-height line?
57 if (dy == 0) {
58 return false;
59 }
60
61 SkASSERT(slope < SK_MaxS32);
62
63 SkFDot6 absSlope = SkAbs32(SkFixedToFDot6(slope));
64 fX = x0;
65 fDX = slope;
66 fUpperX = x0;
67 fY = y0;
68 fUpperY = y0;
69 fLowerY = y1;
70 fDY = (absSlope | dx) == 0
71 ? SK_MaxS32
72 : absSlope < kInverseTableSize
73 ? QuickFDot6Inverse::Lookup(absSlope)
74 : SkAbs32(quickSkFDot6Div(dy, dx));
75
76 return true;
77 }
78
79 void SkAnalyticEdge::chopLineWithClip(const SkIRect& clip) {
80 int top = SkFixedFloorToInt(fUpperY);
81
82 SkASSERT(top < clip.fBottom);
83
84 // clip the line to the clip top
85 if (top < clip.fTop) {
86 SkASSERT(SkFixedCeilToInt(fLowerY) > clip.fTop);
87 SkFixed newY = SkIntToFixed(clip.fTop);
88 this->goY(newY);
89 fUpperY = newY;
90 }
91 }
92
93 bool SkAnalyticQuadraticEdge::setQuadratic(const SkPoint pts[3]) {
94 if (!fQEdge.setQuadraticWithoutUpdate(pts, 2)) {
95 return false;
96 }
97 fQEdge.fQx >>= 2;
98 fQEdge.fQy >>= 2;
99 fQEdge.fQDx >>= 2;
100 fQEdge.fQDy >>= 2;
101 fQEdge.fQDDx >>= 2;
102 fQEdge.fQDDy >>= 2;
103 fQEdge.fQLastX >>= 2;
104 fQEdge.fQLastY >>= 2;
105 fQEdge.fQy = snapY(fQEdge.fQy);
106 fQEdge.fQLastY = snapY(fQEdge.fQLastY);
107
108 fWinding = fQEdge.fWinding;
109 fCurveCount = fQEdge.fCurveCount;
110 fCurveShift = fQEdge.fCurveShift;
111
112 fSnappedX = fQEdge.fQx;
113 fSnappedY = fQEdge.fQy;
114
115 return this->updateQuadratic();
116 }
117
118 bool SkAnalyticQuadraticEdge::updateQuadratic() {
119 int success = 0; // initialize to fail!
120 int count = fCurveCount;
121 SkFixed oldx = fQEdge.fQx;
122 SkFixed oldy = fQEdge.fQy;
123 SkFixed dx = fQEdge.fQDx;
124 SkFixed dy = fQEdge.fQDy;
125 SkFixed newx, newy, newSnappedX, newSnappedY;
126 int shift = fCurveShift;
127
128 SkASSERT(count > 0);
129
130 do {
131 SkFixed slope;
132 if (--count > 0)
133 {
134 newx = oldx + (dx >> shift);
135 newy = snapY(oldy + (dy >> shift));
136 slope = dy >> 10 > 0 ? quickSkFDot6Div(dx >> 10, dy >> 10) : SK_MaxS 32;
137 if (SkAbs32(dy) >= SK_Fixed1 * 2) { // only snap when dy is large en ough
138 newSnappedY = SkTMin<SkFixed>(fQEdge.fQLastY, SkFixedRoundToFixe d(newy));
139 newSnappedX = newx + SkFixedMul_lowprec(slope, newSnappedY - new y);
140 } else {
141 newSnappedY = newy;
142 newSnappedX = newx;
143 }
144 dx += fQEdge.fQDDx;
145 dy += fQEdge.fQDDy;
146 }
147 else // last segment
148 {
149 newx = fQEdge.fQLastX;
150 newy = fQEdge.fQLastY;
151 newSnappedY = newy;
152 newSnappedX = newx;
153 slope = (newSnappedY - fSnappedY) >> 10
154 ? quickSkFDot6Div((newx - fSnappedX) >> 10, (newy - fSnapped Y) >> 10)
155 : SK_MaxS32;
156 }
157 if (slope < SK_MaxS32) {
158 success = this->updateLine(fSnappedX, fSnappedY, newSnappedX, newSna ppedY, slope);
159 }
160 oldx = newx;
161 oldy = newy;
162 } while (count > 0 && !success);
163
164 SkASSERT(newSnappedY <= fQEdge.fQLastY);
165
166 fQEdge.fQx = newx;
167 fQEdge.fQy = newy;
168 fQEdge.fQDx = dx;
169 fQEdge.fQDy = dy;
170 fSnappedX = newSnappedX;
171 fSnappedY = newSnappedY;
172 fCurveCount = SkToS8(count);
173 return success;
174 }
175
176 bool SkAnalyticCubicEdge::setCubic(const SkPoint pts[4]) {
177 if (!fCEdge.setCubicWithoutUpdate(pts, 2)) {
178 return false;
179 }
180
181 fCEdge.fCx >>= 2;
182 fCEdge.fCy >>= 2;
183 fCEdge.fCDx >>= 2;
184 fCEdge.fCDy >>= 2;
185 fCEdge.fCDDx >>= 2;
186 fCEdge.fCDDy >>= 2;
187 fCEdge.fCDDDx >>= 2;
188 fCEdge.fCDDDy >>= 2;
189 fCEdge.fCLastX >>= 2;
190 fCEdge.fCLastY >>= 2;
191 fCEdge.fCy = snapY(fCEdge.fCy);
192 fCEdge.fCLastY = snapY(fCEdge.fCLastY);
193
194 fWinding = fCEdge.fWinding;
195 fCurveCount = fCEdge.fCurveCount;
196 fCurveShift = fCEdge.fCurveShift;
197 fCubicDShift = fCEdge.fCubicDShift;
198
199 return this->updateCubic();
200 }
201
202 bool SkAnalyticCubicEdge::updateCubic() {
203 int success;
204 int count = fCurveCount;
205 SkFixed oldx = fCEdge.fCx;
206 SkFixed oldy = fCEdge.fCy;
207 SkFixed newx, newy;
208 const int ddshift = fCurveShift;
209 const int dshift = fCubicDShift;
210
211 SkASSERT(count < 0);
212
213 do {
214 if (++count < 0) {
215 newx = oldx + (fCEdge.fCDx >> dshift);
216 fCEdge.fCDx += fCEdge.fCDDx >> ddshift;
217 fCEdge.fCDDx += fCEdge.fCDDDx;
218
219 newy = oldy + (fCEdge.fCDy >> dshift);
220 fCEdge.fCDy += fCEdge.fCDDy >> ddshift;
221 fCEdge.fCDDy += fCEdge.fCDDDy;
222 }
223 else { // last segment
224 newx = fCEdge.fCLastX;
225 newy = fCEdge.fCLastY;
226 }
227
228 // we want to say SkASSERT(oldy <= newy), but our finite fixedpoint
229 // doesn't always achieve that, so we have to explicitly pin it here.
230 if (newy < oldy) {
231 newy = oldy;
232 }
233
234 success = this->updateLine(oldx, oldy, newx, newy,
235 SkFixedToFDot6(newy - oldy) == 0 ? SK_MaxS32 :
236 SkFDot6Div(SkFixedToFDot6(newx - oldx), SkFixedToFDot6(n ewy - oldy)));
237 oldx = newx;
238 oldy = newy;
239 } while (count < 0 && !success);
240
241 fCEdge.fCx = newx;
242 fCEdge.fCy = newy;
243 fCurveCount = SkToS8(count);
244 return success;
245 }
OLDNEW
« no previous file with comments | « src/core/SkAnalyticEdge.h ('k') | src/core/SkBlitter.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698