1/*
2 * Copyright 2020 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "src/gpu/geometry/GrAATriangulator.h"
9
10#include "src/gpu/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
23constexpr static float kCosMiterAngle = 0.97f; // Corresponds to an angle of ~14 degrees.
24
25using EdgeType = GrTriangulator::EdgeType;
26using Vertex = GrTriangulator::Vertex;
27using VertexList = GrTriangulator::VertexList;
28using Line = GrTriangulator::Line;
29using Edge = GrTriangulator::Edge;
30using EdgeList = GrTriangulator::EdgeList;
31using Poly = GrTriangulator::Poly;
32using Comparator = GrTriangulator::Comparator;
33using SSEdge = GrAATriangulator::SSEdge;
34using EventList = GrAATriangulator::EventList;
35using Event = GrAATriangulator::Event;
36using EventComparator = GrAATriangulator::EventComparator;
37
38struct SSVertex {
39    SSVertex(Vertex* v) : fVertex(v), fPrev(nullptr), fNext(nullptr) {}
40    Vertex* fVertex;
41    SSEdge* fPrev;
42    SSEdge* fNext;
43};
44
45struct GrAATriangulator::SSEdge {
46    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
55typedef std::unordered_map<Vertex*, SSVertex*> SSVertexMap;
56typedef std::vector<SSEdge*> SSEdgeList;
57typedef std::priority_queue<Event*, std::vector<Event*>, EventComparator> EventPQ;
58
59struct GrAATriangulator::EventList : EventPQ {
60    EventList(EventComparator comparison) : EventPQ(comparison) {
61    }
62};
63
64void 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
84void 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
109void 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
123static 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
142void 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.
175static 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
184void 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
230void 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
245void 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
296static 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.
308bool 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
398static 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
410void 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
570void 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
606void 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
619Poly* 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
662int 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