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