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

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

Issue 2221103002: Analytic AntiAlias for Convex Shapes (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Make alpha computation cleaner and faster Created 4 years, 4 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
OLDNEW
1 /* 1 /*
2 * Copyright 2011 Google Inc. 2 * Copyright 2011 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 #include "SkEdgeBuilder.h" 7 #include "SkEdgeBuilder.h"
8 #include "SkPath.h" 8 #include "SkPath.h"
9 #include "SkEdge.h" 9 #include "SkEdge.h"
10 #include "SkEdgeClipper.h" 10 #include "SkEdgeClipper.h"
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 return kPartial_Combine; 55 return kPartial_Combine;
56 } 56 }
57 last->fLastY = last->fFirstY - 1; 57 last->fLastY = last->fFirstY - 1;
58 last->fFirstY = edge->fFirstY; 58 last->fFirstY = edge->fFirstY;
59 last->fWinding = edge->fWinding; 59 last->fWinding = edge->fWinding;
60 return kPartial_Combine; 60 return kPartial_Combine;
61 } 61 }
62 return kNo_Combine; 62 return kNo_Combine;
63 } 63 }
64 64
65 static bool vertical_line(const SkEdge* edge) { 65 SkEdgeBuilder::Combine SkEdgeBuilder::CombineVertical(
66 const SkAnalyticEdge* edge, SkAnalyticEdge* last) {
67 SkASSERT(fAnalyticAA);
68 if (last->fCurveCount || last->fDX || edge->fX != last->fX) {
69 return kNo_Combine;
70 }
71 if (edge->fWinding == last->fWinding) {
72 if (edge->fLowerY == last->fUpperY) {
73 last->fUpperY = edge->fUpperY;
74 last->fY = last->fUpperY;
75 return kPartial_Combine;
76 }
77 if (edge->fUpperY == last->fLowerY) {
78 last->fLowerY = edge->fLowerY;
79 return kPartial_Combine;
80 }
81 return kNo_Combine;
82 }
83 if (edge->fUpperY == last->fUpperY) {
84 if (edge->fLowerY == last->fLowerY) {
85 return kTotal_Combine;
86 }
87 if (edge->fLowerY < last->fLowerY) {
88 last->fUpperY = edge->fLowerY;
89 last->fY = last->fUpperY;
90 return kPartial_Combine;
91 }
92 last->fUpperY = last->fLowerY;
93 last->fY = last->fUpperY;
94 last->fLowerY = edge->fLowerY;
95 last->fWinding = edge->fWinding;
96 return kPartial_Combine;
97 }
98 if (edge->fLowerY == last->fLowerY) {
99 if (edge->fUpperY > last->fUpperY) {
100 last->fLowerY = edge->fUpperY;
101 return kPartial_Combine;
102 }
103 last->fLowerY = last->fUpperY;
104 last->fUpperY = edge->fUpperY;
105 last->fY = last->fUpperY;
106 last->fWinding = edge->fWinding;
107 return kPartial_Combine;
108 }
109 return kNo_Combine;
110 }
111
112 bool SkEdgeBuilder::vertical_line(const SkEdge* edge) {
113 return !edge->fDX && !edge->fCurveCount;
114 }
115
116 bool SkEdgeBuilder::vertical_line(const SkAnalyticEdge* edge) {
117 SkASSERT(fAnalyticAA);
66 return !edge->fDX && !edge->fCurveCount; 118 return !edge->fDX && !edge->fCurveCount;
67 } 119 }
68 120
69 void SkEdgeBuilder::addLine(const SkPoint pts[]) { 121 void SkEdgeBuilder::addLine(const SkPoint pts[]) {
70 SkEdge* edge = typedAllocThrow<SkEdge>(fAlloc); 122 if (fAnalyticAA) {
71 if (edge->setLine(pts[0], pts[1], fShiftUp)) { 123 SkAnalyticEdge* edge = typedAllocThrow<SkAnalyticEdge>(fAlloc);
72 if (vertical_line(edge) && fList.count()) { 124 if (edge->setLine(pts[0], pts[1])) {
73 Combine combine = CombineVertical(edge, *(fList.end() - 1)); 125 if (vertical_line(edge) && fList.count()) {
74 if (kNo_Combine != combine) { 126 Combine combine = CombineVertical(edge, (SkAnalyticEdge*)*(fList .end() - 1));
75 if (kTotal_Combine == combine) { 127 if (kNo_Combine != combine) {
76 fList.pop(); 128 if (kTotal_Combine == combine) {
129 fList.pop();
130 }
131 goto unallocate_analytic_edge;
77 } 132 }
78 goto unallocate_edge;
79 } 133 }
134 fList.push(edge);
135 } else {
136 unallocate_analytic_edge:
137 ;
138 // TODO: unallocate edge from storage...
80 } 139 }
81 fList.push(edge);
82 } else { 140 } else {
141 SkEdge* edge = typedAllocThrow<SkEdge>(fAlloc);
142 if (edge->setLine(pts[0], pts[1], fShiftUp)) {
143 if (vertical_line(edge) && fList.count()) {
144 Combine combine = CombineVertical(edge, (SkEdge*)*(fList.end() - 1));
145 if (kNo_Combine != combine) {
146 if (kTotal_Combine == combine) {
147 fList.pop();
148 }
149 goto unallocate_edge;
150 }
151 }
152 fList.push(edge);
153 } else {
83 unallocate_edge: 154 unallocate_edge:
84 ; 155 ;
85 // TODO: unallocate edge from storage... 156 // TODO: unallocate edge from storage...
157 }
86 } 158 }
87 } 159 }
88 160
89 void SkEdgeBuilder::addQuad(const SkPoint pts[]) { 161 void SkEdgeBuilder::addQuad(const SkPoint pts[]) {
90 SkQuadraticEdge* edge = typedAllocThrow<SkQuadraticEdge>(fAlloc); 162 if (fAnalyticAA) {
91 if (edge->setQuadratic(pts, fShiftUp)) { 163 SkAnalyticQuadraticEdge* edge = typedAllocThrow<SkAnalyticQuadraticEdge> (fAlloc);
92 fList.push(edge); 164 if (edge->setQuadratic(pts)) {
165 fList.push(edge);
166 } else {
167 // TODO: unallocate edge from storage...
168 }
93 } else { 169 } else {
94 // TODO: unallocate edge from storage... 170 SkQuadraticEdge* edge = typedAllocThrow<SkQuadraticEdge>(fAlloc);
171 if (edge->setQuadratic(pts, fShiftUp)) {
172 fList.push(edge);
173 } else {
174 // TODO: unallocate edge from storage...
175 }
95 } 176 }
96 } 177 }
97 178
98 void SkEdgeBuilder::addCubic(const SkPoint pts[]) { 179 void SkEdgeBuilder::addCubic(const SkPoint pts[]) {
99 SkCubicEdge* edge = typedAllocThrow<SkCubicEdge>(fAlloc); 180 if (fAnalyticAA) {
100 if (edge->setCubic(pts, fShiftUp)) { 181 SkAnalyticCubicEdge* edge = typedAllocThrow<SkAnalyticCubicEdge>(fAlloc) ;
101 fList.push(edge); 182 if (edge->setCubic(pts)) {
183 fList.push(edge);
184 } else {
185 // TODO: unallocate edge from storage...
186 }
102 } else { 187 } else {
103 // TODO: unallocate edge from storage... 188 SkCubicEdge* edge = typedAllocThrow<SkCubicEdge>(fAlloc);
189 if (edge->setCubic(pts, fShiftUp)) {
190 fList.push(edge);
191 } else {
192 // TODO: unallocate edge from storage...
193 }
104 } 194 }
105 } 195 }
106 196
107 void SkEdgeBuilder::addClipper(SkEdgeClipper* clipper) { 197 void SkEdgeBuilder::addClipper(SkEdgeClipper* clipper) {
108 SkPoint pts[4]; 198 SkPoint pts[4];
109 SkPath::Verb verb; 199 SkPath::Verb verb;
110 200
111 while ((verb = clipper->next(pts)) != SkPath::kDone_Verb) { 201 while ((verb = clipper->next(pts)) != SkPath::kDone_Verb) {
112 switch (verb) { 202 switch (verb) {
113 case SkPath::kLine_Verb: 203 case SkPath::kLine_Verb:
(...skipping 14 matching lines...) Expand all
128 /////////////////////////////////////////////////////////////////////////////// 218 ///////////////////////////////////////////////////////////////////////////////
129 219
130 static void setShiftedClip(SkRect* dst, const SkIRect& src, int shift) { 220 static void setShiftedClip(SkRect* dst, const SkIRect& src, int shift) {
131 dst->set(SkIntToScalar(src.fLeft >> shift), 221 dst->set(SkIntToScalar(src.fLeft >> shift),
132 SkIntToScalar(src.fTop >> shift), 222 SkIntToScalar(src.fTop >> shift),
133 SkIntToScalar(src.fRight >> shift), 223 SkIntToScalar(src.fRight >> shift),
134 SkIntToScalar(src.fBottom >> shift)); 224 SkIntToScalar(src.fBottom >> shift));
135 } 225 }
136 226
137 SkEdgeBuilder::Combine SkEdgeBuilder::checkVertical(const SkEdge* edge, SkEdge** edgePtr) { 227 SkEdgeBuilder::Combine SkEdgeBuilder::checkVertical(const SkEdge* edge, SkEdge** edgePtr) {
138 return !vertical_line(edge) || edgePtr <= fEdgeList ? kNo_Combine : 228 return !vertical_line(edge) || edgePtr <= (SkEdge**)fEdgeList ? kNo_Combine :
139 CombineVertical(edge, edgePtr[-1]); 229 CombineVertical(edge, edgePtr[-1]);
140 } 230 }
141 231
232 SkEdgeBuilder::Combine SkEdgeBuilder::checkVertical(const SkAnalyticEdge* edge,
233 SkAnalyticEdge** edgePtr) {
234 SkASSERT(fAnalyticAA);
235 return !vertical_line(edge) || edgePtr <= (SkAnalyticEdge**)fEdgeList ? kNo_ Combine :
236 CombineVertical(edge, edgePtr[-1]);
237 }
238
142 int SkEdgeBuilder::buildPoly(const SkPath& path, const SkIRect* iclip, int shift Up, 239 int SkEdgeBuilder::buildPoly(const SkPath& path, const SkIRect* iclip, int shift Up,
143 bool canCullToTheRight) { 240 bool canCullToTheRight) {
144 SkPath::Iter iter(path, true); 241 SkPath::Iter iter(path, true);
145 SkPoint pts[4]; 242 SkPoint pts[4];
146 SkPath::Verb verb; 243 SkPath::Verb verb;
147 244
148 int maxEdgeCount = path.countPoints(); 245 int maxEdgeCount = path.countPoints();
149 if (iclip) { 246 if (iclip) {
150 // clipping can turn 1 line into (up to) kMaxClippedLineSegments, since 247 // clipping can turn 1 line into (up to) kMaxClippedLineSegments, since
151 // we turn portions that are clipped out on the left/right into vertical 248 // we turn portions that are clipped out on the left/right into vertical
152 // segments. 249 // segments.
153 maxEdgeCount *= SkLineClipper::kMaxClippedLineSegments; 250 maxEdgeCount *= SkLineClipper::kMaxClippedLineSegments;
154 } 251 }
155 size_t maxEdgeSize = maxEdgeCount * sizeof(SkEdge); 252 size_t edgeSize = fAnalyticAA ? sizeof(SkAnalyticEdge) : sizeof(SkEdge);
156 size_t maxEdgePtrSize = maxEdgeCount * sizeof(SkEdge*); 253 size_t maxEdgeSize = maxEdgeCount * edgeSize;
254 size_t maxEdgePtrSize = maxEdgeCount * sizeof(char*);
157 255
158 // lets store the edges and their pointers in the same block 256 // lets store the edges and their pointers in the same block
159 char* storage = (char*)fAlloc.allocThrow(maxEdgeSize + maxEdgePtrSize); 257 char* storage = (char*)fAlloc.allocThrow(maxEdgeSize + maxEdgePtrSize);
160 SkEdge* edge = reinterpret_cast<SkEdge*>(storage); 258 char* edge = (char*)storage;
161 SkEdge** edgePtr = reinterpret_cast<SkEdge**>(storage + maxEdgeSize); 259 char** edgePtr = (char**)(storage + maxEdgeSize);
162 // Record the beginning of our pointers, so we can return them to the caller 260 // Record the beginning of our pointers, so we can return them to the caller
163 fEdgeList = edgePtr; 261 fEdgeList = (void**)edgePtr;
164 262
165 if (iclip) { 263 if (iclip) {
166 SkRect clip; 264 SkRect clip;
167 setShiftedClip(&clip, *iclip, shiftUp); 265 setShiftedClip(&clip, *iclip, shiftUp);
168 266
169 while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) { 267 while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) {
170 switch (verb) { 268 switch (verb) {
171 case SkPath::kMove_Verb: 269 case SkPath::kMove_Verb:
172 case SkPath::kClose_Verb: 270 case SkPath::kClose_Verb:
173 // we ignore these, and just get the whole segment from 271 // we ignore these, and just get the whole segment from
174 // the corresponding line/quad/cubic verbs 272 // the corresponding line/quad/cubic verbs
175 break; 273 break;
176 case SkPath::kLine_Verb: { 274 case SkPath::kLine_Verb: {
177 SkPoint lines[SkLineClipper::kMaxPoints]; 275 SkPoint lines[SkLineClipper::kMaxPoints];
178 int lineCount = SkLineClipper::ClipLine(pts, clip, lines, ca nCullToTheRight); 276 int lineCount = SkLineClipper::ClipLine(pts, clip, lines, ca nCullToTheRight);
179 SkASSERT(lineCount <= SkLineClipper::kMaxClippedLineSegments ); 277 SkASSERT(lineCount <= SkLineClipper::kMaxClippedLineSegments );
180 for (int i = 0; i < lineCount; i++) { 278 for (int i = 0; i < lineCount; i++) {
181 if (edge->setLine(lines[i], lines[i + 1], shiftUp)) { 279 bool setLineResult = fAnalyticAA ?
182 Combine combine = checkVertical(edge, edgePtr); 280 ((SkAnalyticEdge*)edge)->setLine(lines[i], lines [i + 1]) :
281 ((SkEdge*)edge)->setLine(lines[i], lines[i + 1], shiftUp);
282 if (setLineResult) {
283 Combine combine = fAnalyticAA ?
284 checkVertical((SkAnalyticEdge*)edge, (SkAnal yticEdge**)edgePtr) :
285 checkVertical((SkEdge*)edge, (SkEdge**)edgeP tr);
183 if (kNo_Combine == combine) { 286 if (kNo_Combine == combine) {
184 *edgePtr++ = edge++; 287 *edgePtr++ = edge;
288 edge += edgeSize;
185 } else if (kTotal_Combine == combine) { 289 } else if (kTotal_Combine == combine) {
186 --edgePtr; 290 --edgePtr;
187 } 291 }
188 } 292 }
189 } 293 }
190 break; 294 break;
191 } 295 }
192 default: 296 default:
193 SkDEBUGFAIL("unexpected verb"); 297 SkDEBUGFAIL("unexpected verb");
194 break; 298 break;
195 } 299 }
196 } 300 }
197 } else { 301 } else {
198 while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) { 302 while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) {
199 switch (verb) { 303 switch (verb) {
200 case SkPath::kMove_Verb: 304 case SkPath::kMove_Verb:
201 case SkPath::kClose_Verb: 305 case SkPath::kClose_Verb:
202 // we ignore these, and just get the whole segment from 306 // we ignore these, and just get the whole segment from
203 // the corresponding line/quad/cubic verbs 307 // the corresponding line/quad/cubic verbs
204 break; 308 break;
205 case SkPath::kLine_Verb: 309 case SkPath::kLine_Verb: {
206 if (edge->setLine(pts[0], pts[1], shiftUp)) { 310 bool setLineResult = fAnalyticAA ?
207 Combine combine = checkVertical(edge, edgePtr); 311 ((SkAnalyticEdge*)edge)->setLine(pts[0], pts[1]) :
312 ((SkEdge*)edge)->setLine(pts[0], pts[1], shiftUp);
313 if (setLineResult) {
314 Combine combine = fAnalyticAA ?
315 checkVertical((SkAnalyticEdge*)edge, (SkAnalytic Edge**)edgePtr) :
316 checkVertical((SkEdge*)edge, (SkEdge**)edgePtr);
208 if (kNo_Combine == combine) { 317 if (kNo_Combine == combine) {
209 *edgePtr++ = edge++; 318 *edgePtr++ = edge;
319 edge += edgeSize;
210 } else if (kTotal_Combine == combine) { 320 } else if (kTotal_Combine == combine) {
211 --edgePtr; 321 --edgePtr;
212 } 322 }
213 } 323 }
214 break; 324 break;
325 }
215 default: 326 default:
216 SkDEBUGFAIL("unexpected verb"); 327 SkDEBUGFAIL("unexpected verb");
217 break; 328 break;
218 } 329 }
219 } 330 }
220 } 331 }
221 SkASSERT((char*)edge <= (char*)fEdgeList); 332 SkASSERT((char*)edge <= (char*)fEdgeList);
222 SkASSERT(edgePtr - fEdgeList <= maxEdgeCount); 333 SkASSERT(edgePtr - (char**)fEdgeList <= maxEdgeCount);
223 return SkToInt(edgePtr - fEdgeList); 334 return SkToInt(edgePtr - (char**)fEdgeList);
224 } 335 }
225 336
226 static void handle_quad(SkEdgeBuilder* builder, const SkPoint pts[3]) { 337 static void handle_quad(SkEdgeBuilder* builder, const SkPoint pts[3]) {
227 SkPoint monoX[5]; 338 SkPoint monoX[5];
228 int n = SkChopQuadAtYExtrema(pts, monoX); 339 int n = SkChopQuadAtYExtrema(pts, monoX);
229 for (int i = 0; i <= n; i++) { 340 for (int i = 0; i <= n; i++) {
230 builder->addQuad(&monoX[i * 2]); 341 builder->addQuad(&monoX[i * 2]);
231 } 342 }
232 } 343 }
233 344
234 int SkEdgeBuilder::build(const SkPath& path, const SkIRect* iclip, int shiftUp, 345 int SkEdgeBuilder::build(const SkPath& path, const SkIRect* iclip, int shiftUp,
235 bool canCullToTheRight) { 346 bool canCullToTheRight, bool analyticAA) {
236 fAlloc.reset(); 347 fAlloc.reset();
237 fList.reset(); 348 fList.reset();
238 fShiftUp = shiftUp; 349 fShiftUp = shiftUp;
350 fAnalyticAA = analyticAA;
239 351
240 if (SkPath::kLine_SegmentMask == path.getSegmentMasks()) { 352 if (SkPath::kLine_SegmentMask == path.getSegmentMasks()) {
241 return this->buildPoly(path, iclip, shiftUp, canCullToTheRight); 353 return this->buildPoly(path, iclip, shiftUp, canCullToTheRight);
242 } 354 }
243 355
244 SkAutoConicToQuads quadder; 356 SkAutoConicToQuads quadder;
245 const SkScalar conicTol = SK_Scalar1 / 4; 357 const SkScalar conicTol = SK_Scalar1 / 4;
246 358
247 SkPath::Iter iter(path, true); 359 SkPath::Iter iter(path, true);
248 SkPoint pts[4]; 360 SkPoint pts[4];
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 } 438 }
327 default: 439 default:
328 SkDEBUGFAIL("unexpected verb"); 440 SkDEBUGFAIL("unexpected verb");
329 break; 441 break;
330 } 442 }
331 } 443 }
332 } 444 }
333 fEdgeList = fList.begin(); 445 fEdgeList = fList.begin();
334 return fList.count(); 446 return fList.count();
335 } 447 }
OLDNEW
« src/core/SkEdge.cpp ('K') | « src/core/SkEdgeBuilder.h ('k') | src/core/SkScan.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698