1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "src/gpu/geometry/GrTriangulator.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "src/gpu/BufferWriter.h"
11cb93a386Sopenharmony_ci#include "src/gpu/GrEagerVertexAllocator.h"
12cb93a386Sopenharmony_ci#include "src/gpu/geometry/GrPathUtils.h"
13cb93a386Sopenharmony_ci
14cb93a386Sopenharmony_ci#include "src/core/SkGeometry.h"
15cb93a386Sopenharmony_ci#include "src/core/SkPointPriv.h"
16cb93a386Sopenharmony_ci
17cb93a386Sopenharmony_ci#include <algorithm>
18cb93a386Sopenharmony_ci
19cb93a386Sopenharmony_ci
20cb93a386Sopenharmony_ci#if TRIANGULATOR_LOGGING
21cb93a386Sopenharmony_ci#define TESS_LOG printf
22cb93a386Sopenharmony_ci#define DUMP_MESH(M) (M).dump()
23cb93a386Sopenharmony_ci#else
24cb93a386Sopenharmony_ci#define TESS_LOG(...)
25cb93a386Sopenharmony_ci#define DUMP_MESH(M)
26cb93a386Sopenharmony_ci#endif
27cb93a386Sopenharmony_ci
28cb93a386Sopenharmony_ciusing EdgeType = GrTriangulator::EdgeType;
29cb93a386Sopenharmony_ciusing Vertex = GrTriangulator::Vertex;
30cb93a386Sopenharmony_ciusing VertexList = GrTriangulator::VertexList;
31cb93a386Sopenharmony_ciusing Line = GrTriangulator::Line;
32cb93a386Sopenharmony_ciusing Edge = GrTriangulator::Edge;
33cb93a386Sopenharmony_ciusing EdgeList = GrTriangulator::EdgeList;
34cb93a386Sopenharmony_ciusing Poly = GrTriangulator::Poly;
35cb93a386Sopenharmony_ciusing MonotonePoly = GrTriangulator::MonotonePoly;
36cb93a386Sopenharmony_ciusing Comparator = GrTriangulator::Comparator;
37cb93a386Sopenharmony_ci
38cb93a386Sopenharmony_citemplate <class T, T* T::*Prev, T* T::*Next>
39cb93a386Sopenharmony_cistatic void list_insert(T* t, T* prev, T* next, T** head, T** tail) {
40cb93a386Sopenharmony_ci    t->*Prev = prev;
41cb93a386Sopenharmony_ci    t->*Next = next;
42cb93a386Sopenharmony_ci    if (prev) {
43cb93a386Sopenharmony_ci        prev->*Next = t;
44cb93a386Sopenharmony_ci    } else if (head) {
45cb93a386Sopenharmony_ci        *head = t;
46cb93a386Sopenharmony_ci    }
47cb93a386Sopenharmony_ci    if (next) {
48cb93a386Sopenharmony_ci        next->*Prev = t;
49cb93a386Sopenharmony_ci    } else if (tail) {
50cb93a386Sopenharmony_ci        *tail = t;
51cb93a386Sopenharmony_ci    }
52cb93a386Sopenharmony_ci}
53cb93a386Sopenharmony_ci
54cb93a386Sopenharmony_citemplate <class T, T* T::*Prev, T* T::*Next>
55cb93a386Sopenharmony_cistatic void list_remove(T* t, T** head, T** tail) {
56cb93a386Sopenharmony_ci    if (t->*Prev) {
57cb93a386Sopenharmony_ci        t->*Prev->*Next = t->*Next;
58cb93a386Sopenharmony_ci    } else if (head) {
59cb93a386Sopenharmony_ci        *head = t->*Next;
60cb93a386Sopenharmony_ci    }
61cb93a386Sopenharmony_ci    if (t->*Next) {
62cb93a386Sopenharmony_ci        t->*Next->*Prev = t->*Prev;
63cb93a386Sopenharmony_ci    } else if (tail) {
64cb93a386Sopenharmony_ci        *tail = t->*Prev;
65cb93a386Sopenharmony_ci    }
66cb93a386Sopenharmony_ci    t->*Prev = t->*Next = nullptr;
67cb93a386Sopenharmony_ci}
68cb93a386Sopenharmony_ci
69cb93a386Sopenharmony_citypedef bool (*CompareFunc)(const SkPoint& a, const SkPoint& b);
70cb93a386Sopenharmony_ci
71cb93a386Sopenharmony_cistatic bool sweep_lt_horiz(const SkPoint& a, const SkPoint& b) {
72cb93a386Sopenharmony_ci    return a.fX < b.fX || (a.fX == b.fX && a.fY > b.fY);
73cb93a386Sopenharmony_ci}
74cb93a386Sopenharmony_ci
75cb93a386Sopenharmony_cistatic bool sweep_lt_vert(const SkPoint& a, const SkPoint& b) {
76cb93a386Sopenharmony_ci    return a.fY < b.fY || (a.fY == b.fY && a.fX < b.fX);
77cb93a386Sopenharmony_ci}
78cb93a386Sopenharmony_ci
79cb93a386Sopenharmony_cibool GrTriangulator::Comparator::sweep_lt(const SkPoint& a, const SkPoint& b) const {
80cb93a386Sopenharmony_ci    return fDirection == Direction::kHorizontal ? sweep_lt_horiz(a, b) : sweep_lt_vert(a, b);
81cb93a386Sopenharmony_ci}
82cb93a386Sopenharmony_ci
83cb93a386Sopenharmony_cistatic inline void* emit_vertex(Vertex* v, bool emitCoverage, void* data) {
84cb93a386Sopenharmony_ci    skgpu::VertexWriter verts{data};
85cb93a386Sopenharmony_ci    verts << v->fPoint;
86cb93a386Sopenharmony_ci
87cb93a386Sopenharmony_ci    if (emitCoverage) {
88cb93a386Sopenharmony_ci        verts << GrNormalizeByteToFloat(v->fAlpha);
89cb93a386Sopenharmony_ci    }
90cb93a386Sopenharmony_ci
91cb93a386Sopenharmony_ci    return verts.ptr();
92cb93a386Sopenharmony_ci}
93cb93a386Sopenharmony_ci
94cb93a386Sopenharmony_cistatic void* emit_triangle(Vertex* v0, Vertex* v1, Vertex* v2, bool emitCoverage, void* data) {
95cb93a386Sopenharmony_ci    TESS_LOG("emit_triangle %g (%g, %g) %d\n", v0->fID, v0->fPoint.fX, v0->fPoint.fY, v0->fAlpha);
96cb93a386Sopenharmony_ci    TESS_LOG("              %g (%g, %g) %d\n", v1->fID, v1->fPoint.fX, v1->fPoint.fY, v1->fAlpha);
97cb93a386Sopenharmony_ci    TESS_LOG("              %g (%g, %g) %d\n", v2->fID, v2->fPoint.fX, v2->fPoint.fY, v2->fAlpha);
98cb93a386Sopenharmony_ci#if TESSELLATOR_WIREFRAME
99cb93a386Sopenharmony_ci    data = emit_vertex(v0, emitCoverage, data);
100cb93a386Sopenharmony_ci    data = emit_vertex(v1, emitCoverage, data);
101cb93a386Sopenharmony_ci    data = emit_vertex(v1, emitCoverage, data);
102cb93a386Sopenharmony_ci    data = emit_vertex(v2, emitCoverage, data);
103cb93a386Sopenharmony_ci    data = emit_vertex(v2, emitCoverage, data);
104cb93a386Sopenharmony_ci    data = emit_vertex(v0, emitCoverage, data);
105cb93a386Sopenharmony_ci#else
106cb93a386Sopenharmony_ci    data = emit_vertex(v0, emitCoverage, data);
107cb93a386Sopenharmony_ci    data = emit_vertex(v1, emitCoverage, data);
108cb93a386Sopenharmony_ci    data = emit_vertex(v2, emitCoverage, data);
109cb93a386Sopenharmony_ci#endif
110cb93a386Sopenharmony_ci    return data;
111cb93a386Sopenharmony_ci}
112cb93a386Sopenharmony_ci
113cb93a386Sopenharmony_civoid GrTriangulator::VertexList::insert(Vertex* v, Vertex* prev, Vertex* next) {
114cb93a386Sopenharmony_ci    list_insert<Vertex, &Vertex::fPrev, &Vertex::fNext>(v, prev, next, &fHead, &fTail);
115cb93a386Sopenharmony_ci}
116cb93a386Sopenharmony_ci
117cb93a386Sopenharmony_civoid GrTriangulator::VertexList::remove(Vertex* v) {
118cb93a386Sopenharmony_ci    list_remove<Vertex, &Vertex::fPrev, &Vertex::fNext>(v, &fHead, &fTail);
119cb93a386Sopenharmony_ci}
120cb93a386Sopenharmony_ci
121cb93a386Sopenharmony_ci// Round to nearest quarter-pixel. This is used for screenspace tessellation.
122cb93a386Sopenharmony_ci
123cb93a386Sopenharmony_cistatic inline void round(SkPoint* p) {
124cb93a386Sopenharmony_ci    p->fX = SkScalarRoundToScalar(p->fX * SkFloatToScalar(4.0f)) * SkFloatToScalar(0.25f);
125cb93a386Sopenharmony_ci    p->fY = SkScalarRoundToScalar(p->fY * SkFloatToScalar(4.0f)) * SkFloatToScalar(0.25f);
126cb93a386Sopenharmony_ci}
127cb93a386Sopenharmony_ci
128cb93a386Sopenharmony_cistatic inline SkScalar double_to_clamped_scalar(double d) {
129cb93a386Sopenharmony_ci    // Clamps large values to what's finitely representable when cast back to a float.
130cb93a386Sopenharmony_ci    static const double kMaxLimit = (double) SK_ScalarMax;
131cb93a386Sopenharmony_ci    // It's not perfect, but a using a value larger than float_min helps protect from denormalized
132cb93a386Sopenharmony_ci    // values and ill-conditions in intermediate calculations on coordinates.
133cb93a386Sopenharmony_ci    static const double kNearZeroLimit = 16 * (double) std::numeric_limits<float>::min();
134cb93a386Sopenharmony_ci    if (std::abs(d) < kNearZeroLimit) {
135cb93a386Sopenharmony_ci        d = 0.f;
136cb93a386Sopenharmony_ci    }
137cb93a386Sopenharmony_ci    return SkDoubleToScalar(std::max(-kMaxLimit, std::min(d, kMaxLimit)));
138cb93a386Sopenharmony_ci}
139cb93a386Sopenharmony_ci
140cb93a386Sopenharmony_cibool GrTriangulator::Line::intersect(const Line& other, SkPoint* point) const {
141cb93a386Sopenharmony_ci    double denom = fA * other.fB - fB * other.fA;
142cb93a386Sopenharmony_ci    if (denom == 0.0) {
143cb93a386Sopenharmony_ci        return false;
144cb93a386Sopenharmony_ci    }
145cb93a386Sopenharmony_ci    double scale = 1.0 / denom;
146cb93a386Sopenharmony_ci    point->fX = double_to_clamped_scalar((fB * other.fC - other.fB * fC) * scale);
147cb93a386Sopenharmony_ci    point->fY = double_to_clamped_scalar((other.fA * fC - fA * other.fC) * scale);
148cb93a386Sopenharmony_ci     round(point);
149cb93a386Sopenharmony_ci    return point->isFinite();
150cb93a386Sopenharmony_ci}
151cb93a386Sopenharmony_ci
152cb93a386Sopenharmony_ci// If the edge's vertices differ by many orders of magnitude, the computed line equation can have
153cb93a386Sopenharmony_ci// significant error in its distance and intersection tests. To avoid this, we recursively subdivide
154cb93a386Sopenharmony_ci// long edges and effectively perform a binary search to perform a more accurate intersection test.
155cb93a386Sopenharmony_cistatic bool edge_line_needs_recursion(const SkPoint& p0, const SkPoint& p1) {
156cb93a386Sopenharmony_ci    // ilogbf(0) returns an implementation-defined constant, but we are choosing to saturate
157cb93a386Sopenharmony_ci    // negative exponents to 0 for comparisons sake. We're only trying to recurse on lines with
158cb93a386Sopenharmony_ci    // very large coordinates.
159cb93a386Sopenharmony_ci    int expDiffX = std::abs((std::abs(p0.fX) < 1.f ? 0 : std::ilogbf(p0.fX)) -
160cb93a386Sopenharmony_ci                            (std::abs(p1.fX) < 1.f ? 0 : std::ilogbf(p1.fX)));
161cb93a386Sopenharmony_ci    int expDiffY = std::abs((std::abs(p0.fY) < 1.f ? 0 : std::ilogbf(p0.fY)) -
162cb93a386Sopenharmony_ci                            (std::abs(p1.fY) < 1.f ? 0 : std::ilogbf(p1.fY)));
163cb93a386Sopenharmony_ci    // Differ by more than 2^20, or roughly a factor of one million.
164cb93a386Sopenharmony_ci    return expDiffX > 20 || expDiffY > 20;
165cb93a386Sopenharmony_ci}
166cb93a386Sopenharmony_ci
167cb93a386Sopenharmony_cistatic bool recursive_edge_intersect(const Line& u, SkPoint u0, SkPoint u1,
168cb93a386Sopenharmony_ci                                     const Line& v, SkPoint v0, SkPoint v1,
169cb93a386Sopenharmony_ci                                     SkPoint* p, double* s, double* t) {
170cb93a386Sopenharmony_ci    // First check if the bounding boxes of [u0,u1] intersects [v0,v1]. If they do not, then the
171cb93a386Sopenharmony_ci    // two line segments cannot intersect in their domain (even if the lines themselves might).
172cb93a386Sopenharmony_ci    // - don't use SkRect::intersect since the vertices aren't sorted and horiz/vertical lines
173cb93a386Sopenharmony_ci    //   appear as empty rects, which then never "intersect" according to SkRect.
174cb93a386Sopenharmony_ci    if (std::min(u0.fX, u1.fX) > std::max(v0.fX, v1.fX) ||
175cb93a386Sopenharmony_ci        std::max(u0.fX, u1.fX) < std::min(v0.fX, v1.fX) ||
176cb93a386Sopenharmony_ci        std::min(u0.fY, u1.fY) > std::max(v0.fY, v1.fY) ||
177cb93a386Sopenharmony_ci        std::max(u0.fY, u1.fY) < std::min(v0.fY, v1.fY)) {
178cb93a386Sopenharmony_ci        return false;
179cb93a386Sopenharmony_ci    }
180cb93a386Sopenharmony_ci
181cb93a386Sopenharmony_ci    // Compute intersection based on current segment vertices; if an intersection is found but the
182cb93a386Sopenharmony_ci    // vertices differ too much in magnitude, we recurse using the midpoint of the segment to
183cb93a386Sopenharmony_ci    // reject false positives. We don't currently try to avoid false negatives (e.g. large magnitude
184cb93a386Sopenharmony_ci    // line reports no intersection but there is one).
185cb93a386Sopenharmony_ci    double denom = u.fA * v.fB - u.fB * v.fA;
186cb93a386Sopenharmony_ci    if (denom == 0.0) {
187cb93a386Sopenharmony_ci        return false;
188cb93a386Sopenharmony_ci    }
189cb93a386Sopenharmony_ci    double dx = static_cast<double>(v0.fX) - u0.fX;
190cb93a386Sopenharmony_ci    double dy = static_cast<double>(v0.fY) - u0.fY;
191cb93a386Sopenharmony_ci    double sNumer = dy * v.fB + dx * v.fA;
192cb93a386Sopenharmony_ci    double tNumer = dy * u.fB + dx * u.fA;
193cb93a386Sopenharmony_ci    // If (sNumer / denom) or (tNumer / denom) is not in [0..1], exit early.
194cb93a386Sopenharmony_ci    // This saves us doing the divide below unless absolutely necessary.
195cb93a386Sopenharmony_ci    if (denom > 0.0 ? (sNumer < 0.0 || sNumer > denom || tNumer < 0.0 || tNumer > denom)
196cb93a386Sopenharmony_ci                    : (sNumer > 0.0 || sNumer < denom || tNumer > 0.0 || tNumer < denom)) {
197cb93a386Sopenharmony_ci        return false;
198cb93a386Sopenharmony_ci    }
199cb93a386Sopenharmony_ci
200cb93a386Sopenharmony_ci    *s = sNumer / denom;
201cb93a386Sopenharmony_ci    *t = tNumer / denom;
202cb93a386Sopenharmony_ci    SkASSERT(*s >= 0.0 && *s <= 1.0 && *t >= 0.0 && *t <= 1.0);
203cb93a386Sopenharmony_ci
204cb93a386Sopenharmony_ci    const bool uNeedsSplit = edge_line_needs_recursion(u0, u1);
205cb93a386Sopenharmony_ci    const bool vNeedsSplit = edge_line_needs_recursion(v0, v1);
206cb93a386Sopenharmony_ci    if (!uNeedsSplit && !vNeedsSplit) {
207cb93a386Sopenharmony_ci        p->fX = double_to_clamped_scalar(u0.fX - (*s) * u.fB);
208cb93a386Sopenharmony_ci        p->fY = double_to_clamped_scalar(u0.fY + (*s) * u.fA);
209cb93a386Sopenharmony_ci        return true;
210cb93a386Sopenharmony_ci    } else {
211cb93a386Sopenharmony_ci        double sScale = 1.0, sShift = 0.0;
212cb93a386Sopenharmony_ci        double tScale = 1.0, tShift = 0.0;
213cb93a386Sopenharmony_ci
214cb93a386Sopenharmony_ci        if (uNeedsSplit) {
215cb93a386Sopenharmony_ci            SkPoint uM = {(float) (0.5 * u0.fX + 0.5 * u1.fX),
216cb93a386Sopenharmony_ci                          (float) (0.5 * u0.fY + 0.5 * u1.fY)};
217cb93a386Sopenharmony_ci            sScale = 0.5;
218cb93a386Sopenharmony_ci            if (*s >= 0.5) {
219cb93a386Sopenharmony_ci                u1 = uM;
220cb93a386Sopenharmony_ci                sShift = 0.5;
221cb93a386Sopenharmony_ci            } else {
222cb93a386Sopenharmony_ci                u0 = uM;
223cb93a386Sopenharmony_ci            }
224cb93a386Sopenharmony_ci        }
225cb93a386Sopenharmony_ci        if (vNeedsSplit) {
226cb93a386Sopenharmony_ci            SkPoint vM = {(float) (0.5 * v0.fX + 0.5 * v1.fX),
227cb93a386Sopenharmony_ci                          (float) (0.5 * v0.fY + 0.5 * v1.fY)};
228cb93a386Sopenharmony_ci            tScale = 0.5;
229cb93a386Sopenharmony_ci            if (*t >= 0.5) {
230cb93a386Sopenharmony_ci                v1 = vM;
231cb93a386Sopenharmony_ci                tShift = 0.5;
232cb93a386Sopenharmony_ci            } else {
233cb93a386Sopenharmony_ci                v0 = vM;
234cb93a386Sopenharmony_ci            }
235cb93a386Sopenharmony_ci        }
236cb93a386Sopenharmony_ci
237cb93a386Sopenharmony_ci        // Just recompute both lines, even if only one was split; we're already in a slow path.
238cb93a386Sopenharmony_ci        if (recursive_edge_intersect(Line(u0, u1), u0, u1, Line(v0, v1), v0, v1, p, s, t)) {
239cb93a386Sopenharmony_ci            // Adjust s and t back to full range
240cb93a386Sopenharmony_ci            *s = sScale * (*s) + sShift;
241cb93a386Sopenharmony_ci            *t = tScale * (*t) + tShift;
242cb93a386Sopenharmony_ci            return true;
243cb93a386Sopenharmony_ci        } else {
244cb93a386Sopenharmony_ci            // False positive
245cb93a386Sopenharmony_ci            return false;
246cb93a386Sopenharmony_ci        }
247cb93a386Sopenharmony_ci    }
248cb93a386Sopenharmony_ci}
249cb93a386Sopenharmony_ci
250cb93a386Sopenharmony_cibool GrTriangulator::Edge::intersect(const Edge& other, SkPoint* p, uint8_t* alpha) const {
251cb93a386Sopenharmony_ci    TESS_LOG("intersecting %g -> %g with %g -> %g\n",
252cb93a386Sopenharmony_ci             fTop->fID, fBottom->fID, other.fTop->fID, other.fBottom->fID);
253cb93a386Sopenharmony_ci    if (fTop == other.fTop || fBottom == other.fBottom ||
254cb93a386Sopenharmony_ci        fTop == other.fBottom || fBottom == other.fTop) {
255cb93a386Sopenharmony_ci        // If the two edges share a vertex by construction, they have already been split and
256cb93a386Sopenharmony_ci        // shouldn't be considered "intersecting" anymore.
257cb93a386Sopenharmony_ci        return false;
258cb93a386Sopenharmony_ci    }
259cb93a386Sopenharmony_ci
260cb93a386Sopenharmony_ci    double s, t; // needed to interpolate vertex alpha
261cb93a386Sopenharmony_ci    const bool intersects = recursive_edge_intersect(
262cb93a386Sopenharmony_ci            fLine, fTop->fPoint, fBottom->fPoint,
263cb93a386Sopenharmony_ci            other.fLine, other.fTop->fPoint, other.fBottom->fPoint,
264cb93a386Sopenharmony_ci            p, &s, &t);
265cb93a386Sopenharmony_ci    if (!intersects) {
266cb93a386Sopenharmony_ci        return false;
267cb93a386Sopenharmony_ci    }
268cb93a386Sopenharmony_ci
269cb93a386Sopenharmony_ci    if (alpha) {
270cb93a386Sopenharmony_ci        if (fType == EdgeType::kInner || other.fType == EdgeType::kInner) {
271cb93a386Sopenharmony_ci            // If the intersection is on any interior edge, it needs to stay fully opaque or later
272cb93a386Sopenharmony_ci            // triangulation could leech transparency into the inner fill region.
273cb93a386Sopenharmony_ci            *alpha = 255;
274cb93a386Sopenharmony_ci        } else if (fType == EdgeType::kOuter && other.fType == EdgeType::kOuter) {
275cb93a386Sopenharmony_ci            // Trivially, the intersection will be fully transparent since since it is by
276cb93a386Sopenharmony_ci            // construction on the outer edge.
277cb93a386Sopenharmony_ci            *alpha = 0;
278cb93a386Sopenharmony_ci        } else {
279cb93a386Sopenharmony_ci            // Could be two connectors crossing, or a connector crossing an outer edge.
280cb93a386Sopenharmony_ci            // Take the max interpolated alpha
281cb93a386Sopenharmony_ci            SkASSERT(fType == EdgeType::kConnector || other.fType == EdgeType::kConnector);
282cb93a386Sopenharmony_ci            *alpha = std::max((1.0 - s) * fTop->fAlpha + s * fBottom->fAlpha,
283cb93a386Sopenharmony_ci                              (1.0 - t) * other.fTop->fAlpha + t * other.fBottom->fAlpha);
284cb93a386Sopenharmony_ci        }
285cb93a386Sopenharmony_ci    }
286cb93a386Sopenharmony_ci    return true;
287cb93a386Sopenharmony_ci}
288cb93a386Sopenharmony_ci
289cb93a386Sopenharmony_civoid GrTriangulator::EdgeList::insert(Edge* edge, Edge* prev, Edge* next) {
290cb93a386Sopenharmony_ci    list_insert<Edge, &Edge::fLeft, &Edge::fRight>(edge, prev, next, &fHead, &fTail);
291cb93a386Sopenharmony_ci}
292cb93a386Sopenharmony_ci
293cb93a386Sopenharmony_civoid GrTriangulator::EdgeList::remove(Edge* edge) {
294cb93a386Sopenharmony_ci    TESS_LOG("removing edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID);
295cb93a386Sopenharmony_ci    SkASSERT(this->contains(edge));
296cb93a386Sopenharmony_ci    list_remove<Edge, &Edge::fLeft, &Edge::fRight>(edge, &fHead, &fTail);
297cb93a386Sopenharmony_ci}
298cb93a386Sopenharmony_ci
299cb93a386Sopenharmony_civoid GrTriangulator::MonotonePoly::addEdge(Edge* edge) {
300cb93a386Sopenharmony_ci    if (fSide == kRight_Side) {
301cb93a386Sopenharmony_ci        SkASSERT(!edge->fUsedInRightPoly);
302cb93a386Sopenharmony_ci        list_insert<Edge, &Edge::fRightPolyPrev, &Edge::fRightPolyNext>(
303cb93a386Sopenharmony_ci            edge, fLastEdge, nullptr, &fFirstEdge, &fLastEdge);
304cb93a386Sopenharmony_ci        edge->fUsedInRightPoly = true;
305cb93a386Sopenharmony_ci    } else {
306cb93a386Sopenharmony_ci        SkASSERT(!edge->fUsedInLeftPoly);
307cb93a386Sopenharmony_ci        list_insert<Edge, &Edge::fLeftPolyPrev, &Edge::fLeftPolyNext>(
308cb93a386Sopenharmony_ci            edge, fLastEdge, nullptr, &fFirstEdge, &fLastEdge);
309cb93a386Sopenharmony_ci        edge->fUsedInLeftPoly = true;
310cb93a386Sopenharmony_ci    }
311cb93a386Sopenharmony_ci}
312cb93a386Sopenharmony_ci
313cb93a386Sopenharmony_civoid* GrTriangulator::emitMonotonePoly(const MonotonePoly* monotonePoly, void* data) const {
314cb93a386Sopenharmony_ci    SkASSERT(monotonePoly->fWinding != 0);
315cb93a386Sopenharmony_ci    Edge* e = monotonePoly->fFirstEdge;
316cb93a386Sopenharmony_ci    VertexList vertices;
317cb93a386Sopenharmony_ci    vertices.append(e->fTop);
318cb93a386Sopenharmony_ci    int count = 1;
319cb93a386Sopenharmony_ci    while (e != nullptr) {
320cb93a386Sopenharmony_ci        if (kRight_Side == monotonePoly->fSide) {
321cb93a386Sopenharmony_ci            vertices.append(e->fBottom);
322cb93a386Sopenharmony_ci            e = e->fRightPolyNext;
323cb93a386Sopenharmony_ci        } else {
324cb93a386Sopenharmony_ci            vertices.prepend(e->fBottom);
325cb93a386Sopenharmony_ci            e = e->fLeftPolyNext;
326cb93a386Sopenharmony_ci        }
327cb93a386Sopenharmony_ci        count++;
328cb93a386Sopenharmony_ci    }
329cb93a386Sopenharmony_ci    Vertex* first = vertices.fHead;
330cb93a386Sopenharmony_ci    Vertex* v = first->fNext;
331cb93a386Sopenharmony_ci    while (v != vertices.fTail) {
332cb93a386Sopenharmony_ci        SkASSERT(v && v->fPrev && v->fNext);
333cb93a386Sopenharmony_ci        Vertex* prev = v->fPrev;
334cb93a386Sopenharmony_ci        Vertex* curr = v;
335cb93a386Sopenharmony_ci        Vertex* next = v->fNext;
336cb93a386Sopenharmony_ci        if (count == 3) {
337cb93a386Sopenharmony_ci            return this->emitTriangle(prev, curr, next, monotonePoly->fWinding, data);
338cb93a386Sopenharmony_ci        }
339cb93a386Sopenharmony_ci        double ax = static_cast<double>(curr->fPoint.fX) - prev->fPoint.fX;
340cb93a386Sopenharmony_ci        double ay = static_cast<double>(curr->fPoint.fY) - prev->fPoint.fY;
341cb93a386Sopenharmony_ci        double bx = static_cast<double>(next->fPoint.fX) - curr->fPoint.fX;
342cb93a386Sopenharmony_ci        double by = static_cast<double>(next->fPoint.fY) - curr->fPoint.fY;
343cb93a386Sopenharmony_ci        if (ax * by - ay * bx >= 0.0) {
344cb93a386Sopenharmony_ci            data = this->emitTriangle(prev, curr, next, monotonePoly->fWinding, data);
345cb93a386Sopenharmony_ci            v->fPrev->fNext = v->fNext;
346cb93a386Sopenharmony_ci            v->fNext->fPrev = v->fPrev;
347cb93a386Sopenharmony_ci            count--;
348cb93a386Sopenharmony_ci            if (v->fPrev == first) {
349cb93a386Sopenharmony_ci                v = v->fNext;
350cb93a386Sopenharmony_ci            } else {
351cb93a386Sopenharmony_ci                v = v->fPrev;
352cb93a386Sopenharmony_ci            }
353cb93a386Sopenharmony_ci        } else {
354cb93a386Sopenharmony_ci            v = v->fNext;
355cb93a386Sopenharmony_ci        }
356cb93a386Sopenharmony_ci    }
357cb93a386Sopenharmony_ci    return data;
358cb93a386Sopenharmony_ci}
359cb93a386Sopenharmony_ci
360cb93a386Sopenharmony_civoid* GrTriangulator::emitTriangle(Vertex* prev, Vertex* curr, Vertex* next, int winding,
361cb93a386Sopenharmony_ci                                   void* data) const {
362cb93a386Sopenharmony_ci    if (winding > 0) {
363cb93a386Sopenharmony_ci        // Ensure our triangles always wind in the same direction as if the path had been
364cb93a386Sopenharmony_ci        // triangulated as a simple fan (a la red book).
365cb93a386Sopenharmony_ci        std::swap(prev, next);
366cb93a386Sopenharmony_ci    }
367cb93a386Sopenharmony_ci    if (fCollectBreadcrumbTriangles && abs(winding) > 1 &&
368cb93a386Sopenharmony_ci        fPath.getFillType() == SkPathFillType::kWinding) {
369cb93a386Sopenharmony_ci        // The first winding count will come from the actual triangle we emit. The remaining counts
370cb93a386Sopenharmony_ci        // come from the breadcrumb triangle.
371cb93a386Sopenharmony_ci        fBreadcrumbList.append(fAlloc, prev->fPoint, curr->fPoint, next->fPoint, abs(winding) - 1);
372cb93a386Sopenharmony_ci    }
373cb93a386Sopenharmony_ci    return emit_triangle(prev, curr, next, fEmitCoverage, data);
374cb93a386Sopenharmony_ci}
375cb93a386Sopenharmony_ci
376cb93a386Sopenharmony_ciGrTriangulator::Poly::Poly(Vertex* v, int winding)
377cb93a386Sopenharmony_ci        : fFirstVertex(v)
378cb93a386Sopenharmony_ci        , fWinding(winding)
379cb93a386Sopenharmony_ci        , fHead(nullptr)
380cb93a386Sopenharmony_ci        , fTail(nullptr)
381cb93a386Sopenharmony_ci        , fNext(nullptr)
382cb93a386Sopenharmony_ci        , fPartner(nullptr)
383cb93a386Sopenharmony_ci        , fCount(0)
384cb93a386Sopenharmony_ci{
385cb93a386Sopenharmony_ci#if TRIANGULATOR_LOGGING
386cb93a386Sopenharmony_ci    static int gID = 0;
387cb93a386Sopenharmony_ci    fID = gID++;
388cb93a386Sopenharmony_ci    TESS_LOG("*** created Poly %d\n", fID);
389cb93a386Sopenharmony_ci#endif
390cb93a386Sopenharmony_ci}
391cb93a386Sopenharmony_ci
392cb93a386Sopenharmony_ciPoly* GrTriangulator::Poly::addEdge(Edge* e, Side side, SkArenaAlloc* alloc) {
393cb93a386Sopenharmony_ci    TESS_LOG("addEdge (%g -> %g) to poly %d, %s side\n",
394cb93a386Sopenharmony_ci             e->fTop->fID, e->fBottom->fID, fID, side == kLeft_Side ? "left" : "right");
395cb93a386Sopenharmony_ci    Poly* partner = fPartner;
396cb93a386Sopenharmony_ci    Poly* poly = this;
397cb93a386Sopenharmony_ci    if (side == kRight_Side) {
398cb93a386Sopenharmony_ci        if (e->fUsedInRightPoly) {
399cb93a386Sopenharmony_ci            return this;
400cb93a386Sopenharmony_ci        }
401cb93a386Sopenharmony_ci    } else {
402cb93a386Sopenharmony_ci        if (e->fUsedInLeftPoly) {
403cb93a386Sopenharmony_ci            return this;
404cb93a386Sopenharmony_ci        }
405cb93a386Sopenharmony_ci    }
406cb93a386Sopenharmony_ci    if (partner) {
407cb93a386Sopenharmony_ci        fPartner = partner->fPartner = nullptr;
408cb93a386Sopenharmony_ci    }
409cb93a386Sopenharmony_ci    if (!fTail) {
410cb93a386Sopenharmony_ci        fHead = fTail = alloc->make<MonotonePoly>(e, side, fWinding);
411cb93a386Sopenharmony_ci        fCount += 2;
412cb93a386Sopenharmony_ci    } else if (e->fBottom == fTail->fLastEdge->fBottom) {
413cb93a386Sopenharmony_ci        return poly;
414cb93a386Sopenharmony_ci    } else if (side == fTail->fSide) {
415cb93a386Sopenharmony_ci        fTail->addEdge(e);
416cb93a386Sopenharmony_ci        fCount++;
417cb93a386Sopenharmony_ci    } else {
418cb93a386Sopenharmony_ci        e = alloc->make<Edge>(fTail->fLastEdge->fBottom, e->fBottom, 1, EdgeType::kInner);
419cb93a386Sopenharmony_ci        fTail->addEdge(e);
420cb93a386Sopenharmony_ci        fCount++;
421cb93a386Sopenharmony_ci        if (partner) {
422cb93a386Sopenharmony_ci            partner->addEdge(e, side, alloc);
423cb93a386Sopenharmony_ci            poly = partner;
424cb93a386Sopenharmony_ci        } else {
425cb93a386Sopenharmony_ci            MonotonePoly* m = alloc->make<MonotonePoly>(e, side, fWinding);
426cb93a386Sopenharmony_ci            m->fPrev = fTail;
427cb93a386Sopenharmony_ci            fTail->fNext = m;
428cb93a386Sopenharmony_ci            fTail = m;
429cb93a386Sopenharmony_ci        }
430cb93a386Sopenharmony_ci    }
431cb93a386Sopenharmony_ci    return poly;
432cb93a386Sopenharmony_ci}
433cb93a386Sopenharmony_civoid* GrTriangulator::emitPoly(const Poly* poly, void *data) const {
434cb93a386Sopenharmony_ci    if (poly->fCount < 3) {
435cb93a386Sopenharmony_ci        return data;
436cb93a386Sopenharmony_ci    }
437cb93a386Sopenharmony_ci    TESS_LOG("emit() %d, size %d\n", poly->fID, poly->fCount);
438cb93a386Sopenharmony_ci    for (MonotonePoly* m = poly->fHead; m != nullptr; m = m->fNext) {
439cb93a386Sopenharmony_ci        data = this->emitMonotonePoly(m, data);
440cb93a386Sopenharmony_ci    }
441cb93a386Sopenharmony_ci    return data;
442cb93a386Sopenharmony_ci}
443cb93a386Sopenharmony_ci
444cb93a386Sopenharmony_cistatic bool coincident(const SkPoint& a, const SkPoint& b) {
445cb93a386Sopenharmony_ci    return a == b;
446cb93a386Sopenharmony_ci}
447cb93a386Sopenharmony_ci
448cb93a386Sopenharmony_ciPoly* GrTriangulator::makePoly(Poly** head, Vertex* v, int winding) const {
449cb93a386Sopenharmony_ci    Poly* poly = fAlloc->make<Poly>(v, winding);
450cb93a386Sopenharmony_ci    poly->fNext = *head;
451cb93a386Sopenharmony_ci    *head = poly;
452cb93a386Sopenharmony_ci    return poly;
453cb93a386Sopenharmony_ci}
454cb93a386Sopenharmony_ci
455cb93a386Sopenharmony_civoid GrTriangulator::appendPointToContour(const SkPoint& p, VertexList* contour) const {
456cb93a386Sopenharmony_ci    Vertex* v = fAlloc->make<Vertex>(p, 255);
457cb93a386Sopenharmony_ci#if TRIANGULATOR_LOGGING
458cb93a386Sopenharmony_ci    static float gID = 0.0f;
459cb93a386Sopenharmony_ci    v->fID = gID++;
460cb93a386Sopenharmony_ci#endif
461cb93a386Sopenharmony_ci    contour->append(v);
462cb93a386Sopenharmony_ci}
463cb93a386Sopenharmony_ci
464cb93a386Sopenharmony_cistatic SkScalar quad_error_at(const SkPoint pts[3], SkScalar t, SkScalar u) {
465cb93a386Sopenharmony_ci    SkQuadCoeff quad(pts);
466cb93a386Sopenharmony_ci    SkPoint p0 = to_point(quad.eval(t - 0.5f * u));
467cb93a386Sopenharmony_ci    SkPoint mid = to_point(quad.eval(t));
468cb93a386Sopenharmony_ci    SkPoint p1 = to_point(quad.eval(t + 0.5f * u));
469cb93a386Sopenharmony_ci    if (!p0.isFinite() || !mid.isFinite() || !p1.isFinite()) {
470cb93a386Sopenharmony_ci        return 0;
471cb93a386Sopenharmony_ci    }
472cb93a386Sopenharmony_ci    return SkPointPriv::DistanceToLineSegmentBetweenSqd(mid, p0, p1);
473cb93a386Sopenharmony_ci}
474cb93a386Sopenharmony_ci
475cb93a386Sopenharmony_civoid GrTriangulator::appendQuadraticToContour(const SkPoint pts[3], SkScalar toleranceSqd,
476cb93a386Sopenharmony_ci                                              VertexList* contour) const {
477cb93a386Sopenharmony_ci    SkQuadCoeff quad(pts);
478cb93a386Sopenharmony_ci    Sk2s aa = quad.fA * quad.fA;
479cb93a386Sopenharmony_ci    SkScalar denom = 2.0f * (aa[0] + aa[1]);
480cb93a386Sopenharmony_ci    Sk2s ab = quad.fA * quad.fB;
481cb93a386Sopenharmony_ci    SkScalar t = denom ? (-ab[0] - ab[1]) / denom : 0.0f;
482cb93a386Sopenharmony_ci    int nPoints = 1;
483cb93a386Sopenharmony_ci    SkScalar u = 1.0f;
484cb93a386Sopenharmony_ci    // Test possible subdivision values only at the point of maximum curvature.
485cb93a386Sopenharmony_ci    // If it passes the flatness metric there, it'll pass everywhere.
486cb93a386Sopenharmony_ci    while (nPoints < GrPathUtils::kMaxPointsPerCurve) {
487cb93a386Sopenharmony_ci        u = 1.0f / nPoints;
488cb93a386Sopenharmony_ci        if (quad_error_at(pts, t, u) < toleranceSqd) {
489cb93a386Sopenharmony_ci            break;
490cb93a386Sopenharmony_ci        }
491cb93a386Sopenharmony_ci        nPoints++;
492cb93a386Sopenharmony_ci    }
493cb93a386Sopenharmony_ci    for (int j = 1; j <= nPoints; j++) {
494cb93a386Sopenharmony_ci        this->appendPointToContour(to_point(quad.eval(j * u)), contour);
495cb93a386Sopenharmony_ci    }
496cb93a386Sopenharmony_ci}
497cb93a386Sopenharmony_ci
498cb93a386Sopenharmony_civoid GrTriangulator::generateCubicPoints(const SkPoint& p0, const SkPoint& p1, const SkPoint& p2,
499cb93a386Sopenharmony_ci                                         const SkPoint& p3, SkScalar tolSqd, VertexList* contour,
500cb93a386Sopenharmony_ci                                         int pointsLeft) const {
501cb93a386Sopenharmony_ci    SkScalar d1 = SkPointPriv::DistanceToLineSegmentBetweenSqd(p1, p0, p3);
502cb93a386Sopenharmony_ci    SkScalar d2 = SkPointPriv::DistanceToLineSegmentBetweenSqd(p2, p0, p3);
503cb93a386Sopenharmony_ci    if (pointsLeft < 2 || (d1 < tolSqd && d2 < tolSqd) ||
504cb93a386Sopenharmony_ci        !SkScalarIsFinite(d1) || !SkScalarIsFinite(d2)) {
505cb93a386Sopenharmony_ci        this->appendPointToContour(p3, contour);
506cb93a386Sopenharmony_ci        return;
507cb93a386Sopenharmony_ci    }
508cb93a386Sopenharmony_ci    const SkPoint q[] = {
509cb93a386Sopenharmony_ci        { SkScalarAve(p0.fX, p1.fX), SkScalarAve(p0.fY, p1.fY) },
510cb93a386Sopenharmony_ci        { SkScalarAve(p1.fX, p2.fX), SkScalarAve(p1.fY, p2.fY) },
511cb93a386Sopenharmony_ci        { SkScalarAve(p2.fX, p3.fX), SkScalarAve(p2.fY, p3.fY) }
512cb93a386Sopenharmony_ci    };
513cb93a386Sopenharmony_ci    const SkPoint r[] = {
514cb93a386Sopenharmony_ci        { SkScalarAve(q[0].fX, q[1].fX), SkScalarAve(q[0].fY, q[1].fY) },
515cb93a386Sopenharmony_ci        { SkScalarAve(q[1].fX, q[2].fX), SkScalarAve(q[1].fY, q[2].fY) }
516cb93a386Sopenharmony_ci    };
517cb93a386Sopenharmony_ci    const SkPoint s = { SkScalarAve(r[0].fX, r[1].fX), SkScalarAve(r[0].fY, r[1].fY) };
518cb93a386Sopenharmony_ci    pointsLeft >>= 1;
519cb93a386Sopenharmony_ci    this->generateCubicPoints(p0, q[0], r[0], s, tolSqd, contour, pointsLeft);
520cb93a386Sopenharmony_ci    this->generateCubicPoints(s, r[1], q[2], p3, tolSqd, contour, pointsLeft);
521cb93a386Sopenharmony_ci}
522cb93a386Sopenharmony_ci
523cb93a386Sopenharmony_ci// Stage 1: convert the input path to a set of linear contours (linked list of Vertices).
524cb93a386Sopenharmony_ci
525cb93a386Sopenharmony_civoid GrTriangulator::pathToContours(float tolerance, const SkRect& clipBounds,
526cb93a386Sopenharmony_ci                                    VertexList* contours, bool* isLinear) const {
527cb93a386Sopenharmony_ci    SkScalar toleranceSqd = tolerance * tolerance;
528cb93a386Sopenharmony_ci    SkPoint pts[4];
529cb93a386Sopenharmony_ci    *isLinear = true;
530cb93a386Sopenharmony_ci    VertexList* contour = contours;
531cb93a386Sopenharmony_ci    SkPath::Iter iter(fPath, false);
532cb93a386Sopenharmony_ci    if (fPath.isInverseFillType()) {
533cb93a386Sopenharmony_ci        SkPoint quad[4];
534cb93a386Sopenharmony_ci        clipBounds.toQuad(quad);
535cb93a386Sopenharmony_ci        for (int i = 3; i >= 0; i--) {
536cb93a386Sopenharmony_ci            this->appendPointToContour(quad[i], contours);
537cb93a386Sopenharmony_ci        }
538cb93a386Sopenharmony_ci        contour++;
539cb93a386Sopenharmony_ci    }
540cb93a386Sopenharmony_ci    SkAutoConicToQuads converter;
541cb93a386Sopenharmony_ci    SkPath::Verb verb;
542cb93a386Sopenharmony_ci    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
543cb93a386Sopenharmony_ci        switch (verb) {
544cb93a386Sopenharmony_ci            case SkPath::kConic_Verb: {
545cb93a386Sopenharmony_ci                *isLinear = false;
546cb93a386Sopenharmony_ci                if (toleranceSqd == 0) {
547cb93a386Sopenharmony_ci                    this->appendPointToContour(pts[2], contour);
548cb93a386Sopenharmony_ci                    break;
549cb93a386Sopenharmony_ci                }
550cb93a386Sopenharmony_ci                SkScalar weight = iter.conicWeight();
551cb93a386Sopenharmony_ci                const SkPoint* quadPts = converter.computeQuads(pts, weight, toleranceSqd);
552cb93a386Sopenharmony_ci                for (int i = 0; i < converter.countQuads(); ++i) {
553cb93a386Sopenharmony_ci                    this->appendQuadraticToContour(quadPts, toleranceSqd, contour);
554cb93a386Sopenharmony_ci                    quadPts += 2;
555cb93a386Sopenharmony_ci                }
556cb93a386Sopenharmony_ci                break;
557cb93a386Sopenharmony_ci            }
558cb93a386Sopenharmony_ci            case SkPath::kMove_Verb:
559cb93a386Sopenharmony_ci                if (contour->fHead) {
560cb93a386Sopenharmony_ci                    contour++;
561cb93a386Sopenharmony_ci                }
562cb93a386Sopenharmony_ci                this->appendPointToContour(pts[0], contour);
563cb93a386Sopenharmony_ci                break;
564cb93a386Sopenharmony_ci            case SkPath::kLine_Verb: {
565cb93a386Sopenharmony_ci                this->appendPointToContour(pts[1], contour);
566cb93a386Sopenharmony_ci                break;
567cb93a386Sopenharmony_ci            }
568cb93a386Sopenharmony_ci            case SkPath::kQuad_Verb: {
569cb93a386Sopenharmony_ci                *isLinear = false;
570cb93a386Sopenharmony_ci                if (toleranceSqd == 0) {
571cb93a386Sopenharmony_ci                    this->appendPointToContour(pts[2], contour);
572cb93a386Sopenharmony_ci                    break;
573cb93a386Sopenharmony_ci                }
574cb93a386Sopenharmony_ci                this->appendQuadraticToContour(pts, toleranceSqd, contour);
575cb93a386Sopenharmony_ci                break;
576cb93a386Sopenharmony_ci            }
577cb93a386Sopenharmony_ci            case SkPath::kCubic_Verb: {
578cb93a386Sopenharmony_ci                *isLinear = false;
579cb93a386Sopenharmony_ci                if (toleranceSqd == 0) {
580cb93a386Sopenharmony_ci                    this->appendPointToContour(pts[3], contour);
581cb93a386Sopenharmony_ci                    break;
582cb93a386Sopenharmony_ci                }
583cb93a386Sopenharmony_ci                int pointsLeft = GrPathUtils::cubicPointCount(pts, tolerance);
584cb93a386Sopenharmony_ci                this->generateCubicPoints(pts[0], pts[1], pts[2], pts[3], toleranceSqd, contour,
585cb93a386Sopenharmony_ci                                          pointsLeft);
586cb93a386Sopenharmony_ci                break;
587cb93a386Sopenharmony_ci            }
588cb93a386Sopenharmony_ci            case SkPath::kClose_Verb:
589cb93a386Sopenharmony_ci            case SkPath::kDone_Verb:
590cb93a386Sopenharmony_ci                break;
591cb93a386Sopenharmony_ci        }
592cb93a386Sopenharmony_ci    }
593cb93a386Sopenharmony_ci}
594cb93a386Sopenharmony_ci
595cb93a386Sopenharmony_cistatic inline bool apply_fill_type(SkPathFillType fillType, int winding) {
596cb93a386Sopenharmony_ci    switch (fillType) {
597cb93a386Sopenharmony_ci        case SkPathFillType::kWinding:
598cb93a386Sopenharmony_ci            return winding != 0;
599cb93a386Sopenharmony_ci        case SkPathFillType::kEvenOdd:
600cb93a386Sopenharmony_ci            return (winding & 1) != 0;
601cb93a386Sopenharmony_ci        case SkPathFillType::kInverseWinding:
602cb93a386Sopenharmony_ci            return winding == 1;
603cb93a386Sopenharmony_ci        case SkPathFillType::kInverseEvenOdd:
604cb93a386Sopenharmony_ci            return (winding & 1) == 1;
605cb93a386Sopenharmony_ci        default:
606cb93a386Sopenharmony_ci            SkASSERT(false);
607cb93a386Sopenharmony_ci            return false;
608cb93a386Sopenharmony_ci    }
609cb93a386Sopenharmony_ci}
610cb93a386Sopenharmony_ci
611cb93a386Sopenharmony_cibool GrTriangulator::applyFillType(int winding) const {
612cb93a386Sopenharmony_ci    return apply_fill_type(fPath.getFillType(), winding);
613cb93a386Sopenharmony_ci}
614cb93a386Sopenharmony_ci
615cb93a386Sopenharmony_cistatic inline bool apply_fill_type(SkPathFillType fillType, Poly* poly) {
616cb93a386Sopenharmony_ci    return poly && apply_fill_type(fillType, poly->fWinding);
617cb93a386Sopenharmony_ci}
618cb93a386Sopenharmony_ci
619cb93a386Sopenharmony_ciEdge* GrTriangulator::makeEdge(Vertex* prev, Vertex* next, EdgeType type,
620cb93a386Sopenharmony_ci                               const Comparator& c) const {
621cb93a386Sopenharmony_ci    SkASSERT(prev->fPoint != next->fPoint);
622cb93a386Sopenharmony_ci    int winding = c.sweep_lt(prev->fPoint, next->fPoint) ? 1 : -1;
623cb93a386Sopenharmony_ci    Vertex* top = winding < 0 ? next : prev;
624cb93a386Sopenharmony_ci    Vertex* bottom = winding < 0 ? prev : next;
625cb93a386Sopenharmony_ci    return fAlloc->make<Edge>(top, bottom, winding, type);
626cb93a386Sopenharmony_ci}
627cb93a386Sopenharmony_ci
628cb93a386Sopenharmony_civoid EdgeList::insert(Edge* edge, Edge* prev) {
629cb93a386Sopenharmony_ci    TESS_LOG("inserting edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID);
630cb93a386Sopenharmony_ci    SkASSERT(!this->contains(edge));
631cb93a386Sopenharmony_ci    Edge* next = prev ? prev->fRight : fHead;
632cb93a386Sopenharmony_ci    this->insert(edge, prev, next);
633cb93a386Sopenharmony_ci}
634cb93a386Sopenharmony_ci
635cb93a386Sopenharmony_civoid GrTriangulator::FindEnclosingEdges(Vertex* v, EdgeList* edges, Edge** left, Edge** right) {
636cb93a386Sopenharmony_ci    if (v->fFirstEdgeAbove && v->fLastEdgeAbove) {
637cb93a386Sopenharmony_ci        *left = v->fFirstEdgeAbove->fLeft;
638cb93a386Sopenharmony_ci        *right = v->fLastEdgeAbove->fRight;
639cb93a386Sopenharmony_ci        return;
640cb93a386Sopenharmony_ci    }
641cb93a386Sopenharmony_ci    Edge* next = nullptr;
642cb93a386Sopenharmony_ci    Edge* prev;
643cb93a386Sopenharmony_ci    for (prev = edges->fTail; prev != nullptr; prev = prev->fLeft) {
644cb93a386Sopenharmony_ci        if (prev->isLeftOf(v)) {
645cb93a386Sopenharmony_ci            break;
646cb93a386Sopenharmony_ci        }
647cb93a386Sopenharmony_ci        next = prev;
648cb93a386Sopenharmony_ci    }
649cb93a386Sopenharmony_ci    *left = prev;
650cb93a386Sopenharmony_ci    *right = next;
651cb93a386Sopenharmony_ci}
652cb93a386Sopenharmony_ci
653cb93a386Sopenharmony_civoid GrTriangulator::Edge::insertAbove(Vertex* v, const Comparator& c) {
654cb93a386Sopenharmony_ci    if (fTop->fPoint == fBottom->fPoint ||
655cb93a386Sopenharmony_ci        c.sweep_lt(fBottom->fPoint, fTop->fPoint)) {
656cb93a386Sopenharmony_ci        return;
657cb93a386Sopenharmony_ci    }
658cb93a386Sopenharmony_ci    TESS_LOG("insert edge (%g -> %g) above vertex %g\n", fTop->fID, fBottom->fID, v->fID);
659cb93a386Sopenharmony_ci    Edge* prev = nullptr;
660cb93a386Sopenharmony_ci    Edge* next;
661cb93a386Sopenharmony_ci    for (next = v->fFirstEdgeAbove; next; next = next->fNextEdgeAbove) {
662cb93a386Sopenharmony_ci        if (next->isRightOf(fTop)) {
663cb93a386Sopenharmony_ci            break;
664cb93a386Sopenharmony_ci        }
665cb93a386Sopenharmony_ci        prev = next;
666cb93a386Sopenharmony_ci    }
667cb93a386Sopenharmony_ci    list_insert<Edge, &Edge::fPrevEdgeAbove, &Edge::fNextEdgeAbove>(
668cb93a386Sopenharmony_ci        this, prev, next, &v->fFirstEdgeAbove, &v->fLastEdgeAbove);
669cb93a386Sopenharmony_ci}
670cb93a386Sopenharmony_ci
671cb93a386Sopenharmony_civoid GrTriangulator::Edge::insertBelow(Vertex* v, const Comparator& c) {
672cb93a386Sopenharmony_ci    if (fTop->fPoint == fBottom->fPoint ||
673cb93a386Sopenharmony_ci        c.sweep_lt(fBottom->fPoint, fTop->fPoint)) {
674cb93a386Sopenharmony_ci        return;
675cb93a386Sopenharmony_ci    }
676cb93a386Sopenharmony_ci    TESS_LOG("insert edge (%g -> %g) below vertex %g\n", fTop->fID, fBottom->fID, v->fID);
677cb93a386Sopenharmony_ci    Edge* prev = nullptr;
678cb93a386Sopenharmony_ci    Edge* next;
679cb93a386Sopenharmony_ci    for (next = v->fFirstEdgeBelow; next; next = next->fNextEdgeBelow) {
680cb93a386Sopenharmony_ci        if (next->isRightOf(fBottom)) {
681cb93a386Sopenharmony_ci            break;
682cb93a386Sopenharmony_ci        }
683cb93a386Sopenharmony_ci        prev = next;
684cb93a386Sopenharmony_ci    }
685cb93a386Sopenharmony_ci    list_insert<Edge, &Edge::fPrevEdgeBelow, &Edge::fNextEdgeBelow>(
686cb93a386Sopenharmony_ci        this, prev, next, &v->fFirstEdgeBelow, &v->fLastEdgeBelow);
687cb93a386Sopenharmony_ci}
688cb93a386Sopenharmony_ci
689cb93a386Sopenharmony_cistatic void remove_edge_above(Edge* edge) {
690cb93a386Sopenharmony_ci    SkASSERT(edge->fTop && edge->fBottom);
691cb93a386Sopenharmony_ci    TESS_LOG("removing edge (%g -> %g) above vertex %g\n", edge->fTop->fID, edge->fBottom->fID,
692cb93a386Sopenharmony_ci             edge->fBottom->fID);
693cb93a386Sopenharmony_ci    list_remove<Edge, &Edge::fPrevEdgeAbove, &Edge::fNextEdgeAbove>(
694cb93a386Sopenharmony_ci        edge, &edge->fBottom->fFirstEdgeAbove, &edge->fBottom->fLastEdgeAbove);
695cb93a386Sopenharmony_ci}
696cb93a386Sopenharmony_ci
697cb93a386Sopenharmony_cistatic void remove_edge_below(Edge* edge) {
698cb93a386Sopenharmony_ci    SkASSERT(edge->fTop && edge->fBottom);
699cb93a386Sopenharmony_ci    TESS_LOG("removing edge (%g -> %g) below vertex %g\n",
700cb93a386Sopenharmony_ci             edge->fTop->fID, edge->fBottom->fID, edge->fTop->fID);
701cb93a386Sopenharmony_ci    list_remove<Edge, &Edge::fPrevEdgeBelow, &Edge::fNextEdgeBelow>(
702cb93a386Sopenharmony_ci        edge, &edge->fTop->fFirstEdgeBelow, &edge->fTop->fLastEdgeBelow);
703cb93a386Sopenharmony_ci}
704cb93a386Sopenharmony_ci
705cb93a386Sopenharmony_civoid GrTriangulator::Edge::disconnect() {
706cb93a386Sopenharmony_ci    remove_edge_above(this);
707cb93a386Sopenharmony_ci    remove_edge_below(this);
708cb93a386Sopenharmony_ci}
709cb93a386Sopenharmony_ci
710cb93a386Sopenharmony_cistatic void rewind(EdgeList* activeEdges, Vertex** current, Vertex* dst, const Comparator& c) {
711cb93a386Sopenharmony_ci    if (!current || *current == dst || c.sweep_lt((*current)->fPoint, dst->fPoint)) {
712cb93a386Sopenharmony_ci        return;
713cb93a386Sopenharmony_ci    }
714cb93a386Sopenharmony_ci    Vertex* v = *current;
715cb93a386Sopenharmony_ci    TESS_LOG("rewinding active edges from vertex %g to vertex %g\n", v->fID, dst->fID);
716cb93a386Sopenharmony_ci    while (v != dst) {
717cb93a386Sopenharmony_ci        v = v->fPrev;
718cb93a386Sopenharmony_ci        for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
719cb93a386Sopenharmony_ci            activeEdges->remove(e);
720cb93a386Sopenharmony_ci        }
721cb93a386Sopenharmony_ci        Edge* leftEdge = v->fLeftEnclosingEdge;
722cb93a386Sopenharmony_ci        for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
723cb93a386Sopenharmony_ci            activeEdges->insert(e, leftEdge);
724cb93a386Sopenharmony_ci            leftEdge = e;
725cb93a386Sopenharmony_ci            Vertex* top = e->fTop;
726cb93a386Sopenharmony_ci            if (c.sweep_lt(top->fPoint, dst->fPoint) &&
727cb93a386Sopenharmony_ci                ((top->fLeftEnclosingEdge && !top->fLeftEnclosingEdge->isLeftOf(e->fTop)) ||
728cb93a386Sopenharmony_ci                 (top->fRightEnclosingEdge && !top->fRightEnclosingEdge->isRightOf(e->fTop)))) {
729cb93a386Sopenharmony_ci                dst = top;
730cb93a386Sopenharmony_ci            }
731cb93a386Sopenharmony_ci        }
732cb93a386Sopenharmony_ci    }
733cb93a386Sopenharmony_ci    *current = v;
734cb93a386Sopenharmony_ci}
735cb93a386Sopenharmony_ci
736cb93a386Sopenharmony_cistatic void rewind_if_necessary(Edge* edge, EdgeList* activeEdges, Vertex** current,
737cb93a386Sopenharmony_ci                                const Comparator& c) {
738cb93a386Sopenharmony_ci    if (!activeEdges || !current) {
739cb93a386Sopenharmony_ci        return;
740cb93a386Sopenharmony_ci    }
741cb93a386Sopenharmony_ci    Vertex* top = edge->fTop;
742cb93a386Sopenharmony_ci    Vertex* bottom = edge->fBottom;
743cb93a386Sopenharmony_ci    if (edge->fLeft) {
744cb93a386Sopenharmony_ci        Vertex* leftTop = edge->fLeft->fTop;
745cb93a386Sopenharmony_ci        Vertex* leftBottom = edge->fLeft->fBottom;
746cb93a386Sopenharmony_ci        if (c.sweep_lt(leftTop->fPoint, top->fPoint) && !edge->fLeft->isLeftOf(top)) {
747cb93a386Sopenharmony_ci            rewind(activeEdges, current, leftTop, c);
748cb93a386Sopenharmony_ci        } else if (c.sweep_lt(top->fPoint, leftTop->fPoint) && !edge->isRightOf(leftTop)) {
749cb93a386Sopenharmony_ci            rewind(activeEdges, current, top, c);
750cb93a386Sopenharmony_ci        } else if (c.sweep_lt(bottom->fPoint, leftBottom->fPoint) &&
751cb93a386Sopenharmony_ci                   !edge->fLeft->isLeftOf(bottom)) {
752cb93a386Sopenharmony_ci            rewind(activeEdges, current, leftTop, c);
753cb93a386Sopenharmony_ci        } else if (c.sweep_lt(leftBottom->fPoint, bottom->fPoint) && !edge->isRightOf(leftBottom)) {
754cb93a386Sopenharmony_ci            rewind(activeEdges, current, top, c);
755cb93a386Sopenharmony_ci        }
756cb93a386Sopenharmony_ci    }
757cb93a386Sopenharmony_ci    if (edge->fRight) {
758cb93a386Sopenharmony_ci        Vertex* rightTop = edge->fRight->fTop;
759cb93a386Sopenharmony_ci        Vertex* rightBottom = edge->fRight->fBottom;
760cb93a386Sopenharmony_ci        if (c.sweep_lt(rightTop->fPoint, top->fPoint) && !edge->fRight->isRightOf(top)) {
761cb93a386Sopenharmony_ci            rewind(activeEdges, current, rightTop, c);
762cb93a386Sopenharmony_ci        } else if (c.sweep_lt(top->fPoint, rightTop->fPoint) && !edge->isLeftOf(rightTop)) {
763cb93a386Sopenharmony_ci            rewind(activeEdges, current, top, c);
764cb93a386Sopenharmony_ci        } else if (c.sweep_lt(bottom->fPoint, rightBottom->fPoint) &&
765cb93a386Sopenharmony_ci                   !edge->fRight->isRightOf(bottom)) {
766cb93a386Sopenharmony_ci            rewind(activeEdges, current, rightTop, c);
767cb93a386Sopenharmony_ci        } else if (c.sweep_lt(rightBottom->fPoint, bottom->fPoint) &&
768cb93a386Sopenharmony_ci                   !edge->isLeftOf(rightBottom)) {
769cb93a386Sopenharmony_ci            rewind(activeEdges, current, top, c);
770cb93a386Sopenharmony_ci        }
771cb93a386Sopenharmony_ci    }
772cb93a386Sopenharmony_ci}
773cb93a386Sopenharmony_ci
774cb93a386Sopenharmony_civoid GrTriangulator::setTop(Edge* edge, Vertex* v, EdgeList* activeEdges, Vertex** current,
775cb93a386Sopenharmony_ci                            const Comparator& c) const {
776cb93a386Sopenharmony_ci    remove_edge_below(edge);
777cb93a386Sopenharmony_ci    if (fCollectBreadcrumbTriangles) {
778cb93a386Sopenharmony_ci        fBreadcrumbList.append(fAlloc, edge->fTop->fPoint, edge->fBottom->fPoint, v->fPoint,
779cb93a386Sopenharmony_ci                               edge->fWinding);
780cb93a386Sopenharmony_ci    }
781cb93a386Sopenharmony_ci    edge->fTop = v;
782cb93a386Sopenharmony_ci    edge->recompute();
783cb93a386Sopenharmony_ci    edge->insertBelow(v, c);
784cb93a386Sopenharmony_ci    rewind_if_necessary(edge, activeEdges, current, c);
785cb93a386Sopenharmony_ci    this->mergeCollinearEdges(edge, activeEdges, current, c);
786cb93a386Sopenharmony_ci}
787cb93a386Sopenharmony_ci
788cb93a386Sopenharmony_civoid GrTriangulator::setBottom(Edge* edge, Vertex* v, EdgeList* activeEdges, Vertex** current,
789cb93a386Sopenharmony_ci                               const Comparator& c) const {
790cb93a386Sopenharmony_ci    remove_edge_above(edge);
791cb93a386Sopenharmony_ci    if (fCollectBreadcrumbTriangles) {
792cb93a386Sopenharmony_ci        fBreadcrumbList.append(fAlloc, edge->fTop->fPoint, edge->fBottom->fPoint, v->fPoint,
793cb93a386Sopenharmony_ci                               edge->fWinding);
794cb93a386Sopenharmony_ci    }
795cb93a386Sopenharmony_ci    edge->fBottom = v;
796cb93a386Sopenharmony_ci    edge->recompute();
797cb93a386Sopenharmony_ci    edge->insertAbove(v, c);
798cb93a386Sopenharmony_ci    rewind_if_necessary(edge, activeEdges, current, c);
799cb93a386Sopenharmony_ci    this->mergeCollinearEdges(edge, activeEdges, current, c);
800cb93a386Sopenharmony_ci}
801cb93a386Sopenharmony_ci
802cb93a386Sopenharmony_civoid GrTriangulator::mergeEdgesAbove(Edge* edge, Edge* other, EdgeList* activeEdges,
803cb93a386Sopenharmony_ci                                     Vertex** current, const Comparator& c) const {
804cb93a386Sopenharmony_ci    if (coincident(edge->fTop->fPoint, other->fTop->fPoint)) {
805cb93a386Sopenharmony_ci        TESS_LOG("merging coincident above edges (%g, %g) -> (%g, %g)\n",
806cb93a386Sopenharmony_ci                 edge->fTop->fPoint.fX, edge->fTop->fPoint.fY,
807cb93a386Sopenharmony_ci                 edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY);
808cb93a386Sopenharmony_ci        rewind(activeEdges, current, edge->fTop, c);
809cb93a386Sopenharmony_ci        other->fWinding += edge->fWinding;
810cb93a386Sopenharmony_ci        edge->disconnect();
811cb93a386Sopenharmony_ci        edge->fTop = edge->fBottom = nullptr;
812cb93a386Sopenharmony_ci    } else if (c.sweep_lt(edge->fTop->fPoint, other->fTop->fPoint)) {
813cb93a386Sopenharmony_ci        rewind(activeEdges, current, edge->fTop, c);
814cb93a386Sopenharmony_ci        other->fWinding += edge->fWinding;
815cb93a386Sopenharmony_ci        this->setBottom(edge, other->fTop, activeEdges, current, c);
816cb93a386Sopenharmony_ci    } else {
817cb93a386Sopenharmony_ci        rewind(activeEdges, current, other->fTop, c);
818cb93a386Sopenharmony_ci        edge->fWinding += other->fWinding;
819cb93a386Sopenharmony_ci        this->setBottom(other, edge->fTop, activeEdges, current, c);
820cb93a386Sopenharmony_ci    }
821cb93a386Sopenharmony_ci}
822cb93a386Sopenharmony_ci
823cb93a386Sopenharmony_civoid GrTriangulator::mergeEdgesBelow(Edge* edge, Edge* other, EdgeList* activeEdges,
824cb93a386Sopenharmony_ci                                     Vertex** current, const Comparator& c) const {
825cb93a386Sopenharmony_ci    if (coincident(edge->fBottom->fPoint, other->fBottom->fPoint)) {
826cb93a386Sopenharmony_ci        TESS_LOG("merging coincident below edges (%g, %g) -> (%g, %g)\n",
827cb93a386Sopenharmony_ci                 edge->fTop->fPoint.fX, edge->fTop->fPoint.fY,
828cb93a386Sopenharmony_ci                 edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY);
829cb93a386Sopenharmony_ci        rewind(activeEdges, current, edge->fTop, c);
830cb93a386Sopenharmony_ci        other->fWinding += edge->fWinding;
831cb93a386Sopenharmony_ci        edge->disconnect();
832cb93a386Sopenharmony_ci        edge->fTop = edge->fBottom = nullptr;
833cb93a386Sopenharmony_ci    } else if (c.sweep_lt(edge->fBottom->fPoint, other->fBottom->fPoint)) {
834cb93a386Sopenharmony_ci        rewind(activeEdges, current, other->fTop, c);
835cb93a386Sopenharmony_ci        edge->fWinding += other->fWinding;
836cb93a386Sopenharmony_ci        this->setTop(other, edge->fBottom, activeEdges, current, c);
837cb93a386Sopenharmony_ci    } else {
838cb93a386Sopenharmony_ci        rewind(activeEdges, current, edge->fTop, c);
839cb93a386Sopenharmony_ci        other->fWinding += edge->fWinding;
840cb93a386Sopenharmony_ci        this->setTop(edge, other->fBottom, activeEdges, current, c);
841cb93a386Sopenharmony_ci    }
842cb93a386Sopenharmony_ci}
843cb93a386Sopenharmony_ci
844cb93a386Sopenharmony_cistatic bool top_collinear(Edge* left, Edge* right) {
845cb93a386Sopenharmony_ci    if (!left || !right) {
846cb93a386Sopenharmony_ci        return false;
847cb93a386Sopenharmony_ci    }
848cb93a386Sopenharmony_ci    return left->fTop->fPoint == right->fTop->fPoint ||
849cb93a386Sopenharmony_ci           !left->isLeftOf(right->fTop) || !right->isRightOf(left->fTop);
850cb93a386Sopenharmony_ci}
851cb93a386Sopenharmony_ci
852cb93a386Sopenharmony_cistatic bool bottom_collinear(Edge* left, Edge* right) {
853cb93a386Sopenharmony_ci    if (!left || !right) {
854cb93a386Sopenharmony_ci        return false;
855cb93a386Sopenharmony_ci    }
856cb93a386Sopenharmony_ci    return left->fBottom->fPoint == right->fBottom->fPoint ||
857cb93a386Sopenharmony_ci           !left->isLeftOf(right->fBottom) || !right->isRightOf(left->fBottom);
858cb93a386Sopenharmony_ci}
859cb93a386Sopenharmony_ci
860cb93a386Sopenharmony_civoid GrTriangulator::mergeCollinearEdges(Edge* edge, EdgeList* activeEdges, Vertex** current,
861cb93a386Sopenharmony_ci                                         const Comparator& c) const {
862cb93a386Sopenharmony_ci    for (;;) {
863cb93a386Sopenharmony_ci        if (top_collinear(edge->fPrevEdgeAbove, edge)) {
864cb93a386Sopenharmony_ci            this->mergeEdgesAbove(edge->fPrevEdgeAbove, edge, activeEdges, current, c);
865cb93a386Sopenharmony_ci        } else if (top_collinear(edge, edge->fNextEdgeAbove)) {
866cb93a386Sopenharmony_ci            this->mergeEdgesAbove(edge->fNextEdgeAbove, edge, activeEdges, current, c);
867cb93a386Sopenharmony_ci        } else if (bottom_collinear(edge->fPrevEdgeBelow, edge)) {
868cb93a386Sopenharmony_ci            this->mergeEdgesBelow(edge->fPrevEdgeBelow, edge, activeEdges, current, c);
869cb93a386Sopenharmony_ci        } else if (bottom_collinear(edge, edge->fNextEdgeBelow)) {
870cb93a386Sopenharmony_ci            this->mergeEdgesBelow(edge->fNextEdgeBelow, edge, activeEdges, current, c);
871cb93a386Sopenharmony_ci        } else {
872cb93a386Sopenharmony_ci            break;
873cb93a386Sopenharmony_ci        }
874cb93a386Sopenharmony_ci    }
875cb93a386Sopenharmony_ci    SkASSERT(!top_collinear(edge->fPrevEdgeAbove, edge));
876cb93a386Sopenharmony_ci    SkASSERT(!top_collinear(edge, edge->fNextEdgeAbove));
877cb93a386Sopenharmony_ci    SkASSERT(!bottom_collinear(edge->fPrevEdgeBelow, edge));
878cb93a386Sopenharmony_ci    SkASSERT(!bottom_collinear(edge, edge->fNextEdgeBelow));
879cb93a386Sopenharmony_ci}
880cb93a386Sopenharmony_ci
881cb93a386Sopenharmony_cibool GrTriangulator::splitEdge(Edge* edge, Vertex* v, EdgeList* activeEdges, Vertex** current,
882cb93a386Sopenharmony_ci                               const Comparator& c) const {
883cb93a386Sopenharmony_ci    if (!edge->fTop || !edge->fBottom || v == edge->fTop || v == edge->fBottom) {
884cb93a386Sopenharmony_ci        return false;
885cb93a386Sopenharmony_ci    }
886cb93a386Sopenharmony_ci    TESS_LOG("splitting edge (%g -> %g) at vertex %g (%g, %g)\n",
887cb93a386Sopenharmony_ci             edge->fTop->fID, edge->fBottom->fID, v->fID, v->fPoint.fX, v->fPoint.fY);
888cb93a386Sopenharmony_ci    Vertex* top;
889cb93a386Sopenharmony_ci    Vertex* bottom;
890cb93a386Sopenharmony_ci    int winding = edge->fWinding;
891cb93a386Sopenharmony_ci    // Theoretically, and ideally, the edge betwee p0 and p1 is being split by v, and v is "between"
892cb93a386Sopenharmony_ci    // the segment end points according to c. This is equivalent to p0 < v < p1.  Unfortunately, if
893cb93a386Sopenharmony_ci    // v was clamped/rounded this relation doesn't always hold.
894cb93a386Sopenharmony_ci    if (c.sweep_lt(v->fPoint, edge->fTop->fPoint)) {
895cb93a386Sopenharmony_ci        // Actually "v < p0 < p1": update 'edge' to be v->p1 and add v->p0. We flip the winding on
896cb93a386Sopenharmony_ci        // the new edge so that it winds as if it were p0->v.
897cb93a386Sopenharmony_ci        top = v;
898cb93a386Sopenharmony_ci        bottom = edge->fTop;
899cb93a386Sopenharmony_ci        winding *= -1;
900cb93a386Sopenharmony_ci        this->setTop(edge, v, activeEdges, current, c);
901cb93a386Sopenharmony_ci    } else if (c.sweep_lt(edge->fBottom->fPoint, v->fPoint)) {
902cb93a386Sopenharmony_ci        // Actually "p0 < p1 < v": update 'edge' to be p0->v and add p1->v. We flip the winding on
903cb93a386Sopenharmony_ci        // the new edge so that it winds as if it were v->p1.
904cb93a386Sopenharmony_ci        top = edge->fBottom;
905cb93a386Sopenharmony_ci        bottom = v;
906cb93a386Sopenharmony_ci        winding *= -1;
907cb93a386Sopenharmony_ci        this->setBottom(edge, v, activeEdges, current, c);
908cb93a386Sopenharmony_ci    } else {
909cb93a386Sopenharmony_ci        // The ideal case, "p0 < v < p1": update 'edge' to be p0->v and add v->p1. Original winding
910cb93a386Sopenharmony_ci        // is valid for both edges.
911cb93a386Sopenharmony_ci        top = v;
912cb93a386Sopenharmony_ci        bottom = edge->fBottom;
913cb93a386Sopenharmony_ci        this->setBottom(edge, v, activeEdges, current, c);
914cb93a386Sopenharmony_ci    }
915cb93a386Sopenharmony_ci    Edge* newEdge = fAlloc->make<Edge>(top, bottom, winding, edge->fType);
916cb93a386Sopenharmony_ci    newEdge->insertBelow(top, c);
917cb93a386Sopenharmony_ci    newEdge->insertAbove(bottom, c);
918cb93a386Sopenharmony_ci    this->mergeCollinearEdges(newEdge, activeEdges, current, c);
919cb93a386Sopenharmony_ci    return true;
920cb93a386Sopenharmony_ci}
921cb93a386Sopenharmony_ci
922cb93a386Sopenharmony_cibool GrTriangulator::intersectEdgePair(Edge* left, Edge* right, EdgeList* activeEdges,
923cb93a386Sopenharmony_ci                                       Vertex** current, const Comparator& c) const {
924cb93a386Sopenharmony_ci    if (!left->fTop || !left->fBottom || !right->fTop || !right->fBottom) {
925cb93a386Sopenharmony_ci        return false;
926cb93a386Sopenharmony_ci    }
927cb93a386Sopenharmony_ci    if (left->fTop == right->fTop || left->fBottom == right->fBottom) {
928cb93a386Sopenharmony_ci        return false;
929cb93a386Sopenharmony_ci    }
930cb93a386Sopenharmony_ci    if (c.sweep_lt(left->fTop->fPoint, right->fTop->fPoint)) {
931cb93a386Sopenharmony_ci        if (!left->isLeftOf(right->fTop)) {
932cb93a386Sopenharmony_ci            rewind(activeEdges, current, right->fTop, c);
933cb93a386Sopenharmony_ci            return this->splitEdge(left, right->fTop, activeEdges, current, c);
934cb93a386Sopenharmony_ci        }
935cb93a386Sopenharmony_ci    } else {
936cb93a386Sopenharmony_ci        if (!right->isRightOf(left->fTop)) {
937cb93a386Sopenharmony_ci            rewind(activeEdges, current, left->fTop, c);
938cb93a386Sopenharmony_ci            return this->splitEdge(right, left->fTop, activeEdges, current, c);
939cb93a386Sopenharmony_ci        }
940cb93a386Sopenharmony_ci    }
941cb93a386Sopenharmony_ci    if (c.sweep_lt(right->fBottom->fPoint, left->fBottom->fPoint)) {
942cb93a386Sopenharmony_ci        if (!left->isLeftOf(right->fBottom)) {
943cb93a386Sopenharmony_ci            rewind(activeEdges, current, right->fBottom, c);
944cb93a386Sopenharmony_ci            return this->splitEdge(left, right->fBottom, activeEdges, current, c);
945cb93a386Sopenharmony_ci        }
946cb93a386Sopenharmony_ci    } else {
947cb93a386Sopenharmony_ci        if (!right->isRightOf(left->fBottom)) {
948cb93a386Sopenharmony_ci            rewind(activeEdges, current, left->fBottom, c);
949cb93a386Sopenharmony_ci            return this->splitEdge(right, left->fBottom, activeEdges, current, c);
950cb93a386Sopenharmony_ci        }
951cb93a386Sopenharmony_ci    }
952cb93a386Sopenharmony_ci    return false;
953cb93a386Sopenharmony_ci}
954cb93a386Sopenharmony_ci
955cb93a386Sopenharmony_ciEdge* GrTriangulator::makeConnectingEdge(Vertex* prev, Vertex* next, EdgeType type,
956cb93a386Sopenharmony_ci                                         const Comparator& c, int windingScale) const {
957cb93a386Sopenharmony_ci    if (!prev || !next || prev->fPoint == next->fPoint) {
958cb93a386Sopenharmony_ci        return nullptr;
959cb93a386Sopenharmony_ci    }
960cb93a386Sopenharmony_ci    Edge* edge = this->makeEdge(prev, next, type, c);
961cb93a386Sopenharmony_ci    edge->insertBelow(edge->fTop, c);
962cb93a386Sopenharmony_ci    edge->insertAbove(edge->fBottom, c);
963cb93a386Sopenharmony_ci    edge->fWinding *= windingScale;
964cb93a386Sopenharmony_ci    this->mergeCollinearEdges(edge, nullptr, nullptr, c);
965cb93a386Sopenharmony_ci    return edge;
966cb93a386Sopenharmony_ci}
967cb93a386Sopenharmony_ci
968cb93a386Sopenharmony_civoid GrTriangulator::mergeVertices(Vertex* src, Vertex* dst, VertexList* mesh,
969cb93a386Sopenharmony_ci                                   const Comparator& c) const {
970cb93a386Sopenharmony_ci    TESS_LOG("found coincident verts at %g, %g; merging %g into %g\n",
971cb93a386Sopenharmony_ci             src->fPoint.fX, src->fPoint.fY, src->fID, dst->fID);
972cb93a386Sopenharmony_ci    dst->fAlpha = std::max(src->fAlpha, dst->fAlpha);
973cb93a386Sopenharmony_ci    if (src->fPartner) {
974cb93a386Sopenharmony_ci        src->fPartner->fPartner = dst;
975cb93a386Sopenharmony_ci    }
976cb93a386Sopenharmony_ci    while (Edge* edge = src->fFirstEdgeAbove) {
977cb93a386Sopenharmony_ci        this->setBottom(edge, dst, nullptr, nullptr, c);
978cb93a386Sopenharmony_ci    }
979cb93a386Sopenharmony_ci    while (Edge* edge = src->fFirstEdgeBelow) {
980cb93a386Sopenharmony_ci        this->setTop(edge, dst, nullptr, nullptr, c);
981cb93a386Sopenharmony_ci    }
982cb93a386Sopenharmony_ci    mesh->remove(src);
983cb93a386Sopenharmony_ci    dst->fSynthetic = true;
984cb93a386Sopenharmony_ci}
985cb93a386Sopenharmony_ci
986cb93a386Sopenharmony_ciVertex* GrTriangulator::makeSortedVertex(const SkPoint& p, uint8_t alpha, VertexList* mesh,
987cb93a386Sopenharmony_ci                                         Vertex* reference, const Comparator& c) const {
988cb93a386Sopenharmony_ci    Vertex* prevV = reference;
989cb93a386Sopenharmony_ci    while (prevV && c.sweep_lt(p, prevV->fPoint)) {
990cb93a386Sopenharmony_ci        prevV = prevV->fPrev;
991cb93a386Sopenharmony_ci    }
992cb93a386Sopenharmony_ci    Vertex* nextV = prevV ? prevV->fNext : mesh->fHead;
993cb93a386Sopenharmony_ci    while (nextV && c.sweep_lt(nextV->fPoint, p)) {
994cb93a386Sopenharmony_ci        prevV = nextV;
995cb93a386Sopenharmony_ci        nextV = nextV->fNext;
996cb93a386Sopenharmony_ci    }
997cb93a386Sopenharmony_ci    Vertex* v;
998cb93a386Sopenharmony_ci    if (prevV && coincident(prevV->fPoint, p)) {
999cb93a386Sopenharmony_ci        v = prevV;
1000cb93a386Sopenharmony_ci    } else if (nextV && coincident(nextV->fPoint, p)) {
1001cb93a386Sopenharmony_ci        v = nextV;
1002cb93a386Sopenharmony_ci    } else {
1003cb93a386Sopenharmony_ci        v = fAlloc->make<Vertex>(p, alpha);
1004cb93a386Sopenharmony_ci#if TRIANGULATOR_LOGGING
1005cb93a386Sopenharmony_ci        if (!prevV) {
1006cb93a386Sopenharmony_ci            v->fID = mesh->fHead->fID - 1.0f;
1007cb93a386Sopenharmony_ci        } else if (!nextV) {
1008cb93a386Sopenharmony_ci            v->fID = mesh->fTail->fID + 1.0f;
1009cb93a386Sopenharmony_ci        } else {
1010cb93a386Sopenharmony_ci            v->fID = (prevV->fID + nextV->fID) * 0.5f;
1011cb93a386Sopenharmony_ci        }
1012cb93a386Sopenharmony_ci#endif
1013cb93a386Sopenharmony_ci        mesh->insert(v, prevV, nextV);
1014cb93a386Sopenharmony_ci    }
1015cb93a386Sopenharmony_ci    return v;
1016cb93a386Sopenharmony_ci}
1017cb93a386Sopenharmony_ci
1018cb93a386Sopenharmony_ci// Clamps x and y coordinates independently, so the returned point will lie within the bounding
1019cb93a386Sopenharmony_ci// box formed by the corners of 'min' and 'max' (although min/max here refer to the ordering
1020cb93a386Sopenharmony_ci// imposed by 'c').
1021cb93a386Sopenharmony_cistatic SkPoint clamp(SkPoint p, SkPoint min, SkPoint max, const Comparator& c) {
1022cb93a386Sopenharmony_ci    if (c.fDirection == Comparator::Direction::kHorizontal) {
1023cb93a386Sopenharmony_ci        // With horizontal sorting, we know min.x <= max.x, but there's no relation between
1024cb93a386Sopenharmony_ci        // Y components unless min.x == max.x.
1025cb93a386Sopenharmony_ci        return {SkTPin(p.fX, min.fX, max.fX),
1026cb93a386Sopenharmony_ci                min.fY < max.fY ? SkTPin(p.fY, min.fY, max.fY)
1027cb93a386Sopenharmony_ci                                : SkTPin(p.fY, max.fY, min.fY)};
1028cb93a386Sopenharmony_ci    } else {
1029cb93a386Sopenharmony_ci        // And with vertical sorting, we know Y's relation but not necessarily X's.
1030cb93a386Sopenharmony_ci        return {min.fX < max.fX ? SkTPin(p.fX, min.fX, max.fX)
1031cb93a386Sopenharmony_ci                                : SkTPin(p.fX, max.fX, min.fX),
1032cb93a386Sopenharmony_ci                SkTPin(p.fY, min.fY, max.fY)};
1033cb93a386Sopenharmony_ci    }
1034cb93a386Sopenharmony_ci}
1035cb93a386Sopenharmony_ci
1036cb93a386Sopenharmony_civoid GrTriangulator::computeBisector(Edge* edge1, Edge* edge2, Vertex* v) const {
1037cb93a386Sopenharmony_ci    SkASSERT(fEmitCoverage);  // Edge-AA only!
1038cb93a386Sopenharmony_ci    Line line1 = edge1->fLine;
1039cb93a386Sopenharmony_ci    Line line2 = edge2->fLine;
1040cb93a386Sopenharmony_ci    line1.normalize();
1041cb93a386Sopenharmony_ci    line2.normalize();
1042cb93a386Sopenharmony_ci    double cosAngle = line1.fA * line2.fA + line1.fB * line2.fB;
1043cb93a386Sopenharmony_ci    if (cosAngle > 0.999) {
1044cb93a386Sopenharmony_ci        return;
1045cb93a386Sopenharmony_ci    }
1046cb93a386Sopenharmony_ci    line1.fC += edge1->fWinding > 0 ? -1 : 1;
1047cb93a386Sopenharmony_ci    line2.fC += edge2->fWinding > 0 ? -1 : 1;
1048cb93a386Sopenharmony_ci    SkPoint p;
1049cb93a386Sopenharmony_ci    if (line1.intersect(line2, &p)) {
1050cb93a386Sopenharmony_ci        uint8_t alpha = edge1->fType == EdgeType::kOuter ? 255 : 0;
1051cb93a386Sopenharmony_ci        v->fPartner = fAlloc->make<Vertex>(p, alpha);
1052cb93a386Sopenharmony_ci        TESS_LOG("computed bisector (%g,%g) alpha %d for vertex %g\n", p.fX, p.fY, alpha, v->fID);
1053cb93a386Sopenharmony_ci    }
1054cb93a386Sopenharmony_ci}
1055cb93a386Sopenharmony_ci
1056cb93a386Sopenharmony_cibool GrTriangulator::checkForIntersection(Edge* left, Edge* right, EdgeList* activeEdges,
1057cb93a386Sopenharmony_ci                                          Vertex** current, VertexList* mesh,
1058cb93a386Sopenharmony_ci                                          const Comparator& c) const {
1059cb93a386Sopenharmony_ci    if (!left || !right) {
1060cb93a386Sopenharmony_ci        return false;
1061cb93a386Sopenharmony_ci    }
1062cb93a386Sopenharmony_ci    SkPoint p;
1063cb93a386Sopenharmony_ci    uint8_t alpha;
1064cb93a386Sopenharmony_ci    if (left->intersect(*right, &p, &alpha) && p.isFinite()) {
1065cb93a386Sopenharmony_ci        Vertex* v;
1066cb93a386Sopenharmony_ci        TESS_LOG("found intersection, pt is %g, %g\n", p.fX, p.fY);
1067cb93a386Sopenharmony_ci        Vertex* top = *current;
1068cb93a386Sopenharmony_ci        // If the intersection point is above the current vertex, rewind to the vertex above the
1069cb93a386Sopenharmony_ci        // intersection.
1070cb93a386Sopenharmony_ci        while (top && c.sweep_lt(p, top->fPoint)) {
1071cb93a386Sopenharmony_ci            top = top->fPrev;
1072cb93a386Sopenharmony_ci        }
1073cb93a386Sopenharmony_ci
1074cb93a386Sopenharmony_ci        // Always clamp the intersection to lie between the vertices of each segment, since
1075cb93a386Sopenharmony_ci        // in theory that's where the intersection is, but in reality, floating point error may
1076cb93a386Sopenharmony_ci        // have computed an intersection beyond a vertex's component(s).
1077cb93a386Sopenharmony_ci        p = clamp(p, left->fTop->fPoint, left->fBottom->fPoint, c);
1078cb93a386Sopenharmony_ci        p = clamp(p, right->fTop->fPoint, right->fBottom->fPoint, c);
1079cb93a386Sopenharmony_ci
1080cb93a386Sopenharmony_ci        if (coincident(p, left->fTop->fPoint)) {
1081cb93a386Sopenharmony_ci            v = left->fTop;
1082cb93a386Sopenharmony_ci        } else if (coincident(p, left->fBottom->fPoint)) {
1083cb93a386Sopenharmony_ci            v = left->fBottom;
1084cb93a386Sopenharmony_ci        } else if (coincident(p, right->fTop->fPoint)) {
1085cb93a386Sopenharmony_ci            v = right->fTop;
1086cb93a386Sopenharmony_ci        } else if (coincident(p, right->fBottom->fPoint)) {
1087cb93a386Sopenharmony_ci            v = right->fBottom;
1088cb93a386Sopenharmony_ci        } else {
1089cb93a386Sopenharmony_ci            v = this->makeSortedVertex(p, alpha, mesh, top, c);
1090cb93a386Sopenharmony_ci            if (left->fTop->fPartner) {
1091cb93a386Sopenharmony_ci                SkASSERT(fEmitCoverage);  // Edge-AA only!
1092cb93a386Sopenharmony_ci                v->fSynthetic = true;
1093cb93a386Sopenharmony_ci                this->computeBisector(left, right, v);
1094cb93a386Sopenharmony_ci            }
1095cb93a386Sopenharmony_ci        }
1096cb93a386Sopenharmony_ci        rewind(activeEdges, current, top ? top : v, c);
1097cb93a386Sopenharmony_ci        this->splitEdge(left, v, activeEdges, current, c);
1098cb93a386Sopenharmony_ci        this->splitEdge(right, v, activeEdges, current, c);
1099cb93a386Sopenharmony_ci        v->fAlpha = std::max(v->fAlpha, alpha);
1100cb93a386Sopenharmony_ci        return true;
1101cb93a386Sopenharmony_ci    }
1102cb93a386Sopenharmony_ci    return this->intersectEdgePair(left, right, activeEdges, current, c);
1103cb93a386Sopenharmony_ci}
1104cb93a386Sopenharmony_ci
1105cb93a386Sopenharmony_civoid GrTriangulator::sanitizeContours(VertexList* contours, int contourCnt) const {
1106cb93a386Sopenharmony_ci    for (VertexList* contour = contours; contourCnt > 0; --contourCnt, ++contour) {
1107cb93a386Sopenharmony_ci        SkASSERT(contour->fHead);
1108cb93a386Sopenharmony_ci        Vertex* prev = contour->fTail;
1109cb93a386Sopenharmony_ci        prev->fPoint.fX = double_to_clamped_scalar((double) prev->fPoint.fX);
1110cb93a386Sopenharmony_ci        prev->fPoint.fY = double_to_clamped_scalar((double) prev->fPoint.fY);
1111cb93a386Sopenharmony_ci        if (fRoundVerticesToQuarterPixel) {
1112cb93a386Sopenharmony_ci            round(&prev->fPoint);
1113cb93a386Sopenharmony_ci        }
1114cb93a386Sopenharmony_ci        for (Vertex* v = contour->fHead; v;) {
1115cb93a386Sopenharmony_ci            v->fPoint.fX = double_to_clamped_scalar((double) v->fPoint.fX);
1116cb93a386Sopenharmony_ci            v->fPoint.fY = double_to_clamped_scalar((double) v->fPoint.fY);
1117cb93a386Sopenharmony_ci            if (fRoundVerticesToQuarterPixel) {
1118cb93a386Sopenharmony_ci                round(&v->fPoint);
1119cb93a386Sopenharmony_ci            }
1120cb93a386Sopenharmony_ci            Vertex* next = v->fNext;
1121cb93a386Sopenharmony_ci            Vertex* nextWrap = next ? next : contour->fHead;
1122cb93a386Sopenharmony_ci            if (coincident(prev->fPoint, v->fPoint)) {
1123cb93a386Sopenharmony_ci                TESS_LOG("vertex %g,%g coincident; removing\n", v->fPoint.fX, v->fPoint.fY);
1124cb93a386Sopenharmony_ci                contour->remove(v);
1125cb93a386Sopenharmony_ci            } else if (!v->fPoint.isFinite()) {
1126cb93a386Sopenharmony_ci                TESS_LOG("vertex %g,%g non-finite; removing\n", v->fPoint.fX, v->fPoint.fY);
1127cb93a386Sopenharmony_ci                contour->remove(v);
1128cb93a386Sopenharmony_ci            } else if (!fPreserveCollinearVertices &&
1129cb93a386Sopenharmony_ci                       Line(prev->fPoint, nextWrap->fPoint).dist(v->fPoint) == 0.0) {
1130cb93a386Sopenharmony_ci                TESS_LOG("vertex %g,%g collinear; removing\n", v->fPoint.fX, v->fPoint.fY);
1131cb93a386Sopenharmony_ci                contour->remove(v);
1132cb93a386Sopenharmony_ci            } else {
1133cb93a386Sopenharmony_ci                prev = v;
1134cb93a386Sopenharmony_ci            }
1135cb93a386Sopenharmony_ci            v = next;
1136cb93a386Sopenharmony_ci        }
1137cb93a386Sopenharmony_ci    }
1138cb93a386Sopenharmony_ci}
1139cb93a386Sopenharmony_ci
1140cb93a386Sopenharmony_cibool GrTriangulator::mergeCoincidentVertices(VertexList* mesh, const Comparator& c) const {
1141cb93a386Sopenharmony_ci    if (!mesh->fHead) {
1142cb93a386Sopenharmony_ci        return false;
1143cb93a386Sopenharmony_ci    }
1144cb93a386Sopenharmony_ci    bool merged = false;
1145cb93a386Sopenharmony_ci    for (Vertex* v = mesh->fHead->fNext; v;) {
1146cb93a386Sopenharmony_ci        Vertex* next = v->fNext;
1147cb93a386Sopenharmony_ci        if (c.sweep_lt(v->fPoint, v->fPrev->fPoint)) {
1148cb93a386Sopenharmony_ci            v->fPoint = v->fPrev->fPoint;
1149cb93a386Sopenharmony_ci        }
1150cb93a386Sopenharmony_ci        if (coincident(v->fPrev->fPoint, v->fPoint)) {
1151cb93a386Sopenharmony_ci            this->mergeVertices(v, v->fPrev, mesh, c);
1152cb93a386Sopenharmony_ci            merged = true;
1153cb93a386Sopenharmony_ci        }
1154cb93a386Sopenharmony_ci        v = next;
1155cb93a386Sopenharmony_ci    }
1156cb93a386Sopenharmony_ci    return merged;
1157cb93a386Sopenharmony_ci}
1158cb93a386Sopenharmony_ci
1159cb93a386Sopenharmony_ci// Stage 2: convert the contours to a mesh of edges connecting the vertices.
1160cb93a386Sopenharmony_ci
1161cb93a386Sopenharmony_civoid GrTriangulator::buildEdges(VertexList* contours, int contourCnt, VertexList* mesh,
1162cb93a386Sopenharmony_ci                                const Comparator& c) const {
1163cb93a386Sopenharmony_ci    for (VertexList* contour = contours; contourCnt > 0; --contourCnt, ++contour) {
1164cb93a386Sopenharmony_ci        Vertex* prev = contour->fTail;
1165cb93a386Sopenharmony_ci        for (Vertex* v = contour->fHead; v;) {
1166cb93a386Sopenharmony_ci            Vertex* next = v->fNext;
1167cb93a386Sopenharmony_ci            this->makeConnectingEdge(prev, v, EdgeType::kInner, c);
1168cb93a386Sopenharmony_ci            mesh->append(v);
1169cb93a386Sopenharmony_ci            prev = v;
1170cb93a386Sopenharmony_ci            v = next;
1171cb93a386Sopenharmony_ci        }
1172cb93a386Sopenharmony_ci    }
1173cb93a386Sopenharmony_ci}
1174cb93a386Sopenharmony_ci
1175cb93a386Sopenharmony_citemplate <CompareFunc sweep_lt>
1176cb93a386Sopenharmony_cistatic void sorted_merge(VertexList* front, VertexList* back, VertexList* result) {
1177cb93a386Sopenharmony_ci    Vertex* a = front->fHead;
1178cb93a386Sopenharmony_ci    Vertex* b = back->fHead;
1179cb93a386Sopenharmony_ci    while (a && b) {
1180cb93a386Sopenharmony_ci        if (sweep_lt(a->fPoint, b->fPoint)) {
1181cb93a386Sopenharmony_ci            front->remove(a);
1182cb93a386Sopenharmony_ci            result->append(a);
1183cb93a386Sopenharmony_ci            a = front->fHead;
1184cb93a386Sopenharmony_ci        } else {
1185cb93a386Sopenharmony_ci            back->remove(b);
1186cb93a386Sopenharmony_ci            result->append(b);
1187cb93a386Sopenharmony_ci            b = back->fHead;
1188cb93a386Sopenharmony_ci        }
1189cb93a386Sopenharmony_ci    }
1190cb93a386Sopenharmony_ci    result->append(*front);
1191cb93a386Sopenharmony_ci    result->append(*back);
1192cb93a386Sopenharmony_ci}
1193cb93a386Sopenharmony_ci
1194cb93a386Sopenharmony_civoid GrTriangulator::SortedMerge(VertexList* front, VertexList* back, VertexList* result,
1195cb93a386Sopenharmony_ci                                 const Comparator& c) {
1196cb93a386Sopenharmony_ci    if (c.fDirection == Comparator::Direction::kHorizontal) {
1197cb93a386Sopenharmony_ci        sorted_merge<sweep_lt_horiz>(front, back, result);
1198cb93a386Sopenharmony_ci    } else {
1199cb93a386Sopenharmony_ci        sorted_merge<sweep_lt_vert>(front, back, result);
1200cb93a386Sopenharmony_ci    }
1201cb93a386Sopenharmony_ci#if TRIANGULATOR_LOGGING
1202cb93a386Sopenharmony_ci    float id = 0.0f;
1203cb93a386Sopenharmony_ci    for (Vertex* v = result->fHead; v; v = v->fNext) {
1204cb93a386Sopenharmony_ci        v->fID = id++;
1205cb93a386Sopenharmony_ci    }
1206cb93a386Sopenharmony_ci#endif
1207cb93a386Sopenharmony_ci}
1208cb93a386Sopenharmony_ci
1209cb93a386Sopenharmony_ci// Stage 3: sort the vertices by increasing sweep direction.
1210cb93a386Sopenharmony_ci
1211cb93a386Sopenharmony_citemplate <CompareFunc sweep_lt>
1212cb93a386Sopenharmony_cistatic void merge_sort(VertexList* vertices) {
1213cb93a386Sopenharmony_ci    Vertex* slow = vertices->fHead;
1214cb93a386Sopenharmony_ci    if (!slow) {
1215cb93a386Sopenharmony_ci        return;
1216cb93a386Sopenharmony_ci    }
1217cb93a386Sopenharmony_ci    Vertex* fast = slow->fNext;
1218cb93a386Sopenharmony_ci    if (!fast) {
1219cb93a386Sopenharmony_ci        return;
1220cb93a386Sopenharmony_ci    }
1221cb93a386Sopenharmony_ci    do {
1222cb93a386Sopenharmony_ci        fast = fast->fNext;
1223cb93a386Sopenharmony_ci        if (fast) {
1224cb93a386Sopenharmony_ci            fast = fast->fNext;
1225cb93a386Sopenharmony_ci            slow = slow->fNext;
1226cb93a386Sopenharmony_ci        }
1227cb93a386Sopenharmony_ci    } while (fast);
1228cb93a386Sopenharmony_ci    VertexList front(vertices->fHead, slow);
1229cb93a386Sopenharmony_ci    VertexList back(slow->fNext, vertices->fTail);
1230cb93a386Sopenharmony_ci    front.fTail->fNext = back.fHead->fPrev = nullptr;
1231cb93a386Sopenharmony_ci
1232cb93a386Sopenharmony_ci    merge_sort<sweep_lt>(&front);
1233cb93a386Sopenharmony_ci    merge_sort<sweep_lt>(&back);
1234cb93a386Sopenharmony_ci
1235cb93a386Sopenharmony_ci    vertices->fHead = vertices->fTail = nullptr;
1236cb93a386Sopenharmony_ci    sorted_merge<sweep_lt>(&front, &back, vertices);
1237cb93a386Sopenharmony_ci}
1238cb93a386Sopenharmony_ci
1239cb93a386Sopenharmony_ci#if TRIANGULATOR_LOGGING
1240cb93a386Sopenharmony_civoid VertexList::dump() const {
1241cb93a386Sopenharmony_ci    for (Vertex* v = fHead; v; v = v->fNext) {
1242cb93a386Sopenharmony_ci        TESS_LOG("vertex %g (%g, %g) alpha %d", v->fID, v->fPoint.fX, v->fPoint.fY, v->fAlpha);
1243cb93a386Sopenharmony_ci        if (Vertex* p = v->fPartner) {
1244cb93a386Sopenharmony_ci            TESS_LOG(", partner %g (%g, %g) alpha %d\n",
1245cb93a386Sopenharmony_ci                    p->fID, p->fPoint.fX, p->fPoint.fY, p->fAlpha);
1246cb93a386Sopenharmony_ci        } else {
1247cb93a386Sopenharmony_ci            TESS_LOG(", null partner\n");
1248cb93a386Sopenharmony_ci        }
1249cb93a386Sopenharmony_ci        for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
1250cb93a386Sopenharmony_ci            TESS_LOG("  edge %g -> %g, winding %d\n", e->fTop->fID, e->fBottom->fID, e->fWinding);
1251cb93a386Sopenharmony_ci        }
1252cb93a386Sopenharmony_ci        for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1253cb93a386Sopenharmony_ci            TESS_LOG("  edge %g -> %g, winding %d\n", e->fTop->fID, e->fBottom->fID, e->fWinding);
1254cb93a386Sopenharmony_ci        }
1255cb93a386Sopenharmony_ci    }
1256cb93a386Sopenharmony_ci}
1257cb93a386Sopenharmony_ci#endif
1258cb93a386Sopenharmony_ci
1259cb93a386Sopenharmony_ci#ifdef SK_DEBUG
1260cb93a386Sopenharmony_cistatic void validate_edge_pair(Edge* left, Edge* right, const Comparator& c) {
1261cb93a386Sopenharmony_ci    if (!left || !right) {
1262cb93a386Sopenharmony_ci        return;
1263cb93a386Sopenharmony_ci    }
1264cb93a386Sopenharmony_ci    if (left->fTop == right->fTop) {
1265cb93a386Sopenharmony_ci        SkASSERT(left->isLeftOf(right->fBottom));
1266cb93a386Sopenharmony_ci        SkASSERT(right->isRightOf(left->fBottom));
1267cb93a386Sopenharmony_ci    } else if (c.sweep_lt(left->fTop->fPoint, right->fTop->fPoint)) {
1268cb93a386Sopenharmony_ci        SkASSERT(left->isLeftOf(right->fTop));
1269cb93a386Sopenharmony_ci    } else {
1270cb93a386Sopenharmony_ci        SkASSERT(right->isRightOf(left->fTop));
1271cb93a386Sopenharmony_ci    }
1272cb93a386Sopenharmony_ci    if (left->fBottom == right->fBottom) {
1273cb93a386Sopenharmony_ci        SkASSERT(left->isLeftOf(right->fTop));
1274cb93a386Sopenharmony_ci        SkASSERT(right->isRightOf(left->fTop));
1275cb93a386Sopenharmony_ci    } else if (c.sweep_lt(right->fBottom->fPoint, left->fBottom->fPoint)) {
1276cb93a386Sopenharmony_ci        SkASSERT(left->isLeftOf(right->fBottom));
1277cb93a386Sopenharmony_ci    } else {
1278cb93a386Sopenharmony_ci        SkASSERT(right->isRightOf(left->fBottom));
1279cb93a386Sopenharmony_ci    }
1280cb93a386Sopenharmony_ci}
1281cb93a386Sopenharmony_ci
1282cb93a386Sopenharmony_cistatic void validate_edge_list(EdgeList* edges, const Comparator& c) {
1283cb93a386Sopenharmony_ci    Edge* left = edges->fHead;
1284cb93a386Sopenharmony_ci    if (!left) {
1285cb93a386Sopenharmony_ci        return;
1286cb93a386Sopenharmony_ci    }
1287cb93a386Sopenharmony_ci    for (Edge* right = left->fRight; right; right = right->fRight) {
1288cb93a386Sopenharmony_ci        validate_edge_pair(left, right, c);
1289cb93a386Sopenharmony_ci        left = right;
1290cb93a386Sopenharmony_ci    }
1291cb93a386Sopenharmony_ci}
1292cb93a386Sopenharmony_ci#endif
1293cb93a386Sopenharmony_ci
1294cb93a386Sopenharmony_ci// Stage 4: Simplify the mesh by inserting new vertices at intersecting edges.
1295cb93a386Sopenharmony_ci
1296cb93a386Sopenharmony_ciGrTriangulator::SimplifyResult GrTriangulator::simplify(VertexList* mesh,
1297cb93a386Sopenharmony_ci                                                        const Comparator& c) const {
1298cb93a386Sopenharmony_ci    TESS_LOG("simplifying complex polygons\n");
1299cb93a386Sopenharmony_ci    EdgeList activeEdges;
1300cb93a386Sopenharmony_ci    auto result = SimplifyResult::kAlreadySimple;
1301cb93a386Sopenharmony_ci    for (Vertex* v = mesh->fHead; v != nullptr; v = v->fNext) {
1302cb93a386Sopenharmony_ci        if (!v->isConnected()) {
1303cb93a386Sopenharmony_ci            continue;
1304cb93a386Sopenharmony_ci        }
1305cb93a386Sopenharmony_ci        Edge* leftEnclosingEdge;
1306cb93a386Sopenharmony_ci        Edge* rightEnclosingEdge;
1307cb93a386Sopenharmony_ci        bool restartChecks;
1308cb93a386Sopenharmony_ci        do {
1309cb93a386Sopenharmony_ci            TESS_LOG("\nvertex %g: (%g,%g), alpha %d\n",
1310cb93a386Sopenharmony_ci                     v->fID, v->fPoint.fX, v->fPoint.fY, v->fAlpha);
1311cb93a386Sopenharmony_ci            restartChecks = false;
1312cb93a386Sopenharmony_ci            FindEnclosingEdges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
1313cb93a386Sopenharmony_ci            v->fLeftEnclosingEdge = leftEnclosingEdge;
1314cb93a386Sopenharmony_ci            v->fRightEnclosingEdge = rightEnclosingEdge;
1315cb93a386Sopenharmony_ci            if (v->fFirstEdgeBelow) {
1316cb93a386Sopenharmony_ci                for (Edge* edge = v->fFirstEdgeBelow; edge; edge = edge->fNextEdgeBelow) {
1317cb93a386Sopenharmony_ci                    if (this->checkForIntersection(
1318cb93a386Sopenharmony_ci                            leftEnclosingEdge, edge, &activeEdges, &v, mesh, c) ||
1319cb93a386Sopenharmony_ci                        this->checkForIntersection(
1320cb93a386Sopenharmony_ci                            edge, rightEnclosingEdge, &activeEdges, &v, mesh, c)) {
1321cb93a386Sopenharmony_ci                        result = SimplifyResult::kFoundSelfIntersection;
1322cb93a386Sopenharmony_ci                        restartChecks = true;
1323cb93a386Sopenharmony_ci                        break;
1324cb93a386Sopenharmony_ci                    }
1325cb93a386Sopenharmony_ci                }
1326cb93a386Sopenharmony_ci            } else {
1327cb93a386Sopenharmony_ci                if (this->checkForIntersection(leftEnclosingEdge, rightEnclosingEdge, &activeEdges,
1328cb93a386Sopenharmony_ci                                               &v, mesh, c)) {
1329cb93a386Sopenharmony_ci                    result = SimplifyResult::kFoundSelfIntersection;
1330cb93a386Sopenharmony_ci                    restartChecks = true;
1331cb93a386Sopenharmony_ci                }
1332cb93a386Sopenharmony_ci
1333cb93a386Sopenharmony_ci            }
1334cb93a386Sopenharmony_ci        } while (restartChecks);
1335cb93a386Sopenharmony_ci#ifdef SK_DEBUG
1336cb93a386Sopenharmony_ci        validate_edge_list(&activeEdges, c);
1337cb93a386Sopenharmony_ci#endif
1338cb93a386Sopenharmony_ci        for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
1339cb93a386Sopenharmony_ci            activeEdges.remove(e);
1340cb93a386Sopenharmony_ci        }
1341cb93a386Sopenharmony_ci        Edge* leftEdge = leftEnclosingEdge;
1342cb93a386Sopenharmony_ci        for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1343cb93a386Sopenharmony_ci            activeEdges.insert(e, leftEdge);
1344cb93a386Sopenharmony_ci            leftEdge = e;
1345cb93a386Sopenharmony_ci        }
1346cb93a386Sopenharmony_ci    }
1347cb93a386Sopenharmony_ci    SkASSERT(!activeEdges.fHead && !activeEdges.fTail);
1348cb93a386Sopenharmony_ci    return result;
1349cb93a386Sopenharmony_ci}
1350cb93a386Sopenharmony_ci
1351cb93a386Sopenharmony_ci// Stage 5: Tessellate the simplified mesh into monotone polygons.
1352cb93a386Sopenharmony_ci
1353cb93a386Sopenharmony_ciPoly* GrTriangulator::tessellate(const VertexList& vertices, const Comparator&) const {
1354cb93a386Sopenharmony_ci    TESS_LOG("\ntessellating simple polygons\n");
1355cb93a386Sopenharmony_ci    EdgeList activeEdges;
1356cb93a386Sopenharmony_ci    Poly* polys = nullptr;
1357cb93a386Sopenharmony_ci    for (Vertex* v = vertices.fHead; v != nullptr; v = v->fNext) {
1358cb93a386Sopenharmony_ci        if (!v->isConnected()) {
1359cb93a386Sopenharmony_ci            continue;
1360cb93a386Sopenharmony_ci        }
1361cb93a386Sopenharmony_ci#if TRIANGULATOR_LOGGING
1362cb93a386Sopenharmony_ci        TESS_LOG("\nvertex %g: (%g,%g), alpha %d\n", v->fID, v->fPoint.fX, v->fPoint.fY, v->fAlpha);
1363cb93a386Sopenharmony_ci#endif
1364cb93a386Sopenharmony_ci        Edge* leftEnclosingEdge;
1365cb93a386Sopenharmony_ci        Edge* rightEnclosingEdge;
1366cb93a386Sopenharmony_ci        FindEnclosingEdges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
1367cb93a386Sopenharmony_ci        Poly* leftPoly;
1368cb93a386Sopenharmony_ci        Poly* rightPoly;
1369cb93a386Sopenharmony_ci        if (v->fFirstEdgeAbove) {
1370cb93a386Sopenharmony_ci            leftPoly = v->fFirstEdgeAbove->fLeftPoly;
1371cb93a386Sopenharmony_ci            rightPoly = v->fLastEdgeAbove->fRightPoly;
1372cb93a386Sopenharmony_ci        } else {
1373cb93a386Sopenharmony_ci            leftPoly = leftEnclosingEdge ? leftEnclosingEdge->fRightPoly : nullptr;
1374cb93a386Sopenharmony_ci            rightPoly = rightEnclosingEdge ? rightEnclosingEdge->fLeftPoly : nullptr;
1375cb93a386Sopenharmony_ci        }
1376cb93a386Sopenharmony_ci#if TRIANGULATOR_LOGGING
1377cb93a386Sopenharmony_ci        TESS_LOG("edges above:\n");
1378cb93a386Sopenharmony_ci        for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
1379cb93a386Sopenharmony_ci            TESS_LOG("%g -> %g, lpoly %d, rpoly %d\n",
1380cb93a386Sopenharmony_ci                     e->fTop->fID, e->fBottom->fID,
1381cb93a386Sopenharmony_ci                     e->fLeftPoly ? e->fLeftPoly->fID : -1,
1382cb93a386Sopenharmony_ci                     e->fRightPoly ? e->fRightPoly->fID : -1);
1383cb93a386Sopenharmony_ci        }
1384cb93a386Sopenharmony_ci        TESS_LOG("edges below:\n");
1385cb93a386Sopenharmony_ci        for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1386cb93a386Sopenharmony_ci            TESS_LOG("%g -> %g, lpoly %d, rpoly %d\n",
1387cb93a386Sopenharmony_ci                     e->fTop->fID, e->fBottom->fID,
1388cb93a386Sopenharmony_ci                     e->fLeftPoly ? e->fLeftPoly->fID : -1,
1389cb93a386Sopenharmony_ci                     e->fRightPoly ? e->fRightPoly->fID : -1);
1390cb93a386Sopenharmony_ci        }
1391cb93a386Sopenharmony_ci#endif
1392cb93a386Sopenharmony_ci        if (v->fFirstEdgeAbove) {
1393cb93a386Sopenharmony_ci            if (leftPoly) {
1394cb93a386Sopenharmony_ci                leftPoly = leftPoly->addEdge(v->fFirstEdgeAbove, kRight_Side, fAlloc);
1395cb93a386Sopenharmony_ci            }
1396cb93a386Sopenharmony_ci            if (rightPoly) {
1397cb93a386Sopenharmony_ci                rightPoly = rightPoly->addEdge(v->fLastEdgeAbove, kLeft_Side, fAlloc);
1398cb93a386Sopenharmony_ci            }
1399cb93a386Sopenharmony_ci            for (Edge* e = v->fFirstEdgeAbove; e != v->fLastEdgeAbove; e = e->fNextEdgeAbove) {
1400cb93a386Sopenharmony_ci                Edge* rightEdge = e->fNextEdgeAbove;
1401cb93a386Sopenharmony_ci                activeEdges.remove(e);
1402cb93a386Sopenharmony_ci                if (e->fRightPoly) {
1403cb93a386Sopenharmony_ci                    e->fRightPoly->addEdge(e, kLeft_Side, fAlloc);
1404cb93a386Sopenharmony_ci                }
1405cb93a386Sopenharmony_ci                if (rightEdge->fLeftPoly && rightEdge->fLeftPoly != e->fRightPoly) {
1406cb93a386Sopenharmony_ci                    rightEdge->fLeftPoly->addEdge(e, kRight_Side, fAlloc);
1407cb93a386Sopenharmony_ci                }
1408cb93a386Sopenharmony_ci            }
1409cb93a386Sopenharmony_ci            activeEdges.remove(v->fLastEdgeAbove);
1410cb93a386Sopenharmony_ci            if (!v->fFirstEdgeBelow) {
1411cb93a386Sopenharmony_ci                if (leftPoly && rightPoly && leftPoly != rightPoly) {
1412cb93a386Sopenharmony_ci                    SkASSERT(leftPoly->fPartner == nullptr && rightPoly->fPartner == nullptr);
1413cb93a386Sopenharmony_ci                    rightPoly->fPartner = leftPoly;
1414cb93a386Sopenharmony_ci                    leftPoly->fPartner = rightPoly;
1415cb93a386Sopenharmony_ci                }
1416cb93a386Sopenharmony_ci            }
1417cb93a386Sopenharmony_ci        }
1418cb93a386Sopenharmony_ci        if (v->fFirstEdgeBelow) {
1419cb93a386Sopenharmony_ci            if (!v->fFirstEdgeAbove) {
1420cb93a386Sopenharmony_ci                if (leftPoly && rightPoly) {
1421cb93a386Sopenharmony_ci                    if (leftPoly == rightPoly) {
1422cb93a386Sopenharmony_ci                        if (leftPoly->fTail && leftPoly->fTail->fSide == kLeft_Side) {
1423cb93a386Sopenharmony_ci                            leftPoly = this->makePoly(&polys, leftPoly->lastVertex(),
1424cb93a386Sopenharmony_ci                                                      leftPoly->fWinding);
1425cb93a386Sopenharmony_ci                            leftEnclosingEdge->fRightPoly = leftPoly;
1426cb93a386Sopenharmony_ci                        } else {
1427cb93a386Sopenharmony_ci                            rightPoly = this->makePoly(&polys, rightPoly->lastVertex(),
1428cb93a386Sopenharmony_ci                                                       rightPoly->fWinding);
1429cb93a386Sopenharmony_ci                            rightEnclosingEdge->fLeftPoly = rightPoly;
1430cb93a386Sopenharmony_ci                        }
1431cb93a386Sopenharmony_ci                    }
1432cb93a386Sopenharmony_ci                    Edge* join = fAlloc->make<Edge>(leftPoly->lastVertex(), v, 1,
1433cb93a386Sopenharmony_ci                                                   EdgeType::kInner);
1434cb93a386Sopenharmony_ci                    leftPoly = leftPoly->addEdge(join, kRight_Side, fAlloc);
1435cb93a386Sopenharmony_ci                    rightPoly = rightPoly->addEdge(join, kLeft_Side, fAlloc);
1436cb93a386Sopenharmony_ci                }
1437cb93a386Sopenharmony_ci            }
1438cb93a386Sopenharmony_ci            Edge* leftEdge = v->fFirstEdgeBelow;
1439cb93a386Sopenharmony_ci            leftEdge->fLeftPoly = leftPoly;
1440cb93a386Sopenharmony_ci            activeEdges.insert(leftEdge, leftEnclosingEdge);
1441cb93a386Sopenharmony_ci            for (Edge* rightEdge = leftEdge->fNextEdgeBelow; rightEdge;
1442cb93a386Sopenharmony_ci                 rightEdge = rightEdge->fNextEdgeBelow) {
1443cb93a386Sopenharmony_ci                activeEdges.insert(rightEdge, leftEdge);
1444cb93a386Sopenharmony_ci                int winding = leftEdge->fLeftPoly ? leftEdge->fLeftPoly->fWinding : 0;
1445cb93a386Sopenharmony_ci                winding += leftEdge->fWinding;
1446cb93a386Sopenharmony_ci                if (winding != 0) {
1447cb93a386Sopenharmony_ci                    Poly* poly = this->makePoly(&polys, v, winding);
1448cb93a386Sopenharmony_ci                    leftEdge->fRightPoly = rightEdge->fLeftPoly = poly;
1449cb93a386Sopenharmony_ci                }
1450cb93a386Sopenharmony_ci                leftEdge = rightEdge;
1451cb93a386Sopenharmony_ci            }
1452cb93a386Sopenharmony_ci            v->fLastEdgeBelow->fRightPoly = rightPoly;
1453cb93a386Sopenharmony_ci        }
1454cb93a386Sopenharmony_ci#if TRIANGULATOR_LOGGING
1455cb93a386Sopenharmony_ci        TESS_LOG("\nactive edges:\n");
1456cb93a386Sopenharmony_ci        for (Edge* e = activeEdges.fHead; e != nullptr; e = e->fRight) {
1457cb93a386Sopenharmony_ci            TESS_LOG("%g -> %g, lpoly %d, rpoly %d\n",
1458cb93a386Sopenharmony_ci                     e->fTop->fID, e->fBottom->fID,
1459cb93a386Sopenharmony_ci                     e->fLeftPoly ? e->fLeftPoly->fID : -1,
1460cb93a386Sopenharmony_ci                     e->fRightPoly ? e->fRightPoly->fID : -1);
1461cb93a386Sopenharmony_ci        }
1462cb93a386Sopenharmony_ci#endif
1463cb93a386Sopenharmony_ci    }
1464cb93a386Sopenharmony_ci    return polys;
1465cb93a386Sopenharmony_ci}
1466cb93a386Sopenharmony_ci
1467cb93a386Sopenharmony_ci// This is a driver function that calls stages 2-5 in turn.
1468cb93a386Sopenharmony_ci
1469cb93a386Sopenharmony_civoid GrTriangulator::contoursToMesh(VertexList* contours, int contourCnt, VertexList* mesh,
1470cb93a386Sopenharmony_ci                                    const Comparator& c) const {
1471cb93a386Sopenharmony_ci#if TRIANGULATOR_LOGGING
1472cb93a386Sopenharmony_ci    for (int i = 0; i < contourCnt; ++i) {
1473cb93a386Sopenharmony_ci        Vertex* v = contours[i].fHead;
1474cb93a386Sopenharmony_ci        SkASSERT(v);
1475cb93a386Sopenharmony_ci        TESS_LOG("path.moveTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY);
1476cb93a386Sopenharmony_ci        for (v = v->fNext; v; v = v->fNext) {
1477cb93a386Sopenharmony_ci            TESS_LOG("path.lineTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY);
1478cb93a386Sopenharmony_ci        }
1479cb93a386Sopenharmony_ci    }
1480cb93a386Sopenharmony_ci#endif
1481cb93a386Sopenharmony_ci    this->sanitizeContours(contours, contourCnt);
1482cb93a386Sopenharmony_ci    this->buildEdges(contours, contourCnt, mesh, c);
1483cb93a386Sopenharmony_ci}
1484cb93a386Sopenharmony_ci
1485cb93a386Sopenharmony_civoid GrTriangulator::SortMesh(VertexList* vertices, const Comparator& c) {
1486cb93a386Sopenharmony_ci    if (!vertices || !vertices->fHead) {
1487cb93a386Sopenharmony_ci        return;
1488cb93a386Sopenharmony_ci    }
1489cb93a386Sopenharmony_ci
1490cb93a386Sopenharmony_ci    // Sort vertices in Y (secondarily in X).
1491cb93a386Sopenharmony_ci    if (c.fDirection == Comparator::Direction::kHorizontal) {
1492cb93a386Sopenharmony_ci        merge_sort<sweep_lt_horiz>(vertices);
1493cb93a386Sopenharmony_ci    } else {
1494cb93a386Sopenharmony_ci        merge_sort<sweep_lt_vert>(vertices);
1495cb93a386Sopenharmony_ci    }
1496cb93a386Sopenharmony_ci#if TRIANGULATOR_LOGGING
1497cb93a386Sopenharmony_ci    for (Vertex* v = vertices->fHead; v != nullptr; v = v->fNext) {
1498cb93a386Sopenharmony_ci        static float gID = 0.0f;
1499cb93a386Sopenharmony_ci        v->fID = gID++;
1500cb93a386Sopenharmony_ci    }
1501cb93a386Sopenharmony_ci#endif
1502cb93a386Sopenharmony_ci}
1503cb93a386Sopenharmony_ci
1504cb93a386Sopenharmony_ciPoly* GrTriangulator::contoursToPolys(VertexList* contours, int contourCnt) const {
1505cb93a386Sopenharmony_ci    const SkRect& pathBounds = fPath.getBounds();
1506cb93a386Sopenharmony_ci    Comparator c(pathBounds.width() > pathBounds.height() ? Comparator::Direction::kHorizontal
1507cb93a386Sopenharmony_ci                                                          : Comparator::Direction::kVertical);
1508cb93a386Sopenharmony_ci    VertexList mesh;
1509cb93a386Sopenharmony_ci    this->contoursToMesh(contours, contourCnt, &mesh, c);
1510cb93a386Sopenharmony_ci    TESS_LOG("\ninitial mesh:\n");
1511cb93a386Sopenharmony_ci    DUMP_MESH(mesh);
1512cb93a386Sopenharmony_ci    SortMesh(&mesh, c);
1513cb93a386Sopenharmony_ci    TESS_LOG("\nsorted mesh:\n");
1514cb93a386Sopenharmony_ci    DUMP_MESH(mesh);
1515cb93a386Sopenharmony_ci    this->mergeCoincidentVertices(&mesh, c);
1516cb93a386Sopenharmony_ci    TESS_LOG("\nsorted+merged mesh:\n");
1517cb93a386Sopenharmony_ci    DUMP_MESH(mesh);
1518cb93a386Sopenharmony_ci    this->simplify(&mesh, c);
1519cb93a386Sopenharmony_ci    TESS_LOG("\nsimplified mesh:\n");
1520cb93a386Sopenharmony_ci    DUMP_MESH(mesh);
1521cb93a386Sopenharmony_ci    return this->tessellate(mesh, c);
1522cb93a386Sopenharmony_ci}
1523cb93a386Sopenharmony_ci
1524cb93a386Sopenharmony_ci// Stage 6: Triangulate the monotone polygons into a vertex buffer.
1525cb93a386Sopenharmony_civoid* GrTriangulator::polysToTriangles(Poly* polys, void* data,
1526cb93a386Sopenharmony_ci                                       SkPathFillType overrideFillType) const {
1527cb93a386Sopenharmony_ci    for (Poly* poly = polys; poly; poly = poly->fNext) {
1528cb93a386Sopenharmony_ci        if (apply_fill_type(overrideFillType, poly)) {
1529cb93a386Sopenharmony_ci            data = this->emitPoly(poly, data);
1530cb93a386Sopenharmony_ci        }
1531cb93a386Sopenharmony_ci    }
1532cb93a386Sopenharmony_ci    return data;
1533cb93a386Sopenharmony_ci}
1534cb93a386Sopenharmony_ci
1535cb93a386Sopenharmony_cistatic int get_contour_count(const SkPath& path, SkScalar tolerance) {
1536cb93a386Sopenharmony_ci    // We could theoretically be more aggressive about not counting empty contours, but we need to
1537cb93a386Sopenharmony_ci    // actually match the exact number of contour linked lists the tessellator will create later on.
1538cb93a386Sopenharmony_ci    int contourCnt = 1;
1539cb93a386Sopenharmony_ci    bool hasPoints = false;
1540cb93a386Sopenharmony_ci
1541cb93a386Sopenharmony_ci    SkPath::Iter iter(path, false);
1542cb93a386Sopenharmony_ci    SkPath::Verb verb;
1543cb93a386Sopenharmony_ci    SkPoint pts[4];
1544cb93a386Sopenharmony_ci    bool first = true;
1545cb93a386Sopenharmony_ci    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
1546cb93a386Sopenharmony_ci        switch (verb) {
1547cb93a386Sopenharmony_ci            case SkPath::kMove_Verb:
1548cb93a386Sopenharmony_ci                if (!first) {
1549cb93a386Sopenharmony_ci                    ++contourCnt;
1550cb93a386Sopenharmony_ci                }
1551cb93a386Sopenharmony_ci                [[fallthrough]];
1552cb93a386Sopenharmony_ci            case SkPath::kLine_Verb:
1553cb93a386Sopenharmony_ci            case SkPath::kConic_Verb:
1554cb93a386Sopenharmony_ci            case SkPath::kQuad_Verb:
1555cb93a386Sopenharmony_ci            case SkPath::kCubic_Verb:
1556cb93a386Sopenharmony_ci                hasPoints = true;
1557cb93a386Sopenharmony_ci                break;
1558cb93a386Sopenharmony_ci            default:
1559cb93a386Sopenharmony_ci                break;
1560cb93a386Sopenharmony_ci        }
1561cb93a386Sopenharmony_ci        first = false;
1562cb93a386Sopenharmony_ci    }
1563cb93a386Sopenharmony_ci    if (!hasPoints) {
1564cb93a386Sopenharmony_ci        return 0;
1565cb93a386Sopenharmony_ci    }
1566cb93a386Sopenharmony_ci    return contourCnt;
1567cb93a386Sopenharmony_ci}
1568cb93a386Sopenharmony_ci
1569cb93a386Sopenharmony_ciPoly* GrTriangulator::pathToPolys(float tolerance, const SkRect& clipBounds, bool* isLinear) const {
1570cb93a386Sopenharmony_ci    int contourCnt = get_contour_count(fPath, tolerance);
1571cb93a386Sopenharmony_ci    if (contourCnt <= 0) {
1572cb93a386Sopenharmony_ci        *isLinear = true;
1573cb93a386Sopenharmony_ci        return nullptr;
1574cb93a386Sopenharmony_ci    }
1575cb93a386Sopenharmony_ci
1576cb93a386Sopenharmony_ci    if (SkPathFillType_IsInverse(fPath.getFillType())) {
1577cb93a386Sopenharmony_ci        contourCnt++;
1578cb93a386Sopenharmony_ci    }
1579cb93a386Sopenharmony_ci    std::unique_ptr<VertexList[]> contours(new VertexList[contourCnt]);
1580cb93a386Sopenharmony_ci
1581cb93a386Sopenharmony_ci    this->pathToContours(tolerance, clipBounds, contours.get(), isLinear);
1582cb93a386Sopenharmony_ci    return this->contoursToPolys(contours.get(), contourCnt);
1583cb93a386Sopenharmony_ci}
1584cb93a386Sopenharmony_ci
1585cb93a386Sopenharmony_ciint64_t GrTriangulator::CountPoints(Poly* polys, SkPathFillType overrideFillType) {
1586cb93a386Sopenharmony_ci    int64_t count = 0;
1587cb93a386Sopenharmony_ci    for (Poly* poly = polys; poly; poly = poly->fNext) {
1588cb93a386Sopenharmony_ci        if (apply_fill_type(overrideFillType, poly) && poly->fCount >= 3) {
1589cb93a386Sopenharmony_ci            count += (poly->fCount - 2) * (TRIANGULATOR_WIREFRAME ? 6 : 3);
1590cb93a386Sopenharmony_ci        }
1591cb93a386Sopenharmony_ci    }
1592cb93a386Sopenharmony_ci    return count;
1593cb93a386Sopenharmony_ci}
1594cb93a386Sopenharmony_ci
1595cb93a386Sopenharmony_ci// Stage 6: Triangulate the monotone polygons into a vertex buffer.
1596cb93a386Sopenharmony_ci
1597cb93a386Sopenharmony_ciint GrTriangulator::polysToTriangles(Poly* polys, GrEagerVertexAllocator* vertexAllocator) const {
1598cb93a386Sopenharmony_ci    int64_t count64 = CountPoints(polys, fPath.getFillType());
1599cb93a386Sopenharmony_ci    if (0 == count64 || count64 > SK_MaxS32) {
1600cb93a386Sopenharmony_ci        return 0;
1601cb93a386Sopenharmony_ci    }
1602cb93a386Sopenharmony_ci    int count = count64;
1603cb93a386Sopenharmony_ci
1604cb93a386Sopenharmony_ci    size_t vertexStride = sizeof(SkPoint);
1605cb93a386Sopenharmony_ci    if (fEmitCoverage) {
1606cb93a386Sopenharmony_ci        vertexStride += sizeof(float);
1607cb93a386Sopenharmony_ci    }
1608cb93a386Sopenharmony_ci    void* verts = vertexAllocator->lock(vertexStride, count);
1609cb93a386Sopenharmony_ci    if (!verts) {
1610cb93a386Sopenharmony_ci        SkDebugf("Could not allocate vertices\n");
1611cb93a386Sopenharmony_ci        return 0;
1612cb93a386Sopenharmony_ci    }
1613cb93a386Sopenharmony_ci
1614cb93a386Sopenharmony_ci    TESS_LOG("emitting %d verts\n", count);
1615cb93a386Sopenharmony_ci    void* end = this->polysToTriangles(polys, verts, fPath.getFillType());
1616cb93a386Sopenharmony_ci
1617cb93a386Sopenharmony_ci    int actualCount = static_cast<int>((static_cast<uint8_t*>(end) - static_cast<uint8_t*>(verts))
1618cb93a386Sopenharmony_ci                                       / vertexStride);
1619cb93a386Sopenharmony_ci    SkASSERT(actualCount <= count);
1620cb93a386Sopenharmony_ci    vertexAllocator->unlock(actualCount);
1621cb93a386Sopenharmony_ci    return actualCount;
1622cb93a386Sopenharmony_ci}
1623