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