OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 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 | 7 |
8 #include "GrTessellator.h" | 8 #include "GrTessellator.h" |
9 | 9 |
10 #include "GrDefaultGeoProcFactory.h" | |
10 #include "GrPathUtils.h" | 11 #include "GrPathUtils.h" |
11 | 12 |
12 #include "SkChunkAlloc.h" | 13 #include "SkChunkAlloc.h" |
13 #include "SkGeometry.h" | 14 #include "SkGeometry.h" |
14 #include "SkPath.h" | 15 #include "SkPath.h" |
15 | 16 |
16 #include <stdio.h> | 17 #include <stdio.h> |
17 | 18 |
18 /* | 19 /* |
19 * There are six stages to the algorithm: | 20 * There are six stages to the algorithm: |
bsalomon
2016/08/31 14:19:19
Can you update this to document the AA steps?
Stephen White
2016/08/31 15:16:38
Done.
| |
20 * | 21 * |
21 * 1) Linearize the path contours into piecewise linear segments (path_to_contou rs()). | 22 * 1) Linearize the path contours into piecewise linear segments (path_to_contou rs()). |
22 * 2) Build a mesh of edges connecting the vertices (build_edges()). | 23 * 2) Build a mesh of edges connecting the vertices (build_edges()). |
23 * 3) Sort the vertices in Y (and secondarily in X) (merge_sort()). | 24 * 3) Sort the vertices in Y (and secondarily in X) (merge_sort()). |
24 * 4) Simplify the mesh by inserting new vertices at intersecting edges (simplif y()). | 25 * 4) Simplify the mesh by inserting new vertices at intersecting edges (simplif y()). |
25 * 5) Tessellate the simplified mesh into monotone polygons (tessellate()). | 26 * 5) Tessellate the simplified mesh into monotone polygons (tessellate()). |
26 * 6) Triangulate the monotone polygons directly into a vertex buffer (polys_to_ triangles()). | 27 * 6) Triangulate the monotone polygons directly into a vertex buffer (polys_to_ triangles()). |
27 * | 28 * |
28 * The vertex sorting in step (3) is a merge sort, since it plays well with the linked list | 29 * The vertex sorting in step (3) is a merge sort, since it plays well with the linked list |
29 * of vertices (and the necessity of inserting new vertices on intersection). | 30 * of vertices (and the necessity of inserting new vertices on intersection). |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
123 * circularly-linked list of Vertices for each contour. After edge construction, the same Vertices | 124 * circularly-linked list of Vertices for each contour. After edge construction, the same Vertices |
124 * are re-ordered by the merge sort according to the sweep_lt comparator (usuall y, increasing | 125 * are re-ordered by the merge sort according to the sweep_lt comparator (usuall y, increasing |
125 * in Y) using the same fPrev/fNext pointers that were used for the contours, to avoid | 126 * in Y) using the same fPrev/fNext pointers that were used for the contours, to avoid |
126 * reallocation. Finally, MonotonePolys are built containing a circularly-linked list of | 127 * reallocation. Finally, MonotonePolys are built containing a circularly-linked list of |
127 * Vertices. (Currently, those Vertices are newly-allocated for the MonotonePoly s, since | 128 * Vertices. (Currently, those Vertices are newly-allocated for the MonotonePoly s, since |
128 * an individual Vertex from the path mesh may belong to multiple | 129 * an individual Vertex from the path mesh may belong to multiple |
129 * MonotonePolys, so the original Vertices cannot be re-used. | 130 * MonotonePolys, so the original Vertices cannot be re-used. |
130 */ | 131 */ |
131 | 132 |
132 struct Vertex { | 133 struct Vertex { |
133 Vertex(const SkPoint& point) | 134 Vertex(const SkPoint& point, uint8_t alpha) |
134 : fPoint(point), fPrev(nullptr), fNext(nullptr) | 135 : fPoint(point), fPrev(nullptr), fNext(nullptr) |
135 , fFirstEdgeAbove(nullptr), fLastEdgeAbove(nullptr) | 136 , fFirstEdgeAbove(nullptr), fLastEdgeAbove(nullptr) |
136 , fFirstEdgeBelow(nullptr), fLastEdgeBelow(nullptr) | 137 , fFirstEdgeBelow(nullptr), fLastEdgeBelow(nullptr) |
137 , fProcessed(false) | 138 , fProcessed(false) |
139 , fAlpha(alpha) | |
138 #if LOGGING_ENABLED | 140 #if LOGGING_ENABLED |
139 , fID (-1.0f) | 141 , fID (-1.0f) |
140 #endif | 142 #endif |
141 {} | 143 {} |
142 SkPoint fPoint; // Vertex position | 144 SkPoint fPoint; // Vertex position |
143 Vertex* fPrev; // Linked list of contours, then Y-sorted vertices . | 145 Vertex* fPrev; // Linked list of contours, then Y-sorted vertices . |
144 Vertex* fNext; // " | 146 Vertex* fNext; // " |
145 Edge* fFirstEdgeAbove; // Linked list of edges above this vertex. | 147 Edge* fFirstEdgeAbove; // Linked list of edges above this vertex. |
146 Edge* fLastEdgeAbove; // " | 148 Edge* fLastEdgeAbove; // " |
147 Edge* fFirstEdgeBelow; // Linked list of edges below this vertex. | 149 Edge* fFirstEdgeBelow; // Linked list of edges below this vertex. |
148 Edge* fLastEdgeBelow; // " | 150 Edge* fLastEdgeBelow; // " |
149 bool fProcessed; // Has this vertex been seen in simplify()? | 151 bool fProcessed; // Has this vertex been seen in simplify()? |
152 uint8_t fAlpha; | |
150 #if LOGGING_ENABLED | 153 #if LOGGING_ENABLED |
151 float fID; // Identifier used for logging. | 154 float fID; // Identifier used for logging. |
152 #endif | 155 #endif |
153 }; | 156 }; |
154 | 157 |
155 /******************************************************************************* ********/ | 158 /******************************************************************************* ********/ |
156 | 159 |
160 struct AAParams { | |
161 bool fTweakAlpha; | |
162 GrColor fColor; | |
163 }; | |
164 | |
157 typedef bool (*CompareFunc)(const SkPoint& a, const SkPoint& b); | 165 typedef bool (*CompareFunc)(const SkPoint& a, const SkPoint& b); |
158 | 166 |
159 struct Comparator { | 167 struct Comparator { |
160 CompareFunc sweep_lt; | 168 CompareFunc sweep_lt; |
161 CompareFunc sweep_gt; | 169 CompareFunc sweep_gt; |
162 }; | 170 }; |
163 | 171 |
164 bool sweep_lt_horiz(const SkPoint& a, const SkPoint& b) { | 172 bool sweep_lt_horiz(const SkPoint& a, const SkPoint& b) { |
165 return a.fX == b.fX ? a.fY > b.fY : a.fX < b.fX; | 173 return a.fX == b.fX ? a.fY > b.fY : a.fX < b.fX; |
166 } | 174 } |
167 | 175 |
168 bool sweep_lt_vert(const SkPoint& a, const SkPoint& b) { | 176 bool sweep_lt_vert(const SkPoint& a, const SkPoint& b) { |
169 return a.fY == b.fY ? a.fX < b.fX : a.fY < b.fY; | 177 return a.fY == b.fY ? a.fX < b.fX : a.fY < b.fY; |
170 } | 178 } |
171 | 179 |
172 bool sweep_gt_horiz(const SkPoint& a, const SkPoint& b) { | 180 bool sweep_gt_horiz(const SkPoint& a, const SkPoint& b) { |
173 return a.fX == b.fX ? a.fY < b.fY : a.fX > b.fX; | 181 return a.fX == b.fX ? a.fY < b.fY : a.fX > b.fX; |
174 } | 182 } |
175 | 183 |
176 bool sweep_gt_vert(const SkPoint& a, const SkPoint& b) { | 184 bool sweep_gt_vert(const SkPoint& a, const SkPoint& b) { |
177 return a.fY == b.fY ? a.fX > b.fX : a.fY > b.fY; | 185 return a.fY == b.fY ? a.fX > b.fX : a.fY > b.fY; |
178 } | 186 } |
179 | 187 |
180 inline SkPoint* emit_vertex(Vertex* v, SkPoint* data) { | 188 inline void* emit_vertex(Vertex* v, const AAParams* aaParams, void* data) { |
181 *data++ = v->fPoint; | 189 if (!aaParams) { |
182 return data; | 190 SkPoint* d = static_cast<SkPoint*>(data); |
191 *d++ = v->fPoint; | |
192 return d; | |
193 } | |
194 if (aaParams->fTweakAlpha) { | |
195 auto d = static_cast<GrDefaultGeoProcFactory::PositionColorAttr*>(data); | |
196 d->fPosition = v->fPoint; | |
197 d->fColor = SkAlphaMulQ(aaParams->fColor, v->fAlpha); | |
198 d++; | |
199 return d; | |
200 } | |
201 auto d = static_cast<GrDefaultGeoProcFactory::PositionColorCoverageAttr*>(da ta); | |
202 d->fPosition = v->fPoint; | |
203 d->fColor = aaParams->fColor; | |
204 d->fCoverage = GrNormalizeByteToFloat(v->fAlpha); | |
205 d++; | |
206 return d; | |
183 } | 207 } |
184 | 208 |
185 SkPoint* emit_triangle(Vertex* v0, Vertex* v1, Vertex* v2, SkPoint* data) { | 209 void* emit_triangle(Vertex* v0, Vertex* v1, Vertex* v2, const AAParams* aaParams , void* data) { |
186 #if WIREFRAME | 210 #if TESSELLATOR_WIREFRAME |
187 data = emit_vertex(v0, data); | 211 data = emit_vertex(v0, aaParams, data); |
188 data = emit_vertex(v1, data); | 212 data = emit_vertex(v1, aaParams, data); |
189 data = emit_vertex(v1, data); | 213 data = emit_vertex(v1, aaParams, data); |
190 data = emit_vertex(v2, data); | 214 data = emit_vertex(v2, aaParams, data); |
191 data = emit_vertex(v2, data); | 215 data = emit_vertex(v2, aaParams, data); |
192 data = emit_vertex(v0, data); | 216 data = emit_vertex(v0, aaParams, data); |
193 #else | 217 #else |
194 data = emit_vertex(v0, data); | 218 data = emit_vertex(v0, aaParams, data); |
195 data = emit_vertex(v1, data); | 219 data = emit_vertex(v1, aaParams, data); |
196 data = emit_vertex(v2, data); | 220 data = emit_vertex(v2, aaParams, data); |
197 #endif | 221 #endif |
198 return data; | 222 return data; |
199 } | 223 } |
200 | 224 |
201 struct EdgeList { | |
202 EdgeList() : fHead(nullptr), fTail(nullptr) {} | |
203 Edge* fHead; | |
204 Edge* fTail; | |
205 }; | |
206 | |
207 struct VertexList { | 225 struct VertexList { |
208 VertexList() : fHead(nullptr), fTail(nullptr) {} | 226 VertexList() : fHead(nullptr), fTail(nullptr) {} |
209 Vertex* fHead; | 227 Vertex* fHead; |
210 Vertex* fTail; | 228 Vertex* fTail; |
211 void insert(Vertex* v, Vertex* prev, Vertex* next) { | 229 void insert(Vertex* v, Vertex* prev, Vertex* next) { |
212 list_insert<Vertex, &Vertex::fPrev, &Vertex::fNext>(v, prev, next, &fHea d, &fTail); | 230 list_insert<Vertex, &Vertex::fPrev, &Vertex::fNext>(v, prev, next, &fHea d, &fTail); |
213 } | 231 } |
214 void append(Vertex* v) { | 232 void append(Vertex* v) { |
215 insert(v, fTail, nullptr); | 233 insert(v, fTail, nullptr); |
216 } | 234 } |
217 void prepend(Vertex* v) { | 235 void prepend(Vertex* v) { |
218 insert(v, nullptr, fHead); | 236 insert(v, nullptr, fHead); |
219 } | 237 } |
238 void close() { | |
239 if (fHead && fTail) { | |
240 fTail->fNext = fHead; | |
241 fHead->fPrev = fTail; | |
242 } | |
243 } | |
220 }; | 244 }; |
221 | 245 |
246 inline void round(SkPoint* p) { | |
bsalomon
2016/08/31 14:19:19
Is this rounding to 1/4 pixel values?
Stephen White
2016/08/31 15:16:38
Yes; added a comment.
| |
247 p->fX = SkScalarRoundToScalar(p->fX * SkFloatToScalar(4.0f)) * SkFloatToScal ar(0.25f); | |
248 p->fY = SkScalarRoundToScalar(p->fY * SkFloatToScalar(4.0f)) * SkFloatToScal ar(0.25f); | |
249 } | |
250 | |
222 /** | 251 /** |
223 * An Edge joins a top Vertex to a bottom Vertex. Edge ordering for the list of "edges above" and | 252 * An Edge joins a top Vertex to a bottom Vertex. Edge ordering for the list of "edges above" and |
224 * "edge below" a vertex as well as for the active edge list is handled by isLef tOf()/isRightOf(). | 253 * "edge below" a vertex as well as for the active edge list is handled by isLef tOf()/isRightOf(). |
225 * Note that an Edge will give occasionally dist() != 0 for its own endpoints (b ecause floating | 254 * Note that an Edge will give occasionally dist() != 0 for its own endpoints (b ecause floating |
226 * point). For speed, that case is only tested by the callers which require it ( e.g., | 255 * point). For speed, that case is only tested by the callers which require it ( e.g., |
227 * cleanup_active_edges()). Edges also handle checking for intersection with oth er edges. | 256 * cleanup_active_edges()). Edges also handle checking for intersection with oth er edges. |
228 * Currently, this converts the edges to the parametric form, in order to avoid doing a division | 257 * Currently, this converts the edges to the parametric form, in order to avoid doing a division |
229 * until an intersection has been confirmed. This is slightly slower in the "fou nd" case, but | 258 * until an intersection has been confirmed. This is slightly slower in the "fou nd" case, but |
230 * a lot faster in the "not found" case. | 259 * a lot faster in the "not found" case. |
231 * | 260 * |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
313 if (denom > 0.0 ? (sNumer < 0.0 || sNumer > denom || tNumer < 0.0 || tNu mer > denom) | 342 if (denom > 0.0 ? (sNumer < 0.0 || sNumer > denom || tNumer < 0.0 || tNu mer > denom) |
314 : (sNumer > 0.0 || sNumer < denom || tNumer > 0.0 || tNu mer < denom)) { | 343 : (sNumer > 0.0 || sNumer < denom || tNumer > 0.0 || tNu mer < denom)) { |
315 return false; | 344 return false; |
316 } | 345 } |
317 double s = sNumer / denom; | 346 double s = sNumer / denom; |
318 SkASSERT(s >= 0.0 && s <= 1.0); | 347 SkASSERT(s >= 0.0 && s <= 1.0); |
319 p->fX = SkDoubleToScalar(fTop->fPoint.fX + s * fDX); | 348 p->fX = SkDoubleToScalar(fTop->fPoint.fX + s * fDX); |
320 p->fY = SkDoubleToScalar(fTop->fPoint.fY + s * fDY); | 349 p->fY = SkDoubleToScalar(fTop->fPoint.fY + s * fDY); |
321 return true; | 350 return true; |
322 } | 351 } |
323 bool isActive(EdgeList* activeEdges) const { | 352 }; |
324 return activeEdges && (fLeft || fRight || activeEdges->fHead == this); | 353 |
354 struct EdgeList { | |
355 EdgeList() : fHead(nullptr), fTail(nullptr), fNext(nullptr), fCount(0) {} | |
356 Edge* fHead; | |
357 Edge* fTail; | |
358 EdgeList* fNext; | |
359 int fCount; | |
360 void insert(Edge* edge, Edge* prev, Edge* next) { | |
361 list_insert<Edge, &Edge::fLeft, &Edge::fRight>(edge, prev, next, &fHead, &fTail); | |
362 fCount++; | |
363 } | |
364 void append(Edge* e) { | |
365 insert(e, fTail, nullptr); | |
366 } | |
367 void remove(Edge* edge) { | |
368 list_remove<Edge, &Edge::fLeft, &Edge::fRight>(edge, &fHead, &fTail); | |
369 fCount--; | |
370 } | |
371 void close() { | |
372 if (fHead && fTail) { | |
373 fTail->fRight = fHead; | |
374 fHead->fLeft = fTail; | |
375 } | |
376 } | |
377 bool contains(Edge* edge) const { | |
378 return edge->fLeft || edge->fRight || fHead == edge; | |
325 } | 379 } |
326 }; | 380 }; |
327 | 381 |
328 /******************************************************************************* ********/ | 382 /******************************************************************************* ********/ |
329 | 383 |
330 struct Poly { | 384 struct Poly { |
331 Poly(Vertex* v, int winding) | 385 Poly(Vertex* v, int winding) |
332 : fFirstVertex(v) | 386 : fFirstVertex(v) |
333 , fWinding(winding) | 387 , fWinding(winding) |
334 , fHead(nullptr) | 388 , fHead(nullptr) |
(...skipping 30 matching lines...) Expand all Loading... | |
365 edge, fLastEdge, nullptr, &fFirstEdge, &fLastEdge); | 419 edge, fLastEdge, nullptr, &fFirstEdge, &fLastEdge); |
366 edge->fUsedInRightPoly = true; | 420 edge->fUsedInRightPoly = true; |
367 } else { | 421 } else { |
368 SkASSERT(!edge->fUsedInLeftPoly); | 422 SkASSERT(!edge->fUsedInLeftPoly); |
369 list_insert<Edge, &Edge::fLeftPolyPrev, &Edge::fLeftPolyNext>( | 423 list_insert<Edge, &Edge::fLeftPolyPrev, &Edge::fLeftPolyNext>( |
370 edge, fLastEdge, nullptr, &fFirstEdge, &fLastEdge); | 424 edge, fLastEdge, nullptr, &fFirstEdge, &fLastEdge); |
371 edge->fUsedInLeftPoly = true; | 425 edge->fUsedInLeftPoly = true; |
372 } | 426 } |
373 } | 427 } |
374 | 428 |
375 SkPoint* emit(SkPoint* data) { | 429 void* emit(const AAParams* aaParams, void* data) { |
376 Edge* e = fFirstEdge; | 430 Edge* e = fFirstEdge; |
377 e->fTop->fPrev = e->fTop->fNext = nullptr; | 431 e->fTop->fPrev = e->fTop->fNext = nullptr; |
378 VertexList vertices; | 432 VertexList vertices; |
379 vertices.append(e->fTop); | 433 vertices.append(e->fTop); |
380 while (e != nullptr) { | 434 while (e != nullptr) { |
381 e->fBottom->fPrev = e->fBottom->fNext = nullptr; | 435 e->fBottom->fPrev = e->fBottom->fNext = nullptr; |
382 if (kRight_Side == fSide) { | 436 if (kRight_Side == fSide) { |
383 vertices.append(e->fBottom); | 437 vertices.append(e->fBottom); |
384 e = e->fRightPolyNext; | 438 e = e->fRightPolyNext; |
385 } else { | 439 } else { |
386 vertices.prepend(e->fBottom); | 440 vertices.prepend(e->fBottom); |
387 e = e->fLeftPolyNext; | 441 e = e->fLeftPolyNext; |
388 } | 442 } |
389 } | 443 } |
390 Vertex* first = vertices.fHead; | 444 Vertex* first = vertices.fHead; |
391 Vertex* v = first->fNext; | 445 Vertex* v = first->fNext; |
392 while (v != vertices.fTail) { | 446 while (v != vertices.fTail) { |
393 SkASSERT(v && v->fPrev && v->fNext); | 447 SkASSERT(v && v->fPrev && v->fNext); |
394 Vertex* prev = v->fPrev; | 448 Vertex* prev = v->fPrev; |
395 Vertex* curr = v; | 449 Vertex* curr = v; |
396 Vertex* next = v->fNext; | 450 Vertex* next = v->fNext; |
397 double ax = static_cast<double>(curr->fPoint.fX) - prev->fPoint. fX; | 451 double ax = static_cast<double>(curr->fPoint.fX) - prev->fPoint. fX; |
398 double ay = static_cast<double>(curr->fPoint.fY) - prev->fPoint. fY; | 452 double ay = static_cast<double>(curr->fPoint.fY) - prev->fPoint. fY; |
399 double bx = static_cast<double>(next->fPoint.fX) - curr->fPoint. fX; | 453 double bx = static_cast<double>(next->fPoint.fX) - curr->fPoint. fX; |
400 double by = static_cast<double>(next->fPoint.fY) - curr->fPoint. fY; | 454 double by = static_cast<double>(next->fPoint.fY) - curr->fPoint. fY; |
401 if (ax * by - ay * bx >= 0.0) { | 455 if (ax * by - ay * bx >= 0.0) { |
402 data = emit_triangle(prev, curr, next, data); | 456 data = emit_triangle(prev, curr, next, aaParams, data); |
403 v->fPrev->fNext = v->fNext; | 457 v->fPrev->fNext = v->fNext; |
404 v->fNext->fPrev = v->fPrev; | 458 v->fNext->fPrev = v->fPrev; |
405 if (v->fPrev == first) { | 459 if (v->fPrev == first) { |
406 v = v->fNext; | 460 v = v->fNext; |
407 } else { | 461 } else { |
408 v = v->fPrev; | 462 v = v->fPrev; |
409 } | 463 } |
410 } else { | 464 } else { |
411 v = v->fNext; | 465 v = v->fNext; |
412 } | 466 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
448 poly = partner; | 502 poly = partner; |
449 } else { | 503 } else { |
450 MonotonePoly* m = ALLOC_NEW(MonotonePoly, (e, side), alloc); | 504 MonotonePoly* m = ALLOC_NEW(MonotonePoly, (e, side), alloc); |
451 m->fPrev = fTail; | 505 m->fPrev = fTail; |
452 fTail->fNext = m; | 506 fTail->fNext = m; |
453 fTail = m; | 507 fTail = m; |
454 } | 508 } |
455 } | 509 } |
456 return poly; | 510 return poly; |
457 } | 511 } |
458 SkPoint* emit(SkPoint *data) { | 512 void* emit(const AAParams* aaParams, void *data) { |
459 if (fCount < 3) { | 513 if (fCount < 3) { |
460 return data; | 514 return data; |
461 } | 515 } |
462 LOG("emit() %d, size %d\n", fID, fCount); | 516 LOG("emit() %d, size %d\n", fID, fCount); |
463 for (MonotonePoly* m = fHead; m != nullptr; m = m->fNext) { | 517 for (MonotonePoly* m = fHead; m != nullptr; m = m->fNext) { |
464 data = m->emit(data); | 518 data = m->emit(aaParams, data); |
465 } | 519 } |
466 return data; | 520 return data; |
467 } | 521 } |
468 Vertex* lastVertex() const { return fTail ? fTail->fLastEdge->fBottom : fFir stVertex; } | 522 Vertex* lastVertex() const { return fTail ? fTail->fLastEdge->fBottom : fFir stVertex; } |
469 Vertex* fFirstVertex; | 523 Vertex* fFirstVertex; |
470 int fWinding; | 524 int fWinding; |
471 MonotonePoly* fHead; | 525 MonotonePoly* fHead; |
472 MonotonePoly* fTail; | 526 MonotonePoly* fTail; |
473 Poly* fNext; | 527 Poly* fNext; |
474 Poly* fPartner; | 528 Poly* fPartner; |
475 int fCount; | 529 int fCount; |
476 #if LOGGING_ENABLED | 530 #if LOGGING_ENABLED |
477 int fID; | 531 int fID; |
478 #endif | 532 #endif |
479 }; | 533 }; |
480 | 534 |
481 /******************************************************************************* ********/ | 535 /******************************************************************************* ********/ |
482 | 536 |
483 bool coincident(const SkPoint& a, const SkPoint& b) { | 537 bool coincident(const SkPoint& a, const SkPoint& b) { |
484 return a == b; | 538 return a == b; |
485 } | 539 } |
486 | 540 |
487 Poly* new_poly(Poly** head, Vertex* v, int winding, SkChunkAlloc& alloc) { | 541 Poly* new_poly(Poly** head, Vertex* v, int winding, SkChunkAlloc& alloc) { |
488 Poly* poly = ALLOC_NEW(Poly, (v, winding), alloc); | 542 Poly* poly = ALLOC_NEW(Poly, (v, winding), alloc); |
489 poly->fNext = *head; | 543 poly->fNext = *head; |
490 *head = poly; | 544 *head = poly; |
491 return poly; | 545 return poly; |
492 } | 546 } |
493 | 547 |
548 EdgeList* new_contour(EdgeList** head, SkChunkAlloc& alloc) { | |
549 EdgeList* contour = ALLOC_NEW(EdgeList, (), alloc); | |
550 contour->fNext = *head; | |
551 *head = contour; | |
552 return contour; | |
553 } | |
554 | |
494 Vertex* append_point_to_contour(const SkPoint& p, Vertex* prev, Vertex** head, | 555 Vertex* append_point_to_contour(const SkPoint& p, Vertex* prev, Vertex** head, |
495 SkChunkAlloc& alloc) { | 556 SkChunkAlloc& alloc) { |
496 Vertex* v = ALLOC_NEW(Vertex, (p), alloc); | 557 Vertex* v = ALLOC_NEW(Vertex, (p, 255), alloc); |
497 #if LOGGING_ENABLED | 558 #if LOGGING_ENABLED |
498 static float gID = 0.0f; | 559 static float gID = 0.0f; |
499 v->fID = gID++; | 560 v->fID = gID++; |
500 #endif | 561 #endif |
501 if (prev) { | 562 if (prev) { |
502 prev->fNext = v; | 563 prev->fNext = v; |
503 v->fPrev = prev; | 564 v->fPrev = prev; |
504 } else { | 565 } else { |
505 *head = v; | 566 *head = v; |
506 } | 567 } |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
571 | 632 |
572 SkPoint pts[4]; | 633 SkPoint pts[4]; |
573 bool done = false; | 634 bool done = false; |
574 *isLinear = true; | 635 *isLinear = true; |
575 SkPath::Iter iter(path, false); | 636 SkPath::Iter iter(path, false); |
576 Vertex* prev = nullptr; | 637 Vertex* prev = nullptr; |
577 Vertex* head = nullptr; | 638 Vertex* head = nullptr; |
578 if (path.isInverseFillType()) { | 639 if (path.isInverseFillType()) { |
579 SkPoint quad[4]; | 640 SkPoint quad[4]; |
580 clipBounds.toQuad(quad); | 641 clipBounds.toQuad(quad); |
581 for (int i = 3; i >= 0; i--) { | 642 for (int i = 0; i < 4; i++) { |
582 prev = append_point_to_contour(quad[i], prev, &head, alloc); | 643 prev = append_point_to_contour(quad[i], prev, &head, alloc); |
583 } | 644 } |
584 head->fPrev = prev; | 645 head->fPrev = prev; |
585 prev->fNext = head; | 646 prev->fNext = head; |
586 *contours++ = head; | 647 *contours++ = head; |
587 head = prev = nullptr; | 648 head = prev = nullptr; |
588 } | 649 } |
589 SkAutoConicToQuads converter; | 650 SkAutoConicToQuads converter; |
590 while (!done) { | 651 while (!done) { |
591 SkPath::Verb verb = iter.next(pts); | 652 SkPath::Verb verb = iter.next(pts); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
642 head->fPrev = prev; | 703 head->fPrev = prev; |
643 prev->fNext = head; | 704 prev->fNext = head; |
644 *contours++ = head; | 705 *contours++ = head; |
645 } | 706 } |
646 done = true; | 707 done = true; |
647 break; | 708 break; |
648 } | 709 } |
649 } | 710 } |
650 } | 711 } |
651 | 712 |
652 inline bool apply_fill_type(SkPath::FillType fillType, int winding) { | 713 inline bool apply_fill_type(SkPath::FillType fillType, Poly* poly) { |
714 if (!poly) { | |
715 return false; | |
716 } | |
717 int winding = poly->fWinding; | |
653 switch (fillType) { | 718 switch (fillType) { |
654 case SkPath::kWinding_FillType: | 719 case SkPath::kWinding_FillType: |
655 return winding != 0; | 720 return winding != 0; |
656 case SkPath::kEvenOdd_FillType: | 721 case SkPath::kEvenOdd_FillType: |
657 return (winding & 1) != 0; | 722 return (winding & 1) != 0; |
658 case SkPath::kInverseWinding_FillType: | 723 case SkPath::kInverseWinding_FillType: |
659 return winding == 1; | 724 return winding == -1; |
660 case SkPath::kInverseEvenOdd_FillType: | 725 case SkPath::kInverseEvenOdd_FillType: |
661 return (winding & 1) == 1; | 726 return (winding & 1) == 1; |
662 default: | 727 default: |
663 SkASSERT(false); | 728 SkASSERT(false); |
664 return false; | 729 return false; |
665 } | 730 } |
666 } | 731 } |
667 | 732 |
668 Edge* new_edge(Vertex* prev, Vertex* next, SkChunkAlloc& alloc, Comparator& c) { | 733 Edge* new_edge(Vertex* prev, Vertex* next, SkChunkAlloc& alloc, Comparator& c, |
669 int winding = c.sweep_lt(prev->fPoint, next->fPoint) ? 1 : -1; | 734 int winding_scale = 1) { |
735 int winding = c.sweep_lt(prev->fPoint, next->fPoint) ? winding_scale : -wind ing_scale; | |
670 Vertex* top = winding < 0 ? next : prev; | 736 Vertex* top = winding < 0 ? next : prev; |
671 Vertex* bottom = winding < 0 ? prev : next; | 737 Vertex* bottom = winding < 0 ? prev : next; |
672 return ALLOC_NEW(Edge, (top, bottom, winding), alloc); | 738 return ALLOC_NEW(Edge, (top, bottom, winding), alloc); |
673 } | 739 } |
674 | 740 |
675 void remove_edge(Edge* edge, EdgeList* edges) { | 741 void remove_edge(Edge* edge, EdgeList* edges) { |
676 LOG("removing edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID); | 742 LOG("removing edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID); |
677 SkASSERT(edge->isActive(edges)); | 743 SkASSERT(edges->contains(edge)); |
678 list_remove<Edge, &Edge::fLeft, &Edge::fRight>(edge, &edges->fHead, &edges-> fTail); | 744 edges->remove(edge); |
679 } | 745 } |
680 | 746 |
681 void insert_edge(Edge* edge, Edge* prev, EdgeList* edges) { | 747 void insert_edge(Edge* edge, Edge* prev, EdgeList* edges) { |
682 LOG("inserting edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID); | 748 LOG("inserting edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID); |
683 SkASSERT(!edge->isActive(edges)); | 749 SkASSERT(!edges->contains(edge)); |
684 Edge* next = prev ? prev->fRight : edges->fHead; | 750 Edge* next = prev ? prev->fRight : edges->fHead; |
685 list_insert<Edge, &Edge::fLeft, &Edge::fRight>(edge, prev, next, &edges->fHe ad, &edges->fTail); | 751 edges->insert(edge, prev, next); |
686 } | 752 } |
687 | 753 |
688 void find_enclosing_edges(Vertex* v, EdgeList* edges, Edge** left, Edge** right) { | 754 void find_enclosing_edges(Vertex* v, EdgeList* edges, Edge** left, Edge** right) { |
689 if (v->fFirstEdgeAbove) { | 755 if (v->fFirstEdgeAbove) { |
690 *left = v->fFirstEdgeAbove->fLeft; | 756 *left = v->fFirstEdgeAbove->fLeft; |
691 *right = v->fLastEdgeAbove->fRight; | 757 *right = v->fLastEdgeAbove->fRight; |
692 return; | 758 return; |
693 } | 759 } |
694 Edge* next = nullptr; | 760 Edge* next = nullptr; |
695 Edge* prev; | 761 Edge* prev; |
(...skipping 19 matching lines...) Expand all Loading... | |
715 edge->isLeftOf(next->fBottom))) { | 781 edge->isLeftOf(next->fBottom))) { |
716 break; | 782 break; |
717 } | 783 } |
718 prev = next; | 784 prev = next; |
719 } | 785 } |
720 *left = prev; | 786 *left = prev; |
721 *right = next; | 787 *right = next; |
722 } | 788 } |
723 | 789 |
724 void fix_active_state(Edge* edge, EdgeList* activeEdges, Comparator& c) { | 790 void fix_active_state(Edge* edge, EdgeList* activeEdges, Comparator& c) { |
725 if (edge->isActive(activeEdges)) { | 791 if (activeEdges && activeEdges->contains(edge)) { |
726 if (edge->fBottom->fProcessed || !edge->fTop->fProcessed) { | 792 if (edge->fBottom->fProcessed || !edge->fTop->fProcessed) { |
727 remove_edge(edge, activeEdges); | 793 remove_edge(edge, activeEdges); |
728 } | 794 } |
729 } else if (edge->fTop->fProcessed && !edge->fBottom->fProcessed) { | 795 } else if (edge->fTop->fProcessed && !edge->fBottom->fProcessed) { |
730 Edge* left; | 796 Edge* left; |
731 Edge* right; | 797 Edge* right; |
732 find_enclosing_edges(edge, activeEdges, c, &left, &right); | 798 find_enclosing_edges(edge, activeEdges, c, &left, &right); |
733 insert_edge(edge, left, activeEdges); | 799 insert_edge(edge, left, activeEdges); |
734 } | 800 } |
735 } | 801 } |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
784 edge, &edge->fTop->fFirstEdgeBelow, &edge->fTop->fLastEdgeBelow); | 850 edge, &edge->fTop->fFirstEdgeBelow, &edge->fTop->fLastEdgeBelow); |
785 } | 851 } |
786 | 852 |
787 void erase_edge_if_zero_winding(Edge* edge, EdgeList* edges) { | 853 void erase_edge_if_zero_winding(Edge* edge, EdgeList* edges) { |
788 if (edge->fWinding != 0) { | 854 if (edge->fWinding != 0) { |
789 return; | 855 return; |
790 } | 856 } |
791 LOG("erasing edge (%g -> %g)\n", edge->fTop->fID, edge->fBottom->fID); | 857 LOG("erasing edge (%g -> %g)\n", edge->fTop->fID, edge->fBottom->fID); |
792 remove_edge_above(edge); | 858 remove_edge_above(edge); |
793 remove_edge_below(edge); | 859 remove_edge_below(edge); |
794 if (edge->isActive(edges)) { | 860 if (edges && edges->contains(edge)) { |
795 remove_edge(edge, edges); | 861 remove_edge(edge, edges); |
796 } | 862 } |
797 } | 863 } |
798 | 864 |
799 void merge_collinear_edges(Edge* edge, EdgeList* activeEdges, Comparator& c); | 865 void merge_collinear_edges(Edge* edge, EdgeList* activeEdges, Comparator& c); |
800 | 866 |
801 void set_top(Edge* edge, Vertex* v, EdgeList* activeEdges, Comparator& c) { | 867 void set_top(Edge* edge, Vertex* v, EdgeList* activeEdges, Comparator& c) { |
802 remove_edge_below(edge); | 868 remove_edge_below(edge); |
803 edge->fTop = v; | 869 edge->fTop = v; |
804 edge->recompute(); | 870 edge->recompute(); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
921 Edge* newEdge = ALLOC_NEW(Edge, (v, edge->fBottom, edge->fWinding), allo c); | 987 Edge* newEdge = ALLOC_NEW(Edge, (v, edge->fBottom, edge->fWinding), allo c); |
922 insert_edge_below(newEdge, v, c); | 988 insert_edge_below(newEdge, v, c); |
923 insert_edge_above(newEdge, edge->fBottom, c); | 989 insert_edge_above(newEdge, edge->fBottom, c); |
924 set_bottom(edge, v, activeEdges, c); | 990 set_bottom(edge, v, activeEdges, c); |
925 cleanup_active_edges(edge, activeEdges, c, alloc); | 991 cleanup_active_edges(edge, activeEdges, c, alloc); |
926 fix_active_state(newEdge, activeEdges, c); | 992 fix_active_state(newEdge, activeEdges, c); |
927 merge_collinear_edges(newEdge, activeEdges, c); | 993 merge_collinear_edges(newEdge, activeEdges, c); |
928 } | 994 } |
929 } | 995 } |
930 | 996 |
997 Edge* connect(Vertex* prev, Vertex* next, SkChunkAlloc& alloc, Comparator c, | |
998 int winding_scale = 1) { | |
999 Edge* edge = new_edge(prev, next, alloc, c, winding_scale); | |
1000 if (edge->fWinding > 0) { | |
1001 insert_edge_below(edge, prev, c); | |
1002 insert_edge_above(edge, next, c); | |
1003 } else { | |
1004 insert_edge_below(edge, next, c); | |
1005 insert_edge_above(edge, prev, c); | |
1006 } | |
1007 merge_collinear_edges(edge, nullptr, c); | |
1008 return edge; | |
1009 } | |
1010 | |
931 void merge_vertices(Vertex* src, Vertex* dst, Vertex** head, Comparator& c, SkCh unkAlloc& alloc) { | 1011 void merge_vertices(Vertex* src, Vertex* dst, Vertex** head, Comparator& c, SkCh unkAlloc& alloc) { |
932 LOG("found coincident verts at %g, %g; merging %g into %g\n", src->fPoint.fX , src->fPoint.fY, | 1012 LOG("found coincident verts at %g, %g; merging %g into %g\n", src->fPoint.fX , src->fPoint.fY, |
933 src->fID, dst->fID); | 1013 src->fID, dst->fID); |
1014 dst->fAlpha = SkTMax(src->fAlpha, dst->fAlpha); | |
934 for (Edge* edge = src->fFirstEdgeAbove; edge;) { | 1015 for (Edge* edge = src->fFirstEdgeAbove; edge;) { |
935 Edge* next = edge->fNextEdgeAbove; | 1016 Edge* next = edge->fNextEdgeAbove; |
936 set_bottom(edge, dst, nullptr, c); | 1017 set_bottom(edge, dst, nullptr, c); |
937 edge = next; | 1018 edge = next; |
938 } | 1019 } |
939 for (Edge* edge = src->fFirstEdgeBelow; edge;) { | 1020 for (Edge* edge = src->fFirstEdgeBelow; edge;) { |
940 Edge* next = edge->fNextEdgeBelow; | 1021 Edge* next = edge->fNextEdgeBelow; |
941 set_top(edge, dst, nullptr, c); | 1022 set_top(edge, dst, nullptr, c); |
942 edge = next; | 1023 edge = next; |
943 } | 1024 } |
944 list_remove<Vertex, &Vertex::fPrev, &Vertex::fNext>(src, head, nullptr); | 1025 list_remove<Vertex, &Vertex::fPrev, &Vertex::fNext>(src, head, nullptr); |
945 } | 1026 } |
946 | 1027 |
1028 uint8_t max_edge_alpha(Edge* a, Edge* b) { | |
1029 return SkTMax(SkTMax(a->fTop->fAlpha, a->fBottom->fAlpha), | |
1030 SkTMax(b->fTop->fAlpha, b->fBottom->fAlpha)); | |
1031 } | |
1032 | |
947 Vertex* check_for_intersection(Edge* edge, Edge* other, EdgeList* activeEdges, C omparator& c, | 1033 Vertex* check_for_intersection(Edge* edge, Edge* other, EdgeList* activeEdges, C omparator& c, |
948 SkChunkAlloc& alloc) { | 1034 SkChunkAlloc& alloc) { |
949 SkPoint p; | 1035 SkPoint p; |
950 if (!edge || !other) { | 1036 if (!edge || !other) { |
951 return nullptr; | 1037 return nullptr; |
952 } | 1038 } |
953 if (edge->intersect(*other, &p)) { | 1039 if (edge->intersect(*other, &p)) { |
954 Vertex* v; | 1040 Vertex* v; |
955 LOG("found intersection, pt is %g, %g\n", p.fX, p.fY); | 1041 LOG("found intersection, pt is %g, %g\n", p.fX, p.fY); |
956 if (p == edge->fTop->fPoint || c.sweep_lt(p, edge->fTop->fPoint)) { | 1042 if (p == edge->fTop->fPoint || c.sweep_lt(p, edge->fTop->fPoint)) { |
(...skipping 15 matching lines...) Expand all Loading... | |
972 } | 1058 } |
973 while (c.sweep_lt(nextV->fPoint, p)) { | 1059 while (c.sweep_lt(nextV->fPoint, p)) { |
974 nextV = nextV->fNext; | 1060 nextV = nextV->fNext; |
975 } | 1061 } |
976 Vertex* prevV = nextV->fPrev; | 1062 Vertex* prevV = nextV->fPrev; |
977 if (coincident(prevV->fPoint, p)) { | 1063 if (coincident(prevV->fPoint, p)) { |
978 v = prevV; | 1064 v = prevV; |
979 } else if (coincident(nextV->fPoint, p)) { | 1065 } else if (coincident(nextV->fPoint, p)) { |
980 v = nextV; | 1066 v = nextV; |
981 } else { | 1067 } else { |
982 v = ALLOC_NEW(Vertex, (p), alloc); | 1068 uint8_t alpha = max_edge_alpha(edge, other); |
1069 v = ALLOC_NEW(Vertex, (p, alpha), alloc); | |
983 LOG("inserting between %g (%g, %g) and %g (%g, %g)\n", | 1070 LOG("inserting between %g (%g, %g) and %g (%g, %g)\n", |
984 prevV->fID, prevV->fPoint.fX, prevV->fPoint.fY, | 1071 prevV->fID, prevV->fPoint.fX, prevV->fPoint.fY, |
985 nextV->fID, nextV->fPoint.fX, nextV->fPoint.fY); | 1072 nextV->fID, nextV->fPoint.fX, nextV->fPoint.fY); |
986 #if LOGGING_ENABLED | 1073 #if LOGGING_ENABLED |
987 v->fID = (nextV->fID + prevV->fID) * 0.5f; | 1074 v->fID = (nextV->fID + prevV->fID) * 0.5f; |
988 #endif | 1075 #endif |
989 v->fPrev = prevV; | 1076 v->fPrev = prevV; |
990 v->fNext = nextV; | 1077 v->fNext = nextV; |
991 prevV->fNext = v; | 1078 prevV->fNext = v; |
992 nextV->fPrev = v; | 1079 nextV->fPrev = v; |
993 } | 1080 } |
994 split_edge(edge, v, activeEdges, c, alloc); | 1081 split_edge(edge, v, activeEdges, c, alloc); |
995 split_edge(other, v, activeEdges, c, alloc); | 1082 split_edge(other, v, activeEdges, c, alloc); |
996 } | 1083 } |
997 return v; | 1084 return v; |
998 } | 1085 } |
999 return nullptr; | 1086 return nullptr; |
1000 } | 1087 } |
1001 | 1088 |
1002 void sanitize_contours(Vertex** contours, int contourCnt) { | 1089 void sanitize_contours(Vertex** contours, int contourCnt, bool approximate) { |
1003 for (int i = 0; i < contourCnt; ++i) { | 1090 for (int i = 0; i < contourCnt; ++i) { |
1004 SkASSERT(contours[i]); | 1091 SkASSERT(contours[i]); |
1005 for (Vertex* v = contours[i];;) { | 1092 for (Vertex* v = contours[i];;) { |
1093 if (approximate) { | |
1094 round(&v->fPoint); | |
1095 } | |
1006 if (coincident(v->fPrev->fPoint, v->fPoint)) { | 1096 if (coincident(v->fPrev->fPoint, v->fPoint)) { |
1007 LOG("vertex %g,%g coincident; removing\n", v->fPoint.fX, v->fPoi nt.fY); | 1097 LOG("vertex %g,%g coincident; removing\n", v->fPoint.fX, v->fPoi nt.fY); |
1008 if (v->fPrev == v) { | 1098 if (v->fPrev == v) { |
1009 contours[i] = nullptr; | 1099 contours[i] = nullptr; |
1010 break; | 1100 break; |
1011 } | 1101 } |
1012 v->fPrev->fNext = v->fNext; | 1102 v->fPrev->fNext = v->fNext; |
1013 v->fNext->fPrev = v->fPrev; | 1103 v->fNext->fPrev = v->fPrev; |
1014 if (contours[i] == v) { | 1104 if (contours[i] == v) { |
1015 contours[i] = v->fNext; | 1105 contours[i] = v->fNext; |
(...skipping 19 matching lines...) Expand all Loading... | |
1035 } | 1125 } |
1036 | 1126 |
1037 // Stage 2: convert the contours to a mesh of edges connecting the vertices. | 1127 // Stage 2: convert the contours to a mesh of edges connecting the vertices. |
1038 | 1128 |
1039 Vertex* build_edges(Vertex** contours, int contourCnt, Comparator& c, SkChunkAll oc& alloc) { | 1129 Vertex* build_edges(Vertex** contours, int contourCnt, Comparator& c, SkChunkAll oc& alloc) { |
1040 Vertex* vertices = nullptr; | 1130 Vertex* vertices = nullptr; |
1041 Vertex* prev = nullptr; | 1131 Vertex* prev = nullptr; |
1042 for (int i = 0; i < contourCnt; ++i) { | 1132 for (int i = 0; i < contourCnt; ++i) { |
1043 for (Vertex* v = contours[i]; v != nullptr;) { | 1133 for (Vertex* v = contours[i]; v != nullptr;) { |
1044 Vertex* vNext = v->fNext; | 1134 Vertex* vNext = v->fNext; |
1045 Edge* edge = new_edge(v->fPrev, v, alloc, c); | 1135 connect(v->fPrev, v, alloc, c); |
1046 if (edge->fWinding > 0) { | |
1047 insert_edge_below(edge, v->fPrev, c); | |
1048 insert_edge_above(edge, v, c); | |
1049 } else { | |
1050 insert_edge_below(edge, v, c); | |
1051 insert_edge_above(edge, v->fPrev, c); | |
1052 } | |
1053 merge_collinear_edges(edge, nullptr, c); | |
1054 if (prev) { | 1136 if (prev) { |
1055 prev->fNext = v; | 1137 prev->fNext = v; |
1056 v->fPrev = prev; | 1138 v->fPrev = prev; |
1057 } else { | 1139 } else { |
1058 vertices = v; | 1140 vertices = v; |
1059 } | 1141 } |
1060 prev = v; | 1142 prev = v; |
1061 v = vNext; | 1143 v = vNext; |
1062 if (v == contours[i]) break; | 1144 if (v == contours[i]) break; |
1063 } | 1145 } |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1138 // Stage 4: Simplify the mesh by inserting new vertices at intersecting edges. | 1220 // Stage 4: Simplify the mesh by inserting new vertices at intersecting edges. |
1139 | 1221 |
1140 void simplify(Vertex* vertices, Comparator& c, SkChunkAlloc& alloc) { | 1222 void simplify(Vertex* vertices, Comparator& c, SkChunkAlloc& alloc) { |
1141 LOG("simplifying complex polygons\n"); | 1223 LOG("simplifying complex polygons\n"); |
1142 EdgeList activeEdges; | 1224 EdgeList activeEdges; |
1143 for (Vertex* v = vertices; v != nullptr; v = v->fNext) { | 1225 for (Vertex* v = vertices; v != nullptr; v = v->fNext) { |
1144 if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) { | 1226 if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) { |
1145 continue; | 1227 continue; |
1146 } | 1228 } |
1147 #if LOGGING_ENABLED | 1229 #if LOGGING_ENABLED |
1148 LOG("\nvertex %g: (%g,%g)\n", v->fID, v->fPoint.fX, v->fPoint.fY); | 1230 LOG("\nvertex %g: (%g,%g), alpha %d\n", v->fID, v->fPoint.fX, v->fPoint. fY, v->fAlpha); |
1149 #endif | 1231 #endif |
1150 Edge* leftEnclosingEdge = nullptr; | 1232 Edge* leftEnclosingEdge = nullptr; |
1151 Edge* rightEnclosingEdge = nullptr; | 1233 Edge* rightEnclosingEdge = nullptr; |
1152 bool restartChecks; | 1234 bool restartChecks; |
1153 do { | 1235 do { |
1154 restartChecks = false; | 1236 restartChecks = false; |
1155 find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEncl osingEdge); | 1237 find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEncl osingEdge); |
1156 if (v->fFirstEdgeBelow) { | 1238 if (v->fFirstEdgeBelow) { |
1157 for (Edge* edge = v->fFirstEdgeBelow; edge != nullptr; edge = ed ge->fNextEdgeBelow) { | 1239 for (Edge* edge = v->fFirstEdgeBelow; edge != nullptr; edge = ed ge->fNextEdgeBelow) { |
1158 if (check_for_intersection(edge, leftEnclosingEdge, &activeE dges, c, alloc)) { | 1240 if (check_for_intersection(edge, leftEnclosingEdge, &activeE dges, c, alloc)) { |
1159 restartChecks = true; | 1241 restartChecks = true; |
1160 break; | 1242 break; |
1161 } | 1243 } |
1162 if (check_for_intersection(edge, rightEnclosingEdge, &active Edges, c, alloc)) { | 1244 if (check_for_intersection(edge, rightEnclosingEdge, &active Edges, c, alloc)) { |
1163 restartChecks = true; | 1245 restartChecks = true; |
1164 break; | 1246 break; |
1165 } | 1247 } |
1166 } | 1248 } |
1167 } else { | 1249 } else { |
1168 if (Vertex* pv = check_for_intersection(leftEnclosingEdge, right EnclosingEdge, | 1250 if (Vertex* pv = check_for_intersection(leftEnclosingEdge, right EnclosingEdge, |
1169 &activeEdges, c, alloc)) { | 1251 &activeEdges, c, alloc)) { |
1170 if (c.sweep_lt(pv->fPoint, v->fPoint)) { | 1252 if (c.sweep_lt(pv->fPoint, v->fPoint)) { |
1171 v = pv; | 1253 v = pv; |
1172 } | 1254 } |
1173 restartChecks = true; | 1255 restartChecks = true; |
1174 } | 1256 } |
1175 | 1257 |
1176 } | 1258 } |
1177 } while (restartChecks); | 1259 } while (restartChecks); |
1260 if (v->fAlpha == 0) { | |
1261 if ((leftEnclosingEdge && leftEnclosingEdge->fWinding < 0) && | |
1262 (rightEnclosingEdge && rightEnclosingEdge->fWinding > 0)) { | |
1263 v->fAlpha = max_edge_alpha(leftEnclosingEdge, rightEnclosingEdge ); | |
1264 } | |
1265 } | |
1178 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) { | 1266 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) { |
1179 remove_edge(e, &activeEdges); | 1267 remove_edge(e, &activeEdges); |
1180 } | 1268 } |
1181 Edge* leftEdge = leftEnclosingEdge; | 1269 Edge* leftEdge = leftEnclosingEdge; |
1182 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) { | 1270 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) { |
1183 insert_edge(e, leftEdge, &activeEdges); | 1271 insert_edge(e, leftEdge, &activeEdges); |
1184 leftEdge = e; | 1272 leftEdge = e; |
1185 } | 1273 } |
1186 v->fProcessed = true; | 1274 v->fProcessed = true; |
1187 } | 1275 } |
1188 } | 1276 } |
1189 | 1277 |
1190 // Stage 5: Tessellate the simplified mesh into monotone polygons. | 1278 // Stage 5: Tessellate the simplified mesh into monotone polygons. |
1191 | 1279 |
1192 Poly* tessellate(Vertex* vertices, SkChunkAlloc& alloc) { | 1280 Poly* tessellate(Vertex* vertices, SkChunkAlloc& alloc) { |
1193 LOG("tessellating simple polygons\n"); | 1281 LOG("tessellating simple polygons\n"); |
1194 EdgeList activeEdges; | 1282 EdgeList activeEdges; |
1195 Poly* polys = nullptr; | 1283 Poly* polys = nullptr; |
1196 for (Vertex* v = vertices; v != nullptr; v = v->fNext) { | 1284 for (Vertex* v = vertices; v != nullptr; v = v->fNext) { |
1197 if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) { | 1285 if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) { |
1198 continue; | 1286 continue; |
1199 } | 1287 } |
1200 #if LOGGING_ENABLED | 1288 #if LOGGING_ENABLED |
1201 LOG("\nvertex %g: (%g,%g)\n", v->fID, v->fPoint.fX, v->fPoint.fY); | 1289 LOG("\nvertex %g: (%g,%g), alpha %d\n", v->fID, v->fPoint.fX, v->fPoint. fY, v->fAlpha); |
1202 #endif | 1290 #endif |
1203 Edge* leftEnclosingEdge = nullptr; | 1291 Edge* leftEnclosingEdge = nullptr; |
1204 Edge* rightEnclosingEdge = nullptr; | 1292 Edge* rightEnclosingEdge = nullptr; |
1205 find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosin gEdge); | 1293 find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosin gEdge); |
1206 Poly* leftPoly = nullptr; | 1294 Poly* leftPoly = nullptr; |
1207 Poly* rightPoly = nullptr; | 1295 Poly* rightPoly = nullptr; |
1208 if (v->fFirstEdgeAbove) { | 1296 if (v->fFirstEdgeAbove) { |
1209 leftPoly = v->fFirstEdgeAbove->fLeftPoly; | 1297 leftPoly = v->fFirstEdgeAbove->fLeftPoly; |
1210 rightPoly = v->fLastEdgeAbove->fRightPoly; | 1298 rightPoly = v->fLastEdgeAbove->fRightPoly; |
1211 } else { | 1299 } else { |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1291 LOG("\nactive edges:\n"); | 1379 LOG("\nactive edges:\n"); |
1292 for (Edge* e = activeEdges.fHead; e != nullptr; e = e->fRight) { | 1380 for (Edge* e = activeEdges.fHead; e != nullptr; e = e->fRight) { |
1293 LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID, | 1381 LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID, |
1294 e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRight Poly->fID : -1); | 1382 e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRight Poly->fID : -1); |
1295 } | 1383 } |
1296 #endif | 1384 #endif |
1297 } | 1385 } |
1298 return polys; | 1386 return polys; |
1299 } | 1387 } |
1300 | 1388 |
1389 bool is_boundary_edge(Edge* edge, SkPath::FillType fillType) { | |
1390 return apply_fill_type(fillType, edge->fLeftPoly) != | |
1391 apply_fill_type(fillType, edge->fRightPoly); | |
1392 } | |
1393 | |
1394 bool is_boundary_start(Edge* edge, SkPath::FillType fillType) { | |
1395 return !apply_fill_type(fillType, edge->fLeftPoly) && | |
1396 apply_fill_type(fillType, edge->fRightPoly); | |
1397 } | |
1398 | |
1399 Vertex* remove_non_boundary_edges(Vertex* vertices, SkPath::FillType fillType, | |
1400 SkChunkAlloc& alloc) { | |
1401 for (Vertex* v = vertices; v != nullptr; v = v->fNext) { | |
1402 for (Edge* e = v->fFirstEdgeBelow; e != nullptr;) { | |
1403 Edge* next = e->fNextEdgeBelow; | |
1404 if (!is_boundary_edge(e, fillType)) { | |
1405 remove_edge_above(e); | |
1406 remove_edge_below(e); | |
1407 } | |
1408 e = next; | |
1409 } | |
1410 } | |
1411 return vertices; | |
1412 } | |
1413 | |
1414 // This is different from Edge::intersect, in that it intersects lines, not line segments. | |
1415 bool intersect(const Edge& a, const Edge& b, SkPoint* point) { | |
1416 double denom = a.fDX * b.fDY - a.fDY * b.fDX; | |
1417 if (denom == 0.0) { | |
1418 return false; | |
1419 } | |
1420 double scale = 1.0f / denom; | |
1421 point->fX = SkDoubleToScalar((b.fDX * a.fC - a.fDX * b.fC) * scale); | |
1422 point->fY = SkDoubleToScalar((b.fDY * a.fC - a.fDY * b.fC) * scale); | |
1423 round(point); | |
1424 return true; | |
1425 } | |
1426 | |
1427 void get_edge_normal(const Edge* e, SkVector* normal) { | |
1428 normal->setNormalize(SkDoubleToScalar(e->fDX) * e->fWinding, | |
1429 SkDoubleToScalar(e->fDY) * e->fWinding); | |
1430 } | |
1431 | |
1432 void simplify_boundary(EdgeList* boundary, Comparator& c, SkChunkAlloc& alloc) { | |
1433 Edge* prevEdge = boundary->fTail; | |
1434 SkVector prevNormal; | |
1435 get_edge_normal(prevEdge, &prevNormal); | |
1436 for (Edge* e = boundary->fHead; e != nullptr;) { | |
1437 Vertex* prev = prevEdge->fWinding == 1 ? prevEdge->fTop : prevEdge->fBot tom; | |
1438 Vertex* next = e->fWinding == 1 ? e->fBottom : e->fTop; | |
1439 double dist = e->dist(prev->fPoint); | |
1440 SkVector normal; | |
1441 get_edge_normal(e, &normal); | |
1442 float denom = 0.25f * static_cast<float>(e->fDX * e->fDX + e->fDY * e->f DY); | |
1443 if (prevNormal.dot(normal) < 0.0 && (dist * dist) <= denom) { | |
1444 Edge* join = new_edge(prev, next, alloc, c); | |
1445 insert_edge(join, e, boundary); | |
1446 remove_edge(prevEdge, boundary); | |
1447 remove_edge(e, boundary); | |
1448 if (join->fLeft && join->fRight) { | |
1449 prevEdge = join->fLeft; | |
1450 e = join; | |
1451 } else { | |
1452 prevEdge = boundary->fTail; | |
1453 e = boundary->fHead; // join->fLeft ? join->fLeft : join; | |
1454 } | |
1455 get_edge_normal(prevEdge, &prevNormal); | |
1456 } else { | |
1457 prevEdge = e; | |
1458 prevNormal = normal; | |
1459 e = e->fRight; | |
1460 } | |
1461 } | |
1462 } | |
1463 | |
1464 void boundary_to_aa_mesh(EdgeList* boundary, VertexList* mesh, Comparator& c, Sk ChunkAlloc& alloc) { | |
1465 EdgeList outerContour; | |
1466 Edge* prevEdge = boundary->fTail; | |
1467 float radius = 0.5f; | |
1468 double offset = radius * sqrt(prevEdge->fDX * prevEdge->fDX + prevEdge->fDY * prevEdge->fDY) | |
1469 * prevEdge->fWinding; | |
1470 Edge prevInner(prevEdge->fTop, prevEdge->fBottom, prevEdge->fWinding); | |
1471 prevInner.fC -= offset; | |
1472 Edge prevOuter(prevEdge->fTop, prevEdge->fBottom, prevEdge->fWinding); | |
1473 prevOuter.fC += offset; | |
1474 VertexList innerVertices; | |
1475 VertexList outerVertices; | |
1476 SkScalar innerCount = SK_Scalar1, outerCount = SK_Scalar1; | |
1477 for (Edge* e = boundary->fHead; e != nullptr; e = e->fRight) { | |
1478 double offset = radius * sqrt(e->fDX * e->fDX + e->fDY * e->fDY) * e->fW inding; | |
1479 Edge inner(e->fTop, e->fBottom, e->fWinding); | |
1480 inner.fC -= offset; | |
1481 Edge outer(e->fTop, e->fBottom, e->fWinding); | |
1482 outer.fC += offset; | |
1483 SkPoint innerPoint, outerPoint; | |
1484 if (intersect(prevInner, inner, &innerPoint) && | |
1485 intersect(prevOuter, outer, &outerPoint)) { | |
1486 Vertex* innerVertex = ALLOC_NEW(Vertex, (innerPoint, 255), alloc); | |
1487 Vertex* outerVertex = ALLOC_NEW(Vertex, (outerPoint, 0), alloc); | |
1488 if (innerVertices.fTail && outerVertices.fTail) { | |
1489 Edge innerEdge(innerVertices.fTail, innerVertex, 1); | |
1490 Edge outerEdge(outerVertices.fTail, outerVertex, 1); | |
1491 SkVector innerNormal; | |
1492 get_edge_normal(&innerEdge, &innerNormal); | |
1493 SkVector outerNormal; | |
1494 get_edge_normal(&outerEdge, &outerNormal); | |
1495 SkVector normal; | |
1496 get_edge_normal(prevEdge, &normal); | |
1497 if (normal.dot(innerNormal) < 0) { | |
1498 innerPoint += innerVertices.fTail->fPoint * innerCount; | |
1499 innerCount++; | |
1500 innerPoint *= SkScalarInvert(innerCount); | |
1501 innerVertices.fTail->fPoint = innerVertex->fPoint = innerPoi nt; | |
1502 } else { | |
1503 innerCount = SK_Scalar1; | |
1504 } | |
1505 if (normal.dot(outerNormal) < 0) { | |
1506 outerPoint += outerVertices.fTail->fPoint * outerCount; | |
1507 outerCount++; | |
1508 outerPoint *= SkScalarInvert(outerCount); | |
1509 outerVertices.fTail->fPoint = outerVertex->fPoint = outerPoi nt; | |
1510 } else { | |
1511 outerCount = SK_Scalar1; | |
1512 } | |
1513 } | |
1514 innerVertices.append(innerVertex); | |
1515 outerVertices.append(outerVertex); | |
1516 prevEdge = e; | |
1517 } | |
1518 prevInner = inner; | |
1519 prevOuter = outer; | |
1520 } | |
1521 innerVertices.close(); | |
1522 outerVertices.close(); | |
1523 | |
1524 Vertex* innerVertex = innerVertices.fHead; | |
1525 Vertex* outerVertex = outerVertices.fHead; | |
1526 // Alternate clockwise and counterclockwise polys, so the tesselator | |
1527 // doesn't cancel out the interior edges. | |
1528 if (!innerVertex || !outerVertex) { | |
1529 return; | |
1530 } | |
1531 do { | |
1532 connect(outerVertex->fNext, outerVertex, alloc, c); | |
1533 connect(innerVertex->fNext, innerVertex, alloc, c, 2); | |
1534 connect(innerVertex, outerVertex->fNext, alloc, c, 2); | |
1535 connect(outerVertex, innerVertex, alloc, c, 2); | |
1536 Vertex* innerNext = innerVertex->fNext; | |
1537 Vertex* outerNext = outerVertex->fNext; | |
1538 mesh->append(innerVertex); | |
1539 mesh->append(outerVertex); | |
1540 innerVertex = innerNext; | |
1541 outerVertex = outerNext; | |
1542 } while (innerVertex != innerVertices.fHead && outerVertex != outerVertices. fHead); | |
1543 } | |
1544 | |
1545 void extract_boundary(EdgeList* boundary, Edge* e, SkPath::FillType fillType, Sk ChunkAlloc& alloc) { | |
1546 bool down = is_boundary_start(e, fillType); | |
1547 while (e) { | |
1548 e->fWinding = down ? 1 : -1; | |
1549 Edge* next; | |
1550 boundary->append(e); | |
1551 if (down) { | |
1552 // Find outgoing edge, in clockwise order. | |
1553 if ((next = e->fNextEdgeAbove)) { | |
1554 down = false; | |
1555 } else if ((next = e->fBottom->fLastEdgeBelow)) { | |
1556 down = true; | |
1557 } else if ((next = e->fPrevEdgeAbove)) { | |
1558 down = false; | |
1559 } | |
1560 } else { | |
1561 // Find outgoing edge, in counter-clockwise order. | |
1562 if ((next = e->fPrevEdgeBelow)) { | |
1563 down = true; | |
1564 } else if ((next = e->fTop->fFirstEdgeAbove)) { | |
1565 down = false; | |
1566 } else if ((next = e->fNextEdgeBelow)) { | |
1567 down = true; | |
1568 } | |
1569 } | |
1570 remove_edge_above(e); | |
1571 remove_edge_below(e); | |
1572 e = next; | |
1573 } | |
1574 } | |
1575 | |
1576 // Stage 5b: Extract boundary edges. | |
1577 | |
1578 EdgeList* extract_boundaries(Vertex* vertices, SkPath::FillType fillType, SkChun kAlloc& alloc) { | |
1579 LOG("extracting boundaries\n"); | |
1580 vertices = remove_non_boundary_edges(vertices, fillType, alloc); | |
1581 EdgeList* boundaries = nullptr; | |
1582 for (Vertex* v = vertices; v != nullptr; v = v->fNext) { | |
1583 while (v->fFirstEdgeBelow) { | |
1584 EdgeList* boundary = new_contour(&boundaries, alloc); | |
1585 extract_boundary(boundary, v->fFirstEdgeBelow, fillType, alloc); | |
1586 } | |
1587 } | |
1588 return boundaries; | |
1589 } | |
1590 | |
1301 // This is a driver function which calls stages 2-5 in turn. | 1591 // This is a driver function which calls stages 2-5 in turn. |
1302 | 1592 |
1303 Poly* contours_to_polys(Vertex** contours, int contourCnt, const SkRect& pathBou nds, | 1593 Vertex* contours_to_mesh(Vertex** contours, int contourCnt, bool antialias, |
1304 SkChunkAlloc& alloc) { | 1594 Comparator& c, SkChunkAlloc& alloc) { |
1305 Comparator c; | |
1306 if (pathBounds.width() > pathBounds.height()) { | |
1307 c.sweep_lt = sweep_lt_horiz; | |
1308 c.sweep_gt = sweep_gt_horiz; | |
1309 } else { | |
1310 c.sweep_lt = sweep_lt_vert; | |
1311 c.sweep_gt = sweep_gt_vert; | |
1312 } | |
1313 #if LOGGING_ENABLED | 1595 #if LOGGING_ENABLED |
1314 for (int i = 0; i < contourCnt; ++i) { | 1596 for (int i = 0; i < contourCnt; ++i) { |
1315 Vertex* v = contours[i]; | 1597 Vertex* v = contours[i]; |
1316 SkASSERT(v); | 1598 SkASSERT(v); |
1317 LOG("path.moveTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY); | 1599 LOG("path.moveTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY); |
1318 for (v = v->fNext; v != contours[i]; v = v->fNext) { | 1600 for (v = v->fNext; v != contours[i]; v = v->fNext) { |
1319 LOG("path.lineTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY); | 1601 LOG("path.lineTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY); |
1320 } | 1602 } |
1321 } | 1603 } |
1322 #endif | 1604 #endif |
1323 sanitize_contours(contours, contourCnt); | 1605 sanitize_contours(contours, contourCnt, antialias); |
1324 Vertex* vertices = build_edges(contours, contourCnt, c, alloc); | 1606 return build_edges(contours, contourCnt, c, alloc); |
1325 if (!vertices) { | 1607 } |
1608 | |
1609 Poly* mesh_to_polys(Vertex** vertices, SkPath::FillType fillType, Comparator& c, | |
1610 SkChunkAlloc& alloc) { | |
1611 if (!vertices || !*vertices) { | |
1326 return nullptr; | 1612 return nullptr; |
1327 } | 1613 } |
1328 | 1614 |
1329 // Sort vertices in Y (secondarily in X). | 1615 // Sort vertices in Y (secondarily in X). |
1330 merge_sort(&vertices, c); | 1616 merge_sort(vertices, c); |
1331 merge_coincident_vertices(&vertices, c, alloc); | 1617 merge_coincident_vertices(vertices, c, alloc); |
1332 #if LOGGING_ENABLED | 1618 #if LOGGING_ENABLED |
1333 for (Vertex* v = vertices; v != nullptr; v = v->fNext) { | 1619 for (Vertex* v = *vertices; v != nullptr; v = v->fNext) { |
1334 static float gID = 0.0f; | 1620 static float gID = 0.0f; |
1335 v->fID = gID++; | 1621 v->fID = gID++; |
1336 } | 1622 } |
1337 #endif | 1623 #endif |
1338 simplify(vertices, c, alloc); | 1624 simplify(*vertices, c, alloc); |
1339 return tessellate(vertices, alloc); | 1625 return tessellate(*vertices, alloc); |
1626 } | |
1627 | |
1628 Poly* contours_to_polys(Vertex** contours, int contourCnt, SkPath::FillType fill Type, | |
1629 const SkRect& pathBounds, bool antialias, | |
1630 SkChunkAlloc& alloc) { | |
1631 Comparator c; | |
1632 if (pathBounds.width() > pathBounds.height()) { | |
1633 c.sweep_lt = sweep_lt_horiz; | |
1634 c.sweep_gt = sweep_gt_horiz; | |
1635 } else { | |
1636 c.sweep_lt = sweep_lt_vert; | |
1637 c.sweep_gt = sweep_gt_vert; | |
1638 } | |
1639 Vertex* mesh = contours_to_mesh(contours, contourCnt, antialias, c, alloc); | |
1640 Poly* polys = mesh_to_polys(&mesh, fillType, c, alloc); | |
1641 if (antialias) { | |
1642 EdgeList* boundaries = extract_boundaries(mesh, fillType, alloc); | |
1643 VertexList aaMesh; | |
1644 for (EdgeList* boundary = boundaries; boundary != nullptr; boundary = bo undary->fNext) { | |
1645 simplify_boundary(boundary, c, alloc); | |
1646 if (boundary->fCount > 2) { | |
1647 boundary_to_aa_mesh(boundary, &aaMesh, c, alloc); | |
1648 } | |
1649 } | |
1650 return mesh_to_polys(&aaMesh.fHead, SkPath::kWinding_FillType, c, alloc) ; | |
1651 } | |
1652 return polys; | |
1653 } | |
1654 | |
1655 // Stage 6: Triangulate the monotone polygons into a vertex buffer. | |
1656 void* polys_to_triangles(Poly* polys, SkPath::FillType fillType, const AAParams* aaParams, | |
1657 void* data) { | |
1658 for (Poly* poly = polys; poly; poly = poly->fNext) { | |
1659 if (apply_fill_type(fillType, poly)) { | |
1660 data = poly->emit(aaParams, data); | |
1661 } | |
1662 } | |
1663 return data; | |
1340 } | 1664 } |
1341 | 1665 |
1342 Poly* path_to_polys(const SkPath& path, SkScalar tolerance, const SkRect& clipBo unds, | 1666 Poly* path_to_polys(const SkPath& path, SkScalar tolerance, const SkRect& clipBo unds, |
1343 int contourCnt, SkChunkAlloc& alloc, bool* isLinear) { | 1667 int contourCnt, SkChunkAlloc& alloc, bool antialias, bool* i sLinear) { |
1344 SkPath::FillType fillType = path.getFillType(); | 1668 SkPath::FillType fillType = path.getFillType(); |
1345 if (SkPath::IsInverseFillType(fillType)) { | 1669 if (SkPath::IsInverseFillType(fillType)) { |
1346 contourCnt++; | 1670 contourCnt++; |
1347 } | 1671 } |
1348 SkAutoTDeleteArray<Vertex*> contours(new Vertex* [contourCnt]); | 1672 SkAutoTDeleteArray<Vertex*> contours(new Vertex* [contourCnt]); |
1349 | 1673 |
1350 path_to_contours(path, tolerance, clipBounds, contours.get(), alloc, isLinea r); | 1674 path_to_contours(path, tolerance, clipBounds, contours.get(), alloc, isLinea r); |
1351 return contours_to_polys(contours.get(), contourCnt, path.getBounds(), alloc ); | 1675 return contours_to_polys(contours.get(), contourCnt, path.getFillType(), pat h.getBounds(), |
1676 antialias, alloc); | |
1352 } | 1677 } |
1353 | 1678 |
1354 void get_contour_count_and_size_estimate(const SkPath& path, SkScalar tolerance, int* contourCnt, | 1679 void get_contour_count_and_size_estimate(const SkPath& path, SkScalar tolerance, int* contourCnt, |
1355 int* sizeEstimate) { | 1680 int* sizeEstimate) { |
1356 int maxPts = GrPathUtils::worstCasePointCount(path, contourCnt, tolerance); | 1681 int maxPts = GrPathUtils::worstCasePointCount(path, contourCnt, tolerance); |
1357 if (maxPts <= 0) { | 1682 if (maxPts <= 0) { |
1358 *contourCnt = 0; | 1683 *contourCnt = 0; |
1359 return; | 1684 return; |
1360 } | 1685 } |
1361 if (maxPts > ((int)SK_MaxU16 + 1)) { | 1686 if (maxPts > ((int)SK_MaxU16 + 1)) { |
1362 SkDebugf("Path not rendered, too many verts (%d)\n", maxPts); | 1687 SkDebugf("Path not rendered, too many verts (%d)\n", maxPts); |
1363 *contourCnt = 0; | 1688 *contourCnt = 0; |
1364 return; | 1689 return; |
1365 } | 1690 } |
1366 // For the initial size of the chunk allocator, estimate based on the point count: | 1691 // For the initial size of the chunk allocator, estimate based on the point count: |
1367 // one vertex per point for the initial passes, plus two for the vertices in the | 1692 // one vertex per point for the initial passes, plus two for the vertices in the |
1368 // resulting Polys, since the same point may end up in two Polys. Assume mi nimal | 1693 // resulting Polys, since the same point may end up in two Polys. Assume mi nimal |
1369 // connectivity of one Edge per Vertex (will grow for intersections). | 1694 // connectivity of one Edge per Vertex (will grow for intersections). |
1370 *sizeEstimate = maxPts * (3 * sizeof(Vertex) + sizeof(Edge)); | 1695 *sizeEstimate = maxPts * (3 * sizeof(Vertex) + sizeof(Edge)); |
1371 } | 1696 } |
1372 | 1697 |
1373 int count_points(Poly* polys, SkPath::FillType fillType) { | 1698 int count_points(Poly* polys, SkPath::FillType fillType) { |
1374 int count = 0; | 1699 int count = 0; |
1375 for (Poly* poly = polys; poly; poly = poly->fNext) { | 1700 for (Poly* poly = polys; poly; poly = poly->fNext) { |
1376 if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3) { | 1701 if (apply_fill_type(fillType, poly) && poly->fCount >= 3) { |
1377 count += (poly->fCount - 2) * (TESSELLATOR_WIREFRAME ? 6 : 3); | 1702 count += (poly->fCount - 2) * (TESSELLATOR_WIREFRAME ? 6 : 3); |
1378 } | 1703 } |
1379 } | 1704 } |
1380 return count; | 1705 return count; |
1381 } | 1706 } |
1382 | 1707 |
1383 } // namespace | 1708 } // namespace |
1384 | 1709 |
1385 namespace GrTessellator { | 1710 namespace GrTessellator { |
1386 | 1711 |
1387 // Stage 6: Triangulate the monotone polygons into a vertex buffer. | 1712 // Stage 6: Triangulate the monotone polygons into a vertex buffer. |
1388 | 1713 |
1389 int PathToTriangles(const SkPath& path, SkScalar tolerance, const SkRect& clipBo unds, | 1714 int PathToTriangles(const SkPath& path, SkScalar tolerance, const SkRect& clipBo unds, |
1390 VertexAllocator* vertexAllocator, bool* isLinear) { | 1715 VertexAllocator* vertexAllocator, bool antialias, const GrCo lor& color, |
1716 bool canTweakAlphaForCoverage, bool* isLinear) { | |
1391 int contourCnt; | 1717 int contourCnt; |
1392 int sizeEstimate; | 1718 int sizeEstimate; |
1393 get_contour_count_and_size_estimate(path, tolerance, &contourCnt, &sizeEstim ate); | 1719 get_contour_count_and_size_estimate(path, tolerance, &contourCnt, &sizeEstim ate); |
1394 if (contourCnt <= 0) { | 1720 if (contourCnt <= 0) { |
1395 *isLinear = true; | 1721 *isLinear = true; |
1396 return 0; | 1722 return 0; |
1397 } | 1723 } |
1398 SkChunkAlloc alloc(sizeEstimate); | 1724 SkChunkAlloc alloc(sizeEstimate); |
1399 Poly* polys = path_to_polys(path, tolerance, clipBounds, contourCnt, alloc, isLinear); | 1725 Poly* polys = path_to_polys(path, tolerance, clipBounds, contourCnt, alloc, antialias, |
1726 isLinear); | |
1400 SkPath::FillType fillType = path.getFillType(); | 1727 SkPath::FillType fillType = path.getFillType(); |
1401 int count = count_points(polys, fillType); | 1728 int count = count_points(polys, fillType); |
1402 if (0 == count) { | 1729 if (0 == count) { |
1403 return 0; | 1730 return 0; |
1404 } | 1731 } |
1405 | 1732 |
1406 SkPoint* verts = vertexAllocator->lock(count); | 1733 void* verts = vertexAllocator->lock(count); |
1407 if (!verts) { | 1734 if (!verts) { |
1408 SkDebugf("Could not allocate vertices\n"); | 1735 SkDebugf("Could not allocate vertices\n"); |
1409 return 0; | 1736 return 0; |
1410 } | 1737 } |
1411 SkPoint* end = verts; | 1738 |
1412 for (Poly* poly = polys; poly; poly = poly->fNext) { | 1739 LOG("emitting %d verts\n", count); |
1413 if (apply_fill_type(fillType, poly->fWinding)) { | 1740 AAParams aaParams; |
1414 end = poly->emit(end); | 1741 aaParams.fTweakAlpha = canTweakAlphaForCoverage; |
1415 } | 1742 aaParams.fColor = color; |
1416 } | 1743 |
1417 int actualCount = static_cast<int>(end - verts); | 1744 void* end = polys_to_triangles(polys, fillType, antialias ? &aaParams : null ptr, verts); |
1418 LOG("actual count: %d\n", actualCount); | 1745 int actualCount = static_cast<int>((static_cast<uint8_t*>(end) - static_cast <uint8_t*>(verts)) |
1746 / vertexAllocator->stride()); | |
1419 SkASSERT(actualCount <= count); | 1747 SkASSERT(actualCount <= count); |
1420 vertexAllocator->unlock(actualCount); | 1748 vertexAllocator->unlock(actualCount); |
1421 return actualCount; | 1749 return actualCount; |
1422 } | 1750 } |
1423 | 1751 |
1424 int PathToVertices(const SkPath& path, SkScalar tolerance, const SkRect& clipBou nds, | 1752 int PathToVertices(const SkPath& path, SkScalar tolerance, const SkRect& clipBou nds, |
1425 GrTessellator::WindingVertex** verts) { | 1753 GrTessellator::WindingVertex** verts) { |
1426 int contourCnt; | 1754 int contourCnt; |
1427 int sizeEstimate; | 1755 int sizeEstimate; |
1428 get_contour_count_and_size_estimate(path, tolerance, &contourCnt, &sizeEstim ate); | 1756 get_contour_count_and_size_estimate(path, tolerance, &contourCnt, &sizeEstim ate); |
1429 if (contourCnt <= 0) { | 1757 if (contourCnt <= 0) { |
1430 return 0; | 1758 return 0; |
1431 } | 1759 } |
1432 SkChunkAlloc alloc(sizeEstimate); | 1760 SkChunkAlloc alloc(sizeEstimate); |
1433 bool isLinear; | 1761 bool isLinear; |
1434 Poly* polys = path_to_polys(path, tolerance, clipBounds, contourCnt, alloc, &isLinear); | 1762 Poly* polys = path_to_polys(path, tolerance, clipBounds, contourCnt, alloc, false, &isLinear); |
1435 SkPath::FillType fillType = path.getFillType(); | 1763 SkPath::FillType fillType = path.getFillType(); |
1436 int count = count_points(polys, fillType); | 1764 int count = count_points(polys, fillType); |
1437 if (0 == count) { | 1765 if (0 == count) { |
1438 *verts = nullptr; | 1766 *verts = nullptr; |
1439 return 0; | 1767 return 0; |
1440 } | 1768 } |
1441 | 1769 |
1442 *verts = new GrTessellator::WindingVertex[count]; | 1770 *verts = new GrTessellator::WindingVertex[count]; |
1443 GrTessellator::WindingVertex* vertsEnd = *verts; | 1771 GrTessellator::WindingVertex* vertsEnd = *verts; |
1444 SkPoint* points = new SkPoint[count]; | 1772 SkPoint* points = new SkPoint[count]; |
1445 SkPoint* pointsEnd = points; | 1773 SkPoint* pointsEnd = points; |
1446 for (Poly* poly = polys; poly; poly = poly->fNext) { | 1774 for (Poly* poly = polys; poly; poly = poly->fNext) { |
1447 if (apply_fill_type(fillType, poly->fWinding)) { | 1775 if (apply_fill_type(fillType, poly)) { |
1448 SkPoint* start = pointsEnd; | 1776 SkPoint* start = pointsEnd; |
1449 pointsEnd = poly->emit(pointsEnd); | 1777 pointsEnd = static_cast<SkPoint*>(poly->emit(nullptr, pointsEnd)); |
1450 while (start != pointsEnd) { | 1778 while (start != pointsEnd) { |
1451 vertsEnd->fPos = *start; | 1779 vertsEnd->fPos = *start; |
1452 vertsEnd->fWinding = poly->fWinding; | 1780 vertsEnd->fWinding = poly->fWinding; |
1453 ++start; | 1781 ++start; |
1454 ++vertsEnd; | 1782 ++vertsEnd; |
1455 } | 1783 } |
1456 } | 1784 } |
1457 } | 1785 } |
1458 int actualCount = static_cast<int>(vertsEnd - *verts); | 1786 int actualCount = static_cast<int>(vertsEnd - *verts); |
1459 SkASSERT(actualCount <= count); | 1787 SkASSERT(actualCount <= count); |
1460 SkASSERT(pointsEnd - points == actualCount); | 1788 SkASSERT(pointsEnd - points == actualCount); |
1461 delete[] points; | 1789 delete[] points; |
1462 return actualCount; | 1790 return actualCount; |
1463 } | 1791 } |
1464 | 1792 |
1465 } // namespace | 1793 } // namespace |
OLD | NEW |