• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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