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