1 /*
2 * Copyright 2015 Google Inc.
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 #include "GrTessellator.h"
9
10 #include "GrDefaultGeoProcFactory.h"
11 #include "GrPathUtils.h"
12
13 #include "SkArenaAlloc.h"
14 #include "SkGeometry.h"
15 #include "SkPath.h"
16
17 #include <stdio.h>
18
19 /*
20 * There are six stages to the basic algorithm:
21 *
22 * 1) Linearize the path contours into piecewise linear segments (path_to_contours()).
23 * 2) Build a mesh of edges connecting the vertices (build_edges()).
24 * 3) Sort the vertices in Y (and secondarily in X) (merge_sort()).
25 * 4) Simplify the mesh by inserting new vertices at intersecting edges (simplify()).
26 * 5) Tessellate the simplified mesh into monotone polygons (tessellate()).
27 * 6) Triangulate the monotone polygons directly into a vertex buffer (polys_to_triangles()).
28 *
29 * For screenspace antialiasing, the algorithm is modified as follows:
30 *
31 * Run steps 1-5 above to produce polygons.
32 * 5b) Apply fill rules to extract boundary contours from the polygons (extract_boundaries()).
33 * 5c) Simplify boundaries to remove "pointy" vertices that cause inversions (simplify_boundary()).
34 * 5d) Displace edges by half a pixel inward and outward along their normals. Intersect to find
35 * new vertices, and set zero alpha on the exterior and one alpha on the interior. Build a new
36 * antialiased mesh from those vertices (stroke_boundary()).
37 * Run steps 3-6 above on the new mesh, and produce antialiased triangles.
38 *
39 * The vertex sorting in step (3) is a merge sort, since it plays well with the linked list
40 * of vertices (and the necessity of inserting new vertices on intersection).
41 *
42 * Stages (4) and (5) use an active edge list -- a list of all edges for which the
43 * sweep line has crossed the top vertex, but not the bottom vertex. It's sorted
44 * left-to-right based on the point where both edges are active (when both top vertices
45 * have been seen, so the "lower" top vertex of the two). If the top vertices are equal
46 * (shared), it's sorted based on the last point where both edges are active, so the
47 * "upper" bottom vertex.
48 *
49 * The most complex step is the simplification (4). It's based on the Bentley-Ottman
50 * line-sweep algorithm, but due to floating point inaccuracy, the intersection points are
51 * not exact and may violate the mesh topology or active edge list ordering. We
52 * accommodate this by adjusting the topology of the mesh and AEL to match the intersection
53 * points. This occurs in two ways:
54 *
55 * A) Intersections may cause a shortened edge to no longer be ordered with respect to its
56 * neighbouring edges at the top or bottom vertex. This is handled by merging the
57 * edges (merge_collinear_edges()).
58 * B) Intersections may cause an edge to violate the left-to-right ordering of the
59 * active edge list. This is handled by detecting potential violations and rewinding
60 * the active edge list to the vertex before they occur (rewind() during merging,
61 * rewind_if_necessary() during splitting).
62 *
63 * The tessellation steps (5) and (6) are based on "Triangulating Simple Polygons and
64 * Equivalent Problems" (Fournier and Montuno); also a line-sweep algorithm. Note that it
65 * currently uses a linked list for the active edge list, rather than a 2-3 tree as the
66 * paper describes. The 2-3 tree gives O(lg N) lookups, but insertion and removal also
67 * become O(lg N). In all the test cases, it was found that the cost of frequent O(lg N)
68 * insertions and removals was greater than the cost of infrequent O(N) lookups with the
69 * linked list implementation. With the latter, all removals are O(1), and most insertions
70 * are O(1), since we know the adjacent edge in the active edge list based on the topology.
71 * Only type 2 vertices (see paper) require the O(N) lookups, and these are much less
72 * frequent. There may be other data structures worth investigating, however.
73 *
74 * Note that the orientation of the line sweep algorithms is determined by the aspect ratio of the
75 * path bounds. When the path is taller than it is wide, we sort vertices based on increasing Y
76 * coordinate, and secondarily by increasing X coordinate. When the path is wider than it is tall,
77 * we sort by increasing X coordinate, but secondarily by *decreasing* Y coordinate. This is so
78 * that the "left" and "right" orientation in the code remains correct (edges to the left are
79 * increasing in Y; edges to the right are decreasing in Y). That is, the setting rotates 90
80 * degrees counterclockwise, rather that transposing.
81 */
82
83 #define LOGGING_ENABLED 0
84
85 #if LOGGING_ENABLED
86 #define LOG printf
87 #else
88 #define LOG(...)
89 #endif
90
91 namespace {
92
93 const int kArenaChunkSize = 16 * 1024;
94
95 struct Vertex;
96 struct Edge;
97 struct Poly;
98
99 template <class T, T* T::*Prev, T* T::*Next>
list_insert(T * t,T * prev,T * next,T ** head,T ** tail)100 void list_insert(T* t, T* prev, T* next, T** head, T** tail) {
101 t->*Prev = prev;
102 t->*Next = next;
103 if (prev) {
104 prev->*Next = t;
105 } else if (head) {
106 *head = t;
107 }
108 if (next) {
109 next->*Prev = t;
110 } else if (tail) {
111 *tail = t;
112 }
113 }
114
115 template <class T, T* T::*Prev, T* T::*Next>
list_remove(T * t,T ** head,T ** tail)116 void list_remove(T* t, T** head, T** tail) {
117 if (t->*Prev) {
118 t->*Prev->*Next = t->*Next;
119 } else if (head) {
120 *head = t->*Next;
121 }
122 if (t->*Next) {
123 t->*Next->*Prev = t->*Prev;
124 } else if (tail) {
125 *tail = t->*Prev;
126 }
127 t->*Prev = t->*Next = nullptr;
128 }
129
130 /**
131 * Vertices are used in three ways: first, the path contours are converted into a
132 * circularly-linked list of Vertices for each contour. After edge construction, the same Vertices
133 * are re-ordered by the merge sort according to the sweep_lt comparator (usually, increasing
134 * in Y) using the same fPrev/fNext pointers that were used for the contours, to avoid
135 * reallocation. Finally, MonotonePolys are built containing a circularly-linked list of
136 * Vertices. (Currently, those Vertices are newly-allocated for the MonotonePolys, since
137 * an individual Vertex from the path mesh may belong to multiple
138 * MonotonePolys, so the original Vertices cannot be re-used.
139 */
140
141 struct Vertex {
Vertex__anonceb1fd950111::Vertex142 Vertex(const SkPoint& point, uint8_t alpha)
143 : fPoint(point), fPrev(nullptr), fNext(nullptr)
144 , fFirstEdgeAbove(nullptr), fLastEdgeAbove(nullptr)
145 , fFirstEdgeBelow(nullptr), fLastEdgeBelow(nullptr)
146 , fLeftEnclosingEdge(nullptr), fRightEnclosingEdge(nullptr)
147 , fPartner(nullptr)
148 , fAlpha(alpha)
149 #if LOGGING_ENABLED
150 , fID (-1.0f)
151 #endif
152 {}
153 SkPoint fPoint; // Vertex position
154 Vertex* fPrev; // Linked list of contours, then Y-sorted vertices.
155 Vertex* fNext; // "
156 Edge* fFirstEdgeAbove; // Linked list of edges above this vertex.
157 Edge* fLastEdgeAbove; // "
158 Edge* fFirstEdgeBelow; // Linked list of edges below this vertex.
159 Edge* fLastEdgeBelow; // "
160 Edge* fLeftEnclosingEdge; // Nearest edge in the AEL left of this vertex.
161 Edge* fRightEnclosingEdge; // Nearest edge in the AEL right of this vertex.
162 Vertex* fPartner; // Corresponding inner or outer vertex (for AA).
163 uint8_t fAlpha;
164 #if LOGGING_ENABLED
165 float fID; // Identifier used for logging.
166 #endif
167 };
168
169 /***************************************************************************************/
170
171 struct AAParams {
172 bool fTweakAlpha;
173 GrColor fColor;
174 };
175
176 typedef bool (*CompareFunc)(const SkPoint& a, const SkPoint& b);
177
sweep_lt_horiz(const SkPoint & a,const SkPoint & b)178 bool sweep_lt_horiz(const SkPoint& a, const SkPoint& b) {
179 return a.fX < b.fX || (a.fX == b.fX && a.fY > b.fY);
180 }
181
sweep_lt_vert(const SkPoint & a,const SkPoint & b)182 bool sweep_lt_vert(const SkPoint& a, const SkPoint& b) {
183 return a.fY < b.fY || (a.fY == b.fY && a.fX < b.fX);
184 }
185
186 struct Comparator {
187 enum class Direction { kVertical, kHorizontal };
Comparator__anonceb1fd950111::Comparator188 Comparator(Direction direction) : fDirection(direction) {}
sweep_lt__anonceb1fd950111::Comparator189 bool sweep_lt(const SkPoint& a, const SkPoint& b) const {
190 return fDirection == Direction::kHorizontal ? sweep_lt_horiz(a, b) : sweep_lt_vert(a, b);
191 }
192 Direction fDirection;
193 };
194
emit_vertex(Vertex * v,const AAParams * aaParams,void * data)195 inline void* emit_vertex(Vertex* v, const AAParams* aaParams, void* data) {
196 if (!aaParams) {
197 SkPoint* d = static_cast<SkPoint*>(data);
198 *d++ = v->fPoint;
199 return d;
200 }
201 if (aaParams->fTweakAlpha) {
202 auto d = static_cast<GrDefaultGeoProcFactory::PositionColorAttr*>(data);
203 d->fPosition = v->fPoint;
204 d->fColor = SkAlphaMulQ(aaParams->fColor, SkAlpha255To256(v->fAlpha));
205 d++;
206 return d;
207 }
208 auto d = static_cast<GrDefaultGeoProcFactory::PositionColorCoverageAttr*>(data);
209 d->fPosition = v->fPoint;
210 d->fColor = aaParams->fColor;
211 d->fCoverage = GrNormalizeByteToFloat(v->fAlpha);
212 d++;
213 return d;
214 }
215
emit_triangle(Vertex * v0,Vertex * v1,Vertex * v2,const AAParams * aaParams,void * data)216 void* emit_triangle(Vertex* v0, Vertex* v1, Vertex* v2, const AAParams* aaParams, void* data) {
217 LOG("emit_triangle (%g, %g) %d\n", v0->fPoint.fX, v0->fPoint.fY, v0->fAlpha);
218 LOG(" (%g, %g) %d\n", v1->fPoint.fX, v1->fPoint.fY, v1->fAlpha);
219 LOG(" (%g, %g) %d\n", v2->fPoint.fX, v2->fPoint.fY, v2->fAlpha);
220 #if TESSELLATOR_WIREFRAME
221 data = emit_vertex(v0, aaParams, data);
222 data = emit_vertex(v1, aaParams, data);
223 data = emit_vertex(v1, aaParams, data);
224 data = emit_vertex(v2, aaParams, data);
225 data = emit_vertex(v2, aaParams, data);
226 data = emit_vertex(v0, aaParams, data);
227 #else
228 data = emit_vertex(v0, aaParams, data);
229 data = emit_vertex(v1, aaParams, data);
230 data = emit_vertex(v2, aaParams, data);
231 #endif
232 return data;
233 }
234
235 struct VertexList {
VertexList__anonceb1fd950111::VertexList236 VertexList() : fHead(nullptr), fTail(nullptr) {}
VertexList__anonceb1fd950111::VertexList237 VertexList(Vertex* head, Vertex* tail) : fHead(head), fTail(tail) {}
238 Vertex* fHead;
239 Vertex* fTail;
insert__anonceb1fd950111::VertexList240 void insert(Vertex* v, Vertex* prev, Vertex* next) {
241 list_insert<Vertex, &Vertex::fPrev, &Vertex::fNext>(v, prev, next, &fHead, &fTail);
242 }
append__anonceb1fd950111::VertexList243 void append(Vertex* v) {
244 insert(v, fTail, nullptr);
245 }
append__anonceb1fd950111::VertexList246 void append(const VertexList& list) {
247 if (!list.fHead) {
248 return;
249 }
250 if (fTail) {
251 fTail->fNext = list.fHead;
252 list.fHead->fPrev = fTail;
253 } else {
254 fHead = list.fHead;
255 }
256 fTail = list.fTail;
257 }
prepend__anonceb1fd950111::VertexList258 void prepend(Vertex* v) {
259 insert(v, nullptr, fHead);
260 }
remove__anonceb1fd950111::VertexList261 void remove(Vertex* v) {
262 list_remove<Vertex, &Vertex::fPrev, &Vertex::fNext>(v, &fHead, &fTail);
263 }
close__anonceb1fd950111::VertexList264 void close() {
265 if (fHead && fTail) {
266 fTail->fNext = fHead;
267 fHead->fPrev = fTail;
268 }
269 }
270 };
271
272 // Round to nearest quarter-pixel. This is used for screenspace tessellation.
273
round(SkPoint * p)274 inline void round(SkPoint* p) {
275 p->fX = SkScalarRoundToScalar(p->fX * SkFloatToScalar(4.0f)) * SkFloatToScalar(0.25f);
276 p->fY = SkScalarRoundToScalar(p->fY * SkFloatToScalar(4.0f)) * SkFloatToScalar(0.25f);
277 }
278
279 // A line equation in implicit form. fA * x + fB * y + fC = 0, for all points (x, y) on the line.
280 struct Line {
Line__anonceb1fd950111::Line281 Line(Vertex* p, Vertex* q) : Line(p->fPoint, q->fPoint) {}
Line__anonceb1fd950111::Line282 Line(const SkPoint& p, const SkPoint& q)
283 : fA(static_cast<double>(q.fY) - p.fY) // a = dY
284 , fB(static_cast<double>(p.fX) - q.fX) // b = -dX
285 , fC(static_cast<double>(p.fY) * q.fX - // c = cross(q, p)
286 static_cast<double>(p.fX) * q.fY) {}
dist__anonceb1fd950111::Line287 double dist(const SkPoint& p) const {
288 return fA * p.fX + fB * p.fY + fC;
289 }
magSq__anonceb1fd950111::Line290 double magSq() const {
291 return fA * fA + fB * fB;
292 }
293
294 // Compute the intersection of two (infinite) Lines.
intersect__anonceb1fd950111::Line295 bool intersect(const Line& other, SkPoint* point) {
296 double denom = fA * other.fB - fB * other.fA;
297 if (denom == 0.0) {
298 return false;
299 }
300 double scale = 1.0f / denom;
301 point->fX = SkDoubleToScalar((fB * other.fC - other.fB * fC) * scale);
302 point->fY = SkDoubleToScalar((other.fA * fC - fA * other.fC) * scale);
303 round(point);
304 return true;
305 }
306 double fA, fB, fC;
307 };
308
309 /**
310 * An Edge joins a top Vertex to a bottom Vertex. Edge ordering for the list of "edges above" and
311 * "edge below" a vertex as well as for the active edge list is handled by isLeftOf()/isRightOf().
312 * Note that an Edge will give occasionally dist() != 0 for its own endpoints (because floating
313 * point). For speed, that case is only tested by the callers that require it (e.g.,
314 * rewind_if_necessary()). Edges also handle checking for intersection with other edges.
315 * Currently, this converts the edges to the parametric form, in order to avoid doing a division
316 * until an intersection has been confirmed. This is slightly slower in the "found" case, but
317 * a lot faster in the "not found" case.
318 *
319 * The coefficients of the line equation stored in double precision to avoid catastrphic
320 * cancellation in the isLeftOf() and isRightOf() checks. Using doubles ensures that the result is
321 * correct in float, since it's a polynomial of degree 2. The intersect() function, being
322 * degree 5, is still subject to catastrophic cancellation. We deal with that by assuming its
323 * output may be incorrect, and adjusting the mesh topology to match (see comment at the top of
324 * this file).
325 */
326
327 struct Edge {
328 enum class Type { kInner, kOuter, kConnector };
Edge__anonceb1fd950111::Edge329 Edge(Vertex* top, Vertex* bottom, int winding, Type type)
330 : fWinding(winding)
331 , fTop(top)
332 , fBottom(bottom)
333 , fType(type)
334 , fLeft(nullptr)
335 , fRight(nullptr)
336 , fPrevEdgeAbove(nullptr)
337 , fNextEdgeAbove(nullptr)
338 , fPrevEdgeBelow(nullptr)
339 , fNextEdgeBelow(nullptr)
340 , fLeftPoly(nullptr)
341 , fRightPoly(nullptr)
342 , fLeftPolyPrev(nullptr)
343 , fLeftPolyNext(nullptr)
344 , fRightPolyPrev(nullptr)
345 , fRightPolyNext(nullptr)
346 , fUsedInLeftPoly(false)
347 , fUsedInRightPoly(false)
348 , fLine(top, bottom) {
349 }
350 int fWinding; // 1 == edge goes downward; -1 = edge goes upward.
351 Vertex* fTop; // The top vertex in vertex-sort-order (sweep_lt).
352 Vertex* fBottom; // The bottom vertex in vertex-sort-order.
353 Type fType;
354 Edge* fLeft; // The linked list of edges in the active edge list.
355 Edge* fRight; // "
356 Edge* fPrevEdgeAbove; // The linked list of edges in the bottom Vertex's "edges above".
357 Edge* fNextEdgeAbove; // "
358 Edge* fPrevEdgeBelow; // The linked list of edges in the top Vertex's "edges below".
359 Edge* fNextEdgeBelow; // "
360 Poly* fLeftPoly; // The Poly to the left of this edge, if any.
361 Poly* fRightPoly; // The Poly to the right of this edge, if any.
362 Edge* fLeftPolyPrev;
363 Edge* fLeftPolyNext;
364 Edge* fRightPolyPrev;
365 Edge* fRightPolyNext;
366 bool fUsedInLeftPoly;
367 bool fUsedInRightPoly;
368 Line fLine;
dist__anonceb1fd950111::Edge369 double dist(const SkPoint& p) const {
370 return fLine.dist(p);
371 }
isRightOf__anonceb1fd950111::Edge372 bool isRightOf(Vertex* v) const {
373 return fLine.dist(v->fPoint) < 0.0;
374 }
isLeftOf__anonceb1fd950111::Edge375 bool isLeftOf(Vertex* v) const {
376 return fLine.dist(v->fPoint) > 0.0;
377 }
recompute__anonceb1fd950111::Edge378 void recompute() {
379 fLine = Line(fTop, fBottom);
380 }
intersect__anonceb1fd950111::Edge381 bool intersect(const Edge& other, SkPoint* p, uint8_t* alpha = nullptr) {
382 LOG("intersecting %g -> %g with %g -> %g\n",
383 fTop->fID, fBottom->fID,
384 other.fTop->fID, other.fBottom->fID);
385 if (fTop == other.fTop || fBottom == other.fBottom) {
386 return false;
387 }
388 double denom = fLine.fA * other.fLine.fB - fLine.fB * other.fLine.fA;
389 if (denom == 0.0) {
390 return false;
391 }
392 double dx = static_cast<double>(other.fTop->fPoint.fX) - fTop->fPoint.fX;
393 double dy = static_cast<double>(other.fTop->fPoint.fY) - fTop->fPoint.fY;
394 double sNumer = dy * other.fLine.fB + dx * other.fLine.fA;
395 double tNumer = dy * fLine.fB + dx * fLine.fA;
396 // If (sNumer / denom) or (tNumer / denom) is not in [0..1], exit early.
397 // This saves us doing the divide below unless absolutely necessary.
398 if (denom > 0.0 ? (sNumer < 0.0 || sNumer > denom || tNumer < 0.0 || tNumer > denom)
399 : (sNumer > 0.0 || sNumer < denom || tNumer > 0.0 || tNumer < denom)) {
400 return false;
401 }
402 double s = sNumer / denom;
403 SkASSERT(s >= 0.0 && s <= 1.0);
404 p->fX = SkDoubleToScalar(fTop->fPoint.fX - s * fLine.fB);
405 p->fY = SkDoubleToScalar(fTop->fPoint.fY + s * fLine.fA);
406 if (alpha) {
407 if (fType == Type::kConnector) {
408 *alpha = (1.0 - s) * fTop->fAlpha + s * fBottom->fAlpha;
409 } else if (other.fType == Type::kConnector) {
410 double t = tNumer / denom;
411 *alpha = (1.0 - t) * other.fTop->fAlpha + t * other.fBottom->fAlpha;
412 } else if (fType == Type::kOuter && other.fType == Type::kOuter) {
413 *alpha = 0;
414 } else {
415 *alpha = 255;
416 }
417 }
418 return true;
419 }
420 };
421
422 struct EdgeList {
EdgeList__anonceb1fd950111::EdgeList423 EdgeList() : fHead(nullptr), fTail(nullptr) {}
424 Edge* fHead;
425 Edge* fTail;
insert__anonceb1fd950111::EdgeList426 void insert(Edge* edge, Edge* prev, Edge* next) {
427 list_insert<Edge, &Edge::fLeft, &Edge::fRight>(edge, prev, next, &fHead, &fTail);
428 }
append__anonceb1fd950111::EdgeList429 void append(Edge* e) {
430 insert(e, fTail, nullptr);
431 }
remove__anonceb1fd950111::EdgeList432 void remove(Edge* edge) {
433 list_remove<Edge, &Edge::fLeft, &Edge::fRight>(edge, &fHead, &fTail);
434 }
removeAll__anonceb1fd950111::EdgeList435 void removeAll() {
436 while (fHead) {
437 this->remove(fHead);
438 }
439 }
close__anonceb1fd950111::EdgeList440 void close() {
441 if (fHead && fTail) {
442 fTail->fRight = fHead;
443 fHead->fLeft = fTail;
444 }
445 }
contains__anonceb1fd950111::EdgeList446 bool contains(Edge* edge) const {
447 return edge->fLeft || edge->fRight || fHead == edge;
448 }
449 };
450
451 /***************************************************************************************/
452
453 struct Poly {
Poly__anonceb1fd950111::Poly454 Poly(Vertex* v, int winding)
455 : fFirstVertex(v)
456 , fWinding(winding)
457 , fHead(nullptr)
458 , fTail(nullptr)
459 , fNext(nullptr)
460 , fPartner(nullptr)
461 , fCount(0)
462 {
463 #if LOGGING_ENABLED
464 static int gID = 0;
465 fID = gID++;
466 LOG("*** created Poly %d\n", fID);
467 #endif
468 }
469 typedef enum { kLeft_Side, kRight_Side } Side;
470 struct MonotonePoly {
MonotonePoly__anonceb1fd950111::Poly::MonotonePoly471 MonotonePoly(Edge* edge, Side side)
472 : fSide(side)
473 , fFirstEdge(nullptr)
474 , fLastEdge(nullptr)
475 , fPrev(nullptr)
476 , fNext(nullptr) {
477 this->addEdge(edge);
478 }
479 Side fSide;
480 Edge* fFirstEdge;
481 Edge* fLastEdge;
482 MonotonePoly* fPrev;
483 MonotonePoly* fNext;
addEdge__anonceb1fd950111::Poly::MonotonePoly484 void addEdge(Edge* edge) {
485 if (fSide == kRight_Side) {
486 SkASSERT(!edge->fUsedInRightPoly);
487 list_insert<Edge, &Edge::fRightPolyPrev, &Edge::fRightPolyNext>(
488 edge, fLastEdge, nullptr, &fFirstEdge, &fLastEdge);
489 edge->fUsedInRightPoly = true;
490 } else {
491 SkASSERT(!edge->fUsedInLeftPoly);
492 list_insert<Edge, &Edge::fLeftPolyPrev, &Edge::fLeftPolyNext>(
493 edge, fLastEdge, nullptr, &fFirstEdge, &fLastEdge);
494 edge->fUsedInLeftPoly = true;
495 }
496 }
497
emit__anonceb1fd950111::Poly::MonotonePoly498 void* emit(const AAParams* aaParams, void* data) {
499 Edge* e = fFirstEdge;
500 VertexList vertices;
501 vertices.append(e->fTop);
502 int count = 1;
503 while (e != nullptr) {
504 if (kRight_Side == fSide) {
505 vertices.append(e->fBottom);
506 e = e->fRightPolyNext;
507 } else {
508 vertices.prepend(e->fBottom);
509 e = e->fLeftPolyNext;
510 }
511 count++;
512 }
513 Vertex* first = vertices.fHead;
514 Vertex* v = first->fNext;
515 while (v != vertices.fTail) {
516 SkASSERT(v && v->fPrev && v->fNext);
517 Vertex* prev = v->fPrev;
518 Vertex* curr = v;
519 Vertex* next = v->fNext;
520 if (count == 3) {
521 return emit_triangle(prev, curr, next, aaParams, data);
522 }
523 double ax = static_cast<double>(curr->fPoint.fX) - prev->fPoint.fX;
524 double ay = static_cast<double>(curr->fPoint.fY) - prev->fPoint.fY;
525 double bx = static_cast<double>(next->fPoint.fX) - curr->fPoint.fX;
526 double by = static_cast<double>(next->fPoint.fY) - curr->fPoint.fY;
527 if (ax * by - ay * bx >= 0.0) {
528 data = emit_triangle(prev, curr, next, aaParams, data);
529 v->fPrev->fNext = v->fNext;
530 v->fNext->fPrev = v->fPrev;
531 count--;
532 if (v->fPrev == first) {
533 v = v->fNext;
534 } else {
535 v = v->fPrev;
536 }
537 } else {
538 v = v->fNext;
539 }
540 }
541 return data;
542 }
543 };
addEdge__anonceb1fd950111::Poly544 Poly* addEdge(Edge* e, Side side, SkArenaAlloc& alloc) {
545 LOG("addEdge (%g -> %g) to poly %d, %s side\n",
546 e->fTop->fID, e->fBottom->fID, fID, side == kLeft_Side ? "left" : "right");
547 Poly* partner = fPartner;
548 Poly* poly = this;
549 if (side == kRight_Side) {
550 if (e->fUsedInRightPoly) {
551 return this;
552 }
553 } else {
554 if (e->fUsedInLeftPoly) {
555 return this;
556 }
557 }
558 if (partner) {
559 fPartner = partner->fPartner = nullptr;
560 }
561 if (!fTail) {
562 fHead = fTail = alloc.make<MonotonePoly>(e, side);
563 fCount += 2;
564 } else if (e->fBottom == fTail->fLastEdge->fBottom) {
565 return poly;
566 } else if (side == fTail->fSide) {
567 fTail->addEdge(e);
568 fCount++;
569 } else {
570 e = alloc.make<Edge>(fTail->fLastEdge->fBottom, e->fBottom, 1, Edge::Type::kInner);
571 fTail->addEdge(e);
572 fCount++;
573 if (partner) {
574 partner->addEdge(e, side, alloc);
575 poly = partner;
576 } else {
577 MonotonePoly* m = alloc.make<MonotonePoly>(e, side);
578 m->fPrev = fTail;
579 fTail->fNext = m;
580 fTail = m;
581 }
582 }
583 return poly;
584 }
emit__anonceb1fd950111::Poly585 void* emit(const AAParams* aaParams, void *data) {
586 if (fCount < 3) {
587 return data;
588 }
589 LOG("emit() %d, size %d\n", fID, fCount);
590 for (MonotonePoly* m = fHead; m != nullptr; m = m->fNext) {
591 data = m->emit(aaParams, data);
592 }
593 return data;
594 }
lastVertex__anonceb1fd950111::Poly595 Vertex* lastVertex() const { return fTail ? fTail->fLastEdge->fBottom : fFirstVertex; }
596 Vertex* fFirstVertex;
597 int fWinding;
598 MonotonePoly* fHead;
599 MonotonePoly* fTail;
600 Poly* fNext;
601 Poly* fPartner;
602 int fCount;
603 #if LOGGING_ENABLED
604 int fID;
605 #endif
606 };
607
608 /***************************************************************************************/
609
coincident(const SkPoint & a,const SkPoint & b)610 bool coincident(const SkPoint& a, const SkPoint& b) {
611 return a == b;
612 }
613
new_poly(Poly ** head,Vertex * v,int winding,SkArenaAlloc & alloc)614 Poly* new_poly(Poly** head, Vertex* v, int winding, SkArenaAlloc& alloc) {
615 Poly* poly = alloc.make<Poly>(v, winding);
616 poly->fNext = *head;
617 *head = poly;
618 return poly;
619 }
620
append_point_to_contour(const SkPoint & p,VertexList * contour,SkArenaAlloc & alloc)621 void append_point_to_contour(const SkPoint& p, VertexList* contour, SkArenaAlloc& alloc) {
622 Vertex* v = alloc.make<Vertex>(p, 255);
623 #if LOGGING_ENABLED
624 static float gID = 0.0f;
625 v->fID = gID++;
626 #endif
627 contour->append(v);
628 }
629
quad_error_at(const SkPoint pts[3],SkScalar t,SkScalar u)630 SkScalar quad_error_at(const SkPoint pts[3], SkScalar t, SkScalar u) {
631 SkQuadCoeff quad(pts);
632 SkPoint p0 = to_point(quad.eval(t - 0.5f * u));
633 SkPoint mid = to_point(quad.eval(t));
634 SkPoint p1 = to_point(quad.eval(t + 0.5f * u));
635 if (!p0.isFinite() || !mid.isFinite() || !p1.isFinite()) {
636 return 0;
637 }
638 return mid.distanceToLineSegmentBetweenSqd(p0, p1);
639 }
640
append_quadratic_to_contour(const SkPoint pts[3],SkScalar toleranceSqd,VertexList * contour,SkArenaAlloc & alloc)641 void append_quadratic_to_contour(const SkPoint pts[3], SkScalar toleranceSqd, VertexList* contour,
642 SkArenaAlloc& alloc) {
643 SkQuadCoeff quad(pts);
644 Sk2s aa = quad.fA * quad.fA;
645 SkScalar denom = 2.0f * (aa[0] + aa[1]);
646 Sk2s ab = quad.fA * quad.fB;
647 SkScalar t = denom ? (-ab[0] - ab[1]) / denom : 0.0f;
648 int nPoints = 1;
649 SkScalar u;
650 // Test possible subdivision values only at the point of maximum curvature.
651 // If it passes the flatness metric there, it'll pass everywhere.
652 for (;;) {
653 u = 1.0f / nPoints;
654 if (quad_error_at(pts, t, u) < toleranceSqd) {
655 break;
656 }
657 nPoints++;
658 }
659 for (int j = 1; j <= nPoints; j++) {
660 append_point_to_contour(to_point(quad.eval(j * u)), contour, alloc);
661 }
662 }
663
generate_cubic_points(const SkPoint & p0,const SkPoint & p1,const SkPoint & p2,const SkPoint & p3,SkScalar tolSqd,VertexList * contour,int pointsLeft,SkArenaAlloc & alloc)664 void generate_cubic_points(const SkPoint& p0,
665 const SkPoint& p1,
666 const SkPoint& p2,
667 const SkPoint& p3,
668 SkScalar tolSqd,
669 VertexList* contour,
670 int pointsLeft,
671 SkArenaAlloc& alloc) {
672 SkScalar d1 = p1.distanceToLineSegmentBetweenSqd(p0, p3);
673 SkScalar d2 = p2.distanceToLineSegmentBetweenSqd(p0, p3);
674 if (pointsLeft < 2 || (d1 < tolSqd && d2 < tolSqd) ||
675 !SkScalarIsFinite(d1) || !SkScalarIsFinite(d2)) {
676 append_point_to_contour(p3, contour, alloc);
677 return;
678 }
679 const SkPoint q[] = {
680 { SkScalarAve(p0.fX, p1.fX), SkScalarAve(p0.fY, p1.fY) },
681 { SkScalarAve(p1.fX, p2.fX), SkScalarAve(p1.fY, p2.fY) },
682 { SkScalarAve(p2.fX, p3.fX), SkScalarAve(p2.fY, p3.fY) }
683 };
684 const SkPoint r[] = {
685 { SkScalarAve(q[0].fX, q[1].fX), SkScalarAve(q[0].fY, q[1].fY) },
686 { SkScalarAve(q[1].fX, q[2].fX), SkScalarAve(q[1].fY, q[2].fY) }
687 };
688 const SkPoint s = { SkScalarAve(r[0].fX, r[1].fX), SkScalarAve(r[0].fY, r[1].fY) };
689 pointsLeft >>= 1;
690 generate_cubic_points(p0, q[0], r[0], s, tolSqd, contour, pointsLeft, alloc);
691 generate_cubic_points(s, r[1], q[2], p3, tolSqd, contour, pointsLeft, alloc);
692 }
693
694 // Stage 1: convert the input path to a set of linear contours (linked list of Vertices).
695
path_to_contours(const SkPath & path,SkScalar tolerance,const SkRect & clipBounds,VertexList * contours,SkArenaAlloc & alloc,bool * isLinear)696 void path_to_contours(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
697 VertexList* contours, SkArenaAlloc& alloc, bool *isLinear) {
698 SkScalar toleranceSqd = tolerance * tolerance;
699
700 SkPoint pts[4];
701 *isLinear = true;
702 VertexList* contour = contours;
703 SkPath::Iter iter(path, false);
704 if (path.isInverseFillType()) {
705 SkPoint quad[4];
706 clipBounds.toQuad(quad);
707 for (int i = 3; i >= 0; i--) {
708 append_point_to_contour(quad[i], contours, alloc);
709 }
710 contour++;
711 }
712 SkAutoConicToQuads converter;
713 SkPath::Verb verb;
714 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
715 switch (verb) {
716 case SkPath::kConic_Verb: {
717 SkScalar weight = iter.conicWeight();
718 const SkPoint* quadPts = converter.computeQuads(pts, weight, toleranceSqd);
719 for (int i = 0; i < converter.countQuads(); ++i) {
720 append_quadratic_to_contour(quadPts, toleranceSqd, contour, alloc);
721 quadPts += 2;
722 }
723 *isLinear = false;
724 break;
725 }
726 case SkPath::kMove_Verb:
727 if (contour->fHead) {
728 contour++;
729 }
730 append_point_to_contour(pts[0], contour, alloc);
731 break;
732 case SkPath::kLine_Verb: {
733 append_point_to_contour(pts[1], contour, alloc);
734 break;
735 }
736 case SkPath::kQuad_Verb: {
737 append_quadratic_to_contour(pts, toleranceSqd, contour, alloc);
738 *isLinear = false;
739 break;
740 }
741 case SkPath::kCubic_Verb: {
742 int pointsLeft = GrPathUtils::cubicPointCount(pts, tolerance);
743 generate_cubic_points(pts[0], pts[1], pts[2], pts[3], toleranceSqd, contour,
744 pointsLeft, alloc);
745 *isLinear = false;
746 break;
747 }
748 case SkPath::kClose_Verb:
749 case SkPath::kDone_Verb:
750 break;
751 }
752 }
753 }
754
apply_fill_type(SkPath::FillType fillType,int winding)755 inline bool apply_fill_type(SkPath::FillType fillType, int winding) {
756 switch (fillType) {
757 case SkPath::kWinding_FillType:
758 return winding != 0;
759 case SkPath::kEvenOdd_FillType:
760 return (winding & 1) != 0;
761 case SkPath::kInverseWinding_FillType:
762 return winding == 1;
763 case SkPath::kInverseEvenOdd_FillType:
764 return (winding & 1) == 1;
765 default:
766 SkASSERT(false);
767 return false;
768 }
769 }
770
apply_fill_type(SkPath::FillType fillType,Poly * poly)771 inline bool apply_fill_type(SkPath::FillType fillType, Poly* poly) {
772 return poly && apply_fill_type(fillType, poly->fWinding);
773 }
774
new_edge(Vertex * prev,Vertex * next,Edge::Type type,Comparator & c,SkArenaAlloc & alloc)775 Edge* new_edge(Vertex* prev, Vertex* next, Edge::Type type, Comparator& c, SkArenaAlloc& alloc) {
776 int winding = c.sweep_lt(prev->fPoint, next->fPoint) ? 1 : -1;
777 Vertex* top = winding < 0 ? next : prev;
778 Vertex* bottom = winding < 0 ? prev : next;
779 return alloc.make<Edge>(top, bottom, winding, type);
780 }
781
remove_edge(Edge * edge,EdgeList * edges)782 void remove_edge(Edge* edge, EdgeList* edges) {
783 LOG("removing edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID);
784 SkASSERT(edges->contains(edge));
785 edges->remove(edge);
786 }
787
insert_edge(Edge * edge,Edge * prev,EdgeList * edges)788 void insert_edge(Edge* edge, Edge* prev, EdgeList* edges) {
789 LOG("inserting edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID);
790 SkASSERT(!edges->contains(edge));
791 Edge* next = prev ? prev->fRight : edges->fHead;
792 edges->insert(edge, prev, next);
793 }
794
find_enclosing_edges(Vertex * v,EdgeList * edges,Edge ** left,Edge ** right)795 void find_enclosing_edges(Vertex* v, EdgeList* edges, Edge** left, Edge** right) {
796 if (v->fFirstEdgeAbove && v->fLastEdgeAbove) {
797 *left = v->fFirstEdgeAbove->fLeft;
798 *right = v->fLastEdgeAbove->fRight;
799 return;
800 }
801 Edge* next = nullptr;
802 Edge* prev;
803 for (prev = edges->fTail; prev != nullptr; prev = prev->fLeft) {
804 if (prev->isLeftOf(v)) {
805 break;
806 }
807 next = prev;
808 }
809 *left = prev;
810 *right = next;
811 }
812
insert_edge_above(Edge * edge,Vertex * v,Comparator & c)813 void insert_edge_above(Edge* edge, Vertex* v, Comparator& c) {
814 if (edge->fTop->fPoint == edge->fBottom->fPoint ||
815 c.sweep_lt(edge->fBottom->fPoint, edge->fTop->fPoint)) {
816 return;
817 }
818 LOG("insert edge (%g -> %g) above vertex %g\n", edge->fTop->fID, edge->fBottom->fID, v->fID);
819 Edge* prev = nullptr;
820 Edge* next;
821 for (next = v->fFirstEdgeAbove; next; next = next->fNextEdgeAbove) {
822 if (next->isRightOf(edge->fTop)) {
823 break;
824 }
825 prev = next;
826 }
827 list_insert<Edge, &Edge::fPrevEdgeAbove, &Edge::fNextEdgeAbove>(
828 edge, prev, next, &v->fFirstEdgeAbove, &v->fLastEdgeAbove);
829 }
830
insert_edge_below(Edge * edge,Vertex * v,Comparator & c)831 void insert_edge_below(Edge* edge, Vertex* v, Comparator& c) {
832 if (edge->fTop->fPoint == edge->fBottom->fPoint ||
833 c.sweep_lt(edge->fBottom->fPoint, edge->fTop->fPoint)) {
834 return;
835 }
836 LOG("insert edge (%g -> %g) below vertex %g\n", edge->fTop->fID, edge->fBottom->fID, v->fID);
837 Edge* prev = nullptr;
838 Edge* next;
839 for (next = v->fFirstEdgeBelow; next; next = next->fNextEdgeBelow) {
840 if (next->isRightOf(edge->fBottom)) {
841 break;
842 }
843 prev = next;
844 }
845 list_insert<Edge, &Edge::fPrevEdgeBelow, &Edge::fNextEdgeBelow>(
846 edge, prev, next, &v->fFirstEdgeBelow, &v->fLastEdgeBelow);
847 }
848
remove_edge_above(Edge * edge)849 void remove_edge_above(Edge* edge) {
850 LOG("removing edge (%g -> %g) above vertex %g\n", edge->fTop->fID, edge->fBottom->fID,
851 edge->fBottom->fID);
852 list_remove<Edge, &Edge::fPrevEdgeAbove, &Edge::fNextEdgeAbove>(
853 edge, &edge->fBottom->fFirstEdgeAbove, &edge->fBottom->fLastEdgeAbove);
854 }
855
remove_edge_below(Edge * edge)856 void remove_edge_below(Edge* edge) {
857 LOG("removing edge (%g -> %g) below vertex %g\n", edge->fTop->fID, edge->fBottom->fID,
858 edge->fTop->fID);
859 list_remove<Edge, &Edge::fPrevEdgeBelow, &Edge::fNextEdgeBelow>(
860 edge, &edge->fTop->fFirstEdgeBelow, &edge->fTop->fLastEdgeBelow);
861 }
862
disconnect(Edge * edge)863 void disconnect(Edge* edge)
864 {
865 remove_edge_above(edge);
866 remove_edge_below(edge);
867 }
868
869 void merge_collinear_edges(Edge* edge, EdgeList* activeEdges, Vertex** current, Comparator& c);
870
rewind(EdgeList * activeEdges,Vertex ** current,Vertex * dst,Comparator & c)871 void rewind(EdgeList* activeEdges, Vertex** current, Vertex* dst, Comparator& c) {
872 if (!current || *current == dst || c.sweep_lt((*current)->fPoint, dst->fPoint)) {
873 return;
874 }
875 Vertex* v = *current;
876 LOG("rewinding active edges from vertex %g to vertex %g\n", v->fID, dst->fID);
877 while (v != dst) {
878 v = v->fPrev;
879 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
880 remove_edge(e, activeEdges);
881 }
882 Edge* leftEdge = v->fLeftEnclosingEdge;
883 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
884 insert_edge(e, leftEdge, activeEdges);
885 leftEdge = e;
886 }
887 }
888 *current = v;
889 }
890
rewind_if_necessary(Edge * edge,EdgeList * activeEdges,Vertex ** current,Comparator & c)891 void rewind_if_necessary(Edge* edge, EdgeList* activeEdges, Vertex** current, Comparator& c) {
892 if (!activeEdges || !current) {
893 return;
894 }
895 Vertex* top = edge->fTop;
896 Vertex* bottom = edge->fBottom;
897 if (edge->fLeft) {
898 Vertex* leftTop = edge->fLeft->fTop;
899 Vertex* leftBottom = edge->fLeft->fBottom;
900 if (c.sweep_lt(leftTop->fPoint, top->fPoint) && !edge->fLeft->isLeftOf(top)) {
901 rewind(activeEdges, current, leftTop, c);
902 } else if (c.sweep_lt(top->fPoint, leftTop->fPoint) && !edge->isRightOf(leftTop)) {
903 rewind(activeEdges, current, top, c);
904 } else if (c.sweep_lt(bottom->fPoint, leftBottom->fPoint) &&
905 !edge->fLeft->isLeftOf(bottom)) {
906 rewind(activeEdges, current, leftTop, c);
907 } else if (c.sweep_lt(leftBottom->fPoint, bottom->fPoint) && !edge->isRightOf(leftBottom)) {
908 rewind(activeEdges, current, top, c);
909 }
910 }
911 if (edge->fRight) {
912 Vertex* rightTop = edge->fRight->fTop;
913 Vertex* rightBottom = edge->fRight->fBottom;
914 if (c.sweep_lt(rightTop->fPoint, top->fPoint) && !edge->fRight->isRightOf(top)) {
915 rewind(activeEdges, current, rightTop, c);
916 } else if (c.sweep_lt(top->fPoint, rightTop->fPoint) && !edge->isLeftOf(rightTop)) {
917 rewind(activeEdges, current, top, c);
918 } else if (c.sweep_lt(bottom->fPoint, rightBottom->fPoint) &&
919 !edge->fRight->isRightOf(bottom)) {
920 rewind(activeEdges, current, rightTop, c);
921 } else if (c.sweep_lt(rightBottom->fPoint, bottom->fPoint) &&
922 !edge->isLeftOf(rightBottom)) {
923 rewind(activeEdges, current, top, c);
924 }
925 }
926 }
927
set_top(Edge * edge,Vertex * v,EdgeList * activeEdges,Vertex ** current,Comparator & c)928 void set_top(Edge* edge, Vertex* v, EdgeList* activeEdges, Vertex** current, Comparator& c) {
929 remove_edge_below(edge);
930 edge->fTop = v;
931 edge->recompute();
932 insert_edge_below(edge, v, c);
933 rewind_if_necessary(edge, activeEdges, current, c);
934 merge_collinear_edges(edge, activeEdges, current, c);
935 }
936
set_bottom(Edge * edge,Vertex * v,EdgeList * activeEdges,Vertex ** current,Comparator & c)937 void set_bottom(Edge* edge, Vertex* v, EdgeList* activeEdges, Vertex** current, Comparator& c) {
938 remove_edge_above(edge);
939 edge->fBottom = v;
940 edge->recompute();
941 insert_edge_above(edge, v, c);
942 rewind_if_necessary(edge, activeEdges, current, c);
943 merge_collinear_edges(edge, activeEdges, current, c);
944 }
945
merge_edges_above(Edge * edge,Edge * other,EdgeList * activeEdges,Vertex ** current,Comparator & c)946 void merge_edges_above(Edge* edge, Edge* other, EdgeList* activeEdges, Vertex** current,
947 Comparator& c) {
948 if (coincident(edge->fTop->fPoint, other->fTop->fPoint)) {
949 LOG("merging coincident above edges (%g, %g) -> (%g, %g)\n",
950 edge->fTop->fPoint.fX, edge->fTop->fPoint.fY,
951 edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY);
952 rewind(activeEdges, current, edge->fTop, c);
953 other->fWinding += edge->fWinding;
954 disconnect(edge);
955 } else if (c.sweep_lt(edge->fTop->fPoint, other->fTop->fPoint)) {
956 rewind(activeEdges, current, edge->fTop, c);
957 other->fWinding += edge->fWinding;
958 set_bottom(edge, other->fTop, activeEdges, current, c);
959 } else {
960 rewind(activeEdges, current, other->fTop, c);
961 edge->fWinding += other->fWinding;
962 set_bottom(other, edge->fTop, activeEdges, current, c);
963 }
964 }
965
merge_edges_below(Edge * edge,Edge * other,EdgeList * activeEdges,Vertex ** current,Comparator & c)966 void merge_edges_below(Edge* edge, Edge* other, EdgeList* activeEdges, Vertex** current,
967 Comparator& c) {
968 if (coincident(edge->fBottom->fPoint, other->fBottom->fPoint)) {
969 LOG("merging coincident below edges (%g, %g) -> (%g, %g)\n",
970 edge->fTop->fPoint.fX, edge->fTop->fPoint.fY,
971 edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY);
972 rewind(activeEdges, current, edge->fTop, c);
973 other->fWinding += edge->fWinding;
974 disconnect(edge);
975 } else if (c.sweep_lt(edge->fBottom->fPoint, other->fBottom->fPoint)) {
976 rewind(activeEdges, current, other->fTop, c);
977 edge->fWinding += other->fWinding;
978 set_top(other, edge->fBottom, activeEdges, current, c);
979 } else {
980 rewind(activeEdges, current, edge->fTop, c);
981 other->fWinding += edge->fWinding;
982 set_top(edge, other->fBottom, activeEdges, current, c);
983 }
984 }
985
merge_collinear_edges(Edge * edge,EdgeList * activeEdges,Vertex ** current,Comparator & c)986 void merge_collinear_edges(Edge* edge, EdgeList* activeEdges, Vertex** current, Comparator& c) {
987 for (;;) {
988 if (edge->fPrevEdgeAbove && (edge->fTop == edge->fPrevEdgeAbove->fTop ||
989 !edge->fPrevEdgeAbove->isLeftOf(edge->fTop))) {
990 merge_edges_above(edge, edge->fPrevEdgeAbove, activeEdges, current, c);
991 } else if (edge->fNextEdgeAbove && (edge->fTop == edge->fNextEdgeAbove->fTop ||
992 !edge->isLeftOf(edge->fNextEdgeAbove->fTop))) {
993 merge_edges_above(edge, edge->fNextEdgeAbove, activeEdges, current, c);
994 } else if (edge->fPrevEdgeBelow && (edge->fBottom == edge->fPrevEdgeBelow->fBottom ||
995 !edge->fPrevEdgeBelow->isLeftOf(edge->fBottom))) {
996 merge_edges_below(edge, edge->fPrevEdgeBelow, activeEdges, current, c);
997 } else if (edge->fNextEdgeBelow && (edge->fBottom == edge->fNextEdgeBelow->fBottom ||
998 !edge->isLeftOf(edge->fNextEdgeBelow->fBottom))) {
999 merge_edges_below(edge, edge->fNextEdgeBelow, activeEdges, current, c);
1000 } else {
1001 break;
1002 }
1003 }
1004 SkASSERT(!edge->fPrevEdgeAbove || edge->fPrevEdgeAbove->isLeftOf(edge->fTop));
1005 SkASSERT(!edge->fPrevEdgeBelow || edge->fPrevEdgeBelow->isLeftOf(edge->fBottom));
1006 SkASSERT(!edge->fNextEdgeAbove || edge->fNextEdgeAbove->isRightOf(edge->fTop));
1007 SkASSERT(!edge->fNextEdgeBelow || edge->fNextEdgeBelow->isRightOf(edge->fBottom));
1008 }
1009
split_edge(Edge * edge,Vertex * v,EdgeList * activeEdges,Vertex ** current,Comparator & c,SkArenaAlloc & alloc)1010 void split_edge(Edge* edge, Vertex* v, EdgeList* activeEdges, Vertex** current, Comparator& c,
1011 SkArenaAlloc& alloc) {
1012 if (v == edge->fTop || v == edge->fBottom) {
1013 return;
1014 }
1015 LOG("splitting edge (%g -> %g) at vertex %g (%g, %g)\n",
1016 edge->fTop->fID, edge->fBottom->fID,
1017 v->fID, v->fPoint.fX, v->fPoint.fY);
1018 Vertex* top;
1019 Vertex* bottom;
1020 if (c.sweep_lt(v->fPoint, edge->fTop->fPoint)) {
1021 top = v;
1022 bottom = edge->fTop;
1023 set_top(edge, v, activeEdges, current, c);
1024 } else if (c.sweep_lt(edge->fBottom->fPoint, v->fPoint)) {
1025 top = edge->fBottom;
1026 bottom = v;
1027 set_bottom(edge, v, activeEdges, current, c);
1028 } else {
1029 top = v;
1030 bottom = edge->fBottom;
1031 set_bottom(edge, v, activeEdges, current, c);
1032 }
1033 Edge* newEdge = alloc.make<Edge>(top, bottom, edge->fWinding, edge->fType);
1034 insert_edge_below(newEdge, top, c);
1035 insert_edge_above(newEdge, bottom, c);
1036 merge_collinear_edges(newEdge, activeEdges, current, c);
1037 }
1038
connect(Vertex * prev,Vertex * next,Edge::Type type,Comparator & c,SkArenaAlloc & alloc,int winding_scale=1)1039 Edge* connect(Vertex* prev, Vertex* next, Edge::Type type, Comparator& c, SkArenaAlloc& alloc,
1040 int winding_scale = 1) {
1041 Edge* edge = new_edge(prev, next, type, c, alloc);
1042 insert_edge_below(edge, edge->fTop, c);
1043 insert_edge_above(edge, edge->fBottom, c);
1044 edge->fWinding *= winding_scale;
1045 merge_collinear_edges(edge, nullptr, nullptr, c);
1046 return edge;
1047 }
1048
merge_vertices(Vertex * src,Vertex * dst,VertexList * mesh,Comparator & c,SkArenaAlloc & alloc)1049 void merge_vertices(Vertex* src, Vertex* dst, VertexList* mesh, Comparator& c,
1050 SkArenaAlloc& alloc) {
1051 LOG("found coincident verts at %g, %g; merging %g into %g\n", src->fPoint.fX, src->fPoint.fY,
1052 src->fID, dst->fID);
1053 dst->fAlpha = SkTMax(src->fAlpha, dst->fAlpha);
1054 if (src->fPartner) {
1055 src->fPartner->fPartner = dst;
1056 }
1057 for (Edge* edge = src->fFirstEdgeAbove; edge;) {
1058 Edge* next = edge->fNextEdgeAbove;
1059 set_bottom(edge, dst, nullptr, nullptr, c);
1060 edge = next;
1061 }
1062 for (Edge* edge = src->fFirstEdgeBelow; edge;) {
1063 Edge* next = edge->fNextEdgeBelow;
1064 set_top(edge, dst, nullptr, nullptr, c);
1065 edge = next;
1066 }
1067 mesh->remove(src);
1068 }
1069
max_edge_alpha(Edge * a,Edge * b)1070 uint8_t max_edge_alpha(Edge* a, Edge* b) {
1071 if (a->fType == Edge::Type::kInner || b->fType == Edge::Type::kInner) {
1072 return 255;
1073 } else if (a->fType == Edge::Type::kOuter && b->fType == Edge::Type::kOuter) {
1074 return 0;
1075 } else {
1076 return SkTMax(SkTMax(a->fTop->fAlpha, a->fBottom->fAlpha),
1077 SkTMax(b->fTop->fAlpha, b->fBottom->fAlpha));
1078 }
1079 }
1080
check_for_intersection(Edge * edge,Edge * other,EdgeList * activeEdges,Vertex ** current,VertexList * mesh,Comparator & c,SkArenaAlloc & alloc)1081 bool check_for_intersection(Edge* edge, Edge* other, EdgeList* activeEdges, Vertex** current,
1082 VertexList* mesh, Comparator& c, SkArenaAlloc& alloc) {
1083 if (!edge || !other) {
1084 return false;
1085 }
1086 SkPoint p;
1087 uint8_t alpha;
1088 if (edge->intersect(*other, &p, &alpha) && p.isFinite()) {
1089 Vertex* v;
1090 LOG("found intersection, pt is %g, %g\n", p.fX, p.fY);
1091 Vertex* top = *current;
1092 // If the intersection point is above the current vertex, rewind to the vertex above the
1093 // intersection.
1094 while (top && c.sweep_lt(p, top->fPoint)) {
1095 top = top->fPrev;
1096 }
1097 if (p == edge->fTop->fPoint) {
1098 v = edge->fTop;
1099 } else if (p == edge->fBottom->fPoint) {
1100 v = edge->fBottom;
1101 } else if (p == other->fTop->fPoint) {
1102 v = other->fTop;
1103 } else if (p == other->fBottom->fPoint) {
1104 v = other->fBottom;
1105 } else {
1106 Vertex* prevV = top;
1107 Vertex* nextV = top ? top->fNext : mesh->fHead;
1108 while (nextV && c.sweep_lt(nextV->fPoint, p)) {
1109 prevV = nextV;
1110 nextV = nextV->fNext;
1111 }
1112 if (prevV && coincident(prevV->fPoint, p)) {
1113 v = prevV;
1114 } else if (nextV && coincident(nextV->fPoint, p)) {
1115 v = nextV;
1116 } else {
1117 v = alloc.make<Vertex>(p, alpha);
1118 #if LOGGING_ENABLED
1119 if (!prevV) {
1120 v->fID = mesh->fHead->fID - 1.0f;
1121 } else if (!nextV) {
1122 v->fID = mesh->fTail->fID + 1.0f;
1123 } else {
1124 v->fID = (prevV->fID + nextV->fID) * 0.5f;
1125 }
1126 #endif
1127 mesh->insert(v, prevV, nextV);
1128 }
1129 }
1130 rewind(activeEdges, current, top ? top : v, c);
1131 split_edge(edge, v, activeEdges, current, c, alloc);
1132 split_edge(other, v, activeEdges, current, c, alloc);
1133 v->fAlpha = SkTMax(v->fAlpha, alpha);
1134 return true;
1135 }
1136 return false;
1137 }
1138
sanitize_contours(VertexList * contours,int contourCnt,bool approximate)1139 void sanitize_contours(VertexList* contours, int contourCnt, bool approximate) {
1140 for (VertexList* contour = contours; contourCnt > 0; --contourCnt, ++contour) {
1141 SkASSERT(contour->fHead);
1142 Vertex* prev = contour->fTail;
1143 if (approximate) {
1144 round(&prev->fPoint);
1145 }
1146 for (Vertex* v = contour->fHead; v;) {
1147 if (approximate) {
1148 round(&v->fPoint);
1149 }
1150 Vertex* next = v->fNext;
1151 if (coincident(prev->fPoint, v->fPoint)) {
1152 LOG("vertex %g,%g coincident; removing\n", v->fPoint.fX, v->fPoint.fY);
1153 contour->remove(v);
1154 }
1155 prev = v;
1156 v = next;
1157 }
1158 }
1159 }
1160
merge_coincident_vertices(VertexList * mesh,Comparator & c,SkArenaAlloc & alloc)1161 void merge_coincident_vertices(VertexList* mesh, Comparator& c, SkArenaAlloc& alloc) {
1162 if (!mesh->fHead) {
1163 return;
1164 }
1165 for (Vertex* v = mesh->fHead->fNext; v != nullptr; v = v->fNext) {
1166 if (c.sweep_lt(v->fPoint, v->fPrev->fPoint)) {
1167 v->fPoint = v->fPrev->fPoint;
1168 }
1169 if (coincident(v->fPrev->fPoint, v->fPoint)) {
1170 merge_vertices(v->fPrev, v, mesh, c, alloc);
1171 }
1172 }
1173 }
1174
1175 // Stage 2: convert the contours to a mesh of edges connecting the vertices.
1176
build_edges(VertexList * contours,int contourCnt,VertexList * mesh,Comparator & c,SkArenaAlloc & alloc)1177 void build_edges(VertexList* contours, int contourCnt, VertexList* mesh, Comparator& c,
1178 SkArenaAlloc& alloc) {
1179 for (VertexList* contour = contours; contourCnt > 0; --contourCnt, ++contour) {
1180 Vertex* prev = contour->fTail;
1181 for (Vertex* v = contour->fHead; v;) {
1182 Vertex* next = v->fNext;
1183 connect(prev, v, Edge::Type::kInner, c, alloc);
1184 mesh->append(v);
1185 prev = v;
1186 v = next;
1187 }
1188 }
1189 }
1190
connect_partners(VertexList * outerVertices,Comparator & c,SkArenaAlloc & alloc)1191 void connect_partners(VertexList* outerVertices, Comparator& c, SkArenaAlloc& alloc) {
1192 for (Vertex* outer = outerVertices->fHead; outer; outer = outer->fNext) {
1193 if (Vertex* inner = outer->fPartner) {
1194 // Connector edges get zero winding, since they're only structural (i.e., to ensure
1195 // no 0-0-0 alpha triangles are produced), and shouldn't affect the poly winding number.
1196 connect(outer, inner, Edge::Type::kConnector, c, alloc, 0);
1197 inner->fPartner = outer->fPartner = nullptr;
1198 }
1199 }
1200 }
1201
1202 template <CompareFunc sweep_lt>
sorted_merge(VertexList * front,VertexList * back,VertexList * result)1203 void sorted_merge(VertexList* front, VertexList* back, VertexList* result) {
1204 Vertex* a = front->fHead;
1205 Vertex* b = back->fHead;
1206 while (a && b) {
1207 if (sweep_lt(a->fPoint, b->fPoint)) {
1208 front->remove(a);
1209 result->append(a);
1210 a = front->fHead;
1211 } else {
1212 back->remove(b);
1213 result->append(b);
1214 b = back->fHead;
1215 }
1216 }
1217 result->append(*front);
1218 result->append(*back);
1219 }
1220
sorted_merge(VertexList * front,VertexList * back,VertexList * result,Comparator & c)1221 void sorted_merge(VertexList* front, VertexList* back, VertexList* result, Comparator& c) {
1222 if (c.fDirection == Comparator::Direction::kHorizontal) {
1223 sorted_merge<sweep_lt_horiz>(front, back, result);
1224 } else {
1225 sorted_merge<sweep_lt_vert>(front, back, result);
1226 }
1227 #if LOGGING_ENABLED
1228 float id = 0.0f;
1229 for (Vertex* v = result->fHead; v; v = v->fNext) {
1230 v->fID = id++;
1231 }
1232 #endif
1233 }
1234
1235 // Stage 3: sort the vertices by increasing sweep direction.
1236
1237 template <CompareFunc sweep_lt>
merge_sort(VertexList * vertices)1238 void merge_sort(VertexList* vertices) {
1239 Vertex* slow = vertices->fHead;
1240 if (!slow) {
1241 return;
1242 }
1243 Vertex* fast = slow->fNext;
1244 if (!fast) {
1245 return;
1246 }
1247 do {
1248 fast = fast->fNext;
1249 if (fast) {
1250 fast = fast->fNext;
1251 slow = slow->fNext;
1252 }
1253 } while (fast);
1254 VertexList front(vertices->fHead, slow);
1255 VertexList back(slow->fNext, vertices->fTail);
1256 front.fTail->fNext = back.fHead->fPrev = nullptr;
1257
1258 merge_sort<sweep_lt>(&front);
1259 merge_sort<sweep_lt>(&back);
1260
1261 vertices->fHead = vertices->fTail = nullptr;
1262 sorted_merge<sweep_lt>(&front, &back, vertices);
1263 }
1264
1265 // Stage 4: Simplify the mesh by inserting new vertices at intersecting edges.
1266
simplify(VertexList * mesh,Comparator & c,SkArenaAlloc & alloc)1267 void simplify(VertexList* mesh, Comparator& c, SkArenaAlloc& alloc) {
1268 LOG("simplifying complex polygons\n");
1269 EdgeList activeEdges;
1270 for (Vertex* v = mesh->fHead; v != nullptr; v = v->fNext) {
1271 if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) {
1272 continue;
1273 }
1274 Edge* leftEnclosingEdge;
1275 Edge* rightEnclosingEdge;
1276 bool restartChecks;
1277 do {
1278 LOG("\nvertex %g: (%g,%g), alpha %d\n", v->fID, v->fPoint.fX, v->fPoint.fY, v->fAlpha);
1279 restartChecks = false;
1280 find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
1281 if (rightEnclosingEdge && !rightEnclosingEdge->isRightOf(v)) {
1282 split_edge(rightEnclosingEdge, v, &activeEdges, &v, c, alloc);
1283 restartChecks = true;
1284 continue;
1285 }
1286 SkASSERT(!rightEnclosingEdge || rightEnclosingEdge->isRightOf(v));
1287 v->fLeftEnclosingEdge = leftEnclosingEdge;
1288 v->fRightEnclosingEdge = rightEnclosingEdge;
1289 if (v->fFirstEdgeBelow) {
1290 for (Edge* edge = v->fFirstEdgeBelow; edge; edge = edge->fNextEdgeBelow) {
1291 if (check_for_intersection(edge, leftEnclosingEdge, &activeEdges, &v, mesh, c,
1292 alloc)) {
1293 restartChecks = true;
1294 break;
1295 }
1296 if (check_for_intersection(edge, rightEnclosingEdge, &activeEdges, &v, mesh, c,
1297 alloc)) {
1298 restartChecks = true;
1299 break;
1300 }
1301 }
1302 } else {
1303 if (check_for_intersection(leftEnclosingEdge, rightEnclosingEdge,
1304 &activeEdges, &v, mesh, c, alloc)) {
1305 restartChecks = true;
1306 }
1307
1308 }
1309 } while (restartChecks);
1310 if (v->fAlpha == 0) {
1311 if ((leftEnclosingEdge && leftEnclosingEdge->fWinding < 0) &&
1312 (rightEnclosingEdge && rightEnclosingEdge->fWinding > 0)) {
1313 v->fAlpha = max_edge_alpha(leftEnclosingEdge, rightEnclosingEdge);
1314 }
1315 }
1316 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
1317 remove_edge(e, &activeEdges);
1318 }
1319 Edge* leftEdge = leftEnclosingEdge;
1320 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1321 insert_edge(e, leftEdge, &activeEdges);
1322 leftEdge = e;
1323 }
1324 }
1325 }
1326
1327 // This is a stripped-down version of simplify() (the Bentley-Ottmann algorithm) that
1328 // early-returns true on the first found intersection, false if none.
is_complex(const VertexList & vertices)1329 bool is_complex(const VertexList& vertices) {
1330 LOG("testing polygon complexity\n");
1331 EdgeList activeEdges;
1332 for (Vertex* v = vertices.fHead; v != nullptr; v = v->fNext) {
1333 if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) {
1334 continue;
1335 }
1336 Edge* leftEnclosingEdge;
1337 Edge* rightEnclosingEdge;
1338 find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
1339 SkPoint dummy;
1340 if (v->fFirstEdgeBelow) {
1341 for (Edge* edge = v->fFirstEdgeBelow; edge; edge = edge->fNextEdgeBelow) {
1342 if (edge && leftEnclosingEdge && edge->intersect(*leftEnclosingEdge, &dummy)) {
1343 activeEdges.removeAll();
1344 return true;
1345 }
1346 if (edge && rightEnclosingEdge && edge->intersect(*rightEnclosingEdge, &dummy)) {
1347 activeEdges.removeAll();
1348 return true;
1349 }
1350 }
1351 } else if (leftEnclosingEdge && rightEnclosingEdge &&
1352 leftEnclosingEdge->intersect(*rightEnclosingEdge, &dummy)) {
1353 activeEdges.removeAll();
1354 return true;
1355 }
1356 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
1357 remove_edge(e, &activeEdges);
1358 }
1359 Edge* leftEdge = leftEnclosingEdge;
1360 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1361 insert_edge(e, leftEdge, &activeEdges);
1362 leftEdge = e;
1363 }
1364 }
1365 activeEdges.removeAll();
1366 return false;
1367 }
1368
1369 // Stage 5: Tessellate the simplified mesh into monotone polygons.
1370
tessellate(const VertexList & vertices,SkArenaAlloc & alloc)1371 Poly* tessellate(const VertexList& vertices, SkArenaAlloc& alloc) {
1372 LOG("tessellating simple polygons\n");
1373 EdgeList activeEdges;
1374 Poly* polys = nullptr;
1375 for (Vertex* v = vertices.fHead; v != nullptr; v = v->fNext) {
1376 if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) {
1377 continue;
1378 }
1379 #if LOGGING_ENABLED
1380 LOG("\nvertex %g: (%g,%g), alpha %d\n", v->fID, v->fPoint.fX, v->fPoint.fY, v->fAlpha);
1381 #endif
1382 Edge* leftEnclosingEdge;
1383 Edge* rightEnclosingEdge;
1384 find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
1385 Poly* leftPoly;
1386 Poly* rightPoly;
1387 if (v->fFirstEdgeAbove) {
1388 leftPoly = v->fFirstEdgeAbove->fLeftPoly;
1389 rightPoly = v->fLastEdgeAbove->fRightPoly;
1390 } else {
1391 leftPoly = leftEnclosingEdge ? leftEnclosingEdge->fRightPoly : nullptr;
1392 rightPoly = rightEnclosingEdge ? rightEnclosingEdge->fLeftPoly : nullptr;
1393 }
1394 #if LOGGING_ENABLED
1395 LOG("edges above:\n");
1396 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
1397 LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID,
1398 e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRightPoly->fID : -1);
1399 }
1400 LOG("edges below:\n");
1401 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1402 LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID,
1403 e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRightPoly->fID : -1);
1404 }
1405 #endif
1406 if (v->fFirstEdgeAbove) {
1407 if (leftPoly) {
1408 leftPoly = leftPoly->addEdge(v->fFirstEdgeAbove, Poly::kRight_Side, alloc);
1409 }
1410 if (rightPoly) {
1411 rightPoly = rightPoly->addEdge(v->fLastEdgeAbove, Poly::kLeft_Side, alloc);
1412 }
1413 for (Edge* e = v->fFirstEdgeAbove; e != v->fLastEdgeAbove; e = e->fNextEdgeAbove) {
1414 Edge* rightEdge = e->fNextEdgeAbove;
1415 remove_edge(e, &activeEdges);
1416 if (e->fRightPoly) {
1417 e->fRightPoly->addEdge(e, Poly::kLeft_Side, alloc);
1418 }
1419 if (rightEdge->fLeftPoly && rightEdge->fLeftPoly != e->fRightPoly) {
1420 rightEdge->fLeftPoly->addEdge(e, Poly::kRight_Side, alloc);
1421 }
1422 }
1423 remove_edge(v->fLastEdgeAbove, &activeEdges);
1424 if (!v->fFirstEdgeBelow) {
1425 if (leftPoly && rightPoly && leftPoly != rightPoly) {
1426 SkASSERT(leftPoly->fPartner == nullptr && rightPoly->fPartner == nullptr);
1427 rightPoly->fPartner = leftPoly;
1428 leftPoly->fPartner = rightPoly;
1429 }
1430 }
1431 }
1432 if (v->fFirstEdgeBelow) {
1433 if (!v->fFirstEdgeAbove) {
1434 if (leftPoly && rightPoly) {
1435 if (leftPoly == rightPoly) {
1436 if (leftPoly->fTail && leftPoly->fTail->fSide == Poly::kLeft_Side) {
1437 leftPoly = new_poly(&polys, leftPoly->lastVertex(),
1438 leftPoly->fWinding, alloc);
1439 leftEnclosingEdge->fRightPoly = leftPoly;
1440 } else {
1441 rightPoly = new_poly(&polys, rightPoly->lastVertex(),
1442 rightPoly->fWinding, alloc);
1443 rightEnclosingEdge->fLeftPoly = rightPoly;
1444 }
1445 }
1446 Edge* join = alloc.make<Edge>(leftPoly->lastVertex(), v, 1, Edge::Type::kInner);
1447 leftPoly = leftPoly->addEdge(join, Poly::kRight_Side, alloc);
1448 rightPoly = rightPoly->addEdge(join, Poly::kLeft_Side, alloc);
1449 }
1450 }
1451 Edge* leftEdge = v->fFirstEdgeBelow;
1452 leftEdge->fLeftPoly = leftPoly;
1453 insert_edge(leftEdge, leftEnclosingEdge, &activeEdges);
1454 for (Edge* rightEdge = leftEdge->fNextEdgeBelow; rightEdge;
1455 rightEdge = rightEdge->fNextEdgeBelow) {
1456 insert_edge(rightEdge, leftEdge, &activeEdges);
1457 int winding = leftEdge->fLeftPoly ? leftEdge->fLeftPoly->fWinding : 0;
1458 winding += leftEdge->fWinding;
1459 if (winding != 0) {
1460 Poly* poly = new_poly(&polys, v, winding, alloc);
1461 leftEdge->fRightPoly = rightEdge->fLeftPoly = poly;
1462 }
1463 leftEdge = rightEdge;
1464 }
1465 v->fLastEdgeBelow->fRightPoly = rightPoly;
1466 }
1467 #if LOGGING_ENABLED
1468 LOG("\nactive edges:\n");
1469 for (Edge* e = activeEdges.fHead; e != nullptr; e = e->fRight) {
1470 LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID,
1471 e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRightPoly->fID : -1);
1472 }
1473 #endif
1474 }
1475 return polys;
1476 }
1477
remove_non_boundary_edges(const VertexList & mesh,SkPath::FillType fillType,SkArenaAlloc & alloc)1478 void remove_non_boundary_edges(const VertexList& mesh, SkPath::FillType fillType,
1479 SkArenaAlloc& alloc) {
1480 LOG("removing non-boundary edges\n");
1481 EdgeList activeEdges;
1482 for (Vertex* v = mesh.fHead; v != nullptr; v = v->fNext) {
1483 if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) {
1484 continue;
1485 }
1486 Edge* leftEnclosingEdge;
1487 Edge* rightEnclosingEdge;
1488 find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
1489 bool prevFilled = leftEnclosingEdge &&
1490 apply_fill_type(fillType, leftEnclosingEdge->fWinding);
1491 for (Edge* e = v->fFirstEdgeAbove; e;) {
1492 Edge* next = e->fNextEdgeAbove;
1493 remove_edge(e, &activeEdges);
1494 bool filled = apply_fill_type(fillType, e->fWinding);
1495 if (filled == prevFilled) {
1496 disconnect(e);
1497 }
1498 prevFilled = filled;
1499 e = next;
1500 }
1501 Edge* prev = leftEnclosingEdge;
1502 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1503 if (prev) {
1504 e->fWinding += prev->fWinding;
1505 }
1506 insert_edge(e, prev, &activeEdges);
1507 prev = e;
1508 }
1509 }
1510 }
1511
1512 // Note: this is the normal to the edge, but not necessarily unit length.
get_edge_normal(const Edge * e,SkVector * normal)1513 void get_edge_normal(const Edge* e, SkVector* normal) {
1514 normal->set(SkDoubleToScalar(e->fLine.fA) * e->fWinding,
1515 SkDoubleToScalar(e->fLine.fB) * e->fWinding);
1516 }
1517
1518 // Stage 5c: detect and remove "pointy" vertices whose edge normals point in opposite directions
1519 // and whose adjacent vertices are less than a quarter pixel from an edge. These are guaranteed to
1520 // invert on stroking.
1521
simplify_boundary(EdgeList * boundary,Comparator & c,SkArenaAlloc & alloc)1522 void simplify_boundary(EdgeList* boundary, Comparator& c, SkArenaAlloc& alloc) {
1523 Edge* prevEdge = boundary->fTail;
1524 SkVector prevNormal;
1525 get_edge_normal(prevEdge, &prevNormal);
1526 for (Edge* e = boundary->fHead; e != nullptr;) {
1527 Vertex* prev = prevEdge->fWinding == 1 ? prevEdge->fTop : prevEdge->fBottom;
1528 Vertex* next = e->fWinding == 1 ? e->fBottom : e->fTop;
1529 double dist = e->dist(prev->fPoint);
1530 SkVector normal;
1531 get_edge_normal(e, &normal);
1532 double denom = 0.0625f * e->fLine.magSq();
1533 if (prevNormal.dot(normal) < 0.0 && (dist * dist) <= denom) {
1534 Edge* join = new_edge(prev, next, Edge::Type::kInner, c, alloc);
1535 insert_edge(join, e, boundary);
1536 remove_edge(prevEdge, boundary);
1537 remove_edge(e, boundary);
1538 if (join->fLeft && join->fRight) {
1539 prevEdge = join->fLeft;
1540 e = join;
1541 } else {
1542 prevEdge = boundary->fTail;
1543 e = boundary->fHead; // join->fLeft ? join->fLeft : join;
1544 }
1545 get_edge_normal(prevEdge, &prevNormal);
1546 } else {
1547 prevEdge = e;
1548 prevNormal = normal;
1549 e = e->fRight;
1550 }
1551 }
1552 }
1553
fix_inversions(Vertex * prev,Vertex * next,Edge * prevBisector,Edge * nextBisector,Edge * prevEdge,Comparator & c)1554 void fix_inversions(Vertex* prev, Vertex* next, Edge* prevBisector, Edge* nextBisector,
1555 Edge* prevEdge, Comparator& c) {
1556 if (!prev || !next) {
1557 return;
1558 }
1559 int winding = c.sweep_lt(prev->fPoint, next->fPoint) ? 1 : -1;
1560 SkPoint p;
1561 uint8_t alpha;
1562 if (winding != prevEdge->fWinding && prevBisector->intersect(*nextBisector, &p, &alpha)) {
1563 prev->fPoint = next->fPoint = p;
1564 prev->fAlpha = next->fAlpha = alpha;
1565 }
1566 }
1567
1568 // Stage 5d: Displace edges by half a pixel inward and outward along their normals. Intersect to
1569 // find new vertices, and set zero alpha on the exterior and one alpha on the interior. Build a
1570 // new antialiased mesh from those vertices.
1571
stroke_boundary(EdgeList * boundary,VertexList * innerMesh,VertexList * outerMesh,Comparator & c,SkArenaAlloc & alloc)1572 void stroke_boundary(EdgeList* boundary, VertexList* innerMesh, VertexList* outerMesh,
1573 Comparator& c, SkArenaAlloc& alloc) {
1574 // A boundary with fewer than 3 edges is degenerate.
1575 if (!boundary->fHead || !boundary->fHead->fRight || !boundary->fHead->fRight->fRight) {
1576 return;
1577 }
1578 Edge* prevEdge = boundary->fTail;
1579 float radius = 0.5f;
1580 double offset = radius * sqrt(prevEdge->fLine.magSq()) * prevEdge->fWinding;
1581 Line prevInner(prevEdge->fLine);
1582 prevInner.fC -= offset;
1583 Line prevOuter(prevEdge->fLine);
1584 prevOuter.fC += offset;
1585 VertexList innerVertices;
1586 VertexList outerVertices;
1587 Edge* prevBisector = nullptr;
1588 for (Edge* e = boundary->fHead; e != nullptr; e = e->fRight) {
1589 double offset = radius * sqrt(e->fLine.magSq()) * e->fWinding;
1590 Line inner(e->fLine);
1591 inner.fC -= offset;
1592 Line outer(e->fLine);
1593 outer.fC += offset;
1594 SkPoint innerPoint, outerPoint;
1595 if (prevInner.intersect(inner, &innerPoint) &&
1596 prevOuter.intersect(outer, &outerPoint)) {
1597 Vertex* innerVertex = alloc.make<Vertex>(innerPoint, 255);
1598 Vertex* outerVertex = alloc.make<Vertex>(outerPoint, 0);
1599 Edge* bisector = new_edge(outerVertex, innerVertex, Edge::Type::kConnector, c, alloc);
1600 fix_inversions(innerVertices.fTail, innerVertex, prevBisector, bisector, prevEdge, c);
1601 fix_inversions(outerVertices.fTail, outerVertex, prevBisector, bisector, prevEdge, c);
1602 innerVertex->fPartner = outerVertex;
1603 outerVertex->fPartner = innerVertex;
1604 innerVertices.append(innerVertex);
1605 outerVertices.append(outerVertex);
1606 prevBisector = bisector;
1607 }
1608 prevInner = inner;
1609 prevOuter = outer;
1610 prevEdge = e;
1611 }
1612
1613 Vertex* innerVertex = innerVertices.fHead;
1614 Vertex* outerVertex = outerVertices.fHead;
1615 if (!innerVertex || !outerVertex) {
1616 return;
1617 }
1618 Edge* bisector = new_edge(outerVertices.fHead, innerVertices.fHead, Edge::Type::kConnector, c,
1619 alloc);
1620 fix_inversions(innerVertices.fTail, innerVertices.fHead, prevBisector, bisector, prevEdge, c);
1621 fix_inversions(outerVertices.fTail, outerVertices.fHead, prevBisector, bisector, prevEdge, c);
1622 Vertex* prevInnerVertex = innerVertices.fTail;
1623 Vertex* prevOuterVertex = outerVertices.fTail;
1624 while (innerVertex && outerVertex) {
1625 // Connect vertices into a quad mesh. Outer edges get default (1) winding.
1626 // Inner edges get -2 winding. This ensures that the interior is always filled
1627 // (-1 winding number for normal cases, 3 for thin features where the interior inverts).
1628 connect(prevOuterVertex, outerVertex, Edge::Type::kOuter, c, alloc);
1629 connect(prevInnerVertex, innerVertex, Edge::Type::kInner, c, alloc, -2);
1630 prevInnerVertex = innerVertex;
1631 prevOuterVertex = outerVertex;
1632 innerVertex = innerVertex->fNext;
1633 outerVertex = outerVertex->fNext;
1634 }
1635 innerMesh->append(innerVertices);
1636 outerMesh->append(outerVertices);
1637 }
1638
extract_boundary(EdgeList * boundary,Edge * e,SkPath::FillType fillType,SkArenaAlloc & alloc)1639 void extract_boundary(EdgeList* boundary, Edge* e, SkPath::FillType fillType, SkArenaAlloc& alloc) {
1640 bool down = apply_fill_type(fillType, e->fWinding);
1641 while (e) {
1642 e->fWinding = down ? 1 : -1;
1643 Edge* next;
1644 boundary->append(e);
1645 if (down) {
1646 // Find outgoing edge, in clockwise order.
1647 if ((next = e->fNextEdgeAbove)) {
1648 down = false;
1649 } else if ((next = e->fBottom->fLastEdgeBelow)) {
1650 down = true;
1651 } else if ((next = e->fPrevEdgeAbove)) {
1652 down = false;
1653 }
1654 } else {
1655 // Find outgoing edge, in counter-clockwise order.
1656 if ((next = e->fPrevEdgeBelow)) {
1657 down = true;
1658 } else if ((next = e->fTop->fFirstEdgeAbove)) {
1659 down = false;
1660 } else if ((next = e->fNextEdgeBelow)) {
1661 down = true;
1662 }
1663 }
1664 disconnect(e);
1665 e = next;
1666 }
1667 }
1668
1669 // Stage 5b: Extract boundaries from mesh, simplify and stroke them into a new mesh.
1670
extract_boundaries(const VertexList & inMesh,VertexList * innerVertices,VertexList * outerVertices,SkPath::FillType fillType,Comparator & c,SkArenaAlloc & alloc)1671 void extract_boundaries(const VertexList& inMesh, VertexList* innerVertices,
1672 VertexList* outerVertices, SkPath::FillType fillType,
1673 Comparator& c, SkArenaAlloc& alloc) {
1674 remove_non_boundary_edges(inMesh, fillType, alloc);
1675 for (Vertex* v = inMesh.fHead; v; v = v->fNext) {
1676 while (v->fFirstEdgeBelow) {
1677 EdgeList boundary;
1678 extract_boundary(&boundary, v->fFirstEdgeBelow, fillType, alloc);
1679 simplify_boundary(&boundary, c, alloc);
1680 stroke_boundary(&boundary, innerVertices, outerVertices, c, alloc);
1681 }
1682 }
1683 }
1684
1685 // This is a driver function that calls stages 2-5 in turn.
1686
contours_to_mesh(VertexList * contours,int contourCnt,bool antialias,VertexList * mesh,Comparator & c,SkArenaAlloc & alloc)1687 void contours_to_mesh(VertexList* contours, int contourCnt, bool antialias,
1688 VertexList* mesh, Comparator& c, SkArenaAlloc& alloc) {
1689 #if LOGGING_ENABLED
1690 for (int i = 0; i < contourCnt; ++i) {
1691 Vertex* v = contours[i].fHead;
1692 SkASSERT(v);
1693 LOG("path.moveTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY);
1694 for (v = v->fNext; v; v = v->fNext) {
1695 LOG("path.lineTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY);
1696 }
1697 }
1698 #endif
1699 sanitize_contours(contours, contourCnt, antialias);
1700 build_edges(contours, contourCnt, mesh, c, alloc);
1701 }
1702
sort_mesh(VertexList * vertices,Comparator & c,SkArenaAlloc & alloc)1703 void sort_mesh(VertexList* vertices, Comparator& c, SkArenaAlloc& alloc) {
1704 if (!vertices || !vertices->fHead) {
1705 return;
1706 }
1707
1708 // Sort vertices in Y (secondarily in X).
1709 if (c.fDirection == Comparator::Direction::kHorizontal) {
1710 merge_sort<sweep_lt_horiz>(vertices);
1711 } else {
1712 merge_sort<sweep_lt_vert>(vertices);
1713 }
1714 #if LOGGING_ENABLED
1715 for (Vertex* v = vertices->fHead; v != nullptr; v = v->fNext) {
1716 static float gID = 0.0f;
1717 v->fID = gID++;
1718 }
1719 #endif
1720 }
1721
contours_to_polys(VertexList * contours,int contourCnt,SkPath::FillType fillType,const SkRect & pathBounds,bool antialias,VertexList * outerMesh,SkArenaAlloc & alloc)1722 Poly* contours_to_polys(VertexList* contours, int contourCnt, SkPath::FillType fillType,
1723 const SkRect& pathBounds, bool antialias, VertexList* outerMesh,
1724 SkArenaAlloc& alloc) {
1725 Comparator c(pathBounds.width() > pathBounds.height() ? Comparator::Direction::kHorizontal
1726 : Comparator::Direction::kVertical);
1727 VertexList mesh;
1728 contours_to_mesh(contours, contourCnt, antialias, &mesh, c, alloc);
1729 sort_mesh(&mesh, c, alloc);
1730 merge_coincident_vertices(&mesh, c, alloc);
1731 simplify(&mesh, c, alloc);
1732 if (antialias) {
1733 VertexList innerMesh;
1734 extract_boundaries(mesh, &innerMesh, outerMesh, fillType, c, alloc);
1735 sort_mesh(&innerMesh, c, alloc);
1736 sort_mesh(outerMesh, c, alloc);
1737 if (is_complex(innerMesh) || is_complex(*outerMesh)) {
1738 LOG("found complex mesh; taking slow path\n");
1739 VertexList aaMesh;
1740 connect_partners(outerMesh, c, alloc);
1741 sorted_merge(&innerMesh, outerMesh, &aaMesh, c);
1742 merge_coincident_vertices(&aaMesh, c, alloc);
1743 simplify(&aaMesh, c, alloc);
1744 outerMesh->fHead = outerMesh->fTail = nullptr;
1745 return tessellate(aaMesh, alloc);
1746 } else {
1747 LOG("no complex polygons; taking fast path\n");
1748 merge_coincident_vertices(&innerMesh, c, alloc);
1749 return tessellate(innerMesh, alloc);
1750 }
1751 } else {
1752 return tessellate(mesh, alloc);
1753 }
1754 }
1755
1756 // Stage 6: Triangulate the monotone polygons into a vertex buffer.
polys_to_triangles(Poly * polys,SkPath::FillType fillType,const AAParams * aaParams,void * data)1757 void* polys_to_triangles(Poly* polys, SkPath::FillType fillType, const AAParams* aaParams,
1758 void* data) {
1759 for (Poly* poly = polys; poly; poly = poly->fNext) {
1760 if (apply_fill_type(fillType, poly)) {
1761 data = poly->emit(aaParams, data);
1762 }
1763 }
1764 return data;
1765 }
1766
path_to_polys(const SkPath & path,SkScalar tolerance,const SkRect & clipBounds,int contourCnt,SkArenaAlloc & alloc,bool antialias,bool * isLinear,VertexList * outerMesh)1767 Poly* path_to_polys(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
1768 int contourCnt, SkArenaAlloc& alloc, bool antialias, bool* isLinear,
1769 VertexList* outerMesh) {
1770 SkPath::FillType fillType = path.getFillType();
1771 if (SkPath::IsInverseFillType(fillType)) {
1772 contourCnt++;
1773 }
1774 std::unique_ptr<VertexList[]> contours(new VertexList[contourCnt]);
1775
1776 path_to_contours(path, tolerance, clipBounds, contours.get(), alloc, isLinear);
1777 return contours_to_polys(contours.get(), contourCnt, path.getFillType(), path.getBounds(),
1778 antialias, outerMesh, alloc);
1779 }
1780
get_contour_count(const SkPath & path,SkScalar tolerance)1781 int get_contour_count(const SkPath& path, SkScalar tolerance) {
1782 int contourCnt;
1783 int maxPts = GrPathUtils::worstCasePointCount(path, &contourCnt, tolerance);
1784 if (maxPts <= 0) {
1785 return 0;
1786 }
1787 if (maxPts > ((int)SK_MaxU16 + 1)) {
1788 SkDebugf("Path not rendered, too many verts (%d)\n", maxPts);
1789 return 0;
1790 }
1791 return contourCnt;
1792 }
1793
count_points(Poly * polys,SkPath::FillType fillType)1794 int count_points(Poly* polys, SkPath::FillType fillType) {
1795 int count = 0;
1796 for (Poly* poly = polys; poly; poly = poly->fNext) {
1797 if (apply_fill_type(fillType, poly) && poly->fCount >= 3) {
1798 count += (poly->fCount - 2) * (TESSELLATOR_WIREFRAME ? 6 : 3);
1799 }
1800 }
1801 return count;
1802 }
1803
count_outer_mesh_points(const VertexList & outerMesh)1804 int count_outer_mesh_points(const VertexList& outerMesh) {
1805 int count = 0;
1806 for (Vertex* v = outerMesh.fHead; v; v = v->fNext) {
1807 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1808 count += TESSELLATOR_WIREFRAME ? 12 : 6;
1809 }
1810 }
1811 return count;
1812 }
1813
outer_mesh_to_triangles(const VertexList & outerMesh,const AAParams * aaParams,void * data)1814 void* outer_mesh_to_triangles(const VertexList& outerMesh, const AAParams* aaParams, void* data) {
1815 for (Vertex* v = outerMesh.fHead; v; v = v->fNext) {
1816 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1817 Vertex* v0 = e->fTop;
1818 Vertex* v1 = e->fBottom;
1819 Vertex* v2 = e->fBottom->fPartner;
1820 Vertex* v3 = e->fTop->fPartner;
1821 data = emit_triangle(v0, v1, v2, aaParams, data);
1822 data = emit_triangle(v0, v2, v3, aaParams, data);
1823 }
1824 }
1825 return data;
1826 }
1827
1828 } // namespace
1829
1830 namespace GrTessellator {
1831
1832 // Stage 6: Triangulate the monotone polygons into a vertex buffer.
1833
PathToTriangles(const SkPath & path,SkScalar tolerance,const SkRect & clipBounds,VertexAllocator * vertexAllocator,bool antialias,const GrColor & color,bool canTweakAlphaForCoverage,bool * isLinear)1834 int PathToTriangles(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
1835 VertexAllocator* vertexAllocator, bool antialias, const GrColor& color,
1836 bool canTweakAlphaForCoverage, bool* isLinear) {
1837 int contourCnt = get_contour_count(path, tolerance);
1838 if (contourCnt <= 0) {
1839 *isLinear = true;
1840 return 0;
1841 }
1842 SkArenaAlloc alloc(kArenaChunkSize);
1843 VertexList outerMesh;
1844 Poly* polys = path_to_polys(path, tolerance, clipBounds, contourCnt, alloc, antialias,
1845 isLinear, &outerMesh);
1846 SkPath::FillType fillType = antialias ? SkPath::kWinding_FillType : path.getFillType();
1847 int count = count_points(polys, fillType);
1848 if (antialias) {
1849 count += count_outer_mesh_points(outerMesh);
1850 }
1851 if (0 == count) {
1852 return 0;
1853 }
1854
1855 void* verts = vertexAllocator->lock(count);
1856 if (!verts) {
1857 SkDebugf("Could not allocate vertices\n");
1858 return 0;
1859 }
1860
1861 LOG("emitting %d verts\n", count);
1862 AAParams aaParams;
1863 aaParams.fTweakAlpha = canTweakAlphaForCoverage;
1864 aaParams.fColor = color;
1865
1866 void* end = polys_to_triangles(polys, fillType, antialias ? &aaParams : nullptr, verts);
1867 end = outer_mesh_to_triangles(outerMesh, &aaParams, end);
1868 int actualCount = static_cast<int>((static_cast<uint8_t*>(end) - static_cast<uint8_t*>(verts))
1869 / vertexAllocator->stride());
1870 SkASSERT(actualCount <= count);
1871 vertexAllocator->unlock(actualCount);
1872 return actualCount;
1873 }
1874
PathToVertices(const SkPath & path,SkScalar tolerance,const SkRect & clipBounds,GrTessellator::WindingVertex ** verts)1875 int PathToVertices(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
1876 GrTessellator::WindingVertex** verts) {
1877 int contourCnt = get_contour_count(path, tolerance);
1878 if (contourCnt <= 0) {
1879 return 0;
1880 }
1881 SkArenaAlloc alloc(kArenaChunkSize);
1882 bool isLinear;
1883 Poly* polys = path_to_polys(path, tolerance, clipBounds, contourCnt, alloc, false, &isLinear,
1884 nullptr);
1885 SkPath::FillType fillType = path.getFillType();
1886 int count = count_points(polys, fillType);
1887 if (0 == count) {
1888 *verts = nullptr;
1889 return 0;
1890 }
1891
1892 *verts = new GrTessellator::WindingVertex[count];
1893 GrTessellator::WindingVertex* vertsEnd = *verts;
1894 SkPoint* points = new SkPoint[count];
1895 SkPoint* pointsEnd = points;
1896 for (Poly* poly = polys; poly; poly = poly->fNext) {
1897 if (apply_fill_type(fillType, poly)) {
1898 SkPoint* start = pointsEnd;
1899 pointsEnd = static_cast<SkPoint*>(poly->emit(nullptr, pointsEnd));
1900 while (start != pointsEnd) {
1901 vertsEnd->fPos = *start;
1902 vertsEnd->fWinding = poly->fWinding;
1903 ++start;
1904 ++vertsEnd;
1905 }
1906 }
1907 }
1908 int actualCount = static_cast<int>(vertsEnd - *verts);
1909 SkASSERT(actualCount <= count);
1910 SkASSERT(pointsEnd - points == actualCount);
1911 delete[] points;
1912 return actualCount;
1913 }
1914
1915 } // namespace
1916