• 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 "src/gpu/GrTessellator.h"
9 
10 #include "src/gpu/GrDefaultGeoProcFactory.h"
11 #include "src/gpu/GrEagerVertexAllocator.h"
12 #include "src/gpu/GrVertexWriter.h"
13 #include "src/gpu/geometry/GrPathUtils.h"
14 
15 #include "include/core/SkPath.h"
16 #include "src/core/SkArenaAlloc.h"
17 #include "src/core/SkGeometry.h"
18 #include "src/core/SkPointPriv.h"
19 
20 #include <algorithm>
21 #include <cstdio>
22 #include <queue>
23 #include <unordered_map>
24 #include <utility>
25 
26 /*
27  * There are six stages to the basic algorithm:
28  *
29  * 1) Linearize the path contours into piecewise linear segments (path_to_contours()).
30  * 2) Build a mesh of edges connecting the vertices (build_edges()).
31  * 3) Sort the vertices in Y (and secondarily in X) (merge_sort()).
32  * 4) Simplify the mesh by inserting new vertices at intersecting edges (simplify()).
33  * 5) Tessellate the simplified mesh into monotone polygons (tessellate()).
34  * 6) Triangulate the monotone polygons directly into a vertex buffer (polys_to_triangles()).
35  *
36  * For screenspace antialiasing, the algorithm is modified as follows:
37  *
38  * Run steps 1-5 above to produce polygons.
39  * 5b) Apply fill rules to extract boundary contours from the polygons (extract_boundaries()).
40  * 5c) Simplify boundaries to remove "pointy" vertices that cause inversions (simplify_boundary()).
41  * 5d) Displace edges by half a pixel inward and outward along their normals. Intersect to find
42  *     new vertices, and set zero alpha on the exterior and one alpha on the interior. Build a new
43  *     antialiased mesh from those vertices (stroke_boundary()).
44  * Run steps 3-6 above on the new mesh, and produce antialiased triangles.
45  *
46  * The vertex sorting in step (3) is a merge sort, since it plays well with the linked list
47  * of vertices (and the necessity of inserting new vertices on intersection).
48  *
49  * Stages (4) and (5) use an active edge list -- a list of all edges for which the
50  * sweep line has crossed the top vertex, but not the bottom vertex.  It's sorted
51  * left-to-right based on the point where both edges are active (when both top vertices
52  * have been seen, so the "lower" top vertex of the two). If the top vertices are equal
53  * (shared), it's sorted based on the last point where both edges are active, so the
54  * "upper" bottom vertex.
55  *
56  * The most complex step is the simplification (4). It's based on the Bentley-Ottman
57  * line-sweep algorithm, but due to floating point inaccuracy, the intersection points are
58  * not exact and may violate the mesh topology or active edge list ordering. We
59  * accommodate this by adjusting the topology of the mesh and AEL to match the intersection
60  * points. This occurs in two ways:
61  *
62  * A) Intersections may cause a shortened edge to no longer be ordered with respect to its
63  *    neighbouring edges at the top or bottom vertex. This is handled by merging the
64  *    edges (merge_collinear_edges()).
65  * B) Intersections may cause an edge to violate the left-to-right ordering of the
66  *    active edge list. This is handled by detecting potential violations and rewinding
67  *    the active edge list to the vertex before they occur (rewind() during merging,
68  *    rewind_if_necessary() during splitting).
69  *
70  * The tessellation steps (5) and (6) are based on "Triangulating Simple Polygons and
71  * Equivalent Problems" (Fournier and Montuno); also a line-sweep algorithm. Note that it
72  * currently uses a linked list for the active edge list, rather than a 2-3 tree as the
73  * paper describes. The 2-3 tree gives O(lg N) lookups, but insertion and removal also
74  * become O(lg N). In all the test cases, it was found that the cost of frequent O(lg N)
75  * insertions and removals was greater than the cost of infrequent O(N) lookups with the
76  * linked list implementation. With the latter, all removals are O(1), and most insertions
77  * are O(1), since we know the adjacent edge in the active edge list based on the topology.
78  * Only type 2 vertices (see paper) require the O(N) lookups, and these are much less
79  * frequent. There may be other data structures worth investigating, however.
80  *
81  * Note that the orientation of the line sweep algorithms is determined by the aspect ratio of the
82  * path bounds. When the path is taller than it is wide, we sort vertices based on increasing Y
83  * coordinate, and secondarily by increasing X coordinate. When the path is wider than it is tall,
84  * we sort by increasing X coordinate, but secondarily by *decreasing* Y coordinate. This is so
85  * that the "left" and "right" orientation in the code remains correct (edges to the left are
86  * increasing in Y; edges to the right are decreasing in Y). That is, the setting rotates 90
87  * degrees counterclockwise, rather that transposing.
88  */
89 
90 #define LOGGING_ENABLED 0
91 
92 #if LOGGING_ENABLED
93 #define TESS_LOG printf
94 #else
95 #define TESS_LOG(...)
96 #endif
97 
98 namespace {
99 
100 using GrTessellator::Mode;
101 
102 const int kArenaChunkSize = 16 * 1024;
103 const float kCosMiterAngle = 0.97f; // Corresponds to an angle of ~14 degrees.
104 
105 struct Vertex;
106 struct Edge;
107 struct Event;
108 struct Poly;
109 
110 template <class T, T* T::*Prev, T* T::*Next>
list_insert(T * t,T * prev,T * next,T ** head,T ** tail)111 void list_insert(T* t, T* prev, T* next, T** head, T** tail) {
112     t->*Prev = prev;
113     t->*Next = next;
114     if (prev) {
115         prev->*Next = t;
116     } else if (head) {
117         *head = t;
118     }
119     if (next) {
120         next->*Prev = t;
121     } else if (tail) {
122         *tail = t;
123     }
124 }
125 
126 template <class T, T* T::*Prev, T* T::*Next>
list_remove(T * t,T ** head,T ** tail)127 void list_remove(T* t, T** head, T** tail) {
128     if (t->*Prev) {
129         t->*Prev->*Next = t->*Next;
130     } else if (head) {
131         *head = t->*Next;
132     }
133     if (t->*Next) {
134         t->*Next->*Prev = t->*Prev;
135     } else if (tail) {
136         *tail = t->*Prev;
137     }
138     t->*Prev = t->*Next = nullptr;
139 }
140 
141 /**
142  * Vertices are used in three ways: first, the path contours are converted into a
143  * circularly-linked list of Vertices for each contour. After edge construction, the same Vertices
144  * are re-ordered by the merge sort according to the sweep_lt comparator (usually, increasing
145  * in Y) using the same fPrev/fNext pointers that were used for the contours, to avoid
146  * reallocation. Finally, MonotonePolys are built containing a circularly-linked list of
147  * Vertices. (Currently, those Vertices are newly-allocated for the MonotonePolys, since
148  * an individual Vertex from the path mesh may belong to multiple
149  * MonotonePolys, so the original Vertices cannot be re-used.
150  */
151 
152 struct Vertex {
Vertex__anon8dd090a10111::Vertex153   Vertex(const SkPoint& point, uint8_t alpha)
154     : fPoint(point), fPrev(nullptr), fNext(nullptr)
155     , fFirstEdgeAbove(nullptr), fLastEdgeAbove(nullptr)
156     , fFirstEdgeBelow(nullptr), fLastEdgeBelow(nullptr)
157     , fLeftEnclosingEdge(nullptr), fRightEnclosingEdge(nullptr)
158     , fPartner(nullptr)
159     , fAlpha(alpha)
160     , fSynthetic(false)
161 #if LOGGING_ENABLED
162     , fID (-1.0f)
163 #endif
164     {}
165     SkPoint fPoint;               // Vertex position
166     Vertex* fPrev;                // Linked list of contours, then Y-sorted vertices.
167     Vertex* fNext;                // "
168     Edge*   fFirstEdgeAbove;      // Linked list of edges above this vertex.
169     Edge*   fLastEdgeAbove;       // "
170     Edge*   fFirstEdgeBelow;      // Linked list of edges below this vertex.
171     Edge*   fLastEdgeBelow;       // "
172     Edge*   fLeftEnclosingEdge;   // Nearest edge in the AEL left of this vertex.
173     Edge*   fRightEnclosingEdge;  // Nearest edge in the AEL right of this vertex.
174     Vertex* fPartner;             // Corresponding inner or outer vertex (for AA).
175     uint8_t fAlpha;
176     bool    fSynthetic;           // Is this a synthetic vertex?
177 #if LOGGING_ENABLED
178     float   fID;                  // Identifier used for logging.
179 #endif
180 };
181 
182 /***************************************************************************************/
183 
184 typedef bool (*CompareFunc)(const SkPoint& a, const SkPoint& b);
185 
sweep_lt_horiz(const SkPoint & a,const SkPoint & b)186 bool sweep_lt_horiz(const SkPoint& a, const SkPoint& b) {
187     return a.fX < b.fX || (a.fX == b.fX && a.fY > b.fY);
188 }
189 
sweep_lt_vert(const SkPoint & a,const SkPoint & b)190 bool sweep_lt_vert(const SkPoint& a, const SkPoint& b) {
191     return a.fY < b.fY || (a.fY == b.fY && a.fX < b.fX);
192 }
193 
194 struct Comparator {
195     enum class Direction { kVertical, kHorizontal };
Comparator__anon8dd090a10111::Comparator196     Comparator(Direction direction) : fDirection(direction) {}
sweep_lt__anon8dd090a10111::Comparator197     bool sweep_lt(const SkPoint& a, const SkPoint& b) const {
198         return fDirection == Direction::kHorizontal ? sweep_lt_horiz(a, b) : sweep_lt_vert(a, b);
199     }
200     Direction fDirection;
201 };
202 
emit_vertex(Vertex * v,bool emitCoverage,void * data)203 inline void* emit_vertex(Vertex* v, bool emitCoverage, void* data) {
204     GrVertexWriter verts{data};
205     verts.write(v->fPoint);
206 
207     if (emitCoverage) {
208         verts.write(GrNormalizeByteToFloat(v->fAlpha));
209     }
210 
211     return verts.fPtr;
212 }
213 
emit_triangle(Vertex * v0,Vertex * v1,Vertex * v2,bool emitCoverage,void * data)214 void* emit_triangle(Vertex* v0, Vertex* v1, Vertex* v2, bool emitCoverage, void* data) {
215     TESS_LOG("emit_triangle %g (%g, %g) %d\n", v0->fID, v0->fPoint.fX, v0->fPoint.fY, v0->fAlpha);
216     TESS_LOG("              %g (%g, %g) %d\n", v1->fID, v1->fPoint.fX, v1->fPoint.fY, v1->fAlpha);
217     TESS_LOG("              %g (%g, %g) %d\n", v2->fID, v2->fPoint.fX, v2->fPoint.fY, v2->fAlpha);
218 #if TESSELLATOR_WIREFRAME
219     data = emit_vertex(v0, emitCoverage, data);
220     data = emit_vertex(v1, emitCoverage, data);
221     data = emit_vertex(v1, emitCoverage, data);
222     data = emit_vertex(v2, emitCoverage, data);
223     data = emit_vertex(v2, emitCoverage, data);
224     data = emit_vertex(v0, emitCoverage, data);
225 #else
226     data = emit_vertex(v0, emitCoverage, data);
227     data = emit_vertex(v1, emitCoverage, data);
228     data = emit_vertex(v2, emitCoverage, data);
229 #endif
230     return data;
231 }
232 
233 struct VertexList {
VertexList__anon8dd090a10111::VertexList234     VertexList() : fHead(nullptr), fTail(nullptr) {}
VertexList__anon8dd090a10111::VertexList235     VertexList(Vertex* head, Vertex* tail) : fHead(head), fTail(tail) {}
236     Vertex* fHead;
237     Vertex* fTail;
insert__anon8dd090a10111::VertexList238     void insert(Vertex* v, Vertex* prev, Vertex* next) {
239         list_insert<Vertex, &Vertex::fPrev, &Vertex::fNext>(v, prev, next, &fHead, &fTail);
240     }
append__anon8dd090a10111::VertexList241     void append(Vertex* v) {
242         insert(v, fTail, nullptr);
243     }
append__anon8dd090a10111::VertexList244     void append(const VertexList& list) {
245         if (!list.fHead) {
246             return;
247         }
248         if (fTail) {
249             fTail->fNext = list.fHead;
250             list.fHead->fPrev = fTail;
251         } else {
252             fHead = list.fHead;
253         }
254         fTail = list.fTail;
255     }
prepend__anon8dd090a10111::VertexList256     void prepend(Vertex* v) {
257         insert(v, nullptr, fHead);
258     }
remove__anon8dd090a10111::VertexList259     void remove(Vertex* v) {
260         list_remove<Vertex, &Vertex::fPrev, &Vertex::fNext>(v, &fHead, &fTail);
261     }
close__anon8dd090a10111::VertexList262     void close() {
263         if (fHead && fTail) {
264             fTail->fNext = fHead;
265             fHead->fPrev = fTail;
266         }
267     }
268 };
269 
270 // Round to nearest quarter-pixel. This is used for screenspace tessellation.
271 
round(SkPoint * p)272 inline void round(SkPoint* p) {
273     p->fX = SkScalarRoundToScalar(p->fX * SkFloatToScalar(4.0f)) * SkFloatToScalar(0.25f);
274     p->fY = SkScalarRoundToScalar(p->fY * SkFloatToScalar(4.0f)) * SkFloatToScalar(0.25f);
275 }
276 
double_to_clamped_scalar(double d)277 inline SkScalar double_to_clamped_scalar(double d) {
278     return SkDoubleToScalar(std::min((double) SK_ScalarMax, std::max(d, (double) -SK_ScalarMax)));
279 }
280 
281 // A line equation in implicit form. fA * x + fB * y + fC = 0, for all points (x, y) on the line.
282 struct Line {
Line__anon8dd090a10111::Line283     Line(double a, double b, double c) : fA(a), fB(b), fC(c) {}
Line__anon8dd090a10111::Line284     Line(Vertex* p, Vertex* q) : Line(p->fPoint, q->fPoint) {}
Line__anon8dd090a10111::Line285     Line(const SkPoint& p, const SkPoint& q)
286         : fA(static_cast<double>(q.fY) - p.fY)      // a = dY
287         , fB(static_cast<double>(p.fX) - q.fX)      // b = -dX
288         , fC(static_cast<double>(p.fY) * q.fX -     // c = cross(q, p)
289              static_cast<double>(p.fX) * q.fY) {}
dist__anon8dd090a10111::Line290     double dist(const SkPoint& p) const {
291         return fA * p.fX + fB * p.fY + fC;
292     }
operator *__anon8dd090a10111::Line293     Line operator*(double v) const {
294         return Line(fA * v, fB * v, fC * v);
295     }
magSq__anon8dd090a10111::Line296     double magSq() const {
297         return fA * fA + fB * fB;
298     }
normalize__anon8dd090a10111::Line299     void normalize() {
300         double len = sqrt(this->magSq());
301         if (len == 0.0) {
302             return;
303         }
304         double scale = 1.0f / len;
305         fA *= scale;
306         fB *= scale;
307         fC *= scale;
308     }
nearParallel__anon8dd090a10111::Line309     bool nearParallel(const Line& o) const {
310         return fabs(o.fA - fA) < 0.00001 && fabs(o.fB - fB) < 0.00001;
311     }
312 
313     // Compute the intersection of two (infinite) Lines.
intersect__anon8dd090a10111::Line314     bool intersect(const Line& other, SkPoint* point) const {
315         double denom = fA * other.fB - fB * other.fA;
316         if (denom == 0.0) {
317             return false;
318         }
319         double scale = 1.0 / denom;
320         point->fX = double_to_clamped_scalar((fB * other.fC - other.fB * fC) * scale);
321         point->fY = double_to_clamped_scalar((other.fA * fC - fA * other.fC) * scale);
322         round(point);
323         return point->isFinite();
324     }
325     double fA, fB, fC;
326 };
327 
328 /**
329  * An Edge joins a top Vertex to a bottom Vertex. Edge ordering for the list of "edges above" and
330  * "edge below" a vertex as well as for the active edge list is handled by isLeftOf()/isRightOf().
331  * Note that an Edge will give occasionally dist() != 0 for its own endpoints (because floating
332  * point). For speed, that case is only tested by the callers that require it (e.g.,
333  * rewind_if_necessary()). Edges also handle checking for intersection with other edges.
334  * Currently, this converts the edges to the parametric form, in order to avoid doing a division
335  * until an intersection has been confirmed. This is slightly slower in the "found" case, but
336  * a lot faster in the "not found" case.
337  *
338  * The coefficients of the line equation stored in double precision to avoid catastrphic
339  * cancellation in the isLeftOf() and isRightOf() checks. Using doubles ensures that the result is
340  * correct in float, since it's a polynomial of degree 2. The intersect() function, being
341  * degree 5, is still subject to catastrophic cancellation. We deal with that by assuming its
342  * output may be incorrect, and adjusting the mesh topology to match (see comment at the top of
343  * this file).
344  */
345 
346 struct Edge {
347     enum class Type { kInner, kOuter, kConnector };
Edge__anon8dd090a10111::Edge348     Edge(Vertex* top, Vertex* bottom, int winding, Type type)
349         : fWinding(winding)
350         , fTop(top)
351         , fBottom(bottom)
352         , fType(type)
353         , fLeft(nullptr)
354         , fRight(nullptr)
355         , fPrevEdgeAbove(nullptr)
356         , fNextEdgeAbove(nullptr)
357         , fPrevEdgeBelow(nullptr)
358         , fNextEdgeBelow(nullptr)
359         , fLeftPoly(nullptr)
360         , fRightPoly(nullptr)
361         , fLeftPolyPrev(nullptr)
362         , fLeftPolyNext(nullptr)
363         , fRightPolyPrev(nullptr)
364         , fRightPolyNext(nullptr)
365         , fUsedInLeftPoly(false)
366         , fUsedInRightPoly(false)
367         , fLine(top, bottom) {
368         }
369     int      fWinding;          // 1 == edge goes downward; -1 = edge goes upward.
370     Vertex*  fTop;              // The top vertex in vertex-sort-order (sweep_lt).
371     Vertex*  fBottom;           // The bottom vertex in vertex-sort-order.
372     Type     fType;
373     Edge*    fLeft;             // The linked list of edges in the active edge list.
374     Edge*    fRight;            // "
375     Edge*    fPrevEdgeAbove;    // The linked list of edges in the bottom Vertex's "edges above".
376     Edge*    fNextEdgeAbove;    // "
377     Edge*    fPrevEdgeBelow;    // The linked list of edges in the top Vertex's "edges below".
378     Edge*    fNextEdgeBelow;    // "
379     Poly*    fLeftPoly;         // The Poly to the left of this edge, if any.
380     Poly*    fRightPoly;        // The Poly to the right of this edge, if any.
381     Edge*    fLeftPolyPrev;
382     Edge*    fLeftPolyNext;
383     Edge*    fRightPolyPrev;
384     Edge*    fRightPolyNext;
385     bool     fUsedInLeftPoly;
386     bool     fUsedInRightPoly;
387     Line     fLine;
dist__anon8dd090a10111::Edge388     double dist(const SkPoint& p) const {
389         return fLine.dist(p);
390     }
isRightOf__anon8dd090a10111::Edge391     bool isRightOf(Vertex* v) const {
392         return fLine.dist(v->fPoint) < 0.0;
393     }
isLeftOf__anon8dd090a10111::Edge394     bool isLeftOf(Vertex* v) const {
395         return fLine.dist(v->fPoint) > 0.0;
396     }
recompute__anon8dd090a10111::Edge397     void recompute() {
398         fLine = Line(fTop, fBottom);
399     }
intersect__anon8dd090a10111::Edge400     bool intersect(const Edge& other, SkPoint* p, uint8_t* alpha = nullptr) const {
401         TESS_LOG("intersecting %g -> %g with %g -> %g\n",
402                  fTop->fID, fBottom->fID, other.fTop->fID, other.fBottom->fID);
403         if (fTop == other.fTop || fBottom == other.fBottom) {
404             return false;
405         }
406         double denom = fLine.fA * other.fLine.fB - fLine.fB * other.fLine.fA;
407         if (denom == 0.0) {
408             return false;
409         }
410         double dx = static_cast<double>(other.fTop->fPoint.fX) - fTop->fPoint.fX;
411         double dy = static_cast<double>(other.fTop->fPoint.fY) - fTop->fPoint.fY;
412         double sNumer = dy * other.fLine.fB + dx * other.fLine.fA;
413         double tNumer = dy * fLine.fB + dx * fLine.fA;
414         // If (sNumer / denom) or (tNumer / denom) is not in [0..1], exit early.
415         // This saves us doing the divide below unless absolutely necessary.
416         if (denom > 0.0 ? (sNumer < 0.0 || sNumer > denom || tNumer < 0.0 || tNumer > denom)
417                         : (sNumer > 0.0 || sNumer < denom || tNumer > 0.0 || tNumer < denom)) {
418             return false;
419         }
420         double s = sNumer / denom;
421         SkASSERT(s >= 0.0 && s <= 1.0);
422         p->fX = SkDoubleToScalar(fTop->fPoint.fX - s * fLine.fB);
423         p->fY = SkDoubleToScalar(fTop->fPoint.fY + s * fLine.fA);
424         if (alpha) {
425             if (fType == Type::kConnector) {
426                 *alpha = (1.0 - s) * fTop->fAlpha + s * fBottom->fAlpha;
427             } else if (other.fType == Type::kConnector) {
428                 double t = tNumer / denom;
429                 *alpha = (1.0 - t) * other.fTop->fAlpha + t * other.fBottom->fAlpha;
430             } else if (fType == Type::kOuter && other.fType == Type::kOuter) {
431                 *alpha = 0;
432             } else {
433                 *alpha = 255;
434             }
435         }
436         return true;
437     }
438 };
439 
440 struct SSEdge;
441 
442 struct SSVertex {
SSVertex__anon8dd090a10111::SSVertex443     SSVertex(Vertex* v) : fVertex(v), fPrev(nullptr), fNext(nullptr) {}
444     Vertex* fVertex;
445     SSEdge* fPrev;
446     SSEdge* fNext;
447 };
448 
449 struct SSEdge {
SSEdge__anon8dd090a10111::SSEdge450     SSEdge(Edge* edge, SSVertex* prev, SSVertex* next)
451       : fEdge(edge), fEvent(nullptr), fPrev(prev), fNext(next) {
452     }
453     Edge*     fEdge;
454     Event*    fEvent;
455     SSVertex* fPrev;
456     SSVertex* fNext;
457 };
458 
459 typedef std::unordered_map<Vertex*, SSVertex*> SSVertexMap;
460 typedef std::vector<SSEdge*> SSEdgeList;
461 
462 struct EdgeList {
EdgeList__anon8dd090a10111::EdgeList463     EdgeList() : fHead(nullptr), fTail(nullptr) {}
464     Edge* fHead;
465     Edge* fTail;
insert__anon8dd090a10111::EdgeList466     void insert(Edge* edge, Edge* prev, Edge* next) {
467         list_insert<Edge, &Edge::fLeft, &Edge::fRight>(edge, prev, next, &fHead, &fTail);
468     }
append__anon8dd090a10111::EdgeList469     void append(Edge* e) {
470         insert(e, fTail, nullptr);
471     }
remove__anon8dd090a10111::EdgeList472     void remove(Edge* edge) {
473         list_remove<Edge, &Edge::fLeft, &Edge::fRight>(edge, &fHead, &fTail);
474     }
removeAll__anon8dd090a10111::EdgeList475     void removeAll() {
476         while (fHead) {
477             this->remove(fHead);
478         }
479     }
close__anon8dd090a10111::EdgeList480     void close() {
481         if (fHead && fTail) {
482             fTail->fRight = fHead;
483             fHead->fLeft = fTail;
484         }
485     }
contains__anon8dd090a10111::EdgeList486     bool contains(Edge* edge) const {
487         return edge->fLeft || edge->fRight || fHead == edge;
488     }
489 };
490 
491 struct EventList;
492 
493 struct Event {
Event__anon8dd090a10111::Event494     Event(SSEdge* edge, const SkPoint& point, uint8_t alpha)
495       : fEdge(edge), fPoint(point), fAlpha(alpha) {
496     }
497     SSEdge* fEdge;
498     SkPoint fPoint;
499     uint8_t fAlpha;
500     void apply(VertexList* mesh, Comparator& c, EventList* events, SkArenaAlloc& alloc);
501 };
502 
503 struct EventComparator {
504     enum class Op { kLessThan, kGreaterThan };
EventComparator__anon8dd090a10111::EventComparator505     EventComparator(Op op) : fOp(op) {}
operator ()__anon8dd090a10111::EventComparator506     bool operator() (Event* const &e1, Event* const &e2) {
507         return fOp == Op::kLessThan ? e1->fAlpha < e2->fAlpha
508                                     : e1->fAlpha > e2->fAlpha;
509     }
510     Op fOp;
511 };
512 
513 typedef  std::priority_queue<Event*, std::vector<Event*>, EventComparator> EventPQ;
514 
515 struct EventList : EventPQ {
EventList__anon8dd090a10111::EventList516     EventList(EventComparator comparison) : EventPQ(comparison) {
517     }
518 };
519 
create_event(SSEdge * e,EventList * events,SkArenaAlloc & alloc)520 void create_event(SSEdge* e, EventList* events, SkArenaAlloc& alloc) {
521     Vertex* prev = e->fPrev->fVertex;
522     Vertex* next = e->fNext->fVertex;
523     if (prev == next || !prev->fPartner || !next->fPartner) {
524         return;
525     }
526     Edge bisector1(prev, prev->fPartner, 1, Edge::Type::kConnector);
527     Edge bisector2(next, next->fPartner, 1, Edge::Type::kConnector);
528     SkPoint p;
529     uint8_t alpha;
530     if (bisector1.intersect(bisector2, &p, &alpha)) {
531         TESS_LOG("found edge event for %g, %g (original %g -> %g), "
532                  "will collapse to %g,%g alpha %d\n",
533                   prev->fID, next->fID, e->fEdge->fTop->fID, e->fEdge->fBottom->fID, p.fX, p.fY,
534                   alpha);
535         e->fEvent = alloc.make<Event>(e, p, alpha);
536         events->push(e->fEvent);
537     }
538 }
539 
create_event(SSEdge * edge,Vertex * v,SSEdge * other,Vertex * dest,EventList * events,Comparator & c,SkArenaAlloc & alloc)540 void create_event(SSEdge* edge, Vertex* v, SSEdge* other, Vertex* dest, EventList* events,
541                   Comparator& c, SkArenaAlloc& alloc) {
542     if (!v->fPartner) {
543         return;
544     }
545     Vertex* top = edge->fEdge->fTop;
546     Vertex* bottom = edge->fEdge->fBottom;
547     if (!top || !bottom ) {
548         return;
549     }
550     Line line = edge->fEdge->fLine;
551     line.fC = -(dest->fPoint.fX * line.fA  + dest->fPoint.fY * line.fB);
552     Edge bisector(v, v->fPartner, 1, Edge::Type::kConnector);
553     SkPoint p;
554     uint8_t alpha = dest->fAlpha;
555     if (line.intersect(bisector.fLine, &p) && !c.sweep_lt(p, top->fPoint) &&
556                                                c.sweep_lt(p, bottom->fPoint)) {
557         TESS_LOG("found p edge event for %g, %g (original %g -> %g), "
558                  "will collapse to %g,%g alpha %d\n",
559                  dest->fID, v->fID, top->fID, bottom->fID, p.fX, p.fY, alpha);
560         edge->fEvent = alloc.make<Event>(edge, p, alpha);
561         events->push(edge->fEvent);
562     }
563 }
564 
565 /***************************************************************************************/
566 
567 struct Poly {
Poly__anon8dd090a10111::Poly568     Poly(Vertex* v, int winding)
569         : fFirstVertex(v)
570         , fWinding(winding)
571         , fHead(nullptr)
572         , fTail(nullptr)
573         , fNext(nullptr)
574         , fPartner(nullptr)
575         , fCount(0)
576     {
577 #if LOGGING_ENABLED
578         static int gID = 0;
579         fID = gID++;
580         TESS_LOG("*** created Poly %d\n", fID);
581 #endif
582     }
583     typedef enum { kLeft_Side, kRight_Side } Side;
584     struct MonotonePoly {
MonotonePoly__anon8dd090a10111::Poly::MonotonePoly585         MonotonePoly(Edge* edge, Side side, int winding)
586             : fSide(side)
587             , fFirstEdge(nullptr)
588             , fLastEdge(nullptr)
589             , fPrev(nullptr)
590             , fNext(nullptr)
591             , fWinding(winding) {
592             this->addEdge(edge);
593         }
594         Side          fSide;
595         Edge*         fFirstEdge;
596         Edge*         fLastEdge;
597         MonotonePoly* fPrev;
598         MonotonePoly* fNext;
599         int fWinding;
addEdge__anon8dd090a10111::Poly::MonotonePoly600         void addEdge(Edge* edge) {
601             if (fSide == kRight_Side) {
602                 SkASSERT(!edge->fUsedInRightPoly);
603                 list_insert<Edge, &Edge::fRightPolyPrev, &Edge::fRightPolyNext>(
604                     edge, fLastEdge, nullptr, &fFirstEdge, &fLastEdge);
605                 edge->fUsedInRightPoly = true;
606             } else {
607                 SkASSERT(!edge->fUsedInLeftPoly);
608                 list_insert<Edge, &Edge::fLeftPolyPrev, &Edge::fLeftPolyNext>(
609                     edge, fLastEdge, nullptr, &fFirstEdge, &fLastEdge);
610                 edge->fUsedInLeftPoly = true;
611             }
612         }
613 
emit__anon8dd090a10111::Poly::MonotonePoly614         void* emit(bool emitCoverage, void* data) {
615             Edge* e = fFirstEdge;
616             VertexList vertices;
617             vertices.append(e->fTop);
618             int count = 1;
619             while (e != nullptr) {
620                 if (kRight_Side == fSide) {
621                     vertices.append(e->fBottom);
622                     e = e->fRightPolyNext;
623                 } else {
624                     vertices.prepend(e->fBottom);
625                     e = e->fLeftPolyNext;
626                 }
627                 count++;
628             }
629             Vertex* first = vertices.fHead;
630             Vertex* v = first->fNext;
631             while (v != vertices.fTail) {
632                 SkASSERT(v && v->fPrev && v->fNext);
633                 Vertex* prev = v->fPrev;
634                 Vertex* curr = v;
635                 Vertex* next = v->fNext;
636                 if (count == 3) {
637                     return this->emitTriangle(prev, curr, next, emitCoverage, data);
638                 }
639                 double ax = static_cast<double>(curr->fPoint.fX) - prev->fPoint.fX;
640                 double ay = static_cast<double>(curr->fPoint.fY) - prev->fPoint.fY;
641                 double bx = static_cast<double>(next->fPoint.fX) - curr->fPoint.fX;
642                 double by = static_cast<double>(next->fPoint.fY) - curr->fPoint.fY;
643                 if (ax * by - ay * bx >= 0.0) {
644                     data = this->emitTriangle(prev, curr, next, emitCoverage, data);
645                     v->fPrev->fNext = v->fNext;
646                     v->fNext->fPrev = v->fPrev;
647                     count--;
648                     if (v->fPrev == first) {
649                         v = v->fNext;
650                     } else {
651                         v = v->fPrev;
652                     }
653                 } else {
654                     v = v->fNext;
655                 }
656             }
657             return data;
658         }
emitTriangle__anon8dd090a10111::Poly::MonotonePoly659         void* emitTriangle(Vertex* prev, Vertex* curr, Vertex* next, bool emitCoverage,
660                            void* data) const {
661             if (fWinding < 0) {
662                 // Ensure our triangles always wind in the same direction as if the path had been
663                 // triangulated as a simple fan (a la red book).
664                 std::swap(prev, next);
665             }
666             return emit_triangle(next, curr, prev, emitCoverage, data);
667         }
668     };
addEdge__anon8dd090a10111::Poly669     Poly* addEdge(Edge* e, Side side, SkArenaAlloc& alloc) {
670         TESS_LOG("addEdge (%g -> %g) to poly %d, %s side\n",
671                  e->fTop->fID, e->fBottom->fID, fID, side == kLeft_Side ? "left" : "right");
672         Poly* partner = fPartner;
673         Poly* poly = this;
674         if (side == kRight_Side) {
675             if (e->fUsedInRightPoly) {
676                 return this;
677             }
678         } else {
679             if (e->fUsedInLeftPoly) {
680                 return this;
681             }
682         }
683         if (partner) {
684             fPartner = partner->fPartner = nullptr;
685         }
686         if (!fTail) {
687             fHead = fTail = alloc.make<MonotonePoly>(e, side, fWinding);
688             fCount += 2;
689         } else if (e->fBottom == fTail->fLastEdge->fBottom) {
690             return poly;
691         } else if (side == fTail->fSide) {
692             fTail->addEdge(e);
693             fCount++;
694         } else {
695             e = alloc.make<Edge>(fTail->fLastEdge->fBottom, e->fBottom, 1, Edge::Type::kInner);
696             fTail->addEdge(e);
697             fCount++;
698             if (partner) {
699                 partner->addEdge(e, side, alloc);
700                 poly = partner;
701             } else {
702                 MonotonePoly* m = alloc.make<MonotonePoly>(e, side, fWinding);
703                 m->fPrev = fTail;
704                 fTail->fNext = m;
705                 fTail = m;
706             }
707         }
708         return poly;
709     }
emit__anon8dd090a10111::Poly710     void* emit(bool emitCoverage, void *data) {
711         if (fCount < 3) {
712             return data;
713         }
714         TESS_LOG("emit() %d, size %d\n", fID, fCount);
715         for (MonotonePoly* m = fHead; m != nullptr; m = m->fNext) {
716             data = m->emit(emitCoverage, data);
717         }
718         return data;
719     }
lastVertex__anon8dd090a10111::Poly720     Vertex* lastVertex() const { return fTail ? fTail->fLastEdge->fBottom : fFirstVertex; }
721     Vertex* fFirstVertex;
722     int fWinding;
723     MonotonePoly* fHead;
724     MonotonePoly* fTail;
725     Poly* fNext;
726     Poly* fPartner;
727     int fCount;
728 #if LOGGING_ENABLED
729     int fID;
730 #endif
731 };
732 
733 /***************************************************************************************/
734 
coincident(const SkPoint & a,const SkPoint & b)735 bool coincident(const SkPoint& a, const SkPoint& b) {
736     return a == b;
737 }
738 
new_poly(Poly ** head,Vertex * v,int winding,SkArenaAlloc & alloc)739 Poly* new_poly(Poly** head, Vertex* v, int winding, SkArenaAlloc& alloc) {
740     Poly* poly = alloc.make<Poly>(v, winding);
741     poly->fNext = *head;
742     *head = poly;
743     return poly;
744 }
745 
append_point_to_contour(const SkPoint & p,VertexList * contour,SkArenaAlloc & alloc)746 void append_point_to_contour(const SkPoint& p, VertexList* contour, SkArenaAlloc& alloc) {
747     Vertex* v = alloc.make<Vertex>(p, 255);
748 #if LOGGING_ENABLED
749     static float gID = 0.0f;
750     v->fID = gID++;
751 #endif
752     contour->append(v);
753 }
754 
quad_error_at(const SkPoint pts[3],SkScalar t,SkScalar u)755 SkScalar quad_error_at(const SkPoint pts[3], SkScalar t, SkScalar u) {
756     SkQuadCoeff quad(pts);
757     SkPoint p0 = to_point(quad.eval(t - 0.5f * u));
758     SkPoint mid = to_point(quad.eval(t));
759     SkPoint p1 = to_point(quad.eval(t + 0.5f * u));
760     if (!p0.isFinite() || !mid.isFinite() || !p1.isFinite()) {
761         return 0;
762     }
763     return SkPointPriv::DistanceToLineSegmentBetweenSqd(mid, p0, p1);
764 }
765 
append_quadratic_to_contour(const SkPoint pts[3],SkScalar toleranceSqd,VertexList * contour,SkArenaAlloc & alloc)766 void append_quadratic_to_contour(const SkPoint pts[3], SkScalar toleranceSqd, VertexList* contour,
767                                  SkArenaAlloc& alloc) {
768     SkQuadCoeff quad(pts);
769     Sk2s aa = quad.fA * quad.fA;
770     SkScalar denom = 2.0f * (aa[0] + aa[1]);
771     Sk2s ab = quad.fA * quad.fB;
772     SkScalar t = denom ? (-ab[0] - ab[1]) / denom : 0.0f;
773     int nPoints = 1;
774     SkScalar u = 1.0f;
775     // Test possible subdivision values only at the point of maximum curvature.
776     // If it passes the flatness metric there, it'll pass everywhere.
777     while (nPoints < GrPathUtils::kMaxPointsPerCurve) {
778         u = 1.0f / nPoints;
779         if (quad_error_at(pts, t, u) < toleranceSqd) {
780             break;
781         }
782         nPoints++;
783     }
784     for (int j = 1; j <= nPoints; j++) {
785         append_point_to_contour(to_point(quad.eval(j * u)), contour, alloc);
786     }
787 }
788 
generate_cubic_points(const SkPoint & p0,const SkPoint & p1,const SkPoint & p2,const SkPoint & p3,SkScalar tolSqd,VertexList * contour,int pointsLeft,SkArenaAlloc & alloc)789 void generate_cubic_points(const SkPoint& p0,
790                            const SkPoint& p1,
791                            const SkPoint& p2,
792                            const SkPoint& p3,
793                            SkScalar tolSqd,
794                            VertexList* contour,
795                            int pointsLeft,
796                            SkArenaAlloc& alloc) {
797     SkScalar d1 = SkPointPriv::DistanceToLineSegmentBetweenSqd(p1, p0, p3);
798     SkScalar d2 = SkPointPriv::DistanceToLineSegmentBetweenSqd(p2, p0, p3);
799     if (pointsLeft < 2 || (d1 < tolSqd && d2 < tolSqd) ||
800         !SkScalarIsFinite(d1) || !SkScalarIsFinite(d2)) {
801         append_point_to_contour(p3, contour, alloc);
802         return;
803     }
804     const SkPoint q[] = {
805         { SkScalarAve(p0.fX, p1.fX), SkScalarAve(p0.fY, p1.fY) },
806         { SkScalarAve(p1.fX, p2.fX), SkScalarAve(p1.fY, p2.fY) },
807         { SkScalarAve(p2.fX, p3.fX), SkScalarAve(p2.fY, p3.fY) }
808     };
809     const SkPoint r[] = {
810         { SkScalarAve(q[0].fX, q[1].fX), SkScalarAve(q[0].fY, q[1].fY) },
811         { SkScalarAve(q[1].fX, q[2].fX), SkScalarAve(q[1].fY, q[2].fY) }
812     };
813     const SkPoint s = { SkScalarAve(r[0].fX, r[1].fX), SkScalarAve(r[0].fY, r[1].fY) };
814     pointsLeft >>= 1;
815     generate_cubic_points(p0, q[0], r[0], s, tolSqd, contour, pointsLeft, alloc);
816     generate_cubic_points(s, r[1], q[2], p3, tolSqd, contour, pointsLeft, alloc);
817 }
818 
819 // Stage 1: convert the input path to a set of linear contours (linked list of Vertices).
820 
path_to_contours(const SkPath & path,SkScalar tolerance,const SkRect & clipBounds,VertexList * contours,SkArenaAlloc & alloc,Mode mode,bool * isLinear)821 void path_to_contours(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
822                       VertexList* contours, SkArenaAlloc& alloc, Mode mode, bool *isLinear) {
823     SkScalar toleranceSqd = tolerance * tolerance;
824     bool innerPolygons = (Mode::kSimpleInnerPolygons == mode);
825 
826     SkPoint pts[4];
827     *isLinear = true;
828     VertexList* contour = contours;
829     SkPath::Iter iter(path, false);
830     if (path.isInverseFillType()) {
831         SkPoint quad[4];
832         clipBounds.toQuad(quad);
833         for (int i = 3; i >= 0; i--) {
834             append_point_to_contour(quad[i], contours, alloc);
835         }
836         contour++;
837     }
838     SkAutoConicToQuads converter;
839     SkPath::Verb verb;
840     while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
841         switch (verb) {
842             case SkPath::kConic_Verb: {
843                 *isLinear = false;
844                 if (innerPolygons) {
845                     append_point_to_contour(pts[2], contour, alloc);
846                     break;
847                 }
848                 SkScalar weight = iter.conicWeight();
849                 const SkPoint* quadPts = converter.computeQuads(pts, weight, toleranceSqd);
850                 for (int i = 0; i < converter.countQuads(); ++i) {
851                     append_quadratic_to_contour(quadPts, toleranceSqd, contour, alloc);
852                     quadPts += 2;
853                 }
854                 break;
855             }
856             case SkPath::kMove_Verb:
857                 if (contour->fHead) {
858                     contour++;
859                 }
860                 append_point_to_contour(pts[0], contour, alloc);
861                 break;
862             case SkPath::kLine_Verb: {
863                 append_point_to_contour(pts[1], contour, alloc);
864                 break;
865             }
866             case SkPath::kQuad_Verb: {
867                 *isLinear = false;
868                 if (innerPolygons) {
869                     append_point_to_contour(pts[2], contour, alloc);
870                     break;
871                 }
872                 append_quadratic_to_contour(pts, toleranceSqd, contour, alloc);
873                 break;
874             }
875             case SkPath::kCubic_Verb: {
876                 *isLinear = false;
877                 if (innerPolygons) {
878                     append_point_to_contour(pts[3], contour, alloc);
879                     break;
880                 }
881                 int pointsLeft = GrPathUtils::cubicPointCount(pts, tolerance);
882                 generate_cubic_points(pts[0], pts[1], pts[2], pts[3], toleranceSqd, contour,
883                                       pointsLeft, alloc);
884                 break;
885             }
886             case SkPath::kClose_Verb:
887             case SkPath::kDone_Verb:
888                 break;
889         }
890     }
891 }
892 
apply_fill_type(SkPathFillType fillType,int winding)893 inline bool apply_fill_type(SkPathFillType fillType, int winding) {
894     switch (fillType) {
895         case SkPathFillType::kWinding:
896             return winding != 0;
897         case SkPathFillType::kEvenOdd:
898             return (winding & 1) != 0;
899         case SkPathFillType::kInverseWinding:
900             return winding == 1;
901         case SkPathFillType::kInverseEvenOdd:
902             return (winding & 1) == 1;
903         default:
904             SkASSERT(false);
905             return false;
906     }
907 }
908 
apply_fill_type(SkPathFillType fillType,Poly * poly)909 inline bool apply_fill_type(SkPathFillType fillType, Poly* poly) {
910     return poly && apply_fill_type(fillType, poly->fWinding);
911 }
912 
new_edge(Vertex * prev,Vertex * next,Edge::Type type,Comparator & c,SkArenaAlloc & alloc)913 Edge* new_edge(Vertex* prev, Vertex* next, Edge::Type type, Comparator& c, SkArenaAlloc& alloc) {
914     int winding = c.sweep_lt(prev->fPoint, next->fPoint) ? 1 : -1;
915     Vertex* top = winding < 0 ? next : prev;
916     Vertex* bottom = winding < 0 ? prev : next;
917     return alloc.make<Edge>(top, bottom, winding, type);
918 }
919 
remove_edge(Edge * edge,EdgeList * edges)920 void remove_edge(Edge* edge, EdgeList* edges) {
921     TESS_LOG("removing edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID);
922     SkASSERT(edges->contains(edge));
923     edges->remove(edge);
924 }
925 
insert_edge(Edge * edge,Edge * prev,EdgeList * edges)926 void insert_edge(Edge* edge, Edge* prev, EdgeList* edges) {
927     TESS_LOG("inserting edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID);
928     SkASSERT(!edges->contains(edge));
929     Edge* next = prev ? prev->fRight : edges->fHead;
930     edges->insert(edge, prev, next);
931 }
932 
find_enclosing_edges(Vertex * v,EdgeList * edges,Edge ** left,Edge ** right)933 void find_enclosing_edges(Vertex* v, EdgeList* edges, Edge** left, Edge** right) {
934     if (v->fFirstEdgeAbove && v->fLastEdgeAbove) {
935         *left = v->fFirstEdgeAbove->fLeft;
936         *right = v->fLastEdgeAbove->fRight;
937         return;
938     }
939     Edge* next = nullptr;
940     Edge* prev;
941     for (prev = edges->fTail; prev != nullptr; prev = prev->fLeft) {
942         if (prev->isLeftOf(v)) {
943             break;
944         }
945         next = prev;
946     }
947     *left = prev;
948     *right = next;
949 }
950 
insert_edge_above(Edge * edge,Vertex * v,Comparator & c)951 void insert_edge_above(Edge* edge, Vertex* v, Comparator& c) {
952     if (edge->fTop->fPoint == edge->fBottom->fPoint ||
953         c.sweep_lt(edge->fBottom->fPoint, edge->fTop->fPoint)) {
954         return;
955     }
956     TESS_LOG("insert edge (%g -> %g) above vertex %g\n",
957              edge->fTop->fID, edge->fBottom->fID, v->fID);
958     Edge* prev = nullptr;
959     Edge* next;
960     for (next = v->fFirstEdgeAbove; next; next = next->fNextEdgeAbove) {
961         if (next->isRightOf(edge->fTop)) {
962             break;
963         }
964         prev = next;
965     }
966     list_insert<Edge, &Edge::fPrevEdgeAbove, &Edge::fNextEdgeAbove>(
967         edge, prev, next, &v->fFirstEdgeAbove, &v->fLastEdgeAbove);
968 }
969 
insert_edge_below(Edge * edge,Vertex * v,Comparator & c)970 void insert_edge_below(Edge* edge, Vertex* v, Comparator& c) {
971     if (edge->fTop->fPoint == edge->fBottom->fPoint ||
972         c.sweep_lt(edge->fBottom->fPoint, edge->fTop->fPoint)) {
973         return;
974     }
975     TESS_LOG("insert edge (%g -> %g) below vertex %g\n",
976              edge->fTop->fID, edge->fBottom->fID, v->fID);
977     Edge* prev = nullptr;
978     Edge* next;
979     for (next = v->fFirstEdgeBelow; next; next = next->fNextEdgeBelow) {
980         if (next->isRightOf(edge->fBottom)) {
981             break;
982         }
983         prev = next;
984     }
985     list_insert<Edge, &Edge::fPrevEdgeBelow, &Edge::fNextEdgeBelow>(
986         edge, prev, next, &v->fFirstEdgeBelow, &v->fLastEdgeBelow);
987 }
988 
remove_edge_above(Edge * edge)989 void remove_edge_above(Edge* edge) {
990     SkASSERT(edge->fTop && edge->fBottom);
991     TESS_LOG("removing edge (%g -> %g) above vertex %g\n", edge->fTop->fID, edge->fBottom->fID,
992              edge->fBottom->fID);
993     list_remove<Edge, &Edge::fPrevEdgeAbove, &Edge::fNextEdgeAbove>(
994         edge, &edge->fBottom->fFirstEdgeAbove, &edge->fBottom->fLastEdgeAbove);
995 }
996 
remove_edge_below(Edge * edge)997 void remove_edge_below(Edge* edge) {
998     SkASSERT(edge->fTop && edge->fBottom);
999     TESS_LOG("removing edge (%g -> %g) below vertex %g\n",
1000              edge->fTop->fID, edge->fBottom->fID, edge->fTop->fID);
1001     list_remove<Edge, &Edge::fPrevEdgeBelow, &Edge::fNextEdgeBelow>(
1002         edge, &edge->fTop->fFirstEdgeBelow, &edge->fTop->fLastEdgeBelow);
1003 }
1004 
disconnect(Edge * edge)1005 void disconnect(Edge* edge)
1006 {
1007     remove_edge_above(edge);
1008     remove_edge_below(edge);
1009 }
1010 
1011 void merge_collinear_edges(Edge* edge, EdgeList* activeEdges, Vertex** current, Comparator& c);
1012 
rewind(EdgeList * activeEdges,Vertex ** current,Vertex * dst,Comparator & c)1013 void rewind(EdgeList* activeEdges, Vertex** current, Vertex* dst, Comparator& c) {
1014     if (!current || *current == dst || c.sweep_lt((*current)->fPoint, dst->fPoint)) {
1015         return;
1016     }
1017     Vertex* v = *current;
1018     TESS_LOG("rewinding active edges from vertex %g to vertex %g\n", v->fID, dst->fID);
1019     while (v != dst) {
1020         v = v->fPrev;
1021         for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1022             remove_edge(e, activeEdges);
1023         }
1024         Edge* leftEdge = v->fLeftEnclosingEdge;
1025         for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
1026             insert_edge(e, leftEdge, activeEdges);
1027             leftEdge = e;
1028             Vertex* top = e->fTop;
1029             if (c.sweep_lt(top->fPoint, dst->fPoint) &&
1030                 ((top->fLeftEnclosingEdge && !top->fLeftEnclosingEdge->isLeftOf(e->fTop)) ||
1031                  (top->fRightEnclosingEdge && !top->fRightEnclosingEdge->isRightOf(e->fTop)))) {
1032                 dst = top;
1033             }
1034         }
1035     }
1036     *current = v;
1037 }
1038 
rewind_if_necessary(Edge * edge,EdgeList * activeEdges,Vertex ** current,Comparator & c)1039 void rewind_if_necessary(Edge* edge, EdgeList* activeEdges, Vertex** current, Comparator& c) {
1040     if (!activeEdges || !current) {
1041         return;
1042     }
1043     Vertex* top = edge->fTop;
1044     Vertex* bottom = edge->fBottom;
1045     if (edge->fLeft) {
1046         Vertex* leftTop = edge->fLeft->fTop;
1047         Vertex* leftBottom = edge->fLeft->fBottom;
1048         if (c.sweep_lt(leftTop->fPoint, top->fPoint) && !edge->fLeft->isLeftOf(top)) {
1049             rewind(activeEdges, current, leftTop, c);
1050         } else if (c.sweep_lt(top->fPoint, leftTop->fPoint) && !edge->isRightOf(leftTop)) {
1051             rewind(activeEdges, current, top, c);
1052         } else if (c.sweep_lt(bottom->fPoint, leftBottom->fPoint) &&
1053                    !edge->fLeft->isLeftOf(bottom)) {
1054             rewind(activeEdges, current, leftTop, c);
1055         } else if (c.sweep_lt(leftBottom->fPoint, bottom->fPoint) && !edge->isRightOf(leftBottom)) {
1056             rewind(activeEdges, current, top, c);
1057         }
1058     }
1059     if (edge->fRight) {
1060         Vertex* rightTop = edge->fRight->fTop;
1061         Vertex* rightBottom = edge->fRight->fBottom;
1062         if (c.sweep_lt(rightTop->fPoint, top->fPoint) && !edge->fRight->isRightOf(top)) {
1063             rewind(activeEdges, current, rightTop, c);
1064         } else if (c.sweep_lt(top->fPoint, rightTop->fPoint) && !edge->isLeftOf(rightTop)) {
1065             rewind(activeEdges, current, top, c);
1066         } else if (c.sweep_lt(bottom->fPoint, rightBottom->fPoint) &&
1067                    !edge->fRight->isRightOf(bottom)) {
1068             rewind(activeEdges, current, rightTop, c);
1069         } else if (c.sweep_lt(rightBottom->fPoint, bottom->fPoint) &&
1070                    !edge->isLeftOf(rightBottom)) {
1071             rewind(activeEdges, current, top, c);
1072         }
1073     }
1074 }
1075 
set_top(Edge * edge,Vertex * v,EdgeList * activeEdges,Vertex ** current,Comparator & c)1076 void set_top(Edge* edge, Vertex* v, EdgeList* activeEdges, Vertex** current, Comparator& c) {
1077     remove_edge_below(edge);
1078     edge->fTop = v;
1079     edge->recompute();
1080     insert_edge_below(edge, v, c);
1081     rewind_if_necessary(edge, activeEdges, current, c);
1082     merge_collinear_edges(edge, activeEdges, current, c);
1083 }
1084 
set_bottom(Edge * edge,Vertex * v,EdgeList * activeEdges,Vertex ** current,Comparator & c)1085 void set_bottom(Edge* edge, Vertex* v, EdgeList* activeEdges, Vertex** current, Comparator& c) {
1086     remove_edge_above(edge);
1087     edge->fBottom = v;
1088     edge->recompute();
1089     insert_edge_above(edge, v, c);
1090     rewind_if_necessary(edge, activeEdges, current, c);
1091     merge_collinear_edges(edge, activeEdges, current, c);
1092 }
1093 
merge_edges_above(Edge * edge,Edge * other,EdgeList * activeEdges,Vertex ** current,Comparator & c)1094 void merge_edges_above(Edge* edge, Edge* other, EdgeList* activeEdges, Vertex** current,
1095                        Comparator& c) {
1096     if (coincident(edge->fTop->fPoint, other->fTop->fPoint)) {
1097         TESS_LOG("merging coincident above edges (%g, %g) -> (%g, %g)\n",
1098                  edge->fTop->fPoint.fX, edge->fTop->fPoint.fY,
1099                  edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY);
1100         rewind(activeEdges, current, edge->fTop, c);
1101         other->fWinding += edge->fWinding;
1102         disconnect(edge);
1103         edge->fTop = edge->fBottom = nullptr;
1104     } else if (c.sweep_lt(edge->fTop->fPoint, other->fTop->fPoint)) {
1105         rewind(activeEdges, current, edge->fTop, c);
1106         other->fWinding += edge->fWinding;
1107         set_bottom(edge, other->fTop, activeEdges, current, c);
1108     } else {
1109         rewind(activeEdges, current, other->fTop, c);
1110         edge->fWinding += other->fWinding;
1111         set_bottom(other, edge->fTop, activeEdges, current, c);
1112     }
1113 }
1114 
merge_edges_below(Edge * edge,Edge * other,EdgeList * activeEdges,Vertex ** current,Comparator & c)1115 void merge_edges_below(Edge* edge, Edge* other, EdgeList* activeEdges, Vertex** current,
1116                        Comparator& c) {
1117     if (coincident(edge->fBottom->fPoint, other->fBottom->fPoint)) {
1118         TESS_LOG("merging coincident below edges (%g, %g) -> (%g, %g)\n",
1119                  edge->fTop->fPoint.fX, edge->fTop->fPoint.fY,
1120                  edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY);
1121         rewind(activeEdges, current, edge->fTop, c);
1122         other->fWinding += edge->fWinding;
1123         disconnect(edge);
1124         edge->fTop = edge->fBottom = nullptr;
1125     } else if (c.sweep_lt(edge->fBottom->fPoint, other->fBottom->fPoint)) {
1126         rewind(activeEdges, current, other->fTop, c);
1127         edge->fWinding += other->fWinding;
1128         set_top(other, edge->fBottom, activeEdges, current, c);
1129     } else {
1130         rewind(activeEdges, current, edge->fTop, c);
1131         other->fWinding += edge->fWinding;
1132         set_top(edge, other->fBottom, activeEdges, current, c);
1133     }
1134 }
1135 
top_collinear(Edge * left,Edge * right)1136 bool top_collinear(Edge* left, Edge* right) {
1137     if (!left || !right) {
1138         return false;
1139     }
1140     return left->fTop->fPoint == right->fTop->fPoint ||
1141            !left->isLeftOf(right->fTop) || !right->isRightOf(left->fTop);
1142 }
1143 
bottom_collinear(Edge * left,Edge * right)1144 bool bottom_collinear(Edge* left, Edge* right) {
1145     if (!left || !right) {
1146         return false;
1147     }
1148     return left->fBottom->fPoint == right->fBottom->fPoint ||
1149            !left->isLeftOf(right->fBottom) || !right->isRightOf(left->fBottom);
1150 }
1151 
merge_collinear_edges(Edge * edge,EdgeList * activeEdges,Vertex ** current,Comparator & c)1152 void merge_collinear_edges(Edge* edge, EdgeList* activeEdges, Vertex** current, Comparator& c) {
1153     for (;;) {
1154         if (top_collinear(edge->fPrevEdgeAbove, edge)) {
1155             merge_edges_above(edge->fPrevEdgeAbove, edge, activeEdges, current, c);
1156         } else if (top_collinear(edge, edge->fNextEdgeAbove)) {
1157             merge_edges_above(edge->fNextEdgeAbove, edge, activeEdges, current, c);
1158         } else if (bottom_collinear(edge->fPrevEdgeBelow, edge)) {
1159             merge_edges_below(edge->fPrevEdgeBelow, edge, activeEdges, current, c);
1160         } else if (bottom_collinear(edge, edge->fNextEdgeBelow)) {
1161             merge_edges_below(edge->fNextEdgeBelow, edge, activeEdges, current, c);
1162         } else {
1163             break;
1164         }
1165     }
1166     SkASSERT(!top_collinear(edge->fPrevEdgeAbove, edge));
1167     SkASSERT(!top_collinear(edge, edge->fNextEdgeAbove));
1168     SkASSERT(!bottom_collinear(edge->fPrevEdgeBelow, edge));
1169     SkASSERT(!bottom_collinear(edge, edge->fNextEdgeBelow));
1170 }
1171 
split_edge(Edge * edge,Vertex * v,EdgeList * activeEdges,Vertex ** current,Comparator & c,SkArenaAlloc & alloc)1172 bool split_edge(Edge* edge, Vertex* v, EdgeList* activeEdges, Vertex** current, Comparator& c,
1173                 SkArenaAlloc& alloc) {
1174     if (!edge->fTop || !edge->fBottom || v == edge->fTop || v == edge->fBottom) {
1175         return false;
1176     }
1177     TESS_LOG("splitting edge (%g -> %g) at vertex %g (%g, %g)\n",
1178              edge->fTop->fID, edge->fBottom->fID, v->fID, v->fPoint.fX, v->fPoint.fY);
1179     Vertex* top;
1180     Vertex* bottom;
1181     int winding = edge->fWinding;
1182     if (c.sweep_lt(v->fPoint, edge->fTop->fPoint)) {
1183         top = v;
1184         bottom = edge->fTop;
1185         set_top(edge, v, activeEdges, current, c);
1186     } else if (c.sweep_lt(edge->fBottom->fPoint, v->fPoint)) {
1187         top = edge->fBottom;
1188         bottom = v;
1189         set_bottom(edge, v, activeEdges, current, c);
1190     } else {
1191         top = v;
1192         bottom = edge->fBottom;
1193         set_bottom(edge, v, activeEdges, current, c);
1194     }
1195     Edge* newEdge = alloc.make<Edge>(top, bottom, winding, edge->fType);
1196     insert_edge_below(newEdge, top, c);
1197     insert_edge_above(newEdge, bottom, c);
1198     merge_collinear_edges(newEdge, activeEdges, current, c);
1199     return true;
1200 }
1201 
intersect_edge_pair(Edge * left,Edge * right,EdgeList * activeEdges,Vertex ** current,Comparator & c,SkArenaAlloc & alloc)1202 bool intersect_edge_pair(Edge* left, Edge* right, EdgeList* activeEdges, Vertex** current, Comparator& c, SkArenaAlloc& alloc) {
1203     if (!left->fTop || !left->fBottom || !right->fTop || !right->fBottom) {
1204         return false;
1205     }
1206     if (left->fTop == right->fTop || left->fBottom == right->fBottom) {
1207         return false;
1208     }
1209     if (c.sweep_lt(left->fTop->fPoint, right->fTop->fPoint)) {
1210         if (!left->isLeftOf(right->fTop)) {
1211             rewind(activeEdges, current, right->fTop, c);
1212             return split_edge(left, right->fTop, activeEdges, current, c, alloc);
1213         }
1214     } else {
1215         if (!right->isRightOf(left->fTop)) {
1216             rewind(activeEdges, current, left->fTop, c);
1217             return split_edge(right, left->fTop, activeEdges, current, c, alloc);
1218         }
1219     }
1220     if (c.sweep_lt(right->fBottom->fPoint, left->fBottom->fPoint)) {
1221         if (!left->isLeftOf(right->fBottom)) {
1222             rewind(activeEdges, current, right->fBottom, c);
1223             return split_edge(left, right->fBottom, activeEdges, current, c, alloc);
1224         }
1225     } else {
1226         if (!right->isRightOf(left->fBottom)) {
1227             rewind(activeEdges, current, left->fBottom, c);
1228             return split_edge(right, left->fBottom, activeEdges, current, c, alloc);
1229         }
1230     }
1231     return false;
1232 }
1233 
connect(Vertex * prev,Vertex * next,Edge::Type type,Comparator & c,SkArenaAlloc & alloc,int winding_scale=1)1234 Edge* connect(Vertex* prev, Vertex* next, Edge::Type type, Comparator& c, SkArenaAlloc& alloc,
1235               int winding_scale = 1) {
1236     if (!prev || !next || prev->fPoint == next->fPoint) {
1237         return nullptr;
1238     }
1239     Edge* edge = new_edge(prev, next, type, c, alloc);
1240     insert_edge_below(edge, edge->fTop, c);
1241     insert_edge_above(edge, edge->fBottom, c);
1242     edge->fWinding *= winding_scale;
1243     merge_collinear_edges(edge, nullptr, nullptr, c);
1244     return edge;
1245 }
1246 
merge_vertices(Vertex * src,Vertex * dst,VertexList * mesh,Comparator & c,SkArenaAlloc & alloc)1247 void merge_vertices(Vertex* src, Vertex* dst, VertexList* mesh, Comparator& c,
1248                     SkArenaAlloc& alloc) {
1249     TESS_LOG("found coincident verts at %g, %g; merging %g into %g\n",
1250              src->fPoint.fX, src->fPoint.fY, src->fID, dst->fID);
1251     dst->fAlpha = std::max(src->fAlpha, dst->fAlpha);
1252     if (src->fPartner) {
1253         src->fPartner->fPartner = dst;
1254     }
1255     while (Edge* edge = src->fFirstEdgeAbove) {
1256         set_bottom(edge, dst, nullptr, nullptr, c);
1257     }
1258     while (Edge* edge = src->fFirstEdgeBelow) {
1259         set_top(edge, dst, nullptr, nullptr, c);
1260     }
1261     mesh->remove(src);
1262     dst->fSynthetic = true;
1263 }
1264 
create_sorted_vertex(const SkPoint & p,uint8_t alpha,VertexList * mesh,Vertex * reference,Comparator & c,SkArenaAlloc & alloc)1265 Vertex* create_sorted_vertex(const SkPoint& p, uint8_t alpha, VertexList* mesh,
1266                              Vertex* reference, Comparator& c, SkArenaAlloc& alloc) {
1267     Vertex* prevV = reference;
1268     while (prevV && c.sweep_lt(p, prevV->fPoint)) {
1269         prevV = prevV->fPrev;
1270     }
1271     Vertex* nextV = prevV ? prevV->fNext : mesh->fHead;
1272     while (nextV && c.sweep_lt(nextV->fPoint, p)) {
1273         prevV = nextV;
1274         nextV = nextV->fNext;
1275     }
1276     Vertex* v;
1277     if (prevV && coincident(prevV->fPoint, p)) {
1278         v = prevV;
1279     } else if (nextV && coincident(nextV->fPoint, p)) {
1280         v = nextV;
1281     } else {
1282         v = alloc.make<Vertex>(p, alpha);
1283 #if LOGGING_ENABLED
1284         if (!prevV) {
1285             v->fID = mesh->fHead->fID - 1.0f;
1286         } else if (!nextV) {
1287             v->fID = mesh->fTail->fID + 1.0f;
1288         } else {
1289             v->fID = (prevV->fID + nextV->fID) * 0.5f;
1290         }
1291 #endif
1292         mesh->insert(v, prevV, nextV);
1293     }
1294     return v;
1295 }
1296 
1297 // If an edge's top and bottom points differ only by 1/2 machine epsilon in the primary
1298 // sort criterion, it may not be possible to split correctly, since there is no point which is
1299 // below the top and above the bottom. This function detects that case.
nearly_flat(Comparator & c,Edge * edge)1300 bool nearly_flat(Comparator& c, Edge* edge) {
1301     SkPoint diff = edge->fBottom->fPoint - edge->fTop->fPoint;
1302     float primaryDiff = c.fDirection == Comparator::Direction::kHorizontal ? diff.fX : diff.fY;
1303     return fabs(primaryDiff) < std::numeric_limits<float>::epsilon() && primaryDiff != 0.0f;
1304 }
1305 
clamp(SkPoint p,SkPoint min,SkPoint max,Comparator & c)1306 SkPoint clamp(SkPoint p, SkPoint min, SkPoint max, Comparator& c) {
1307     if (c.sweep_lt(p, min)) {
1308         return min;
1309     } else if (c.sweep_lt(max, p)) {
1310         return max;
1311     } else {
1312         return p;
1313     }
1314 }
1315 
compute_bisector(Edge * edge1,Edge * edge2,Vertex * v,SkArenaAlloc & alloc)1316 void compute_bisector(Edge* edge1, Edge* edge2, Vertex* v, SkArenaAlloc& alloc) {
1317     Line line1 = edge1->fLine;
1318     Line line2 = edge2->fLine;
1319     line1.normalize();
1320     line2.normalize();
1321     double cosAngle = line1.fA * line2.fA + line1.fB * line2.fB;
1322     if (cosAngle > 0.999) {
1323         return;
1324     }
1325     line1.fC += edge1->fWinding > 0 ? -1 : 1;
1326     line2.fC += edge2->fWinding > 0 ? -1 : 1;
1327     SkPoint p;
1328     if (line1.intersect(line2, &p)) {
1329         uint8_t alpha = edge1->fType == Edge::Type::kOuter ? 255 : 0;
1330         v->fPartner = alloc.make<Vertex>(p, alpha);
1331         TESS_LOG("computed bisector (%g,%g) alpha %d for vertex %g\n", p.fX, p.fY, alpha, v->fID);
1332     }
1333 }
1334 
check_for_intersection(Edge * left,Edge * right,EdgeList * activeEdges,Vertex ** current,VertexList * mesh,Comparator & c,SkArenaAlloc & alloc)1335 bool check_for_intersection(Edge* left, Edge* right, EdgeList* activeEdges, Vertex** current,
1336                             VertexList* mesh, Comparator& c, SkArenaAlloc& alloc) {
1337     if (!left || !right) {
1338         return false;
1339     }
1340     SkPoint p;
1341     uint8_t alpha;
1342     if (left->intersect(*right, &p, &alpha) && p.isFinite()) {
1343         Vertex* v;
1344         TESS_LOG("found intersection, pt is %g, %g\n", p.fX, p.fY);
1345         Vertex* top = *current;
1346         // If the intersection point is above the current vertex, rewind to the vertex above the
1347         // intersection.
1348         while (top && c.sweep_lt(p, top->fPoint)) {
1349             top = top->fPrev;
1350         }
1351         if (!nearly_flat(c, left)) {
1352             p = clamp(p, left->fTop->fPoint, left->fBottom->fPoint, c);
1353         }
1354         if (!nearly_flat(c, right)) {
1355             p = clamp(p, right->fTop->fPoint, right->fBottom->fPoint, c);
1356         }
1357         if (p == left->fTop->fPoint) {
1358             v = left->fTop;
1359         } else if (p == left->fBottom->fPoint) {
1360             v = left->fBottom;
1361         } else if (p == right->fTop->fPoint) {
1362             v = right->fTop;
1363         } else if (p == right->fBottom->fPoint) {
1364             v = right->fBottom;
1365         } else {
1366             v = create_sorted_vertex(p, alpha, mesh, top, c, alloc);
1367             if (left->fTop->fPartner) {
1368                 v->fSynthetic = true;
1369                 compute_bisector(left, right, v, alloc);
1370             }
1371         }
1372         rewind(activeEdges, current, top ? top : v, c);
1373         split_edge(left, v, activeEdges, current, c, alloc);
1374         split_edge(right, v, activeEdges, current, c, alloc);
1375         v->fAlpha = std::max(v->fAlpha, alpha);
1376         return true;
1377     }
1378     return intersect_edge_pair(left, right, activeEdges, current, c, alloc);
1379 }
1380 
sanitize_contours(VertexList * contours,int contourCnt,Mode mode)1381 void sanitize_contours(VertexList* contours, int contourCnt, Mode mode) {
1382     bool approximate = (Mode::kEdgeAntialias == mode);
1383     bool removeCollinearVertices = (Mode::kSimpleInnerPolygons != mode);
1384     for (VertexList* contour = contours; contourCnt > 0; --contourCnt, ++contour) {
1385         SkASSERT(contour->fHead);
1386         Vertex* prev = contour->fTail;
1387         if (approximate) {
1388             round(&prev->fPoint);
1389         }
1390         for (Vertex* v = contour->fHead; v;) {
1391             if (approximate) {
1392                 round(&v->fPoint);
1393             }
1394             Vertex* next = v->fNext;
1395             Vertex* nextWrap = next ? next : contour->fHead;
1396             if (coincident(prev->fPoint, v->fPoint)) {
1397                 TESS_LOG("vertex %g,%g coincident; removing\n", v->fPoint.fX, v->fPoint.fY);
1398                 contour->remove(v);
1399             } else if (!v->fPoint.isFinite()) {
1400                 TESS_LOG("vertex %g,%g non-finite; removing\n", v->fPoint.fX, v->fPoint.fY);
1401                 contour->remove(v);
1402             } else if (removeCollinearVertices &&
1403                        Line(prev->fPoint, nextWrap->fPoint).dist(v->fPoint) == 0.0) {
1404                 TESS_LOG("vertex %g,%g collinear; removing\n", v->fPoint.fX, v->fPoint.fY);
1405                 contour->remove(v);
1406             } else {
1407                 prev = v;
1408             }
1409             v = next;
1410         }
1411     }
1412 }
1413 
merge_coincident_vertices(VertexList * mesh,Comparator & c,SkArenaAlloc & alloc)1414 bool merge_coincident_vertices(VertexList* mesh, Comparator& c, SkArenaAlloc& alloc) {
1415     if (!mesh->fHead) {
1416         return false;
1417     }
1418     bool merged = false;
1419     for (Vertex* v = mesh->fHead->fNext; v;) {
1420         Vertex* next = v->fNext;
1421         if (c.sweep_lt(v->fPoint, v->fPrev->fPoint)) {
1422             v->fPoint = v->fPrev->fPoint;
1423         }
1424         if (coincident(v->fPrev->fPoint, v->fPoint)) {
1425             merge_vertices(v, v->fPrev, mesh, c, alloc);
1426             merged = true;
1427         }
1428         v = next;
1429     }
1430     return merged;
1431 }
1432 
1433 // Stage 2: convert the contours to a mesh of edges connecting the vertices.
1434 
build_edges(VertexList * contours,int contourCnt,VertexList * mesh,Comparator & c,SkArenaAlloc & alloc)1435 void build_edges(VertexList* contours, int contourCnt, VertexList* mesh, Comparator& c,
1436                  SkArenaAlloc& alloc) {
1437     for (VertexList* contour = contours; contourCnt > 0; --contourCnt, ++contour) {
1438         Vertex* prev = contour->fTail;
1439         for (Vertex* v = contour->fHead; v;) {
1440             Vertex* next = v->fNext;
1441             connect(prev, v, Edge::Type::kInner, c, alloc);
1442             mesh->append(v);
1443             prev = v;
1444             v = next;
1445         }
1446     }
1447 }
1448 
connect_partners(VertexList * mesh,Comparator & c,SkArenaAlloc & alloc)1449 void connect_partners(VertexList* mesh, Comparator& c, SkArenaAlloc& alloc) {
1450     for (Vertex* outer = mesh->fHead; outer; outer = outer->fNext) {
1451         if (Vertex* inner = outer->fPartner) {
1452             if ((inner->fPrev || inner->fNext) && (outer->fPrev || outer->fNext)) {
1453                 // Connector edges get zero winding, since they're only structural (i.e., to ensure
1454                 // no 0-0-0 alpha triangles are produced), and shouldn't affect the poly winding
1455                 // number.
1456                 connect(outer, inner, Edge::Type::kConnector, c, alloc, 0);
1457                 inner->fPartner = outer->fPartner = nullptr;
1458             }
1459         }
1460     }
1461 }
1462 
1463 template <CompareFunc sweep_lt>
sorted_merge(VertexList * front,VertexList * back,VertexList * result)1464 void sorted_merge(VertexList* front, VertexList* back, VertexList* result) {
1465     Vertex* a = front->fHead;
1466     Vertex* b = back->fHead;
1467     while (a && b) {
1468         if (sweep_lt(a->fPoint, b->fPoint)) {
1469             front->remove(a);
1470             result->append(a);
1471             a = front->fHead;
1472         } else {
1473             back->remove(b);
1474             result->append(b);
1475             b = back->fHead;
1476         }
1477     }
1478     result->append(*front);
1479     result->append(*back);
1480 }
1481 
sorted_merge(VertexList * front,VertexList * back,VertexList * result,Comparator & c)1482 void sorted_merge(VertexList* front, VertexList* back, VertexList* result, Comparator& c) {
1483     if (c.fDirection == Comparator::Direction::kHorizontal) {
1484         sorted_merge<sweep_lt_horiz>(front, back, result);
1485     } else {
1486         sorted_merge<sweep_lt_vert>(front, back, result);
1487     }
1488 #if LOGGING_ENABLED
1489     float id = 0.0f;
1490     for (Vertex* v = result->fHead; v; v = v->fNext) {
1491         v->fID = id++;
1492     }
1493 #endif
1494 }
1495 
1496 // Stage 3: sort the vertices by increasing sweep direction.
1497 
1498 template <CompareFunc sweep_lt>
merge_sort(VertexList * vertices)1499 void merge_sort(VertexList* vertices) {
1500     Vertex* slow = vertices->fHead;
1501     if (!slow) {
1502         return;
1503     }
1504     Vertex* fast = slow->fNext;
1505     if (!fast) {
1506         return;
1507     }
1508     do {
1509         fast = fast->fNext;
1510         if (fast) {
1511             fast = fast->fNext;
1512             slow = slow->fNext;
1513         }
1514     } while (fast);
1515     VertexList front(vertices->fHead, slow);
1516     VertexList back(slow->fNext, vertices->fTail);
1517     front.fTail->fNext = back.fHead->fPrev = nullptr;
1518 
1519     merge_sort<sweep_lt>(&front);
1520     merge_sort<sweep_lt>(&back);
1521 
1522     vertices->fHead = vertices->fTail = nullptr;
1523     sorted_merge<sweep_lt>(&front, &back, vertices);
1524 }
1525 
dump_mesh(const VertexList & mesh)1526 void dump_mesh(const VertexList& mesh) {
1527 #if LOGGING_ENABLED
1528     for (Vertex* v = mesh.fHead; v; v = v->fNext) {
1529         TESS_LOG("vertex %g (%g, %g) alpha %d", v->fID, v->fPoint.fX, v->fPoint.fY, v->fAlpha);
1530         if (Vertex* p = v->fPartner) {
1531             TESS_LOG(", partner %g (%g, %g) alpha %d\n",
1532                     p->fID, p->fPoint.fX, p->fPoint.fY, p->fAlpha);
1533         } else {
1534             TESS_LOG(", null partner\n");
1535         }
1536         for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
1537             TESS_LOG("  edge %g -> %g, winding %d\n", e->fTop->fID, e->fBottom->fID, e->fWinding);
1538         }
1539         for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1540             TESS_LOG("  edge %g -> %g, winding %d\n", e->fTop->fID, e->fBottom->fID, e->fWinding);
1541         }
1542     }
1543 #endif
1544 }
1545 
dump_skel(const SSEdgeList & ssEdges)1546 void dump_skel(const SSEdgeList& ssEdges) {
1547 #if LOGGING_ENABLED
1548     for (SSEdge* edge : ssEdges) {
1549         if (edge->fEdge) {
1550             TESS_LOG("skel edge %g -> %g",
1551                 edge->fPrev->fVertex->fID,
1552                 edge->fNext->fVertex->fID);
1553             if (edge->fEdge->fTop && edge->fEdge->fBottom) {
1554                 TESS_LOG(" (original %g -> %g)\n",
1555                          edge->fEdge->fTop->fID,
1556                          edge->fEdge->fBottom->fID);
1557             } else {
1558                 TESS_LOG("\n");
1559             }
1560         }
1561     }
1562 #endif
1563 }
1564 
1565 #ifdef SK_DEBUG
validate_edge_pair(Edge * left,Edge * right,Comparator & c)1566 void validate_edge_pair(Edge* left, Edge* right, Comparator& c) {
1567     if (!left || !right) {
1568         return;
1569     }
1570     if (left->fTop == right->fTop) {
1571         SkASSERT(left->isLeftOf(right->fBottom));
1572         SkASSERT(right->isRightOf(left->fBottom));
1573     } else if (c.sweep_lt(left->fTop->fPoint, right->fTop->fPoint)) {
1574         SkASSERT(left->isLeftOf(right->fTop));
1575     } else {
1576         SkASSERT(right->isRightOf(left->fTop));
1577     }
1578     if (left->fBottom == right->fBottom) {
1579         SkASSERT(left->isLeftOf(right->fTop));
1580         SkASSERT(right->isRightOf(left->fTop));
1581     } else if (c.sweep_lt(right->fBottom->fPoint, left->fBottom->fPoint)) {
1582         SkASSERT(left->isLeftOf(right->fBottom));
1583     } else {
1584         SkASSERT(right->isRightOf(left->fBottom));
1585     }
1586 }
1587 
validate_edge_list(EdgeList * edges,Comparator & c)1588 void validate_edge_list(EdgeList* edges, Comparator& c) {
1589     Edge* left = edges->fHead;
1590     if (!left) {
1591         return;
1592     }
1593     for (Edge* right = left->fRight; right; right = right->fRight) {
1594         validate_edge_pair(left, right, c);
1595         left = right;
1596     }
1597 }
1598 #endif
1599 
1600 // Stage 4: Simplify the mesh by inserting new vertices at intersecting edges.
1601 
connected(Vertex * v)1602 bool connected(Vertex* v) {
1603     return v->fFirstEdgeAbove || v->fFirstEdgeBelow;
1604 }
1605 
1606 enum class SimplifyResult {
1607     kAlreadySimple,
1608     kFoundSelfIntersection,
1609     kAbort
1610 };
1611 
simplify(Mode mode,VertexList * mesh,Comparator & c,SkArenaAlloc & alloc)1612 SimplifyResult simplify(Mode mode, VertexList* mesh, Comparator& c, SkArenaAlloc& alloc) {
1613     TESS_LOG("simplifying complex polygons\n");
1614     EdgeList activeEdges;
1615     auto result = SimplifyResult::kAlreadySimple;
1616     for (Vertex* v = mesh->fHead; v != nullptr; v = v->fNext) {
1617         if (!connected(v)) {
1618             continue;
1619         }
1620         Edge* leftEnclosingEdge;
1621         Edge* rightEnclosingEdge;
1622         bool restartChecks;
1623         do {
1624             TESS_LOG("\nvertex %g: (%g,%g), alpha %d\n",
1625                      v->fID, v->fPoint.fX, v->fPoint.fY, v->fAlpha);
1626             restartChecks = false;
1627             find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
1628             v->fLeftEnclosingEdge = leftEnclosingEdge;
1629             v->fRightEnclosingEdge = rightEnclosingEdge;
1630             if (v->fFirstEdgeBelow) {
1631                 for (Edge* edge = v->fFirstEdgeBelow; edge; edge = edge->fNextEdgeBelow) {
1632                     if (check_for_intersection(
1633                             leftEnclosingEdge, edge, &activeEdges, &v, mesh, c, alloc) ||
1634                         check_for_intersection(
1635                             edge, rightEnclosingEdge, &activeEdges, &v, mesh, c, alloc)) {
1636                         if (Mode::kSimpleInnerPolygons == mode) {
1637                             return SimplifyResult::kAbort;
1638                         }
1639                         result = SimplifyResult::kFoundSelfIntersection;
1640                         restartChecks = true;
1641                         break;
1642                     }
1643                 }
1644             } else {
1645                 if (check_for_intersection(leftEnclosingEdge, rightEnclosingEdge,
1646                                            &activeEdges, &v, mesh, c, alloc)) {
1647                     if (Mode::kSimpleInnerPolygons == mode) {
1648                         return SimplifyResult::kAbort;
1649                     }
1650                     result = SimplifyResult::kFoundSelfIntersection;
1651                     restartChecks = true;
1652                 }
1653 
1654             }
1655         } while (restartChecks);
1656 #ifdef SK_DEBUG
1657         validate_edge_list(&activeEdges, c);
1658 #endif
1659         for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
1660             remove_edge(e, &activeEdges);
1661         }
1662         Edge* leftEdge = leftEnclosingEdge;
1663         for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1664             insert_edge(e, leftEdge, &activeEdges);
1665             leftEdge = e;
1666         }
1667     }
1668     SkASSERT(!activeEdges.fHead && !activeEdges.fTail);
1669     return result;
1670 }
1671 
1672 // Stage 5: Tessellate the simplified mesh into monotone polygons.
1673 
tessellate(SkPathFillType fillType,Mode mode,const VertexList & vertices,SkArenaAlloc & alloc)1674 Poly* tessellate(SkPathFillType fillType, Mode mode, const VertexList& vertices,
1675                  SkArenaAlloc& alloc) {
1676     TESS_LOG("\ntessellating simple polygons\n");
1677     int maxWindMagnitude = std::numeric_limits<int>::max();
1678     if (Mode::kSimpleInnerPolygons == mode && !SkPathFillType_IsEvenOdd(fillType)) {
1679         maxWindMagnitude = 1;
1680     }
1681     EdgeList activeEdges;
1682     Poly* polys = nullptr;
1683     for (Vertex* v = vertices.fHead; v != nullptr; v = v->fNext) {
1684         if (!connected(v)) {
1685             continue;
1686         }
1687 #if LOGGING_ENABLED
1688         TESS_LOG("\nvertex %g: (%g,%g), alpha %d\n", v->fID, v->fPoint.fX, v->fPoint.fY, v->fAlpha);
1689 #endif
1690         Edge* leftEnclosingEdge;
1691         Edge* rightEnclosingEdge;
1692         find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
1693         Poly* leftPoly;
1694         Poly* rightPoly;
1695         if (v->fFirstEdgeAbove) {
1696             leftPoly = v->fFirstEdgeAbove->fLeftPoly;
1697             rightPoly = v->fLastEdgeAbove->fRightPoly;
1698         } else {
1699             leftPoly = leftEnclosingEdge ? leftEnclosingEdge->fRightPoly : nullptr;
1700             rightPoly = rightEnclosingEdge ? rightEnclosingEdge->fLeftPoly : nullptr;
1701         }
1702 #if LOGGING_ENABLED
1703         TESS_LOG("edges above:\n");
1704         for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
1705             TESS_LOG("%g -> %g, lpoly %d, rpoly %d\n",
1706                      e->fTop->fID, e->fBottom->fID,
1707                      e->fLeftPoly ? e->fLeftPoly->fID : -1,
1708                      e->fRightPoly ? e->fRightPoly->fID : -1);
1709         }
1710         TESS_LOG("edges below:\n");
1711         for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1712             TESS_LOG("%g -> %g, lpoly %d, rpoly %d\n",
1713                      e->fTop->fID, e->fBottom->fID,
1714                      e->fLeftPoly ? e->fLeftPoly->fID : -1,
1715                      e->fRightPoly ? e->fRightPoly->fID : -1);
1716         }
1717 #endif
1718         if (v->fFirstEdgeAbove) {
1719             if (leftPoly) {
1720                 leftPoly = leftPoly->addEdge(v->fFirstEdgeAbove, Poly::kRight_Side, alloc);
1721             }
1722             if (rightPoly) {
1723                 rightPoly = rightPoly->addEdge(v->fLastEdgeAbove, Poly::kLeft_Side, alloc);
1724             }
1725             for (Edge* e = v->fFirstEdgeAbove; e != v->fLastEdgeAbove; e = e->fNextEdgeAbove) {
1726                 Edge* rightEdge = e->fNextEdgeAbove;
1727                 remove_edge(e, &activeEdges);
1728                 if (e->fRightPoly) {
1729                     e->fRightPoly->addEdge(e, Poly::kLeft_Side, alloc);
1730                 }
1731                 if (rightEdge->fLeftPoly && rightEdge->fLeftPoly != e->fRightPoly) {
1732                     rightEdge->fLeftPoly->addEdge(e, Poly::kRight_Side, alloc);
1733                 }
1734             }
1735             remove_edge(v->fLastEdgeAbove, &activeEdges);
1736             if (!v->fFirstEdgeBelow) {
1737                 if (leftPoly && rightPoly && leftPoly != rightPoly) {
1738                     SkASSERT(leftPoly->fPartner == nullptr && rightPoly->fPartner == nullptr);
1739                     rightPoly->fPartner = leftPoly;
1740                     leftPoly->fPartner = rightPoly;
1741                 }
1742             }
1743         }
1744         if (v->fFirstEdgeBelow) {
1745             if (!v->fFirstEdgeAbove) {
1746                 if (leftPoly && rightPoly) {
1747                     if (leftPoly == rightPoly) {
1748                         if (leftPoly->fTail && leftPoly->fTail->fSide == Poly::kLeft_Side) {
1749                             leftPoly = new_poly(&polys, leftPoly->lastVertex(),
1750                                                  leftPoly->fWinding, alloc);
1751                             leftEnclosingEdge->fRightPoly = leftPoly;
1752                         } else {
1753                             rightPoly = new_poly(&polys, rightPoly->lastVertex(),
1754                                                  rightPoly->fWinding, alloc);
1755                             rightEnclosingEdge->fLeftPoly = rightPoly;
1756                         }
1757                     }
1758                     Edge* join = alloc.make<Edge>(leftPoly->lastVertex(), v, 1, Edge::Type::kInner);
1759                     leftPoly = leftPoly->addEdge(join, Poly::kRight_Side, alloc);
1760                     rightPoly = rightPoly->addEdge(join, Poly::kLeft_Side, alloc);
1761                 }
1762             }
1763             Edge* leftEdge = v->fFirstEdgeBelow;
1764             leftEdge->fLeftPoly = leftPoly;
1765             insert_edge(leftEdge, leftEnclosingEdge, &activeEdges);
1766             for (Edge* rightEdge = leftEdge->fNextEdgeBelow; rightEdge;
1767                  rightEdge = rightEdge->fNextEdgeBelow) {
1768                 insert_edge(rightEdge, leftEdge, &activeEdges);
1769                 int winding = leftEdge->fLeftPoly ? leftEdge->fLeftPoly->fWinding : 0;
1770                 winding += leftEdge->fWinding;
1771                 if (winding != 0) {
1772                     if (abs(winding) > maxWindMagnitude) {
1773                         return nullptr;  // We can't have weighted wind in kSimpleInnerPolygons mode
1774                     }
1775                     Poly* poly = new_poly(&polys, v, winding, alloc);
1776                     leftEdge->fRightPoly = rightEdge->fLeftPoly = poly;
1777                 }
1778                 leftEdge = rightEdge;
1779             }
1780             v->fLastEdgeBelow->fRightPoly = rightPoly;
1781         }
1782 #if LOGGING_ENABLED
1783         TESS_LOG("\nactive edges:\n");
1784         for (Edge* e = activeEdges.fHead; e != nullptr; e = e->fRight) {
1785             TESS_LOG("%g -> %g, lpoly %d, rpoly %d\n",
1786                      e->fTop->fID, e->fBottom->fID,
1787                      e->fLeftPoly ? e->fLeftPoly->fID : -1,
1788                      e->fRightPoly ? e->fRightPoly->fID : -1);
1789         }
1790 #endif
1791     }
1792     return polys;
1793 }
1794 
remove_non_boundary_edges(const VertexList & mesh,SkPathFillType fillType,SkArenaAlloc & alloc)1795 void remove_non_boundary_edges(const VertexList& mesh, SkPathFillType fillType,
1796                                SkArenaAlloc& alloc) {
1797     TESS_LOG("removing non-boundary edges\n");
1798     EdgeList activeEdges;
1799     for (Vertex* v = mesh.fHead; v != nullptr; v = v->fNext) {
1800         if (!connected(v)) {
1801             continue;
1802         }
1803         Edge* leftEnclosingEdge;
1804         Edge* rightEnclosingEdge;
1805         find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
1806         bool prevFilled = leftEnclosingEdge &&
1807                           apply_fill_type(fillType, leftEnclosingEdge->fWinding);
1808         for (Edge* e = v->fFirstEdgeAbove; e;) {
1809             Edge* next = e->fNextEdgeAbove;
1810             remove_edge(e, &activeEdges);
1811             bool filled = apply_fill_type(fillType, e->fWinding);
1812             if (filled == prevFilled) {
1813                 disconnect(e);
1814             }
1815             prevFilled = filled;
1816             e = next;
1817         }
1818         Edge* prev = leftEnclosingEdge;
1819         for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1820             if (prev) {
1821                 e->fWinding += prev->fWinding;
1822             }
1823             insert_edge(e, prev, &activeEdges);
1824             prev = e;
1825         }
1826     }
1827 }
1828 
1829 // Note: this is the normal to the edge, but not necessarily unit length.
get_edge_normal(const Edge * e,SkVector * normal)1830 void get_edge_normal(const Edge* e, SkVector* normal) {
1831     normal->set(SkDoubleToScalar(e->fLine.fA),
1832                 SkDoubleToScalar(e->fLine.fB));
1833 }
1834 
1835 // Stage 5c: detect and remove "pointy" vertices whose edge normals point in opposite directions
1836 // and whose adjacent vertices are less than a quarter pixel from an edge. These are guaranteed to
1837 // invert on stroking.
1838 
simplify_boundary(EdgeList * boundary,Comparator & c,SkArenaAlloc & alloc)1839 void simplify_boundary(EdgeList* boundary, Comparator& c, SkArenaAlloc& alloc) {
1840     Edge* prevEdge = boundary->fTail;
1841     SkVector prevNormal;
1842     get_edge_normal(prevEdge, &prevNormal);
1843     for (Edge* e = boundary->fHead; e != nullptr;) {
1844         Vertex* prev = prevEdge->fWinding == 1 ? prevEdge->fTop : prevEdge->fBottom;
1845         Vertex* next = e->fWinding == 1 ? e->fBottom : e->fTop;
1846         double distPrev = e->dist(prev->fPoint);
1847         double distNext = prevEdge->dist(next->fPoint);
1848         SkVector normal;
1849         get_edge_normal(e, &normal);
1850         constexpr double kQuarterPixelSq = 0.25f * 0.25f;
1851         if (prev == next) {
1852             remove_edge(prevEdge, boundary);
1853             remove_edge(e, boundary);
1854             prevEdge = boundary->fTail;
1855             e = boundary->fHead;
1856             if (prevEdge) {
1857                 get_edge_normal(prevEdge, &prevNormal);
1858             }
1859         } else if (prevNormal.dot(normal) < 0.0 &&
1860             (distPrev * distPrev <= kQuarterPixelSq || distNext * distNext <= kQuarterPixelSq)) {
1861             Edge* join = new_edge(prev, next, Edge::Type::kInner, c, alloc);
1862             if (prev->fPoint != next->fPoint) {
1863                 join->fLine.normalize();
1864                 join->fLine = join->fLine * join->fWinding;
1865             }
1866             insert_edge(join, e, boundary);
1867             remove_edge(prevEdge, boundary);
1868             remove_edge(e, boundary);
1869             if (join->fLeft && join->fRight) {
1870                 prevEdge = join->fLeft;
1871                 e = join;
1872             } else {
1873                 prevEdge = boundary->fTail;
1874                 e = boundary->fHead; // join->fLeft ? join->fLeft : join;
1875             }
1876             get_edge_normal(prevEdge, &prevNormal);
1877         } else {
1878             prevEdge = e;
1879             prevNormal = normal;
1880             e = e->fRight;
1881         }
1882     }
1883 }
1884 
ss_connect(Vertex * v,Vertex * dest,Comparator & c,SkArenaAlloc & alloc)1885 void ss_connect(Vertex* v, Vertex* dest, Comparator& c, SkArenaAlloc& alloc) {
1886     if (v == dest) {
1887         return;
1888     }
1889     TESS_LOG("ss_connecting vertex %g to vertex %g\n", v->fID, dest->fID);
1890     if (v->fSynthetic) {
1891         connect(v, dest, Edge::Type::kConnector, c, alloc, 0);
1892     } else if (v->fPartner) {
1893         TESS_LOG("setting %g's partner to %g ", v->fPartner->fID, dest->fID);
1894         TESS_LOG("and %g's partner to null\n", v->fID);
1895         v->fPartner->fPartner = dest;
1896         v->fPartner = nullptr;
1897     }
1898 }
1899 
apply(VertexList * mesh,Comparator & c,EventList * events,SkArenaAlloc & alloc)1900 void Event::apply(VertexList* mesh, Comparator& c, EventList* events, SkArenaAlloc& alloc) {
1901     if (!fEdge) {
1902         return;
1903     }
1904     Vertex* prev = fEdge->fPrev->fVertex;
1905     Vertex* next = fEdge->fNext->fVertex;
1906     SSEdge* prevEdge = fEdge->fPrev->fPrev;
1907     SSEdge* nextEdge = fEdge->fNext->fNext;
1908     if (!prevEdge || !nextEdge || !prevEdge->fEdge || !nextEdge->fEdge) {
1909         return;
1910     }
1911     Vertex* dest = create_sorted_vertex(fPoint, fAlpha, mesh, prev, c, alloc);
1912     dest->fSynthetic = true;
1913     SSVertex* ssv = alloc.make<SSVertex>(dest);
1914     TESS_LOG("collapsing %g, %g (original edge %g -> %g) to %g (%g, %g) alpha %d\n",
1915              prev->fID, next->fID, fEdge->fEdge->fTop->fID, fEdge->fEdge->fBottom->fID, dest->fID,
1916              fPoint.fX, fPoint.fY, fAlpha);
1917     fEdge->fEdge = nullptr;
1918 
1919     ss_connect(prev, dest, c, alloc);
1920     ss_connect(next, dest, c, alloc);
1921 
1922     prevEdge->fNext = nextEdge->fPrev = ssv;
1923     ssv->fPrev = prevEdge;
1924     ssv->fNext = nextEdge;
1925     if (!prevEdge->fEdge || !nextEdge->fEdge) {
1926         return;
1927     }
1928     if (prevEdge->fEvent) {
1929         prevEdge->fEvent->fEdge = nullptr;
1930     }
1931     if (nextEdge->fEvent) {
1932         nextEdge->fEvent->fEdge = nullptr;
1933     }
1934     if (prevEdge->fPrev == nextEdge->fNext) {
1935         ss_connect(prevEdge->fPrev->fVertex, dest, c, alloc);
1936         prevEdge->fEdge = nextEdge->fEdge = nullptr;
1937     } else {
1938         compute_bisector(prevEdge->fEdge, nextEdge->fEdge, dest, alloc);
1939         SkASSERT(prevEdge != fEdge && nextEdge != fEdge);
1940         if (dest->fPartner) {
1941             create_event(prevEdge, events, alloc);
1942             create_event(nextEdge, events, alloc);
1943         } else {
1944             create_event(prevEdge, prevEdge->fPrev->fVertex, nextEdge, dest, events, c, alloc);
1945             create_event(nextEdge, nextEdge->fNext->fVertex, prevEdge, dest, events, c, alloc);
1946         }
1947     }
1948 }
1949 
is_overlap_edge(Edge * e)1950 bool is_overlap_edge(Edge* e) {
1951     if (e->fType == Edge::Type::kOuter) {
1952         return e->fWinding != 0 && e->fWinding != 1;
1953     } else if (e->fType == Edge::Type::kInner) {
1954         return e->fWinding != 0 && e->fWinding != -2;
1955     } else {
1956         return false;
1957     }
1958 }
1959 
1960 // This is a stripped-down version of tessellate() which computes edges which
1961 // join two filled regions, which represent overlap regions, and collapses them.
collapse_overlap_regions(VertexList * mesh,Comparator & c,SkArenaAlloc & alloc,EventComparator comp)1962 bool collapse_overlap_regions(VertexList* mesh, Comparator& c, SkArenaAlloc& alloc,
1963                               EventComparator comp) {
1964     TESS_LOG("\nfinding overlap regions\n");
1965     EdgeList activeEdges;
1966     EventList events(comp);
1967     SSVertexMap ssVertices;
1968     SSEdgeList ssEdges;
1969     for (Vertex* v = mesh->fHead; v != nullptr; v = v->fNext) {
1970         if (!connected(v)) {
1971             continue;
1972         }
1973         Edge* leftEnclosingEdge;
1974         Edge* rightEnclosingEdge;
1975         find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
1976         for (Edge* e = v->fLastEdgeAbove; e && e != leftEnclosingEdge;) {
1977             Edge* prev = e->fPrevEdgeAbove ? e->fPrevEdgeAbove : leftEnclosingEdge;
1978             remove_edge(e, &activeEdges);
1979             bool leftOverlap = prev && is_overlap_edge(prev);
1980             bool rightOverlap = is_overlap_edge(e);
1981             bool isOuterBoundary = e->fType == Edge::Type::kOuter &&
1982                                    (!prev || prev->fWinding == 0 || e->fWinding == 0);
1983             if (prev) {
1984                 e->fWinding -= prev->fWinding;
1985             }
1986             if (leftOverlap && rightOverlap) {
1987                 TESS_LOG("found interior overlap edge %g -> %g, disconnecting\n",
1988                          e->fTop->fID, e->fBottom->fID);
1989                 disconnect(e);
1990             } else if (leftOverlap || rightOverlap) {
1991                 TESS_LOG("found overlap edge %g -> %g%s\n",
1992                          e->fTop->fID, e->fBottom->fID,
1993                          isOuterBoundary ? ", is outer boundary" : "");
1994                 Vertex* prevVertex = e->fWinding < 0 ? e->fBottom : e->fTop;
1995                 Vertex* nextVertex = e->fWinding < 0 ? e->fTop : e->fBottom;
1996                 SSVertex* ssPrev = ssVertices[prevVertex];
1997                 if (!ssPrev) {
1998                     ssPrev = ssVertices[prevVertex] = alloc.make<SSVertex>(prevVertex);
1999                 }
2000                 SSVertex* ssNext = ssVertices[nextVertex];
2001                 if (!ssNext) {
2002                     ssNext = ssVertices[nextVertex] = alloc.make<SSVertex>(nextVertex);
2003                 }
2004                 SSEdge* ssEdge = alloc.make<SSEdge>(e, ssPrev, ssNext);
2005                 ssEdges.push_back(ssEdge);
2006 //                SkASSERT(!ssPrev->fNext && !ssNext->fPrev);
2007                 ssPrev->fNext = ssNext->fPrev = ssEdge;
2008                 create_event(ssEdge, &events, alloc);
2009                 if (!isOuterBoundary) {
2010                     disconnect(e);
2011                 }
2012             }
2013             e = prev;
2014         }
2015         Edge* prev = leftEnclosingEdge;
2016         for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
2017             if (prev) {
2018                 e->fWinding += prev->fWinding;
2019             }
2020             insert_edge(e, prev, &activeEdges);
2021             prev = e;
2022         }
2023     }
2024     bool complex = events.size() > 0;
2025 
2026     TESS_LOG("\ncollapsing overlap regions\n");
2027     TESS_LOG("skeleton before:\n");
2028     dump_skel(ssEdges);
2029     while (events.size() > 0) {
2030         Event* event = events.top();
2031         events.pop();
2032         event->apply(mesh, c, &events, alloc);
2033     }
2034     TESS_LOG("skeleton after:\n");
2035     dump_skel(ssEdges);
2036     for (SSEdge* edge : ssEdges) {
2037         if (Edge* e = edge->fEdge) {
2038             connect(edge->fPrev->fVertex, edge->fNext->fVertex, e->fType, c, alloc, 0);
2039         }
2040     }
2041     return complex;
2042 }
2043 
inversion(Vertex * prev,Vertex * next,Edge * origEdge,Comparator & c)2044 bool inversion(Vertex* prev, Vertex* next, Edge* origEdge, Comparator& c) {
2045     if (!prev || !next) {
2046         return true;
2047     }
2048     int winding = c.sweep_lt(prev->fPoint, next->fPoint) ? 1 : -1;
2049     return winding != origEdge->fWinding;
2050 }
2051 
2052 // Stage 5d: Displace edges by half a pixel inward and outward along their normals. Intersect to
2053 // find new vertices, and set zero alpha on the exterior and one alpha on the interior. Build a
2054 // new antialiased mesh from those vertices.
2055 
stroke_boundary(EdgeList * boundary,VertexList * innerMesh,VertexList * outerMesh,Comparator & c,SkArenaAlloc & alloc)2056 void stroke_boundary(EdgeList* boundary, VertexList* innerMesh, VertexList* outerMesh,
2057                      Comparator& c, SkArenaAlloc& alloc) {
2058     TESS_LOG("\nstroking boundary\n");
2059     // A boundary with fewer than 3 edges is degenerate.
2060     if (!boundary->fHead || !boundary->fHead->fRight || !boundary->fHead->fRight->fRight) {
2061         return;
2062     }
2063     Edge* prevEdge = boundary->fTail;
2064     Vertex* prevV = prevEdge->fWinding > 0 ? prevEdge->fTop : prevEdge->fBottom;
2065     SkVector prevNormal;
2066     get_edge_normal(prevEdge, &prevNormal);
2067     double radius = 0.5;
2068     Line prevInner(prevEdge->fLine);
2069     prevInner.fC -= radius;
2070     Line prevOuter(prevEdge->fLine);
2071     prevOuter.fC += radius;
2072     VertexList innerVertices;
2073     VertexList outerVertices;
2074     bool innerInversion = true;
2075     bool outerInversion = true;
2076     for (Edge* e = boundary->fHead; e != nullptr; e = e->fRight) {
2077         Vertex* v = e->fWinding > 0 ? e->fTop : e->fBottom;
2078         SkVector normal;
2079         get_edge_normal(e, &normal);
2080         Line inner(e->fLine);
2081         inner.fC -= radius;
2082         Line outer(e->fLine);
2083         outer.fC += radius;
2084         SkPoint innerPoint, outerPoint;
2085         TESS_LOG("stroking vertex %g (%g, %g)\n", v->fID, v->fPoint.fX, v->fPoint.fY);
2086         if (!prevEdge->fLine.nearParallel(e->fLine) && prevInner.intersect(inner, &innerPoint) &&
2087             prevOuter.intersect(outer, &outerPoint)) {
2088             float cosAngle = normal.dot(prevNormal);
2089             if (cosAngle < -kCosMiterAngle) {
2090                 Vertex* nextV = e->fWinding > 0 ? e->fBottom : e->fTop;
2091 
2092                 // This is a pointy vertex whose angle is smaller than the threshold; miter it.
2093                 Line bisector(innerPoint, outerPoint);
2094                 Line tangent(v->fPoint, v->fPoint + SkPoint::Make(bisector.fA, bisector.fB));
2095                 if (tangent.fA == 0 && tangent.fB == 0) {
2096                     continue;
2097                 }
2098                 tangent.normalize();
2099                 Line innerTangent(tangent);
2100                 Line outerTangent(tangent);
2101                 innerTangent.fC -= 0.5;
2102                 outerTangent.fC += 0.5;
2103                 SkPoint innerPoint1, innerPoint2, outerPoint1, outerPoint2;
2104                 if (prevNormal.cross(normal) > 0) {
2105                     // Miter inner points
2106                     if (!innerTangent.intersect(prevInner, &innerPoint1) ||
2107                         !innerTangent.intersect(inner, &innerPoint2) ||
2108                         !outerTangent.intersect(bisector, &outerPoint)) {
2109                         continue;
2110                     }
2111                     Line prevTangent(prevV->fPoint,
2112                                      prevV->fPoint + SkVector::Make(prevOuter.fA, prevOuter.fB));
2113                     Line nextTangent(nextV->fPoint,
2114                                      nextV->fPoint + SkVector::Make(outer.fA, outer.fB));
2115                     if (prevTangent.dist(outerPoint) > 0) {
2116                         bisector.intersect(prevTangent, &outerPoint);
2117                     }
2118                     if (nextTangent.dist(outerPoint) < 0) {
2119                         bisector.intersect(nextTangent, &outerPoint);
2120                     }
2121                     outerPoint1 = outerPoint2 = outerPoint;
2122                 } else {
2123                     // Miter outer points
2124                     if (!outerTangent.intersect(prevOuter, &outerPoint1) ||
2125                         !outerTangent.intersect(outer, &outerPoint2)) {
2126                         continue;
2127                     }
2128                     Line prevTangent(prevV->fPoint,
2129                                      prevV->fPoint + SkVector::Make(prevInner.fA, prevInner.fB));
2130                     Line nextTangent(nextV->fPoint,
2131                                      nextV->fPoint + SkVector::Make(inner.fA, inner.fB));
2132                     if (prevTangent.dist(innerPoint) > 0) {
2133                         bisector.intersect(prevTangent, &innerPoint);
2134                     }
2135                     if (nextTangent.dist(innerPoint) < 0) {
2136                         bisector.intersect(nextTangent, &innerPoint);
2137                     }
2138                     innerPoint1 = innerPoint2 = innerPoint;
2139                 }
2140                 if (!innerPoint1.isFinite() || !innerPoint2.isFinite() ||
2141                     !outerPoint1.isFinite() || !outerPoint2.isFinite()) {
2142                     continue;
2143                 }
2144                 TESS_LOG("inner (%g, %g), (%g, %g), ",
2145                          innerPoint1.fX, innerPoint1.fY, innerPoint2.fX, innerPoint2.fY);
2146                 TESS_LOG("outer (%g, %g), (%g, %g)\n",
2147                          outerPoint1.fX, outerPoint1.fY, outerPoint2.fX, outerPoint2.fY);
2148                 Vertex* innerVertex1 = alloc.make<Vertex>(innerPoint1, 255);
2149                 Vertex* innerVertex2 = alloc.make<Vertex>(innerPoint2, 255);
2150                 Vertex* outerVertex1 = alloc.make<Vertex>(outerPoint1, 0);
2151                 Vertex* outerVertex2 = alloc.make<Vertex>(outerPoint2, 0);
2152                 innerVertex1->fPartner = outerVertex1;
2153                 innerVertex2->fPartner = outerVertex2;
2154                 outerVertex1->fPartner = innerVertex1;
2155                 outerVertex2->fPartner = innerVertex2;
2156                 if (!inversion(innerVertices.fTail, innerVertex1, prevEdge, c)) {
2157                     innerInversion = false;
2158                 }
2159                 if (!inversion(outerVertices.fTail, outerVertex1, prevEdge, c)) {
2160                     outerInversion = false;
2161                 }
2162                 innerVertices.append(innerVertex1);
2163                 innerVertices.append(innerVertex2);
2164                 outerVertices.append(outerVertex1);
2165                 outerVertices.append(outerVertex2);
2166             } else {
2167                 TESS_LOG("inner (%g, %g), ", innerPoint.fX, innerPoint.fY);
2168                 TESS_LOG("outer (%g, %g)\n", outerPoint.fX, outerPoint.fY);
2169                 Vertex* innerVertex = alloc.make<Vertex>(innerPoint, 255);
2170                 Vertex* outerVertex = alloc.make<Vertex>(outerPoint, 0);
2171                 innerVertex->fPartner = outerVertex;
2172                 outerVertex->fPartner = innerVertex;
2173                 if (!inversion(innerVertices.fTail, innerVertex, prevEdge, c)) {
2174                     innerInversion = false;
2175                 }
2176                 if (!inversion(outerVertices.fTail, outerVertex, prevEdge, c)) {
2177                     outerInversion = false;
2178                 }
2179                 innerVertices.append(innerVertex);
2180                 outerVertices.append(outerVertex);
2181             }
2182         }
2183         prevInner = inner;
2184         prevOuter = outer;
2185         prevV = v;
2186         prevEdge = e;
2187         prevNormal = normal;
2188     }
2189     if (!inversion(innerVertices.fTail, innerVertices.fHead, prevEdge, c)) {
2190         innerInversion = false;
2191     }
2192     if (!inversion(outerVertices.fTail, outerVertices.fHead, prevEdge, c)) {
2193         outerInversion = false;
2194     }
2195     // Outer edges get 1 winding, and inner edges get -2 winding. This ensures that the interior
2196     // is always filled (1 + -2 = -1 for normal cases, 1 + 2 = 3 for thin features where the
2197     // interior inverts).
2198     // For total inversion cases, the shape has now reversed handedness, so invert the winding
2199     // so it will be detected during collapse_overlap_regions().
2200     int innerWinding = innerInversion ? 2 : -2;
2201     int outerWinding = outerInversion ? -1 : 1;
2202     for (Vertex* v = innerVertices.fHead; v && v->fNext; v = v->fNext) {
2203         connect(v, v->fNext, Edge::Type::kInner, c, alloc, innerWinding);
2204     }
2205     connect(innerVertices.fTail, innerVertices.fHead, Edge::Type::kInner, c, alloc, innerWinding);
2206     for (Vertex* v = outerVertices.fHead; v && v->fNext; v = v->fNext) {
2207         connect(v, v->fNext, Edge::Type::kOuter, c, alloc, outerWinding);
2208     }
2209     connect(outerVertices.fTail, outerVertices.fHead, Edge::Type::kOuter, c, alloc, outerWinding);
2210     innerMesh->append(innerVertices);
2211     outerMesh->append(outerVertices);
2212 }
2213 
extract_boundary(EdgeList * boundary,Edge * e,SkPathFillType fillType,SkArenaAlloc & alloc)2214 void extract_boundary(EdgeList* boundary, Edge* e, SkPathFillType fillType, SkArenaAlloc& alloc) {
2215     TESS_LOG("\nextracting boundary\n");
2216     bool down = apply_fill_type(fillType, e->fWinding);
2217     Vertex* start = down ? e->fTop : e->fBottom;
2218     do {
2219         e->fWinding = down ? 1 : -1;
2220         Edge* next;
2221         e->fLine.normalize();
2222         e->fLine = e->fLine * e->fWinding;
2223         boundary->append(e);
2224         if (down) {
2225             // Find outgoing edge, in clockwise order.
2226             if ((next = e->fNextEdgeAbove)) {
2227                 down = false;
2228             } else if ((next = e->fBottom->fLastEdgeBelow)) {
2229                 down = true;
2230             } else if ((next = e->fPrevEdgeAbove)) {
2231                 down = false;
2232             }
2233         } else {
2234             // Find outgoing edge, in counter-clockwise order.
2235             if ((next = e->fPrevEdgeBelow)) {
2236                 down = true;
2237             } else if ((next = e->fTop->fFirstEdgeAbove)) {
2238                 down = false;
2239             } else if ((next = e->fNextEdgeBelow)) {
2240                 down = true;
2241             }
2242         }
2243         disconnect(e);
2244         e = next;
2245     } while (e && (down ? e->fTop : e->fBottom) != start);
2246 }
2247 
2248 // Stage 5b: Extract boundaries from mesh, simplify and stroke them into a new mesh.
2249 
extract_boundaries(const VertexList & inMesh,VertexList * innerVertices,VertexList * outerVertices,SkPathFillType fillType,Comparator & c,SkArenaAlloc & alloc)2250 void extract_boundaries(const VertexList& inMesh, VertexList* innerVertices,
2251                         VertexList* outerVertices, SkPathFillType fillType,
2252                         Comparator& c, SkArenaAlloc& alloc) {
2253     remove_non_boundary_edges(inMesh, fillType, alloc);
2254     for (Vertex* v = inMesh.fHead; v; v = v->fNext) {
2255         while (v->fFirstEdgeBelow) {
2256             EdgeList boundary;
2257             extract_boundary(&boundary, v->fFirstEdgeBelow, fillType, alloc);
2258             simplify_boundary(&boundary, c, alloc);
2259             stroke_boundary(&boundary, innerVertices, outerVertices, c, alloc);
2260         }
2261     }
2262 }
2263 
2264 // This is a driver function that calls stages 2-5 in turn.
2265 
contours_to_mesh(VertexList * contours,int contourCnt,Mode mode,VertexList * mesh,Comparator & c,SkArenaAlloc & alloc)2266 void contours_to_mesh(VertexList* contours, int contourCnt, Mode mode,
2267                       VertexList* mesh, Comparator& c, SkArenaAlloc& alloc) {
2268 #if LOGGING_ENABLED
2269     for (int i = 0; i < contourCnt; ++i) {
2270         Vertex* v = contours[i].fHead;
2271         SkASSERT(v);
2272         TESS_LOG("path.moveTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY);
2273         for (v = v->fNext; v; v = v->fNext) {
2274             TESS_LOG("path.lineTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY);
2275         }
2276     }
2277 #endif
2278     sanitize_contours(contours, contourCnt, mode);
2279     build_edges(contours, contourCnt, mesh, c, alloc);
2280 }
2281 
sort_mesh(VertexList * vertices,Comparator & c,SkArenaAlloc & alloc)2282 void sort_mesh(VertexList* vertices, Comparator& c, SkArenaAlloc& alloc) {
2283     if (!vertices || !vertices->fHead) {
2284         return;
2285     }
2286 
2287     // Sort vertices in Y (secondarily in X).
2288     if (c.fDirection == Comparator::Direction::kHorizontal) {
2289         merge_sort<sweep_lt_horiz>(vertices);
2290     } else {
2291         merge_sort<sweep_lt_vert>(vertices);
2292     }
2293 #if LOGGING_ENABLED
2294     for (Vertex* v = vertices->fHead; v != nullptr; v = v->fNext) {
2295         static float gID = 0.0f;
2296         v->fID = gID++;
2297     }
2298 #endif
2299 }
2300 
contours_to_polys(VertexList * contours,int contourCnt,SkPathFillType fillType,const SkRect & pathBounds,Mode mode,VertexList * outerMesh,SkArenaAlloc & alloc)2301 Poly* contours_to_polys(VertexList* contours, int contourCnt, SkPathFillType fillType,
2302                         const SkRect& pathBounds, Mode mode, VertexList* outerMesh,
2303                         SkArenaAlloc& alloc) {
2304     Comparator c(pathBounds.width() > pathBounds.height() ? Comparator::Direction::kHorizontal
2305                                                           : Comparator::Direction::kVertical);
2306     VertexList mesh;
2307     contours_to_mesh(contours, contourCnt, mode, &mesh, c, alloc);
2308     sort_mesh(&mesh, c, alloc);
2309     merge_coincident_vertices(&mesh, c, alloc);
2310     if (SimplifyResult::kAbort == simplify(mode, &mesh, c, alloc)) {
2311         return nullptr;
2312     }
2313     TESS_LOG("\nsimplified mesh:\n");
2314     dump_mesh(mesh);
2315     if (Mode::kEdgeAntialias == mode) {
2316         VertexList innerMesh;
2317         extract_boundaries(mesh, &innerMesh, outerMesh, fillType, c, alloc);
2318         sort_mesh(&innerMesh, c, alloc);
2319         sort_mesh(outerMesh, c, alloc);
2320         merge_coincident_vertices(&innerMesh, c, alloc);
2321         bool was_complex = merge_coincident_vertices(outerMesh, c, alloc);
2322         auto result = simplify(mode, &innerMesh, c, alloc);
2323         SkASSERT(SimplifyResult::kAbort != result);
2324         was_complex = (SimplifyResult::kFoundSelfIntersection == result) || was_complex;
2325         result = simplify(mode, outerMesh, c, alloc);
2326         SkASSERT(SimplifyResult::kAbort != result);
2327         was_complex = (SimplifyResult::kFoundSelfIntersection == result) || was_complex;
2328         TESS_LOG("\ninner mesh before:\n");
2329         dump_mesh(innerMesh);
2330         TESS_LOG("\nouter mesh before:\n");
2331         dump_mesh(*outerMesh);
2332         EventComparator eventLT(EventComparator::Op::kLessThan);
2333         EventComparator eventGT(EventComparator::Op::kGreaterThan);
2334         was_complex = collapse_overlap_regions(&innerMesh, c, alloc, eventLT) || was_complex;
2335         was_complex = collapse_overlap_regions(outerMesh, c, alloc, eventGT) || was_complex;
2336         if (was_complex) {
2337             TESS_LOG("found complex mesh; taking slow path\n");
2338             VertexList aaMesh;
2339             TESS_LOG("\ninner mesh after:\n");
2340             dump_mesh(innerMesh);
2341             TESS_LOG("\nouter mesh after:\n");
2342             dump_mesh(*outerMesh);
2343             connect_partners(outerMesh, c, alloc);
2344             connect_partners(&innerMesh, c, alloc);
2345             sorted_merge(&innerMesh, outerMesh, &aaMesh, c);
2346             merge_coincident_vertices(&aaMesh, c, alloc);
2347             result = simplify(mode, &aaMesh, c, alloc);
2348             SkASSERT(SimplifyResult::kAbort != result);
2349             TESS_LOG("combined and simplified mesh:\n");
2350             dump_mesh(aaMesh);
2351             outerMesh->fHead = outerMesh->fTail = nullptr;
2352             return tessellate(fillType, mode, aaMesh, alloc);
2353         } else {
2354             TESS_LOG("no complex polygons; taking fast path\n");
2355             return tessellate(fillType, mode, innerMesh, alloc);
2356         }
2357     } else {
2358         return tessellate(fillType, mode, mesh, alloc);
2359     }
2360 }
2361 
2362 // Stage 6: Triangulate the monotone polygons into a vertex buffer.
polys_to_triangles(Poly * polys,SkPathFillType fillType,Mode mode,void * data)2363 void* polys_to_triangles(Poly* polys, SkPathFillType fillType, Mode mode, void* data) {
2364     bool emitCoverage = (Mode::kEdgeAntialias == mode);
2365     for (Poly* poly = polys; poly; poly = poly->fNext) {
2366         if (apply_fill_type(fillType, poly)) {
2367             data = poly->emit(emitCoverage, data);
2368         }
2369     }
2370     return data;
2371 }
2372 
path_to_polys(const SkPath & path,SkScalar tolerance,const SkRect & clipBounds,int contourCnt,SkArenaAlloc & alloc,Mode mode,bool * isLinear,VertexList * outerMesh)2373 Poly* path_to_polys(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
2374                     int contourCnt, SkArenaAlloc& alloc, Mode mode, bool* isLinear,
2375                     VertexList* outerMesh) {
2376     SkPathFillType fillType = path.getFillType();
2377     if (SkPathFillType_IsInverse(fillType)) {
2378         contourCnt++;
2379     }
2380     std::unique_ptr<VertexList[]> contours(new VertexList[contourCnt]);
2381 
2382     path_to_contours(path, tolerance, clipBounds, contours.get(), alloc, mode, isLinear);
2383     return contours_to_polys(contours.get(), contourCnt, path.getFillType(), path.getBounds(),
2384                              mode, outerMesh, alloc);
2385 }
2386 
get_contour_count(const SkPath & path,SkScalar tolerance)2387 int get_contour_count(const SkPath& path, SkScalar tolerance) {
2388     // We could theoretically be more aggressive about not counting empty contours, but we need to
2389     // actually match the exact number of contour linked lists the tessellator will create later on.
2390     int contourCnt = 1;
2391     bool hasPoints = false;
2392 
2393     SkPath::Iter iter(path, false);
2394     SkPath::Verb verb;
2395     SkPoint pts[4];
2396     bool first = true;
2397     while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
2398         switch (verb) {
2399             case SkPath::kMove_Verb:
2400                 if (!first) {
2401                     ++contourCnt;
2402                 }
2403                 // fallthru.
2404             case SkPath::kLine_Verb:
2405             case SkPath::kConic_Verb:
2406             case SkPath::kQuad_Verb:
2407             case SkPath::kCubic_Verb:
2408                 hasPoints = true;
2409                 // fallthru to break.
2410             default:
2411                 break;
2412         }
2413         first = false;
2414     }
2415     if (!hasPoints) {
2416         return 0;
2417     }
2418     return contourCnt;
2419 }
2420 
count_points(Poly * polys,SkPathFillType fillType)2421 int64_t count_points(Poly* polys, SkPathFillType fillType) {
2422     int64_t count = 0;
2423     for (Poly* poly = polys; poly; poly = poly->fNext) {
2424         if (apply_fill_type(fillType, poly) && poly->fCount >= 3) {
2425             count += (poly->fCount - 2) * (TESSELLATOR_WIREFRAME ? 6 : 3);
2426         }
2427     }
2428     return count;
2429 }
2430 
count_outer_mesh_points(const VertexList & outerMesh)2431 int64_t count_outer_mesh_points(const VertexList& outerMesh) {
2432     int64_t count = 0;
2433     for (Vertex* v = outerMesh.fHead; v; v = v->fNext) {
2434         for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
2435             count += TESSELLATOR_WIREFRAME ? 12 : 6;
2436         }
2437     }
2438     return count;
2439 }
2440 
outer_mesh_to_triangles(const VertexList & outerMesh,bool emitCoverage,void * data)2441 void* outer_mesh_to_triangles(const VertexList& outerMesh, bool emitCoverage, void* data) {
2442     for (Vertex* v = outerMesh.fHead; v; v = v->fNext) {
2443         for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
2444             Vertex* v0 = e->fTop;
2445             Vertex* v1 = e->fBottom;
2446             Vertex* v2 = e->fBottom->fPartner;
2447             Vertex* v3 = e->fTop->fPartner;
2448             data = emit_triangle(v0, v1, v2, emitCoverage, data);
2449             data = emit_triangle(v0, v2, v3, emitCoverage, data);
2450         }
2451     }
2452     return data;
2453 }
2454 
2455 } // namespace
2456 
2457 namespace GrTessellator {
2458 
2459 // Stage 6: Triangulate the monotone polygons into a vertex buffer.
2460 
PathToTriangles(const SkPath & path,SkScalar tolerance,const SkRect & clipBounds,GrEagerVertexAllocator * vertexAllocator,Mode mode,bool * isLinear)2461 int PathToTriangles(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
2462                     GrEagerVertexAllocator* vertexAllocator, Mode mode, bool* isLinear) {
2463     int contourCnt = get_contour_count(path, tolerance);
2464     if (contourCnt <= 0) {
2465         *isLinear = true;
2466         return 0;
2467     }
2468     SkArenaAlloc alloc(kArenaChunkSize);
2469     VertexList outerMesh;
2470     Poly* polys = path_to_polys(path, tolerance, clipBounds, contourCnt, alloc, mode,
2471                                 isLinear, &outerMesh);
2472     SkPathFillType fillType = (Mode::kEdgeAntialias == mode) ?
2473             SkPathFillType::kWinding : path.getFillType();
2474     int64_t count64 = count_points(polys, fillType);
2475     if (Mode::kEdgeAntialias == mode) {
2476         count64 += count_outer_mesh_points(outerMesh);
2477     }
2478     if (0 == count64 || count64 > SK_MaxS32) {
2479         return 0;
2480     }
2481     int count = count64;
2482 
2483     size_t vertexStride = GetVertexStride(mode);
2484     void* verts = vertexAllocator->lock(vertexStride, count);
2485     if (!verts) {
2486         SkDebugf("Could not allocate vertices\n");
2487         return 0;
2488     }
2489 
2490     TESS_LOG("emitting %d verts\n", count);
2491     void* end = polys_to_triangles(polys, fillType, mode, verts);
2492     end = outer_mesh_to_triangles(outerMesh, true, end);
2493 
2494     int actualCount = static_cast<int>((static_cast<uint8_t*>(end) - static_cast<uint8_t*>(verts))
2495                                        / vertexStride);
2496     SkASSERT(actualCount <= count);
2497     vertexAllocator->unlock(actualCount);
2498     return actualCount;
2499 }
2500 
PathToVertices(const SkPath & path,SkScalar tolerance,const SkRect & clipBounds,GrTessellator::WindingVertex ** verts)2501 int PathToVertices(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
2502                    GrTessellator::WindingVertex** verts) {
2503     int contourCnt = get_contour_count(path, tolerance);
2504     if (contourCnt <= 0) {
2505         *verts = nullptr;
2506         return 0;
2507     }
2508     SkArenaAlloc alloc(kArenaChunkSize);
2509     bool isLinear;
2510     Poly* polys = path_to_polys(path, tolerance, clipBounds, contourCnt, alloc, Mode::kNormal,
2511                                 &isLinear, nullptr);
2512     SkPathFillType fillType = path.getFillType();
2513     int64_t count64 = count_points(polys, fillType);
2514     if (0 == count64 || count64 > SK_MaxS32) {
2515         *verts = nullptr;
2516         return 0;
2517     }
2518     int count = count64;
2519 
2520     *verts = new GrTessellator::WindingVertex[count];
2521     GrTessellator::WindingVertex* vertsEnd = *verts;
2522     SkPoint* points = new SkPoint[count];
2523     SkPoint* pointsEnd = points;
2524     for (Poly* poly = polys; poly; poly = poly->fNext) {
2525         if (apply_fill_type(fillType, poly)) {
2526             SkPoint* start = pointsEnd;
2527             pointsEnd = static_cast<SkPoint*>(poly->emit(false, pointsEnd));
2528             while (start != pointsEnd) {
2529                 vertsEnd->fPos = *start;
2530                 vertsEnd->fWinding = poly->fWinding;
2531                 ++start;
2532                 ++vertsEnd;
2533             }
2534         }
2535     }
2536     int actualCount = static_cast<int>(vertsEnd - *verts);
2537     SkASSERT(actualCount <= count);
2538     SkASSERT(pointsEnd - points == actualCount);
2539     delete[] points;
2540     return actualCount;
2541 }
2542 
2543 } // namespace
2544