• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 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/geometry/GrAATriangulator.h"
9 
10 #include "src/gpu/BufferWriter.h"
11 #include "src/gpu/GrEagerVertexAllocator.h"
12 #include <queue>
13 #include <vector>
14 #include <unordered_map>
15 
16 #if TRIANGULATOR_LOGGING
17 #define TESS_LOG SkDebugf
18 #define DUMP_MESH(MESH) (MESH).dump()
19 #else
20 #define TESS_LOG(...)
21 #define DUMP_MESH(MESH)
22 #endif
23 
24 constexpr static float kCosMiterAngle = 0.97f; // Corresponds to an angle of ~14 degrees.
25 
26 using EdgeType = GrTriangulator::EdgeType;
27 using Vertex = GrTriangulator::Vertex;
28 using VertexList = GrTriangulator::VertexList;
29 using Line = GrTriangulator::Line;
30 using Edge = GrTriangulator::Edge;
31 using EdgeList = GrTriangulator::EdgeList;
32 using Poly = GrTriangulator::Poly;
33 using Comparator = GrTriangulator::Comparator;
34 using SSEdge = GrAATriangulator::SSEdge;
35 using EventList = GrAATriangulator::EventList;
36 using Event = GrAATriangulator::Event;
37 using EventComparator = GrAATriangulator::EventComparator;
38 
39 struct SSVertex {
SSVertexSSVertex40     SSVertex(Vertex* v) : fVertex(v), fPrev(nullptr), fNext(nullptr) {}
41     Vertex* fVertex;
42     SSEdge* fPrev;
43     SSEdge* fNext;
44 };
45 
46 struct GrAATriangulator::SSEdge {
SSEdgeGrAATriangulator::SSEdge47     SSEdge(Edge* edge, SSVertex* prev, SSVertex* next)
48       : fEdge(edge), fEvent(nullptr), fPrev(prev), fNext(next) {
49     }
50     Edge*     fEdge;
51     Event*    fEvent;
52     SSVertex* fPrev;
53     SSVertex* fNext;
54 };
55 
56 typedef std::unordered_map<Vertex*, SSVertex*> SSVertexMap;
57 typedef std::vector<SSEdge*> SSEdgeList;
58 typedef std::priority_queue<Event*, std::vector<Event*>, EventComparator> EventPQ;
59 
60 struct GrAATriangulator::EventList : EventPQ {
EventListGrAATriangulator::EventList61     EventList(EventComparator comparison) : EventPQ(comparison) {
62     }
63 };
64 
makeEvent(SSEdge * e,EventList * events) const65 void GrAATriangulator::makeEvent(SSEdge* e, EventList* events) const {
66     Vertex* prev = e->fPrev->fVertex;
67     Vertex* next = e->fNext->fVertex;
68     if (prev == next || !prev->fPartner || !next->fPartner) {
69         return;
70     }
71     Edge bisector1(prev, prev->fPartner, 1, EdgeType::kConnector);
72     Edge bisector2(next, next->fPartner, 1, EdgeType::kConnector);
73     SkPoint p;
74     uint8_t alpha;
75     if (bisector1.intersect(bisector2, &p, &alpha)) {
76         TESS_LOG("found edge event for %g, %g (original %g -> %g), "
77                  "will collapse to %g,%g alpha %d\n",
78                   prev->fID, next->fID, e->fEdge->fTop->fID, e->fEdge->fBottom->fID, p.fX, p.fY,
79                   alpha);
80         e->fEvent = fAlloc->make<Event>(e, p, alpha);
81         events->push(e->fEvent);
82     }
83 }
84 
makeEvent(SSEdge * edge,Vertex * v,SSEdge * other,Vertex * dest,EventList * events,const Comparator & c) const85 void GrAATriangulator::makeEvent(SSEdge* edge, Vertex* v, SSEdge* other, Vertex* dest,
86                                  EventList* events, const Comparator& c) const {
87     if (!v->fPartner) {
88         return;
89     }
90     Vertex* top = edge->fEdge->fTop;
91     Vertex* bottom = edge->fEdge->fBottom;
92     if (!top || !bottom ) {
93         return;
94     }
95     Line line = edge->fEdge->fLine;
96     line.fC = -(dest->fPoint.fX * line.fA  + dest->fPoint.fY * line.fB);
97     Edge bisector(v, v->fPartner, 1, EdgeType::kConnector);
98     SkPoint p;
99     uint8_t alpha = dest->fAlpha;
100     if (line.intersect(bisector.fLine, &p) && !c.sweep_lt(p, top->fPoint) &&
101                                                c.sweep_lt(p, bottom->fPoint)) {
102         TESS_LOG("found p edge event for %g, %g (original %g -> %g), "
103                  "will collapse to %g,%g alpha %d\n",
104                  dest->fID, v->fID, top->fID, bottom->fID, p.fX, p.fY, alpha);
105         edge->fEvent = fAlloc->make<Event>(edge, p, alpha);
106         events->push(edge->fEvent);
107     }
108 }
109 
connectPartners(VertexList * mesh,const Comparator & c)110 void GrAATriangulator::connectPartners(VertexList* mesh, const Comparator& c) {
111     for (Vertex* outer = mesh->fHead; outer; outer = outer->fNext) {
112         if (Vertex* inner = outer->fPartner) {
113             if ((inner->fPrev || inner->fNext) && (outer->fPrev || outer->fNext)) {
114                 // Connector edges get zero winding, since they're only structural (i.e., to ensure
115                 // no 0-0-0 alpha triangles are produced), and shouldn't affect the poly winding
116                 // number.
117                 this->makeConnectingEdge(outer, inner, EdgeType::kConnector, c, 0);
118                 inner->fPartner = outer->fPartner = nullptr;
119             }
120         }
121     }
122 }
123 
dump_skel(const SSEdgeList & ssEdges)124 static void dump_skel(const SSEdgeList& ssEdges) {
125 #if TRIANGULATOR_LOGGING
126     for (SSEdge* edge : ssEdges) {
127         if (edge->fEdge) {
128             TESS_LOG("skel edge %g -> %g",
129                 edge->fPrev->fVertex->fID,
130                 edge->fNext->fVertex->fID);
131             if (edge->fEdge->fTop && edge->fEdge->fBottom) {
132                 TESS_LOG(" (original %g -> %g)\n",
133                          edge->fEdge->fTop->fID,
134                          edge->fEdge->fBottom->fID);
135             } else {
136                 TESS_LOG("\n");
137             }
138         }
139     }
140 #endif
141 }
142 
removeNonBoundaryEdges(const VertexList & mesh) const143 void GrAATriangulator::removeNonBoundaryEdges(const VertexList& mesh) const {
144     TESS_LOG("removing non-boundary edges\n");
145     EdgeList activeEdges;
146     for (Vertex* v = mesh.fHead; v != nullptr; v = v->fNext) {
147         if (!v->isConnected()) {
148             continue;
149         }
150         Edge* leftEnclosingEdge;
151         Edge* rightEnclosingEdge;
152         FindEnclosingEdges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
153         bool prevFilled = leftEnclosingEdge && this->applyFillType(leftEnclosingEdge->fWinding);
154         for (Edge* e = v->fFirstEdgeAbove; e;) {
155             Edge* next = e->fNextEdgeAbove;
156             activeEdges.remove(e);
157             bool filled = this->applyFillType(e->fWinding);
158             if (filled == prevFilled) {
159                 e->disconnect();
160             }
161             prevFilled = filled;
162             e = next;
163         }
164         Edge* prev = leftEnclosingEdge;
165         for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
166             if (prev) {
167                 e->fWinding += prev->fWinding;
168             }
169             activeEdges.insert(e, prev);
170             prev = e;
171         }
172     }
173 }
174 
175 // Note: this is the normal to the edge, but not necessarily unit length.
get_edge_normal(const Edge * e,SkVector * normal)176 static void get_edge_normal(const Edge* e, SkVector* normal) {
177     normal->set(SkDoubleToScalar(e->fLine.fA),
178                 SkDoubleToScalar(e->fLine.fB));
179 }
180 
181 // Stage 5c: detect and remove "pointy" vertices whose edge normals point in opposite directions
182 // and whose adjacent vertices are less than a quarter pixel from an edge. These are guaranteed to
183 // invert on stroking.
184 
simplifyBoundary(EdgeList * boundary,const Comparator & c)185 void GrAATriangulator::simplifyBoundary(EdgeList* boundary, const Comparator& c) {
186     Edge* prevEdge = boundary->fTail;
187     SkVector prevNormal;
188     get_edge_normal(prevEdge, &prevNormal);
189     for (Edge* e = boundary->fHead; e != nullptr;) {
190         Vertex* prev = prevEdge->fWinding == 1 ? prevEdge->fTop : prevEdge->fBottom;
191         Vertex* next = e->fWinding == 1 ? e->fBottom : e->fTop;
192         double distPrev = e->dist(prev->fPoint);
193         double distNext = prevEdge->dist(next->fPoint);
194         SkVector normal;
195         get_edge_normal(e, &normal);
196         constexpr double kQuarterPixelSq = 0.25f * 0.25f;
197         if (prev == next) {
198             boundary->remove(prevEdge);
199             boundary->remove(e);
200             prevEdge = boundary->fTail;
201             e = boundary->fHead;
202             if (prevEdge) {
203                 get_edge_normal(prevEdge, &prevNormal);
204             }
205         } else if (prevNormal.dot(normal) < 0.0 &&
206             (distPrev * distPrev <= kQuarterPixelSq || distNext * distNext <= kQuarterPixelSq)) {
207             Edge* join = this->makeEdge(prev, next, EdgeType::kInner, c);
208             if (prev->fPoint != next->fPoint) {
209                 join->fLine.normalize();
210                 join->fLine = join->fLine * join->fWinding;
211             }
212             boundary->insert(join, e);
213             boundary->remove(prevEdge);
214             boundary->remove(e);
215             if (join->fLeft && join->fRight) {
216                 prevEdge = join->fLeft;
217                 e = join;
218             } else {
219                 prevEdge = boundary->fTail;
220                 e = boundary->fHead; // join->fLeft ? join->fLeft : join;
221             }
222             get_edge_normal(prevEdge, &prevNormal);
223         } else {
224             prevEdge = e;
225             prevNormal = normal;
226             e = e->fRight;
227         }
228     }
229 }
230 
connectSSEdge(Vertex * v,Vertex * dest,const Comparator & c)231 void GrAATriangulator::connectSSEdge(Vertex* v, Vertex* dest, const Comparator& c) {
232     if (v == dest) {
233         return;
234     }
235     TESS_LOG("ss_connecting vertex %g to vertex %g\n", v->fID, dest->fID);
236     if (v->fSynthetic) {
237         this->makeConnectingEdge(v, dest, EdgeType::kConnector, c, 0);
238     } else if (v->fPartner) {
239         TESS_LOG("setting %g's partner to %g ", v->fPartner->fID, dest->fID);
240         TESS_LOG("and %g's partner to null\n", v->fID);
241         v->fPartner->fPartner = dest;
242         v->fPartner = nullptr;
243     }
244 }
245 
apply(VertexList * mesh,const Comparator & c,EventList * events,GrAATriangulator * triangulator)246 void GrAATriangulator::Event::apply(VertexList* mesh, const Comparator& c, EventList* events,
247                                     GrAATriangulator* triangulator) {
248     if (!fEdge) {
249         return;
250     }
251     Vertex* prev = fEdge->fPrev->fVertex;
252     Vertex* next = fEdge->fNext->fVertex;
253     SSEdge* prevEdge = fEdge->fPrev->fPrev;
254     SSEdge* nextEdge = fEdge->fNext->fNext;
255     if (!prevEdge || !nextEdge || !prevEdge->fEdge || !nextEdge->fEdge) {
256         return;
257     }
258     Vertex* dest = triangulator->makeSortedVertex(fPoint, fAlpha, mesh, prev, c);
259     dest->fSynthetic = true;
260     SSVertex* ssv = triangulator->fAlloc->make<SSVertex>(dest);
261     TESS_LOG("collapsing %g, %g (original edge %g -> %g) to %g (%g, %g) alpha %d\n",
262              prev->fID, next->fID, fEdge->fEdge->fTop->fID, fEdge->fEdge->fBottom->fID, dest->fID,
263              fPoint.fX, fPoint.fY, fAlpha);
264     fEdge->fEdge = nullptr;
265 
266     triangulator->connectSSEdge(prev, dest, c);
267     triangulator->connectSSEdge(next, dest, c);
268 
269     prevEdge->fNext = nextEdge->fPrev = ssv;
270     ssv->fPrev = prevEdge;
271     ssv->fNext = nextEdge;
272     if (!prevEdge->fEdge || !nextEdge->fEdge) {
273         return;
274     }
275     if (prevEdge->fEvent) {
276         prevEdge->fEvent->fEdge = nullptr;
277     }
278     if (nextEdge->fEvent) {
279         nextEdge->fEvent->fEdge = nullptr;
280     }
281     if (prevEdge->fPrev == nextEdge->fNext) {
282         triangulator->connectSSEdge(prevEdge->fPrev->fVertex, dest, c);
283         prevEdge->fEdge = nextEdge->fEdge = nullptr;
284     } else {
285         triangulator->computeBisector(prevEdge->fEdge, nextEdge->fEdge, dest);
286         SkASSERT(prevEdge != fEdge && nextEdge != fEdge);
287         if (dest->fPartner) {
288             triangulator->makeEvent(prevEdge, events);
289             triangulator->makeEvent(nextEdge, events);
290         } else {
291             triangulator->makeEvent(prevEdge, prevEdge->fPrev->fVertex, nextEdge, dest, events, c);
292             triangulator->makeEvent(nextEdge, nextEdge->fNext->fVertex, prevEdge, dest, events, c);
293         }
294     }
295 }
296 
is_overlap_edge(Edge * e)297 static bool is_overlap_edge(Edge* e) {
298     if (e->fType == EdgeType::kOuter) {
299         return e->fWinding != 0 && e->fWinding != 1;
300     } else if (e->fType == EdgeType::kInner) {
301         return e->fWinding != 0 && e->fWinding != -2;
302     } else {
303         return false;
304     }
305 }
306 
307 // This is a stripped-down version of tessellate() which computes edges which
308 // join two filled regions, which represent overlap regions, and collapses them.
collapseOverlapRegions(VertexList * mesh,const Comparator & c,EventComparator comp)309 bool GrAATriangulator::collapseOverlapRegions(VertexList* mesh, const Comparator& c,
310                                               EventComparator comp) {
311     TESS_LOG("\nfinding overlap regions\n");
312     EdgeList activeEdges;
313     EventList events(comp);
314     SSVertexMap ssVertices;
315     SSEdgeList ssEdges;
316     for (Vertex* v = mesh->fHead; v != nullptr; v = v->fNext) {
317         if (!v->isConnected()) {
318             continue;
319         }
320         Edge* leftEnclosingEdge;
321         Edge* rightEnclosingEdge;
322         FindEnclosingEdges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
323         for (Edge* e = v->fLastEdgeAbove; e && e != leftEnclosingEdge;) {
324             Edge* prev = e->fPrevEdgeAbove ? e->fPrevEdgeAbove : leftEnclosingEdge;
325             activeEdges.remove(e);
326             bool leftOverlap = prev && is_overlap_edge(prev);
327             bool rightOverlap = is_overlap_edge(e);
328             bool isOuterBoundary = e->fType == EdgeType::kOuter &&
329                                    (!prev || prev->fWinding == 0 || e->fWinding == 0);
330             if (prev) {
331                 e->fWinding -= prev->fWinding;
332             }
333             if (leftOverlap && rightOverlap) {
334                 TESS_LOG("found interior overlap edge %g -> %g, disconnecting\n",
335                          e->fTop->fID, e->fBottom->fID);
336                 e->disconnect();
337             } else if (leftOverlap || rightOverlap) {
338                 TESS_LOG("found overlap edge %g -> %g%s\n",
339                          e->fTop->fID, e->fBottom->fID,
340                          isOuterBoundary ? ", is outer boundary" : "");
341                 Vertex* prevVertex = e->fWinding < 0 ? e->fBottom : e->fTop;
342                 Vertex* nextVertex = e->fWinding < 0 ? e->fTop : e->fBottom;
343                 SSVertex* ssPrev = ssVertices[prevVertex];
344                 if (!ssPrev) {
345                     ssPrev = ssVertices[prevVertex] = fAlloc->make<SSVertex>(prevVertex);
346                 }
347                 SSVertex* ssNext = ssVertices[nextVertex];
348                 if (!ssNext) {
349                     ssNext = ssVertices[nextVertex] = fAlloc->make<SSVertex>(nextVertex);
350                 }
351                 SSEdge* ssEdge = fAlloc->make<SSEdge>(e, ssPrev, ssNext);
352                 ssEdges.push_back(ssEdge);
353 //                SkASSERT(!ssPrev->fNext && !ssNext->fPrev);
354                 ssPrev->fNext = ssNext->fPrev = ssEdge;
355                 this->makeEvent(ssEdge, &events);
356                 if (!isOuterBoundary) {
357                     e->disconnect();
358                 } else {
359                     SkASSERT(e->fType != EdgeType::kConnector);
360                     // Ensure winding values match expected scale for the edge type. During merging of
361                     // collinear edges in overlap regions, windings are summed and so could exceed the
362                     // expected +/-1 for outer and +/-2 for inner that is used to fill properly during
363                     // subsequent polygon generation.
364                     e->fWinding = SkScalarCopySign(e->fType == EdgeType::kInner ? 2 : 1,
365                                                    e->fWinding);
366                 }
367             }
368             e = prev;
369         }
370         Edge* prev = leftEnclosingEdge;
371         for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
372             if (prev) {
373                 e->fWinding += prev->fWinding;
374             }
375             activeEdges.insert(e, prev);
376             prev = e;
377         }
378     }
379     bool complex = events.size() > 0;
380 
381     TESS_LOG("\ncollapsing overlap regions\n");
382     TESS_LOG("skeleton before:\n");
383     dump_skel(ssEdges);
384     while (events.size() > 0) {
385         Event* event = events.top();
386         events.pop();
387         event->apply(mesh, c, &events, this);
388     }
389     TESS_LOG("skeleton after:\n");
390     dump_skel(ssEdges);
391     for (SSEdge* edge : ssEdges) {
392         if (Edge* e = edge->fEdge) {
393             this->makeConnectingEdge(edge->fPrev->fVertex, edge->fNext->fVertex, e->fType, c, 0);
394         }
395     }
396     return complex;
397 }
398 
inversion(Vertex * prev,Vertex * next,Edge * origEdge,const Comparator & c)399 static bool inversion(Vertex* prev, Vertex* next, Edge* origEdge, const Comparator& c) {
400     if (!prev || !next) {
401         return true;
402     }
403     int winding = c.sweep_lt(prev->fPoint, next->fPoint) ? 1 : -1;
404     return winding != origEdge->fWinding;
405 }
406 
407 // Stage 5d: Displace edges by half a pixel inward and outward along their normals. Intersect to
408 // find new vertices, and set zero alpha on the exterior and one alpha on the interior. Build a
409 // new antialiased mesh from those vertices.
410 
strokeBoundary(EdgeList * boundary,VertexList * innerMesh,const Comparator & c)411 void GrAATriangulator::strokeBoundary(EdgeList* boundary, VertexList* innerMesh,
412                                       const Comparator& c) {
413     TESS_LOG("\nstroking boundary\n");
414     // A boundary with fewer than 3 edges is degenerate.
415     if (!boundary->fHead || !boundary->fHead->fRight || !boundary->fHead->fRight->fRight) {
416         return;
417     }
418     Edge* prevEdge = boundary->fTail;
419     Vertex* prevV = prevEdge->fWinding > 0 ? prevEdge->fTop : prevEdge->fBottom;
420     SkVector prevNormal;
421     get_edge_normal(prevEdge, &prevNormal);
422     double radius = 0.5;
423     Line prevInner(prevEdge->fLine);
424     prevInner.fC -= radius;
425     Line prevOuter(prevEdge->fLine);
426     prevOuter.fC += radius;
427     VertexList innerVertices;
428     VertexList outerVertices;
429     bool innerInversion = true;
430     bool outerInversion = true;
431     for (Edge* e = boundary->fHead; e != nullptr; e = e->fRight) {
432         Vertex* v = e->fWinding > 0 ? e->fTop : e->fBottom;
433         SkVector normal;
434         get_edge_normal(e, &normal);
435         Line inner(e->fLine);
436         inner.fC -= radius;
437         Line outer(e->fLine);
438         outer.fC += radius;
439         SkPoint innerPoint, outerPoint;
440         TESS_LOG("stroking vertex %g (%g, %g)\n", v->fID, v->fPoint.fX, v->fPoint.fY);
441         if (!prevEdge->fLine.nearParallel(e->fLine) && prevInner.intersect(inner, &innerPoint) &&
442             prevOuter.intersect(outer, &outerPoint)) {
443             float cosAngle = normal.dot(prevNormal);
444             if (cosAngle < -kCosMiterAngle) {
445                 Vertex* nextV = e->fWinding > 0 ? e->fBottom : e->fTop;
446 
447                 // This is a pointy vertex whose angle is smaller than the threshold; miter it.
448                 Line bisector(innerPoint, outerPoint);
449                 Line tangent(v->fPoint, v->fPoint + SkPoint::Make(bisector.fA, bisector.fB));
450                 if (tangent.fA == 0 && tangent.fB == 0) {
451                     continue;
452                 }
453                 tangent.normalize();
454                 Line innerTangent(tangent);
455                 Line outerTangent(tangent);
456                 innerTangent.fC -= 0.5;
457                 outerTangent.fC += 0.5;
458                 SkPoint innerPoint1, innerPoint2, outerPoint1, outerPoint2;
459                 if (prevNormal.cross(normal) > 0) {
460                     // Miter inner points
461                     if (!innerTangent.intersect(prevInner, &innerPoint1) ||
462                         !innerTangent.intersect(inner, &innerPoint2) ||
463                         !outerTangent.intersect(bisector, &outerPoint)) {
464                         continue;
465                     }
466                     Line prevTangent(prevV->fPoint,
467                                      prevV->fPoint + SkVector::Make(prevOuter.fA, prevOuter.fB));
468                     Line nextTangent(nextV->fPoint,
469                                      nextV->fPoint + SkVector::Make(outer.fA, outer.fB));
470                     if (prevTangent.dist(outerPoint) > 0) {
471                         bisector.intersect(prevTangent, &outerPoint);
472                     }
473                     if (nextTangent.dist(outerPoint) < 0) {
474                         bisector.intersect(nextTangent, &outerPoint);
475                     }
476                     outerPoint1 = outerPoint2 = outerPoint;
477                 } else {
478                     // Miter outer points
479                     if (!outerTangent.intersect(prevOuter, &outerPoint1) ||
480                         !outerTangent.intersect(outer, &outerPoint2)) {
481                         continue;
482                     }
483                     Line prevTangent(prevV->fPoint,
484                                      prevV->fPoint + SkVector::Make(prevInner.fA, prevInner.fB));
485                     Line nextTangent(nextV->fPoint,
486                                      nextV->fPoint + SkVector::Make(inner.fA, inner.fB));
487                     if (prevTangent.dist(innerPoint) > 0) {
488                         bisector.intersect(prevTangent, &innerPoint);
489                     }
490                     if (nextTangent.dist(innerPoint) < 0) {
491                         bisector.intersect(nextTangent, &innerPoint);
492                     }
493                     innerPoint1 = innerPoint2 = innerPoint;
494                 }
495                 if (!innerPoint1.isFinite() || !innerPoint2.isFinite() ||
496                     !outerPoint1.isFinite() || !outerPoint2.isFinite()) {
497                     continue;
498                 }
499                 TESS_LOG("inner (%g, %g), (%g, %g), ",
500                          innerPoint1.fX, innerPoint1.fY, innerPoint2.fX, innerPoint2.fY);
501                 TESS_LOG("outer (%g, %g), (%g, %g)\n",
502                          outerPoint1.fX, outerPoint1.fY, outerPoint2.fX, outerPoint2.fY);
503                 Vertex* innerVertex1 = fAlloc->make<Vertex>(innerPoint1, 255);
504                 Vertex* innerVertex2 = fAlloc->make<Vertex>(innerPoint2, 255);
505                 Vertex* outerVertex1 = fAlloc->make<Vertex>(outerPoint1, 0);
506                 Vertex* outerVertex2 = fAlloc->make<Vertex>(outerPoint2, 0);
507                 innerVertex1->fPartner = outerVertex1;
508                 innerVertex2->fPartner = outerVertex2;
509                 outerVertex1->fPartner = innerVertex1;
510                 outerVertex2->fPartner = innerVertex2;
511                 if (!inversion(innerVertices.fTail, innerVertex1, prevEdge, c)) {
512                     innerInversion = false;
513                 }
514                 if (!inversion(outerVertices.fTail, outerVertex1, prevEdge, c)) {
515                     outerInversion = false;
516                 }
517                 innerVertices.append(innerVertex1);
518                 innerVertices.append(innerVertex2);
519                 outerVertices.append(outerVertex1);
520                 outerVertices.append(outerVertex2);
521             } else {
522                 TESS_LOG("inner (%g, %g), ", innerPoint.fX, innerPoint.fY);
523                 TESS_LOG("outer (%g, %g)\n", outerPoint.fX, outerPoint.fY);
524                 Vertex* innerVertex = fAlloc->make<Vertex>(innerPoint, 255);
525                 Vertex* outerVertex = fAlloc->make<Vertex>(outerPoint, 0);
526                 innerVertex->fPartner = outerVertex;
527                 outerVertex->fPartner = innerVertex;
528                 if (!inversion(innerVertices.fTail, innerVertex, prevEdge, c)) {
529                     innerInversion = false;
530                 }
531                 if (!inversion(outerVertices.fTail, outerVertex, prevEdge, c)) {
532                     outerInversion = false;
533                 }
534                 innerVertices.append(innerVertex);
535                 outerVertices.append(outerVertex);
536             }
537         }
538         prevInner = inner;
539         prevOuter = outer;
540         prevV = v;
541         prevEdge = e;
542         prevNormal = normal;
543     }
544     if (!inversion(innerVertices.fTail, innerVertices.fHead, prevEdge, c)) {
545         innerInversion = false;
546     }
547     if (!inversion(outerVertices.fTail, outerVertices.fHead, prevEdge, c)) {
548         outerInversion = false;
549     }
550     // Outer edges get 1 winding, and inner edges get -2 winding. This ensures that the interior
551     // is always filled (1 + -2 = -1 for normal cases, 1 + 2 = 3 for thin features where the
552     // interior inverts).
553     // For total inversion cases, the shape has now reversed handedness, so invert the winding
554     // so it will be detected during collapseOverlapRegions().
555     int innerWinding = innerInversion ? 2 : -2;
556     int outerWinding = outerInversion ? -1 : 1;
557     for (Vertex* v = innerVertices.fHead; v && v->fNext; v = v->fNext) {
558         this->makeConnectingEdge(v, v->fNext, EdgeType::kInner, c, innerWinding);
559     }
560     this->makeConnectingEdge(innerVertices.fTail, innerVertices.fHead, EdgeType::kInner, c,
561                              innerWinding);
562     for (Vertex* v = outerVertices.fHead; v && v->fNext; v = v->fNext) {
563         this->makeConnectingEdge(v, v->fNext, EdgeType::kOuter, c, outerWinding);
564     }
565     this->makeConnectingEdge(outerVertices.fTail, outerVertices.fHead, EdgeType::kOuter, c,
566                              outerWinding);
567     innerMesh->append(innerVertices);
568     fOuterMesh.append(outerVertices);
569 }
570 
extractBoundary(EdgeList * boundary,Edge * e) const571 void GrAATriangulator::extractBoundary(EdgeList* boundary, Edge* e) const {
572     TESS_LOG("\nextracting boundary\n");
573     bool down = this->applyFillType(e->fWinding);
574     Vertex* start = down ? e->fTop : e->fBottom;
575     do {
576         e->fWinding = down ? 1 : -1;
577         Edge* next;
578         e->fLine.normalize();
579         e->fLine = e->fLine * e->fWinding;
580         boundary->append(e);
581         if (down) {
582             // Find outgoing edge, in clockwise order.
583             if ((next = e->fNextEdgeAbove)) {
584                 down = false;
585             } else if ((next = e->fBottom->fLastEdgeBelow)) {
586                 down = true;
587             } else if ((next = e->fPrevEdgeAbove)) {
588                 down = false;
589             }
590         } else {
591             // Find outgoing edge, in counter-clockwise order.
592             if ((next = e->fPrevEdgeBelow)) {
593                 down = true;
594             } else if ((next = e->fTop->fFirstEdgeAbove)) {
595                 down = false;
596             } else if ((next = e->fNextEdgeBelow)) {
597                 down = true;
598             }
599         }
600         e->disconnect();
601         e = next;
602     } while (e && (down ? e->fTop : e->fBottom) != start);
603 }
604 
605 // Stage 5b: Extract boundaries from mesh, simplify and stroke them into a new mesh.
606 
extractBoundaries(const VertexList & inMesh,VertexList * innerVertices,const Comparator & c)607 void GrAATriangulator::extractBoundaries(const VertexList& inMesh, VertexList* innerVertices,
608                                          const Comparator& c) {
609     this->removeNonBoundaryEdges(inMesh);
610     for (Vertex* v = inMesh.fHead; v; v = v->fNext) {
611         while (v->fFirstEdgeBelow) {
612             EdgeList boundary;
613             this->extractBoundary(&boundary, v->fFirstEdgeBelow);
614             this->simplifyBoundary(&boundary, c);
615             this->strokeBoundary(&boundary, innerVertices, c);
616         }
617     }
618 }
619 
tessellate(const VertexList & mesh,const Comparator & c)620 std::tuple<Poly*, bool> GrAATriangulator::tessellate(const VertexList& mesh, const Comparator& c) {
621     VertexList innerMesh;
622     this->extractBoundaries(mesh, &innerMesh, c);
623     SortMesh(&innerMesh, c);
624     SortMesh(&fOuterMesh, c);
625     this->mergeCoincidentVertices(&innerMesh, c);
626     bool was_complex = this->mergeCoincidentVertices(&fOuterMesh, c);
627     auto result = this->simplify(&innerMesh, c);
628     if (result == SimplifyResult::kFailed) {
629         return { nullptr, false };
630     }
631     was_complex = (SimplifyResult::kFoundSelfIntersection == result) || was_complex;
632     result = this->simplify(&fOuterMesh, c);
633     if (result == SimplifyResult::kFailed) {
634         return { nullptr, false };
635     }
636     was_complex = (SimplifyResult::kFoundSelfIntersection == result) || was_complex;
637     TESS_LOG("\ninner mesh before:\n");
638     DUMP_MESH(innerMesh);
639     TESS_LOG("\nouter mesh before:\n");
640     DUMP_MESH(fOuterMesh);
641     EventComparator eventLT(EventComparator::Op::kLessThan);
642     EventComparator eventGT(EventComparator::Op::kGreaterThan);
643     was_complex = this->collapseOverlapRegions(&innerMesh, c, eventLT) || was_complex;
644     was_complex = this->collapseOverlapRegions(&fOuterMesh, c, eventGT) || was_complex;
645     if (was_complex) {
646         TESS_LOG("found complex mesh; taking slow path\n");
647         VertexList aaMesh;
648         TESS_LOG("\ninner mesh after:\n");
649         DUMP_MESH(innerMesh);
650         TESS_LOG("\nouter mesh after:\n");
651         DUMP_MESH(fOuterMesh);
652         this->connectPartners(&fOuterMesh, c);
653         this->connectPartners(&innerMesh, c);
654         SortedMerge(&innerMesh, &fOuterMesh, &aaMesh, c);
655         TESS_LOG("\nmerged mesh:\n");
656         DUMP_MESH(aaMesh);
657         this->mergeCoincidentVertices(&aaMesh, c);
658         result = this->simplify(&aaMesh, c);
659         if (result == SimplifyResult::kFailed) {
660             return { nullptr, false };
661         }
662         TESS_LOG("combined and simplified mesh:\n");
663         DUMP_MESH(aaMesh);
664         fOuterMesh.fHead = fOuterMesh.fTail = nullptr;
665         return this->GrTriangulator::tessellate(aaMesh, c);
666     } else {
667         TESS_LOG("no complex polygons; taking fast path\n");
668         return this->GrTriangulator::tessellate(innerMesh, c);
669     }
670 }
671 
polysToAATriangles(Poly * polys,GrEagerVertexAllocator * vertexAllocator) const672 int GrAATriangulator::polysToAATriangles(Poly* polys,
673                                          GrEagerVertexAllocator* vertexAllocator) const {
674     int64_t count64 = CountPoints(polys, SkPathFillType::kWinding);
675     // Count the points from the outer mesh.
676     for (Vertex* v = fOuterMesh.fHead; v; v = v->fNext) {
677         for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
678             count64 += TRIANGULATOR_WIREFRAME ? 12 : 6;
679         }
680     }
681     if (0 == count64 || count64 > SK_MaxS32) {
682         return 0;
683     }
684     int count = count64;
685 
686     size_t vertexStride = sizeof(SkPoint) + sizeof(float);
687     skgpu::VertexWriter verts = vertexAllocator->lockWriter(vertexStride, count);
688     if (!verts) {
689         SkDebugf("Could not allocate vertices\n");
690         return 0;
691     }
692 
693     TESS_LOG("emitting %d verts\n", count);
694     skgpu::BufferWriter::Mark start = verts.mark();
695     verts = this->polysToTriangles(polys, SkPathFillType::kWinding, std::move(verts));
696     // Emit the triangles from the outer mesh.
697     for (Vertex* v = fOuterMesh.fHead; v; v = v->fNext) {
698         for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
699             Vertex* v0 = e->fTop;
700             Vertex* v1 = e->fBottom;
701             Vertex* v2 = e->fBottom->fPartner;
702             Vertex* v3 = e->fTop->fPartner;
703             verts = this->emitTriangle(v0, v1, v2, 0/*winding*/, std::move(verts));
704             verts = this->emitTriangle(v0, v2, v3, 0/*winding*/, std::move(verts));
705         }
706     }
707 
708     int actualCount = static_cast<int>((verts.mark() - start) / vertexStride);
709     SkASSERT(actualCount <= count);
710     vertexAllocator->unlock(actualCount);
711     return actualCount;
712 }
713