/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * Initial import from
 * skia:c2a399a74da523ec445f1202367764d04b5df2ec@src/gpu/ganesh/geometry/GrTriangulator.h
 * Last synced to
 * skia:fee7272f5bc258d2b4199c7ed133a72d996c0fb0@src/gpu/ganesh/geometry/GrTriangulator.cpp
 *
 * Copyright 2023 Rive
 */

#include "gr_triangulator.hpp"

#include "rive/renderer/stack_vector.hpp"
#include <algorithm>

#if !defined(SK_ENABLE_OPTIMIZE_SIZE)

#if TRIANGULATOR_LOGGING
#define TESS_LOG printf
#define DUMP_MESH(M) (M).dump()
#else
#define TESS_LOG(...)
#define DUMP_MESH(M)
#endif

namespace rive
{
using EdgeType = GrTriangulator::EdgeType;
using Vertex = GrTriangulator::Vertex;
using VertexList = GrTriangulator::VertexList;
using Line = GrTriangulator::Line;
using Edge = GrTriangulator::Edge;
using EdgeList = GrTriangulator::EdgeList;
using Poly = GrTriangulator::Poly;
using MonotonePoly = GrTriangulator::MonotonePoly;
using Comparator = GrTriangulator::Comparator;

static bool is_finite(Vec2D pt)
{
    float accum = 0;
    accum *= pt.x;
    accum *= pt.y;

    // accum is either NaN or it is finite (zero).
    assert(0 == accum || std::isnan(accum));

    // value==value will be true iff value is not NaN
    // TODO: is it faster to say !accum or accum==accum?
    return !std::isnan(accum);
}

template <class T, T* T::* Prev, T* T::* Next>
static void list_insert(T* t, T* prev, T* next, T** head, T** tail)
{
    t->*Prev = prev;
    t->*Next = next;
    if (prev)
    {
        prev->*Next = t;
    }
    else if (head)
    {
        *head = t;
    }
    if (next)
    {
        next->*Prev = t;
    }
    else if (tail)
    {
        *tail = t;
    }
}

template <class T, T* T::* Prev, T* T::* Next>
static void list_remove(T* t, T** head, T** tail)
{
    if (t->*Prev)
    {
        t->*Prev->*Next = t->*Next;
    }
    else if (head)
    {
        *head = t->*Next;
    }
    if (t->*Next)
    {
        t->*Next->*Prev = t->*Prev;
    }
    else if (tail)
    {
        *tail = t->*Prev;
    }
    t->*Prev = t->*Next = nullptr;
}

typedef bool (*CompareFunc)(const Vec2D& a, const Vec2D& b);

static bool sweep_lt_horiz(const Vec2D& a, const Vec2D& b)
{
    return a.x < b.x || (a.x == b.x && a.y > b.y);
}

static bool sweep_lt_vert(const Vec2D& a, const Vec2D& b)
{
    return a.y < b.y || (a.y == b.y && a.x < b.x);
}

bool GrTriangulator::Comparator::sweep_lt(const Vec2D& a, const Vec2D& b) const
{
    return fDirection == Direction::kHorizontal ? sweep_lt_horiz(a, b)
                                                : sweep_lt_vert(a, b);
}

template <typename Sink>
static size_t emit_triangle(Vertex* v0,
                            Vertex* v1,
                            Vertex* v2,
                            int16_t riveWeight,
                            Sink* sink)
{
    TESS_LOG("emit_triangle %g (%g, %g) %d\n",
             v0->fID,
             v0->fPoint.x,
             v0->fPoint.y,
             v0->fAlpha);
    TESS_LOG("              %g (%g, %g) %d\n",
             v1->fID,
             v1->fPoint.x,
             v1->fPoint.y,
             v1->fAlpha);
    TESS_LOG("              %g (%g, %g) %d\n",
             v2->fID,
             v2->fPoint.x,
             v2->fPoint.y,
             v2->fAlpha);
    sink->emitTriangle(v0->fPoint, v1->fPoint, v2->fPoint, riveWeight);
    return 3;
}

void GrTriangulator::VertexList::insert(Vertex* v, Vertex* prev, Vertex* next)
{
    list_insert<Vertex, &Vertex::fPrev, &Vertex::fNext>(v,
                                                        prev,
                                                        next,
                                                        &fHead,
                                                        &fTail);
}

void GrTriangulator::VertexList::remove(Vertex* v)
{
    list_remove<Vertex, &Vertex::fPrev, &Vertex::fNext>(v, &fHead, &fTail);
}

// Round to nearest quarter-pixel. This is used for screenspace tessellation.

#if 0
static inline void round(Vec2D* p)
{
    p->x = SkScalarRoundToScalar(p->x * 4.0f) * 0.25f;
    p->y = SkScalarRoundToScalar(p->y * 4.0f) * 0.25f;
}
#endif

static inline float double_to_clamped_scalar(double d)
{
    // Clamps large values to what's finitely representable when cast back to a
    // float.
    static const double kMaxLimit = (double)std::numeric_limits<float>::max();
    // It's not perfect, but a using a value larger than float_min helps protect
    // from denormalized values and ill-conditions in intermediate calculations
    // on coordinates.
    static const double kNearZeroLimit =
        16 * (double)std::numeric_limits<float>::min();
    if (std::abs(d) < kNearZeroLimit)
    {
        d = 0.f;
    }
    return static_cast<float>(std::max(-kMaxLimit, std::min(d, kMaxLimit)));
}

#if 0
bool GrTriangulator::Line::intersect(const Line& other, Vec2D* point) const
{
    double denom = fA * other.fB - fB * other.fA;
    if (denom == 0.0)
    {
        return false;
    }
    double scale = 1.0 / denom;
    point->x = double_to_clamped_scalar((fB * other.fC - other.fB * fC) * scale);
    point->y = double_to_clamped_scalar((other.fA * fC - fA * other.fC) * scale);
    round(point);
    return point->isFinite();
}
#endif

// If the edge's vertices differ by many orders of magnitude, the computed line
// equation can have significant error in its distance and intersection tests.
// To avoid this, we recursively subdivide long edges and effectively perform a
// binary search to perform a more accurate intersection test.
static bool edge_line_needs_recursion(const Vec2D& p0, const Vec2D& p1)
{
    // ilogbf(0) returns an implementation-defined constant, but we are choosing
    // to saturate negative exponents to 0 for comparisons sake. We're only
    // trying to recurse on lines with very large coordinates.
    int expDiffX = std::abs((std::abs(p0.x) < 1.f ? 0 : std::ilogbf(p0.x)) -
                            (std::abs(p1.x) < 1.f ? 0 : std::ilogbf(p1.x)));
    int expDiffY = std::abs((std::abs(p0.y) < 1.f ? 0 : std::ilogbf(p0.y)) -
                            (std::abs(p1.y) < 1.f ? 0 : std::ilogbf(p1.y)));
    // Differ by more than 2^20, or roughly a factor of one million.
    return expDiffX > 20 || expDiffY > 20;
}

static bool recursive_edge_intersect(const Line& u,
                                     Vec2D u0,
                                     Vec2D u1,
                                     const Line& v,
                                     Vec2D v0,
                                     Vec2D v1,
                                     Vec2D* p,
                                     double* s,
                                     double* t)
{
    // First check if the bounding boxes of [u0,u1] intersects [v0,v1]. If they
    // do not, then the two line segments cannot intersect in their domain (even
    // if the lines themselves might).
    // - don't use AABB::intersect since the vertices aren't sorted and
    // horiz/vertical lines
    //   appear as empty rects, which then never "intersect" according to AABB.
    if (std::min(u0.x, u1.x) > std::max(v0.x, v1.x) ||
        std::max(u0.x, u1.x) < std::min(v0.x, v1.x) ||
        std::min(u0.y, u1.y) > std::max(v0.y, v1.y) ||
        std::max(u0.y, u1.y) < std::min(v0.y, v1.y))
    {
        return false;
    }

    // Compute intersection based on current segment vertices; if an
    // intersection is found but the vertices differ too much in magnitude, we
    // recurse using the midpoint of the segment to reject false positives. We
    // don't currently try to avoid false negatives (e.g. large magnitude line
    // reports no intersection but there is one).
    double denom = u.fA * v.fB - u.fB * v.fA;
    if (denom == 0.0)
    {
        return false;
    }
    double dx = static_cast<double>(v0.x) - u0.x;
    double dy = static_cast<double>(v0.y) - u0.y;
    double sNumer = dy * v.fB + dx * v.fA;
    double tNumer = dy * u.fB + dx * u.fA;
    // If (sNumer / denom) or (tNumer / denom) is not in [0..1], exit early.
    // This saves us doing the divide below unless absolutely necessary.
    if (denom > 0.0
            ? (sNumer < 0.0 || sNumer > denom || tNumer < 0.0 || tNumer > denom)
            : (sNumer > 0.0 || sNumer < denom || tNumer > 0.0 ||
               tNumer < denom))
    {
        return false;
    }

    *s = sNumer / denom;
    *t = tNumer / denom;
    assert(*s >= 0.0 && *s <= 1.0 && *t >= 0.0 && *t <= 1.0);

    const bool uNeedsSplit = edge_line_needs_recursion(u0, u1);
    const bool vNeedsSplit = edge_line_needs_recursion(v0, v1);
    if (!uNeedsSplit && !vNeedsSplit)
    {
        p->x = double_to_clamped_scalar(u0.x - (*s) * u.fB);
        p->y = double_to_clamped_scalar(u0.y + (*s) * u.fA);
        return true;
    }
    else
    {
        double sScale = 1.0, sShift = 0.0;
        double tScale = 1.0, tShift = 0.0;

        if (uNeedsSplit)
        {
            Vec2D uM = {(float)(0.5 * u0.x + 0.5 * u1.x),
                        (float)(0.5 * u0.y + 0.5 * u1.y)};
            sScale = 0.5;
            if (*s >= 0.5)
            {
                u0 = uM;
                sShift = 0.5;
            }
            else
            {
                u1 = uM;
            }
        }
        if (vNeedsSplit)
        {
            Vec2D vM = {(float)(0.5 * v0.x + 0.5 * v1.x),
                        (float)(0.5 * v0.y + 0.5 * v1.y)};
            tScale = 0.5;
            if (*t >= 0.5)
            {
                v0 = vM;
                tShift = 0.5;
            }
            else
            {
                v1 = vM;
            }
        }

        // Just recompute both lines, even if only one was split; we're already
        // in a slow path.
        if (recursive_edge_intersect(Line(u0, u1),
                                     u0,
                                     u1,
                                     Line(v0, v1),
                                     v0,
                                     v1,
                                     p,
                                     s,
                                     t))
        {
            // Adjust s and t back to full range
            *s = sScale * (*s) + sShift;
            *t = tScale * (*t) + tShift;
            return true;
        }
        else
        {
            // False positive
            return false;
        }
    }
}

bool GrTriangulator::Edge::intersect(const Edge& other,
                                     Vec2D* p,
                                     uint8_t* alpha) const
{
    TESS_LOG("intersecting %g -> %g with %g -> %g\n",
             fTop->fID,
             fBottom->fID,
             other.fTop->fID,
             other.fBottom->fID);
    if (fTop == other.fTop || fBottom == other.fBottom ||
        fTop == other.fBottom || fBottom == other.fTop)
    {
        // If the two edges share a vertex by construction, they have already
        // been split and shouldn't be considered "intersecting" anymore.
        return false;
    }

    double s, t; // needed to interpolate vertex alpha
    const bool intersects = recursive_edge_intersect(fLine,
                                                     fTop->fPoint,
                                                     fBottom->fPoint,
                                                     other.fLine,
                                                     other.fTop->fPoint,
                                                     other.fBottom->fPoint,
                                                     p,
                                                     &s,
                                                     &t);
    if (!intersects)
    {
        return false;
    }

    if (alpha)
    {
        if (fType == EdgeType::kInner || other.fType == EdgeType::kInner)
        {
            // If the intersection is on any interior edge, it needs to stay
            // fully opaque or later triangulation could leech transparency into
            // the inner fill region.
            *alpha = 255;
        }
        else if (fType == EdgeType::kOuter && other.fType == EdgeType::kOuter)
        {
            // Trivially, the intersection will be fully transparent since since
            // it is by construction on the outer edge.
            *alpha = 0;
        }
        else
        {
            // Could be two connectors crossing, or a connector crossing an
            // outer edge. Take the max interpolated alpha
            assert(fType == EdgeType::kConnector ||
                   other.fType == EdgeType::kConnector);
            *alpha = std::max((1.0 - s) * fTop->fAlpha + s * fBottom->fAlpha,
                              (1.0 - t) * other.fTop->fAlpha +
                                  t * other.fBottom->fAlpha);
        }
    }
    return true;
}

void GrTriangulator::EdgeList::insert(Edge* edge, Edge* prev, Edge* next)
{
    list_insert<Edge, &Edge::fLeft, &Edge::fRight>(edge,
                                                   prev,
                                                   next,
                                                   &fHead,
                                                   &fTail);
}

bool GrTriangulator::EdgeList::remove(Edge* edge)
{
    TESS_LOG("removing edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID);
    // assert(this->contains(edge));  // Leave this here for future debugging.
    if (!this->contains(edge))
    {
        return false;
    }
    list_remove<Edge, &Edge::fLeft, &Edge::fRight>(edge, &fHead, &fTail);
    return true;
}

void GrTriangulator::MonotonePoly::addEdge(Edge* edge)
{
    if (fSide == Side::kRight)
    {
        assert(!edge->fUsedInRightPoly);
        list_insert<Edge, &Edge::fRightPolyPrev, &Edge::fRightPolyNext>(
            edge,
            fLastEdge,
            nullptr,
            &fFirstEdge,
            &fLastEdge);
        edge->fUsedInRightPoly = true;
    }
    else
    {
        assert(!edge->fUsedInLeftPoly);
        list_insert<Edge, &Edge::fLeftPolyPrev, &Edge::fLeftPolyNext>(
            edge,
            fLastEdge,
            nullptr,
            &fFirstEdge,
            &fLastEdge);
        edge->fUsedInLeftPoly = true;
    }
}

template <typename Sink>
size_t GrTriangulator::emitMonotonePoly(const MonotonePoly* monotonePoly,
                                        bool negateWinding,
                                        gpu::WindingFaces windingFaces,
                                        Sink* sink) const
{
    // GrTriangulator and Rive unfortunately have opposite winding senses.
    int16_t riveWeight = -monotonePoly->fWinding;
    assert(riveWeight != 0);
    if (negateWinding)
    {
        riveWeight = -riveWeight;
    }
    if ((riveWeight < 0 &&
         !enums::is_flag_set(windingFaces, gpu::WindingFaces::negative)) ||
        (riveWeight >= 0 &&
         !enums::is_flag_set(windingFaces, gpu::WindingFaces::positive)))
    {
        return 0;
    }
    Edge* e = monotonePoly->fFirstEdge;
    VertexList vertices;
    vertices.append(e->fTop);
    int count = 1;
    while (e != nullptr)
    {
        if (Side::kRight == monotonePoly->fSide)
        {
            vertices.append(e->fBottom);
            e = e->fRightPolyNext;
        }
        else
        {
            vertices.prepend(e->fBottom);
            e = e->fLeftPolyNext;
        }
        count++;
    }
    Vertex* first = vertices.fHead;
    Vertex* v = first->fNext;
    size_t vertexCount = 0;
    while (v != vertices.fTail)
    {
        assert(v && v->fPrev && v->fNext);
        Vertex* prev = v->fPrev;
        Vertex* curr = v;
        Vertex* next = v->fNext;
        if (count == 3)
        {
            vertexCount += emitTriangle(prev, curr, next, riveWeight, sink);
            break;
        }
        double ax = static_cast<double>(curr->fPoint.x) - prev->fPoint.x;
        double ay = static_cast<double>(curr->fPoint.y) - prev->fPoint.y;
        double bx = static_cast<double>(next->fPoint.x) - curr->fPoint.x;
        double by = static_cast<double>(next->fPoint.y) - curr->fPoint.y;
        if (ax * by - ay * bx >= 0.0)
        {
            vertexCount += emitTriangle(prev, curr, next, riveWeight, sink);
            v->fPrev->fNext = v->fNext;
            v->fNext->fPrev = v->fPrev;
            count--;
            if (v->fPrev == first)
            {
                v = v->fNext;
            }
            else
            {
                v = v->fPrev;
            }
        }
        else
        {
            v = v->fNext;
        }
    }
    return vertexCount;
}

template <typename Sink>
size_t GrTriangulator::emitTriangle(Vertex* prev,
                                    Vertex* curr,
                                    Vertex* next,
                                    int16_t riveWeight,
                                    Sink* sink) const
{
    return emit_triangle(prev, curr, next, riveWeight, sink);
}

GrTriangulator::Poly::Poly(Vertex* v, int winding) :
    fFirstVertex(v),
    fWinding(winding),
    fHead(nullptr),
    fTail(nullptr),
    fNext(nullptr),
    fPartner(nullptr),
    fCount(0)
{
#if TRIANGULATOR_LOGGING
    static int gID = 0;
    fID = gID++;
    TESS_LOG("*** created Poly %d\n", fID);
#endif
}

Poly* GrTriangulator::Poly::addEdge(Edge* e, Side side, GrTriangulator* tri)
{
    TESS_LOG("addEdge (%g -> %g) to poly %d, %s side\n",
             e->fTop->fID,
             e->fBottom->fID,
             fID,
             side == Side::kLeft ? "left" : "right");
    Poly* partner = fPartner;
    Poly* poly = this;
    if (side == Side::kRight)
    {
        if (e->fUsedInRightPoly)
        {
            return this;
        }
    }
    else
    {
        if (e->fUsedInLeftPoly)
        {
            return this;
        }
    }
    if (partner)
    {
        fPartner = partner->fPartner = nullptr;
    }
    if (!fTail)
    {
        fHead = fTail = tri->allocateMonotonePoly(e, side, fWinding);
        fCount += 2;
    }
    else if (e->fBottom == fTail->fLastEdge->fBottom)
    {
        return poly;
    }
    else if (side == fTail->fSide)
    {
        fTail->addEdge(e);
        fCount++;
    }
    else
    {
        e = tri->allocateEdge(fTail->fLastEdge->fBottom,
                              e->fBottom,
                              1,
                              EdgeType::kInner);
        fTail->addEdge(e);
        fCount++;
        if (partner)
        {
            partner->addEdge(e, side, tri);
            poly = partner;
        }
        else
        {
            MonotonePoly* m = tri->allocateMonotonePoly(e, side, fWinding);
            m->fPrev = fTail;
            fTail->fNext = m;
            fTail = m;
        }
    }
    return poly;
}

template <typename Sink>
size_t GrTriangulator::emitPoly(const Poly* poly,
                                bool negateWinding,
                                gpu::WindingFaces windingFaces,
                                Sink* sink) const
{
    if (poly->fCount < 3)
    {
        return 0;
    }
    TESS_LOG("emit() %d, size %d\n", poly->fID, poly->fCount);
    size_t vertexCount = 0;
    for (MonotonePoly* m = poly->fHead; m != nullptr; m = m->fNext)
    {
        vertexCount += emitMonotonePoly(m, negateWinding, windingFaces, sink);
    }
    return vertexCount;
}

static bool coincident(const Vec2D& a, const Vec2D& b) { return a == b; }

Poly* GrTriangulator::makePoly(Poly** head, Vertex* v, int winding) const
{
    Poly* poly = fAlloc->make<Poly>(v, winding);
    poly->fNext = *head;
    *head = poly;
    return poly;
}

void GrTriangulator::appendPointToContour(const Vec2D& p,
                                          VertexList* contour) const
{
    Vertex* v = fAlloc->make<Vertex>(p, 255);
#if TRIANGULATOR_LOGGING
    static float gID = 0.0f;
    v->fID = gID++;
#endif
    contour->append(v);
}

#if 0
static float quad_error_at(const Vec2D pts[3], float t, float u)
{
    SkQuadCoeff quad(pts);
    Vec2D p0 = to_point(quad.eval(t - 0.5f * u));
    Vec2D mid = to_point(quad.eval(t));
    Vec2D p1 = to_point(quad.eval(t + 0.5f * u));
    if (!p0.isFinite() || !mid.isFinite() || !p1.isFinite())
    {
        return 0;
    }
    return SkPointPriv::DistanceToLineSegmentBetweenSqd(mid, p0, p1);
}

void GrTriangulator::appendQuadraticToContour(const Vec2D pts[3],
                                              float toleranceSqd,
                                              VertexList* contour) const
{
    SkQuadCoeff quad(pts);
    skvx::float2 aa = quad.fA * quad.fA;
    float denom = 2.0f * (aa[0] + aa[1]);
    skvx::float2 ab = quad.fA * quad.fB;
    float t = denom ? (-ab[0] - ab[1]) / denom : 0.0f;
    int nPoints = 1;
    float u = 1.0f;
    // Test possible subdivision values only at the point of maximum curvature.
    // If it passes the flatness metric there, it'll pass everywhere.
    while (nPoints < GrPathUtils::kMaxPointsPerCurve)
    {
        u = 1.0f / nPoints;
        if (quad_error_at(pts, t, u) < toleranceSqd)
        {
            break;
        }
        nPoints++;
    }
    for (int j = 1; j <= nPoints; j++)
    {
        this->appendPointToContour(to_point(quad.eval(j * u)), contour);
    }
}

void GrTriangulator::generateCubicPoints(const Vec2D& p0,
                                         const Vec2D& p1,
                                         const Vec2D& p2,
                                         const Vec2D& p3,
                                         float tolSqd,
                                         VertexList* contour,
                                         int pointsLeft) const
{
    float d1 = SkPointPriv::DistanceToLineSegmentBetweenSqd(p1, p0, p3);
    float d2 = SkPointPriv::DistanceToLineSegmentBetweenSqd(p2, p0, p3);
    if (pointsLeft < 2 || (d1 < tolSqd && d2 < tolSqd) || !SkIsFinite(d1, d2))
    {
        this->appendPointToContour(p3, contour);
        return;
    }
    const Vec2D q[] = {{SkScalarAve(p0.x, p1.x), SkScalarAve(p0.y, p1.y)},
                       {SkScalarAve(p1.x, p2.x), SkScalarAve(p1.y, p2.y)},
                       {SkScalarAve(p2.x, p3.x), SkScalarAve(p2.y, p3.y)}};
    const Vec2D r[] = {{SkScalarAve(q[0].x, q[1].x), SkScalarAve(q[0].y, q[1].y)},
                       {SkScalarAve(q[1].x, q[2].x), SkScalarAve(q[1].y, q[2].y)}};
    const Vec2D s = {SkScalarAve(r[0].x, r[1].x), SkScalarAve(r[0].y, r[1].y)};
    pointsLeft >>= 1;
    this->generateCubicPoints(p0, q[0], r[0], s, tolSqd, contour, pointsLeft);
    this->generateCubicPoints(s, r[1], q[2], p3, tolSqd, contour, pointsLeft);
}
#endif

// Stage 1: convert the input path to a set of linear contours (linked list of
// Vertices).

void GrTriangulator::pathToContours(const RawPath& path,
                                    float tolerance,
                                    const AABB& clipBounds,
                                    VertexList* contours,
                                    bool* isLinear) const
{
#if 0
    float toleranceSqd = tolerance * tolerance;
    Vec2D pts[4];
#endif
    *isLinear = true;
    VertexList* contour = contours;
#if 0
    RawPath::Iter iter(fPath, false);
    if (path.isInverseFillType())
    {
        Vec2D quad[4];
        clipBounds.toQuad(quad);
        for (int i = 3; i >= 0; i--)
        {
            this->appendPointToContour(quad[i], contours);
        }
        contour++;
    }
    SkAutoConicToQuads converter;
#endif
    for (const auto [verb, pts] : path)
    {
        switch (verb)
        {
#if 0
            case SkPath::kConic_Verb:
            {
                *isLinear = false;
                if (toleranceSqd == 0)
                {
                    this->appendPointToContour(pts[2], contour);
                    break;
                }
                float weight = iter.conicWeight();
                const Vec2D* quadPts = converter.computeQuads(pts, weight, toleranceSqd);
                for (int i = 0; i < converter.countQuads(); ++i)
                {
                    this->appendQuadraticToContour(quadPts, toleranceSqd, contour);
                    quadPts += 2;
                }
                break;
            }
#endif
            case PathVerb::move:
                if (contour->fHead)
                {
                    contour++;
                }
                if (is_finite(pts[0]))
                {
                    this->appendPointToContour(pts[0], contour);
                }
                break;
            case PathVerb::line:
            {
                if (is_finite(pts[1]))
                {
                    this->appendPointToContour(pts[1], contour);
                }
                break;
            }
            case PathVerb::quad:
            {
#if 0
                *isLinear = false;
                if (toleranceSqd == 0)
                {
                    this->appendPointToContour(pts[2], contour);
                    break;
                }
                this->appendQuadraticToContour(pts, toleranceSqd, contour);
#else
                // RIVE edit: We only triangulate the interior polygon, so just
                // draw a flat line from the beginning to the end of the
                // quadratic.
                if (is_finite(pts[2]))
                {
                    this->appendPointToContour(pts[2], contour);
                }
#endif
                break;
            }
            case PathVerb::cubic:
            {
#if 0
                *isLinear = false;
                if (toleranceSqd == 0)
                {
                    this->appendPointToContour(pts[3], contour);
                    break;
                }
                int pointsLeft = GrPathUtils::cubicPointCount(pts, tolerance);
                this->generateCubicPoints(pts[0],
                                          pts[1],
                                          pts[2],
                                          pts[3],
                                          toleranceSqd,
                                          contour,
                                          pointsLeft);
#else
                // RIVE edit: We only triangulate the interior polygon, so just
                // draw a flat line from the beginning to the end of the cubic.
                if (is_finite(pts[3]))
                {
                    this->appendPointToContour(pts[3], contour);
                }
#endif
                break;
            }
            case PathVerb::close:
                break;
        }
    }
}

static inline bool apply_fill_type(FillRule fillRule, int winding)
{
    switch (fillRule)
    {
        // Clockwise triangulates the same as nonZero because clockwise still
        // uses the backward ones for borrowed coverage.
        case FillRule::nonZero:
        case FillRule::clockwise:
            return winding != 0;
        case FillRule::evenOdd:
            return (winding & 1) != 0;
    }
    RIVE_UNREACHABLE();
}

static inline bool apply_fill_type(FillRule fillType, const Poly* poly)
{
    return poly && apply_fill_type(fillType, poly->fWinding);
}

MonotonePoly* GrTriangulator::allocateMonotonePoly(Edge* edge,
                                                   Side side,
                                                   int winding)
{
    ++fNumMonotonePolys;
    return fAlloc->make<MonotonePoly>(edge, side, winding);
}

Edge* GrTriangulator::allocateEdge(Vertex* top,
                                   Vertex* bottom,
                                   int winding,
                                   EdgeType type)
{
    ++fNumEdges;
    return fAlloc->make<Edge>(top, bottom, winding, type);
}

Edge* GrTriangulator::makeEdge(Vertex* prev,
                               Vertex* next,
                               EdgeType type,
                               const Comparator& c)
{
    assert(prev->fPoint != next->fPoint);
    int winding = c.sweep_lt(prev->fPoint, next->fPoint) ? 1 : -1;
    Vertex* top = winding < 0 ? next : prev;
    Vertex* bottom = winding < 0 ? prev : next;
    return this->allocateEdge(top, bottom, winding, type);
}

bool EdgeList::insert(Edge* edge, Edge* prev)
{
    TESS_LOG("inserting edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID);
    // assert(!this->contains(edge));  // Leave this here for debugging.
    if (this->contains(edge))
    {
        return false;
    }
    Edge* next = prev ? prev->fRight : fHead;
    this->insert(edge, prev, next);
    return true;
}

void GrTriangulator::FindEnclosingEdges(const Vertex& v,
                                        const EdgeList& edges,
                                        Edge** left,
                                        Edge** right)
{
    if (v.fFirstEdgeAbove && v.fLastEdgeAbove)
    {
        *left = v.fFirstEdgeAbove->fLeft;
        *right = v.fLastEdgeAbove->fRight;
        return;
    }
    Edge* next = nullptr;
    Edge* prev;
    for (prev = edges.fTail; prev != nullptr; prev = prev->fLeft)
    {
        if (prev->isLeftOf(v))
        {
            break;
        }
        next = prev;
    }
    *left = prev;
    *right = next;
}

void GrTriangulator::Edge::insertAbove(Vertex* v, const Comparator& c)
{
    if (fTop->fPoint == fBottom->fPoint ||
        c.sweep_lt(fBottom->fPoint, fTop->fPoint))
    {
        return;
    }
    TESS_LOG("insert edge (%g -> %g) above vertex %g\n",
             fTop->fID,
             fBottom->fID,
             v->fID);
    Edge* prev = nullptr;
    Edge* next;
    for (next = v->fFirstEdgeAbove; next; next = next->fNextEdgeAbove)
    {
        if (next->isRightOf(*fTop))
        {
            break;
        }
        prev = next;
    }
    list_insert<Edge, &Edge::fPrevEdgeAbove, &Edge::fNextEdgeAbove>(
        this,
        prev,
        next,
        &v->fFirstEdgeAbove,
        &v->fLastEdgeAbove);
}

void GrTriangulator::Edge::insertBelow(Vertex* v, const Comparator& c)
{
    if (fTop->fPoint == fBottom->fPoint ||
        c.sweep_lt(fBottom->fPoint, fTop->fPoint))
    {
        return;
    }
    TESS_LOG("insert edge (%g -> %g) below vertex %g\n",
             fTop->fID,
             fBottom->fID,
             v->fID);
    Edge* prev = nullptr;
    Edge* next;
    for (next = v->fFirstEdgeBelow; next; next = next->fNextEdgeBelow)
    {
        if (next->isRightOf(*fBottom))
        {
            break;
        }
        prev = next;
    }
    list_insert<Edge, &Edge::fPrevEdgeBelow, &Edge::fNextEdgeBelow>(
        this,
        prev,
        next,
        &v->fFirstEdgeBelow,
        &v->fLastEdgeBelow);
}

static void remove_edge_above(Edge* edge)
{
    assert(edge->fTop && edge->fBottom);
    TESS_LOG("removing edge (%g -> %g) above vertex %g\n",
             edge->fTop->fID,
             edge->fBottom->fID,
             edge->fBottom->fID);
    list_remove<Edge, &Edge::fPrevEdgeAbove, &Edge::fNextEdgeAbove>(
        edge,
        &edge->fBottom->fFirstEdgeAbove,
        &edge->fBottom->fLastEdgeAbove);
}

static void remove_edge_below(Edge* edge)
{
    assert(edge->fTop && edge->fBottom);
    TESS_LOG("removing edge (%g -> %g) below vertex %g\n",
             edge->fTop->fID,
             edge->fBottom->fID,
             edge->fTop->fID);
    list_remove<Edge, &Edge::fPrevEdgeBelow, &Edge::fNextEdgeBelow>(
        edge,
        &edge->fTop->fFirstEdgeBelow,
        &edge->fTop->fLastEdgeBelow);
}

void GrTriangulator::Edge::disconnect()
{
    remove_edge_above(this);
    remove_edge_below(this);
}

static bool rewind(EdgeList* activeEdges,
                   Vertex** current,
                   Vertex* dst,
                   const Comparator& c)
{
    if (!current || *current == dst ||
        c.sweep_lt((*current)->fPoint, dst->fPoint))
    {
        return true;
    }
    Vertex* v = *current;
    TESS_LOG("rewinding active edges from vertex %g to vertex %g\n",
             v->fID,
             dst->fID);
    while (v != dst)
    {
        v = v->fPrev;
        for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow)
        {
            if (!activeEdges->remove(e))
            {
                return false;
            }
        }
        Edge* leftEdge = v->fLeftEnclosingEdge;
        for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove)
        {
            if (!e)
            {
                return false;
            }
            if (!activeEdges->insert(e, leftEdge))
            {
                return false;
            }
            leftEdge = e;
            Vertex* top = e->fTop;
            if (!top ||
                (top->fLeftEnclosingEdge &&
                 !top->fLeftEnclosingEdge->hasTopAndBottom()) ||
                (top->fRightEnclosingEdge &&
                 !top->fRightEnclosingEdge->hasTopAndBottom()))
            {
                return false;
            }
            if (c.sweep_lt(top->fPoint, dst->fPoint) &&
                ((top->fLeftEnclosingEdge &&
                  !top->fLeftEnclosingEdge->isLeftOf(*top)) ||
                 (top->fRightEnclosingEdge &&
                  !top->fRightEnclosingEdge->isRightOf(*top))))
            {
                dst = top;
            }
        }
    }
    *current = v;
    return true;
}

static bool rewind_if_necessary(Edge* edge,
                                EdgeList* activeEdges,
                                Vertex** current,
                                const Comparator& c)
{
    if (!activeEdges || !current)
    {
        return true;
    }
    if (!edge)
    {
        return false;
    }
    Vertex* top = edge->fTop;
    Vertex* bottom = edge->fBottom;
    if (edge->fLeft)
    {
        Vertex* leftTop = edge->fLeft->fTop;
        Vertex* leftBottom = edge->fLeft->fBottom;
        if (leftTop && leftBottom)
        {
            if (c.sweep_lt(leftTop->fPoint, top->fPoint) &&
                !edge->fLeft->isLeftOf(*top))
            {
                if (!rewind(activeEdges, current, leftTop, c))
                {
                    return false;
                }
            }
            else if (c.sweep_lt(top->fPoint, leftTop->fPoint) &&
                     !edge->isRightOf(*leftTop))
            {
                if (!rewind(activeEdges, current, top, c))
                {
                    return false;
                }
            }
            else if (c.sweep_lt(bottom->fPoint, leftBottom->fPoint) &&
                     !edge->fLeft->isLeftOf(*bottom))
            {
                if (!rewind(activeEdges, current, leftTop, c))
                {
                    return false;
                }
            }
            else if (c.sweep_lt(leftBottom->fPoint, bottom->fPoint) &&
                     !edge->isRightOf(*leftBottom))
            {
                if (!rewind(activeEdges, current, top, c))
                {
                    return false;
                }
            }
        }
    }
    if (edge->fRight)
    {
        Vertex* rightTop = edge->fRight->fTop;
        Vertex* rightBottom = edge->fRight->fBottom;
        if (rightTop && rightBottom)
        {
            if (c.sweep_lt(rightTop->fPoint, top->fPoint) &&
                !edge->fRight->isRightOf(*top))
            {
                if (!rewind(activeEdges, current, rightTop, c))
                {
                    return false;
                }
            }
            else if (c.sweep_lt(top->fPoint, rightTop->fPoint) &&
                     !edge->isLeftOf(*rightTop))
            {
                if (!rewind(activeEdges, current, top, c))
                {
                    return false;
                }
            }
            else if (c.sweep_lt(bottom->fPoint, rightBottom->fPoint) &&
                     !edge->fRight->isRightOf(*bottom))
            {
                if (!rewind(activeEdges, current, rightTop, c))
                {
                    return false;
                }
            }
            else if (c.sweep_lt(rightBottom->fPoint, bottom->fPoint) &&
                     !edge->isLeftOf(*rightBottom))
            {
                if (!rewind(activeEdges, current, top, c))
                {
                    return false;
                }
            }
        }
    }
    return true;
}

bool GrTriangulator::setTop(Edge* edge,
                            Vertex* v,
                            EdgeList* activeEdges,
                            Vertex** current,
                            const Comparator& c) const
{
    remove_edge_below(edge);
    if (fCollectBreadcrumbTriangles)
    {
        fBreadcrumbList.append(fAlloc,
                               edge->fTop->fPoint,
                               edge->fBottom->fPoint,
                               v->fPoint,
                               edge->fWinding);
    }
    edge->fTop = v;
    edge->recompute();
    edge->insertBelow(v, c);
    if (!rewind_if_necessary(edge, activeEdges, current, c))
    {
        return false;
    }
    return this->mergeCollinearEdges(edge, activeEdges, current, c);
}

bool GrTriangulator::setBottom(Edge* edge,
                               Vertex* v,
                               EdgeList* activeEdges,
                               Vertex** current,
                               const Comparator& c) const
{
    remove_edge_above(edge);
    if (fCollectBreadcrumbTriangles)
    {
        fBreadcrumbList.append(fAlloc,
                               edge->fTop->fPoint,
                               edge->fBottom->fPoint,
                               v->fPoint,
                               edge->fWinding);
    }
    edge->fBottom = v;
    edge->recompute();
    edge->insertAbove(v, c);
    if (!rewind_if_necessary(edge, activeEdges, current, c))
    {
        return false;
    }
    return this->mergeCollinearEdges(edge, activeEdges, current, c);
}

/*
 * NOTE: Also used in mergeEdgesBelow().
 * Merges two adjacent, collinear edges. Two main cases:
 *
 * 1. Coincident endpoints: if the edges share the exact same top/bottom vertex,
 *    one edge's winding is absorbed into the other. The now-unused "zombie"
 * edge is fully disconnected and also explicitly removed from activeEdges, to
 *    prevent state corruption that can lead to null-pointer dereferences
 *    (b/419397557, b/421959607).
 *
 * 2. Non-coincident (overlapping) endpoints: one edge is shortened in place to
 *    meet the other's endpoint. This is fragile -- it relies on the stability
 * of the floating-point geometric comparisons (isLeftOf, etc.) to succeed on
 *    pathological coordinates.
 */
bool GrTriangulator::mergeEdgesAbove(Edge* edge,
                                     Edge* other,
                                     EdgeList* activeEdges,
                                     Vertex** current,
                                     const Comparator& c) const
{
    if (!edge || !other)
    {
        return false;
    }
    if (coincident(edge->fTop->fPoint, other->fTop->fPoint))
    {
        TESS_LOG("merging coincident above edges (%g, %g) -> (%g, %g)\n",
                 edge->fTop->fPoint.x,
                 edge->fTop->fPoint.y,
                 edge->fBottom->fPoint.x,
                 edge->fBottom->fPoint.y);
        if (!rewind(activeEdges, current, edge->fTop, c))
        {
            return false;
        }
        other->fWinding += edge->fWinding;
        edge->disconnect();
        if (activeEdges)
        {
            activeEdges->remove(edge);
        }
        edge->fTop = edge->fBottom = nullptr;
    }
    else if (c.sweep_lt(edge->fTop->fPoint, other->fTop->fPoint))
    {
        if (!rewind(activeEdges, current, edge->fTop, c))
        {
            return false;
        }
        other->fWinding += edge->fWinding;
        if (!this->setBottom(edge, other->fTop, activeEdges, current, c))
        {
            return false;
        }
    }
    else
    {
        if (!rewind(activeEdges, current, other->fTop, c))
        {
            return false;
        }
        edge->fWinding += other->fWinding;
        if (!this->setBottom(other, edge->fTop, activeEdges, current, c))
        {
            return false;
        }
    }
    return true;
}

// NOTE: See mergeEdgesAbove() comment.
bool GrTriangulator::mergeEdgesBelow(Edge* edge,
                                     Edge* other,
                                     EdgeList* activeEdges,
                                     Vertex** current,
                                     const Comparator& c) const
{
    if (!edge || !other)
    {
        return false;
    }
    if (coincident(edge->fBottom->fPoint, other->fBottom->fPoint))
    {
        TESS_LOG("merging coincident below edges (%g, %g) -> (%g, %g)\n",
                 edge->fTop->fPoint.x,
                 edge->fTop->fPoint.y,
                 edge->fBottom->fPoint.x,
                 edge->fBottom->fPoint.y);
        if (!rewind(activeEdges, current, edge->fTop, c))
        {
            return false;
        }
        other->fWinding += edge->fWinding;
        edge->disconnect();
        if (activeEdges)
        {
            activeEdges->remove(edge);
        }
        edge->fTop = edge->fBottom = nullptr;
    }
    else if (c.sweep_lt(edge->fBottom->fPoint, other->fBottom->fPoint))
    {
        if (!rewind(activeEdges, current, other->fTop, c))
        {
            return false;
        }
        edge->fWinding += other->fWinding;
        if (!this->setTop(other, edge->fBottom, activeEdges, current, c))
        {
            return false;
        }
    }
    else
    {
        if (!rewind(activeEdges, current, edge->fTop, c))
        {
            return false;
        }
        other->fWinding += edge->fWinding;
        if (!this->setTop(edge, other->fBottom, activeEdges, current, c))
        {
            return false;
        }
    }
    return true;
}

static bool top_collinear(Edge* left, Edge* right)
{
    if (!left || !right)
    {
        return false;
    }
    return left->fTop->fPoint == right->fTop->fPoint ||
           !left->isLeftOf(*right->fTop) || !right->isRightOf(*left->fTop);
}

static bool bottom_collinear(Edge* left, Edge* right)
{
    if (!left || !right)
    {
        return false;
    }
    return left->fBottom->fPoint == right->fBottom->fPoint ||
           !left->isLeftOf(*right->fBottom) ||
           !right->isRightOf(*left->fBottom);
}

// How deep of a stack of mergeCollinearEdges() we'll accept.
static constexpr int kMaxMergeCollinearCalls = 64;

bool GrTriangulator::mergeCollinearEdges(Edge* edge,
                                         EdgeList* activeEdges,
                                         Vertex** current,
                                         const Comparator& c) const
{
    // Stack is unreasonably deep.
    if (++fMergeCollinearStackCount > kMaxMergeCollinearCalls)
    {
        return false;
    }
    for (;;)
    {
        if (top_collinear(edge->fPrevEdgeAbove, edge))
        {
            if (!this->mergeEdgesAbove(edge->fPrevEdgeAbove,
                                       edge,
                                       activeEdges,
                                       current,
                                       c))
            {
                return false;
            }
        }
        else if (top_collinear(edge, edge->fNextEdgeAbove))
        {
            if (!this->mergeEdgesAbove(edge->fNextEdgeAbove,
                                       edge,
                                       activeEdges,
                                       current,
                                       c))
            {
                return false;
            }
        }
        else if (bottom_collinear(edge->fPrevEdgeBelow, edge))
        {
            if (!this->mergeEdgesBelow(edge->fPrevEdgeBelow,
                                       edge,
                                       activeEdges,
                                       current,
                                       c))
            {
                return false;
            }
        }
        else if (bottom_collinear(edge, edge->fNextEdgeBelow))
        {
            if (!this->mergeEdgesBelow(edge->fNextEdgeBelow,
                                       edge,
                                       activeEdges,
                                       current,
                                       c))
            {
                return false;
            }
        }
        else
        {
            break;
        }
    }
    assert(!top_collinear(edge->fPrevEdgeAbove, edge));
    assert(!top_collinear(edge, edge->fNextEdgeAbove));
    assert(!bottom_collinear(edge->fPrevEdgeBelow, edge));
    assert(!bottom_collinear(edge, edge->fNextEdgeBelow));
    return true;
}

GrTriangulator::BoolFail GrTriangulator::splitEdge(Edge* edge,
                                                   Vertex* v,
                                                   EdgeList* activeEdges,
                                                   Vertex** current,
                                                   const Comparator& c)
{
    if (!edge->fTop || !edge->fBottom || v == edge->fTop || v == edge->fBottom)
    {
        return BoolFail::kFalse;
    }
    TESS_LOG("splitting edge (%g -> %g) at vertex %g (%g, %g)\n",
             edge->fTop->fID,
             edge->fBottom->fID,
             v->fID,
             v->fPoint.x,
             v->fPoint.y);
    Vertex* top;
    Vertex* bottom;
    int winding = edge->fWinding;
    // Theoretically, and ideally, the edge betwee p0 and p1 is being split by
    // v, and v is "between" the segment end points according to c. This is
    // equivalent to p0 < v < p1.  Unfortunately, if v was clamped/rounded this
    // relation doesn't always hold.
    if (c.sweep_lt(v->fPoint, edge->fTop->fPoint))
    {
        // Actually "v < p0 < p1": update 'edge' to be v->p1 and add v->p0. We
        // flip the winding on the new edge so that it winds as if it were
        // p0->v.
        top = v;
        bottom = edge->fTop;
        winding *= -1;
        if (!this->setTop(edge, v, activeEdges, current, c))
        {
            return BoolFail::kFail;
        }
    }
    else if (c.sweep_lt(edge->fBottom->fPoint, v->fPoint))
    {
        // Actually "p0 < p1 < v": update 'edge' to be p0->v and add p1->v. We
        // flip the winding on the new edge so that it winds as if it were
        // v->p1.
        top = edge->fBottom;
        bottom = v;
        winding *= -1;
        if (!this->setBottom(edge, v, activeEdges, current, c))
        {
            return BoolFail::kFail;
        }
    }
    else
    {
        // The ideal case, "p0 < v < p1": update 'edge' to be p0->v and add
        // v->p1. Original winding is valid for both edges.
        top = v;
        bottom = edge->fBottom;
        if (!this->setBottom(edge, v, activeEdges, current, c))
        {
            return BoolFail::kFail;
        }
    }
    Edge* newEdge = this->allocateEdge(top, bottom, winding, edge->fType);
    newEdge->insertBelow(top, c);
    newEdge->insertAbove(bottom, c);
    fMergeCollinearStackCount = 0;
    if (!this->mergeCollinearEdges(newEdge, activeEdges, current, c))
    {
        return BoolFail::kFail;
    }
    return BoolFail::kTrue;
}

GrTriangulator::BoolFail GrTriangulator::intersectEdgePair(
    Edge* left,
    Edge* right,
    EdgeList* activeEdges,
    Vertex** current,
    const Comparator& c)
{
    if (!left->fTop || !left->fBottom || !right->fTop || !right->fBottom)
    {
        return BoolFail::kFalse;
    }
    if (left->fTop == right->fTop || left->fBottom == right->fBottom)
    {
        return BoolFail::kFalse;
    }

    // Check if the lines intersect as determined by isLeftOf and isRightOf,
    // since that is the source of ground truth. It may suggest an intersection
    // even if Edge::intersect() did not have the precision to check it. In this
    // case we are explicitly correcting the edge topology to match the
    // sided-ness checks.
    Edge* split = nullptr;
    Vertex* splitAt = nullptr;
    if (c.sweep_lt(left->fTop->fPoint, right->fTop->fPoint))
    {
        if (!left->isLeftOf(*right->fTop))
        {
            split = left;
            splitAt = right->fTop;
        }
    }
    else
    {
        if (!right->isRightOf(*left->fTop))
        {
            split = right;
            splitAt = left->fTop;
        }
    }
    if (c.sweep_lt(right->fBottom->fPoint, left->fBottom->fPoint))
    {
        if (!left->isLeftOf(*right->fBottom))
        {
            split = left;
            splitAt = right->fBottom;
        }
    }
    else
    {
        if (!right->isRightOf(*left->fBottom))
        {
            split = right;
            splitAt = left->fBottom;
        }
    }

    if (!split)
    {
        return BoolFail::kFalse;
    }

    // Rewind to the top of the edge that is "moving" since this topology
    // correction can change the geometry of the split edge.
    if (!rewind(activeEdges, current, split->fTop, c))
    {
        return BoolFail::kFail;
    }
    return this->splitEdge(split, splitAt, activeEdges, current, c);
}

Edge* GrTriangulator::makeConnectingEdge(Vertex* prev,
                                         Vertex* next,
                                         EdgeType type,
                                         const Comparator& c,
                                         int windingScale)
{
    if (!prev || !next || prev->fPoint == next->fPoint)
    {
        return nullptr;
    }
    Edge* edge = this->makeEdge(prev, next, type, c);
    edge->insertBelow(edge->fTop, c);
    edge->insertAbove(edge->fBottom, c);
    edge->fWinding *= windingScale;
    fMergeCollinearStackCount = 0;
    this->mergeCollinearEdges(edge, nullptr, nullptr, c);
    return edge;
}

void GrTriangulator::mergeVertices(Vertex* src,
                                   Vertex* dst,
                                   VertexList* mesh,
                                   const Comparator& c) const
{
    TESS_LOG("found coincident verts at %g, %g; merging %g into %g\n",
             src->fPoint.x,
             src->fPoint.y,
             src->fID,
             dst->fID);
    dst->fAlpha = std::max(src->fAlpha, dst->fAlpha);
    if (src->fPartner)
    {
        src->fPartner->fPartner = dst;
    }
    // setBottom()/setTop() call mergeCollinearEdges(), which can recurse, so
    // clear the stack count before each.
    while (Edge* edge = src->fFirstEdgeAbove)
    {
        fMergeCollinearStackCount = 0;
        std::ignore = this->setBottom(edge, dst, nullptr, nullptr, c);
    }
    while (Edge* edge = src->fFirstEdgeBelow)
    {
        fMergeCollinearStackCount = 0;
        std::ignore = this->setTop(edge, dst, nullptr, nullptr, c);
    }
    mesh->remove(src);
    dst->fSynthetic = true;
}

Vertex* GrTriangulator::makeSortedVertex(const Vec2D& p,
                                         uint8_t alpha,
                                         VertexList* mesh,
                                         Vertex* reference,
                                         const Comparator& c) const
{
    Vertex* prevV = reference;
    while (prevV && c.sweep_lt(p, prevV->fPoint))
    {
        prevV = prevV->fPrev;
    }
    Vertex* nextV = prevV ? prevV->fNext : mesh->fHead;
    while (nextV && c.sweep_lt(nextV->fPoint, p))
    {
        prevV = nextV;
        nextV = nextV->fNext;
    }
    Vertex* v;
    if (prevV && coincident(prevV->fPoint, p))
    {
        v = prevV;
    }
    else if (nextV && coincident(nextV->fPoint, p))
    {
        v = nextV;
    }
    else
    {
        v = fAlloc->make<Vertex>(p, alpha);
#if TRIANGULATOR_LOGGING
        if (!prevV)
        {
            v->fID = mesh->fHead->fID - 1.0f;
        }
        else if (!nextV)
        {
            v->fID = mesh->fTail->fID + 1.0f;
        }
        else
        {
            v->fID = (prevV->fID + nextV->fID) * 0.5f;
        }
#endif
        mesh->insert(v, prevV, nextV);
    }
    return v;
}

// Clamps x and y coordinates independently, so the returned point will lie
// within the bounding box formed by the corners of 'min' and 'max' (although
// min/max here refer to the ordering imposed by 'c').
static Vec2D clamp(Vec2D p, Vec2D min, Vec2D max, const Comparator& c)
{
    if (c.fDirection == Comparator::Direction::kHorizontal)
    {
        // With horizontal sorting, we know min.x <= max.x, but there's no
        // relation between Y components unless min.x == max.x.
        return {std::clamp(p.x, min.x, max.x),
                min.y < max.y ? std::clamp(p.y, min.y, max.y)
                              : std::clamp(p.y, max.y, min.y)};
    }
    else
    {
        // And with vertical sorting, we know Y's relation but not necessarily
        // X's.
        return {min.x < max.x ? std::clamp(p.x, min.x, max.x)
                              : std::clamp(p.x, max.x, min.x),
                std::clamp(p.y, min.y, max.y)};
    }
}

#if 0
void GrTriangulator::computeBisector(Edge* edge1, Edge* edge2, Vertex* v) const
{
    assert(fEmitCoverage); // Edge-AA only!
    Line line1 = edge1->fLine;
    Line line2 = edge2->fLine;
    line1.normalize();
    line2.normalize();
    double cosAngle = line1.fA * line2.fA + line1.fB * line2.fB;
    if (cosAngle > 0.999)
    {
        return;
    }
    line1.fC += edge1->fWinding > 0 ? -1 : 1;
    line2.fC += edge2->fWinding > 0 ? -1 : 1;
    Vec2D p;
    if (line1.intersect(line2, &p))
    {
        uint8_t alpha = edge1->fType == EdgeType::kOuter ? 255 : 0;
        v->fPartner = fAlloc->make<Vertex>(p, alpha);
        TESS_LOG("computed bisector (%g,%g) alpha %d for vertex %g\n", p.x, p.y, alpha, v->fID);
    }
}
#endif

GrTriangulator::BoolFail GrTriangulator::checkForIntersection(
    Edge* left,
    Edge* right,
    EdgeList* activeEdges,
    Vertex** current,
    VertexList* mesh,
    const Comparator& c)
{
    if (!left || !right)
    {
        return BoolFail::kFalse;
    }
    Vec2D p;
    uint8_t alpha;
    // If we are going to call intersect, then there must be tops and bottoms.
    if (!left->fTop || !left->fBottom || !right->fTop || !right->fBottom)
    {
        return BoolFail::kFail;
    }
    if (left->intersect(*right, &p, &alpha) && is_finite(p))
    {
        Vertex* v;
        TESS_LOG("found intersection, pt is %g, %g\n", p.x, p.y);
        Vertex* top = *current;
        // If the intersection point is above the current vertex, rewind to the
        // vertex above the intersection.
        while (top && c.sweep_lt(p, top->fPoint))
        {
            top = top->fPrev;
        }

        // Always clamp the intersection to lie between the vertices of each
        // segment, since in theory that's where the intersection is, but in
        // reality, floating point error may have computed an intersection
        // beyond a vertex's component(s).
        p = clamp(p, left->fTop->fPoint, left->fBottom->fPoint, c);
        p = clamp(p, right->fTop->fPoint, right->fBottom->fPoint, c);

        if (coincident(p, left->fTop->fPoint))
        {
            v = left->fTop;
        }
        else if (coincident(p, left->fBottom->fPoint))
        {
            v = left->fBottom;
        }
        else if (coincident(p, right->fTop->fPoint))
        {
            v = right->fTop;
        }
        else if (coincident(p, right->fBottom->fPoint))
        {
            v = right->fBottom;
        }
        else
        {
            v = this->makeSortedVertex(p, alpha, mesh, top, c);
#if 0
            if (left->fTop->fPartner)
            {
                assert(fEmitCoverage); // Edge-AA only!
                v->fSynthetic = true;
                this->computeBisector(left, right, v);
            }
#endif
        }
        if (!rewind(activeEdges, current, top ? top : v, c))
        {
            return BoolFail::kFail;
        }
        if (this->splitEdge(left, v, activeEdges, current, c) ==
            BoolFail::kFail)
        {
            return BoolFail::kFail;
        }
        if (this->splitEdge(right, v, activeEdges, current, c) ==
            BoolFail::kFail)
        {
            return BoolFail::kFail;
        }
        v->fAlpha = std::max(v->fAlpha, alpha);
        return BoolFail::kTrue;
    }
    return this->intersectEdgePair(left, right, activeEdges, current, c);
}

void GrTriangulator::sanitizeContours(VertexList* contours,
                                      int contourCnt) const
{
    for (VertexList* contour = contours; contourCnt > 0;
         --contourCnt, ++contour)
    {
        if (contour->fHead == nullptr)
        {
            continue; // empty
        }

        Vertex* prev = contour->fTail;
        prev->fPoint.x = double_to_clamped_scalar((double)prev->fPoint.x);
        prev->fPoint.y = double_to_clamped_scalar((double)prev->fPoint.y);
#if 0
        if (fRoundVerticesToQuarterPixel)
        {
            round(&prev->fPoint);
        }
#endif
        for (Vertex* v = contour->fHead; v;)
        {
            v->fPoint.x = double_to_clamped_scalar((double)v->fPoint.x);
            v->fPoint.y = double_to_clamped_scalar((double)v->fPoint.y);
#if 0
            if (fRoundVerticesToQuarterPixel)
            {
                round(&v->fPoint);
            }
#endif
            Vertex* next = v->fNext;
            Vertex* nextWrap = next ? next : contour->fHead;
            if (coincident(prev->fPoint, v->fPoint))
            {
                TESS_LOG("vertex %g,%g coincident; removing\n",
                         v->fPoint.x,
                         v->fPoint.y);
                contour->remove(v);
            }
            else if (!is_finite(v->fPoint))
            {
                TESS_LOG("vertex %g,%g non-finite; removing\n",
                         v->fPoint.x,
                         v->fPoint.y);
                contour->remove(v);
            }
            else if (!fPreserveCollinearVertices &&
                     Line(prev->fPoint, nextWrap->fPoint).dist(v->fPoint) ==
                         0.0)
            {
                TESS_LOG("vertex %g,%g collinear; removing\n",
                         v->fPoint.x,
                         v->fPoint.y);
                contour->remove(v);
            }
            else
            {
                prev = v;
            }
            v = next;
        }
    }
}

bool GrTriangulator::mergeCoincidentVertices(VertexList* mesh,
                                             const Comparator& c) const
{
    if (!mesh->fHead)
    {
        return false;
    }
    bool merged = false;
    for (Vertex* v = mesh->fHead->fNext; v;)
    {
        Vertex* next = v->fNext;
        if (c.sweep_lt(v->fPoint, v->fPrev->fPoint))
        {
            v->fPoint = v->fPrev->fPoint;
        }
        if (coincident(v->fPrev->fPoint, v->fPoint))
        {
            this->mergeVertices(v, v->fPrev, mesh, c);
            merged = true;
        }
        v = next;
    }
    return merged;
}

// Stage 2: convert the contours to a mesh of edges connecting the vertices.

void GrTriangulator::buildEdges(VertexList* contours,
                                int contourCnt,
                                VertexList* mesh,
                                const Comparator& c)
{
    for (VertexList* contour = contours; contourCnt > 0;
         --contourCnt, ++contour)
    {
        Vertex* prev = contour->fTail;
        for (Vertex* v = contour->fHead; v;)
        {
            Vertex* next = v->fNext;
            this->makeConnectingEdge(prev, v, EdgeType::kInner, c);
            mesh->append(v);
            prev = v;
            v = next;
        }
    }
}

template <CompareFunc sweep_lt>
static void sorted_merge(VertexList* front,
                         VertexList* back,
                         VertexList* result)
{
    Vertex* a = front->fHead;
    Vertex* b = back->fHead;
    while (a && b)
    {
        if (sweep_lt(a->fPoint, b->fPoint))
        {
            front->remove(a);
            result->append(a);
            a = front->fHead;
        }
        else
        {
            back->remove(b);
            result->append(b);
            b = back->fHead;
        }
    }
    result->append(*front);
    result->append(*back);
}

void GrTriangulator::SortedMerge(VertexList* front,
                                 VertexList* back,
                                 VertexList* result,
                                 const Comparator& c)
{
    if (c.fDirection == Comparator::Direction::kHorizontal)
    {
        sorted_merge<sweep_lt_horiz>(front, back, result);
    }
    else
    {
        sorted_merge<sweep_lt_vert>(front, back, result);
    }
#if TRIANGULATOR_LOGGING
    float id = 0.0f;
    for (Vertex* v = result->fHead; v; v = v->fNext)
    {
        v->fID = id++;
    }
#endif
}

// Stage 3: sort the vertices by increasing sweep direction.

template <CompareFunc sweep_lt> static void merge_sort(VertexList* vertices)
{
    Vertex* slow = vertices->fHead;
    if (!slow)
    {
        return;
    }
    Vertex* fast = slow->fNext;
    if (!fast)
    {
        return;
    }
    do
    {
        fast = fast->fNext;
        if (fast)
        {
            fast = fast->fNext;
            slow = slow->fNext;
        }
    } while (fast);
    VertexList front(vertices->fHead, slow);
    VertexList back(slow->fNext, vertices->fTail);
    front.fTail->fNext = back.fHead->fPrev = nullptr;

    merge_sort<sweep_lt>(&front);
    merge_sort<sweep_lt>(&back);

    vertices->fHead = vertices->fTail = nullptr;
    sorted_merge<sweep_lt>(&front, &back, vertices);
}

#if TRIANGULATOR_LOGGING
void VertexList::dump() const
{
    for (Vertex* v = fHead; v; v = v->fNext)
    {
        TESS_LOG("vertex %g (%g, %g) alpha %d",
                 v->fID,
                 v->fPoint.x,
                 v->fPoint.y,
                 v->fAlpha);
        if (Vertex* p = v->fPartner)
        {
            TESS_LOG(", partner %g (%g, %g) alpha %d\n",
                     p->fID,
                     p->fPoint.x,
                     p->fPoint.y,
                     p->fAlpha);
        }
        else
        {
            TESS_LOG(", null partner\n");
        }
        for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove)
        {
            TESS_LOG("  edge %g -> %g, winding %d\n",
                     e->fTop->fID,
                     e->fBottom->fID,
                     e->fWinding);
        }
        for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow)
        {
            TESS_LOG("  edge %g -> %g, winding %d\n",
                     e->fTop->fID,
                     e->fBottom->fID,
                     e->fWinding);
        }
    }
}
#endif

#ifdef SK_DEBUG
static void validate_edge_pair(Edge* left, Edge* right, const Comparator& c)
{
    if (!left || !right)
    {
        return;
    }
    if (left->fTop == right->fTop)
    {
        assert(left->isLeftOf(*right->fBottom));
        assert(right->isRightOf(*left->fBottom));
    }
    else if (c.sweep_lt(left->fTop->fPoint, right->fTop->fPoint))
    {
        assert(left->isLeftOf(*right->fTop));
    }
    else
    {
        assert(right->isRightOf(*left->fTop));
    }
    if (left->fBottom == right->fBottom)
    {
        assert(left->isLeftOf(*right->fTop));
        assert(right->isRightOf(*left->fTop));
    }
    else if (c.sweep_lt(right->fBottom->fPoint, left->fBottom->fPoint))
    {
        assert(left->isLeftOf(*right->fBottom));
    }
    else
    {
        assert(right->isRightOf(*left->fBottom));
    }
}

static void validate_edge_list(EdgeList* edges, const Comparator& c)
{
    Edge* left = edges->fHead;
    if (!left)
    {
        return;
    }
    for (Edge* right = left->fRight; right; right = right->fRight)
    {
        validate_edge_pair(left, right, c);
        left = right;
    }
}
#endif

// Stage 4: Simplify the mesh by inserting new vertices at intersecting edges.

GrTriangulator::SimplifyResult GrTriangulator::simplify(VertexList* mesh,
                                                        const Comparator& c)
{
    TESS_LOG("simplifying complex polygons\n");

    int initialNumEdges = fNumEdges;
    int initialNumVertices = 0;
    for (Vertex* v = mesh->fHead; v != nullptr; v = v->fNext)
    {
        ++initialNumVertices;
    }
    int numSelfIntersections = 0;

    EdgeList activeEdges;
    auto result = SimplifyResult::kAlreadySimple;
    int numVisitedVertices = 0;
    for (Vertex* v = mesh->fHead; v != nullptr; v = v->fNext)
    {
        ++numVisitedVertices;
        if (!v->isConnected())
        {
            continue;
        }

        // The max increase across all skps, svgs and gms with only the
        // triangulating and SW path renderers enabled and with the
        // triangulator's maxVerbCount set to the Chrome value is 17x.
        if (fNumEdges > 170 * initialNumEdges)
        {
            return SimplifyResult::kFailed;
        }

        if (numVisitedVertices > 170 * initialNumVertices)
        {
            return SimplifyResult::kFailed;
        }

        Edge* leftEnclosingEdge;
        Edge* rightEnclosingEdge;
        bool restartChecks;
        do
        {
            TESS_LOG("\nvertex %g: (%g,%g), alpha %d\n",
                     v->fID,
                     v->fPoint.x,
                     v->fPoint.y,
                     v->fAlpha);
            restartChecks = false;
            FindEnclosingEdges(*v,
                               activeEdges,
                               &leftEnclosingEdge,
                               &rightEnclosingEdge);
            v->fLeftEnclosingEdge = leftEnclosingEdge;
            v->fRightEnclosingEdge = rightEnclosingEdge;
            if (v->fFirstEdgeBelow)
            {
                for (Edge* edge = v->fFirstEdgeBelow; edge;
                     edge = edge->fNextEdgeBelow)
                {
                    BoolFail l = this->checkForIntersection(leftEnclosingEdge,
                                                            edge,
                                                            &activeEdges,
                                                            &v,
                                                            mesh,
                                                            c);
                    if (l == BoolFail::kFail)
                    {
                        return SimplifyResult::kFailed;
                    }
                    if (l == BoolFail::kFalse)
                    {
                        BoolFail r =
                            this->checkForIntersection(edge,
                                                       rightEnclosingEdge,
                                                       &activeEdges,
                                                       &v,
                                                       mesh,
                                                       c);
                        if (r == BoolFail::kFail)
                        {
                            return SimplifyResult::kFailed;
                        }
                        if (r == BoolFail::kFalse)
                        {
                            // Neither l and r are both false.
                            continue;
                        }
                    }

                    // Either l or r are true.
                    result = SimplifyResult::kFoundSelfIntersection;
                    restartChecks = true;
                    ++numSelfIntersections;
                    break;
                } // for
            }
            else
            {
                BoolFail bf = this->checkForIntersection(leftEnclosingEdge,
                                                         rightEnclosingEdge,
                                                         &activeEdges,
                                                         &v,
                                                         mesh,
                                                         c);
                if (bf == BoolFail::kFail)
                {
                    return SimplifyResult::kFailed;
                }
                if (bf == BoolFail::kTrue)
                {
                    result = SimplifyResult::kFoundSelfIntersection;
                    restartChecks = true;
                    ++numSelfIntersections;
                }
            }

            // In pathological cases, a path can intersect itself millions of
            // times. After 500,000 self-intersections are found, reject the
            // path.
            if (numSelfIntersections > 500000)
            {
                return SimplifyResult::kFailed;
            }
        } while (restartChecks);
#ifdef SK_DEBUG
        validate_edge_list(&activeEdges, c);
#endif
        for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove)
        {
            if (!activeEdges.remove(e))
            {
                return SimplifyResult::kFailed;
            }
        }
        Edge* leftEdge = leftEnclosingEdge;
        for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow)
        {
            activeEdges.insert(e, leftEdge);
            leftEdge = e;
        }
    }
    assert(!activeEdges.fHead && !activeEdges.fTail);
    return result;
}

// Stage 5: Tessellate the simplified mesh into monotone polygons.

std::tuple<Poly*, bool> GrTriangulator::tessellate(const VertexList& vertices,
                                                   const Comparator&)
{
    TESS_LOG("\ntessellating simple polygons\n");
    EdgeList activeEdges;
    Poly* polys = nullptr;
    for (Vertex* v = vertices.fHead; v != nullptr; v = v->fNext)
    {
        if (!v->isConnected())
        {
            continue;
        }
#if TRIANGULATOR_LOGGING
        TESS_LOG("\nvertex %g: (%g,%g), alpha %d\n",
                 v->fID,
                 v->fPoint.x,
                 v->fPoint.y,
                 v->fAlpha);
#endif
        Edge* leftEnclosingEdge;
        Edge* rightEnclosingEdge;
        FindEnclosingEdges(*v,
                           activeEdges,
                           &leftEnclosingEdge,
                           &rightEnclosingEdge);
        Poly* leftPoly;
        Poly* rightPoly;
        if (v->fFirstEdgeAbove)
        {
            leftPoly = v->fFirstEdgeAbove->fLeftPoly;
            rightPoly = v->fLastEdgeAbove->fRightPoly;
        }
        else
        {
            leftPoly =
                leftEnclosingEdge ? leftEnclosingEdge->fRightPoly : nullptr;
            rightPoly =
                rightEnclosingEdge ? rightEnclosingEdge->fLeftPoly : nullptr;
        }
#if TRIANGULATOR_LOGGING
        TESS_LOG("edges above:\n");
        for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove)
        {
            TESS_LOG("%g -> %g, lpoly %d, rpoly %d\n",
                     e->fTop->fID,
                     e->fBottom->fID,
                     e->fLeftPoly ? e->fLeftPoly->fID : -1,
                     e->fRightPoly ? e->fRightPoly->fID : -1);
        }
        TESS_LOG("edges below:\n");
        for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow)
        {
            TESS_LOG("%g -> %g, lpoly %d, rpoly %d\n",
                     e->fTop->fID,
                     e->fBottom->fID,
                     e->fLeftPoly ? e->fLeftPoly->fID : -1,
                     e->fRightPoly ? e->fRightPoly->fID : -1);
        }
#endif
        if (v->fFirstEdgeAbove)
        {
            if (leftPoly)
            {
                leftPoly =
                    leftPoly->addEdge(v->fFirstEdgeAbove, Side::kRight, this);
            }
            if (rightPoly)
            {
                rightPoly =
                    rightPoly->addEdge(v->fLastEdgeAbove, Side::kLeft, this);
            }
            for (Edge* e = v->fFirstEdgeAbove; e != v->fLastEdgeAbove;
                 e = e->fNextEdgeAbove)
            {
                Edge* rightEdge = e->fNextEdgeAbove;
                activeEdges.remove(e);
                if (e->fRightPoly)
                {
                    e->fRightPoly->addEdge(e, Side::kLeft, this);
                }
                if (rightEdge->fLeftPoly &&
                    rightEdge->fLeftPoly != e->fRightPoly)
                {
                    rightEdge->fLeftPoly->addEdge(e, Side::kRight, this);
                }
            }
            activeEdges.remove(v->fLastEdgeAbove);
            if (!v->fFirstEdgeBelow)
            {
                if (leftPoly && rightPoly && leftPoly != rightPoly)
                {
                    assert(leftPoly->fPartner == nullptr &&
                           rightPoly->fPartner == nullptr);
                    rightPoly->fPartner = leftPoly;
                    leftPoly->fPartner = rightPoly;
                }
            }
        }
        if (v->fFirstEdgeBelow)
        {
            if (!v->fFirstEdgeAbove)
            {
                if (leftPoly && rightPoly)
                {
                    if (leftPoly == rightPoly)
                    {
                        if (leftPoly->fTail &&
                            leftPoly->fTail->fSide == Side::kLeft)
                        {
                            leftPoly = this->makePoly(&polys,
                                                      leftPoly->lastVertex(),
                                                      leftPoly->fWinding);
                            leftEnclosingEdge->fRightPoly = leftPoly;
                        }
                        else
                        {
                            rightPoly = this->makePoly(&polys,
                                                       rightPoly->lastVertex(),
                                                       rightPoly->fWinding);
                            rightEnclosingEdge->fLeftPoly = rightPoly;
                        }
                    }
                    Edge* join = this->allocateEdge(leftPoly->lastVertex(),
                                                    v,
                                                    1,
                                                    EdgeType::kInner);
                    leftPoly = leftPoly->addEdge(join, Side::kRight, this);
                    rightPoly = rightPoly->addEdge(join, Side::kLeft, this);
                }
            }
            Edge* leftEdge = v->fFirstEdgeBelow;
            leftEdge->fLeftPoly = leftPoly;
            activeEdges.insert(leftEdge, leftEnclosingEdge);
            for (Edge* rightEdge = leftEdge->fNextEdgeBelow; rightEdge;
                 rightEdge = rightEdge->fNextEdgeBelow)
            {
                activeEdges.insert(rightEdge, leftEdge);
                int winding =
                    leftEdge->fLeftPoly ? leftEdge->fLeftPoly->fWinding : 0;
                winding += leftEdge->fWinding;
                if (winding != 0)
                {
                    Poly* poly = this->makePoly(&polys, v, winding);
                    leftEdge->fRightPoly = rightEdge->fLeftPoly = poly;
                }
                leftEdge = rightEdge;
            }
            v->fLastEdgeBelow->fRightPoly = rightPoly;
        }
#if TRIANGULATOR_LOGGING
        TESS_LOG("\nactive edges:\n");
        for (Edge* e = activeEdges.fHead; e != nullptr; e = e->fRight)
        {
            TESS_LOG("%g -> %g, lpoly %d, rpoly %d\n",
                     e->fTop->fID,
                     e->fBottom->fID,
                     e->fLeftPoly ? e->fLeftPoly->fID : -1,
                     e->fRightPoly ? e->fRightPoly->fID : -1);
        }
#endif
    }
    return {polys, true};
}

// This is a driver function that calls stages 2-5 in turn.

void GrTriangulator::contoursToMesh(VertexList* contours,
                                    int contourCnt,
                                    VertexList* mesh,
                                    const Comparator& c)
{
#if TRIANGULATOR_LOGGING
    for (int i = 0; i < contourCnt; ++i)
    {
        Vertex* v = contours[i].fHead;
        assert(v);
        TESS_LOG("path.moveTo(%20.20g, %20.20g);\n", v->fPoint.x, v->fPoint.y);
        for (v = v->fNext; v; v = v->fNext)
        {
            TESS_LOG("path.lineTo(%20.20g, %20.20g);\n",
                     v->fPoint.x,
                     v->fPoint.y);
        }
    }
#endif
    this->sanitizeContours(contours, contourCnt);
    this->buildEdges(contours, contourCnt, mesh, c);
}

void GrTriangulator::SortMesh(VertexList* vertices, const Comparator& c)
{
    if (!vertices || !vertices->fHead)
    {
        return;
    }

    // Sort vertices in Y (secondarily in X).
    if (c.fDirection == Comparator::Direction::kHorizontal)
    {
        merge_sort<sweep_lt_horiz>(vertices);
    }
    else
    {
        merge_sort<sweep_lt_vert>(vertices);
    }
#if TRIANGULATOR_LOGGING
    for (Vertex* v = vertices->fHead; v != nullptr; v = v->fNext)
    {
        static float gID = 0.0f;
        v->fID = gID++;
    }
#endif
}

std::tuple<Poly*, bool> GrTriangulator::contoursToPolys(VertexList* contours,
                                                        int contourCnt)
{
    Comparator c(fDirection);
    VertexList mesh;
    this->contoursToMesh(contours, contourCnt, &mesh, c);
    TESS_LOG("\ninitial mesh:\n");
    DUMP_MESH(mesh);
    SortMesh(&mesh, c);
    TESS_LOG("\nsorted mesh:\n");
    DUMP_MESH(mesh);
    this->mergeCoincidentVertices(&mesh, c);
    TESS_LOG("\nsorted+merged mesh:\n");
    DUMP_MESH(mesh);
    auto result = this->simplify(&mesh, c);
    if (result == SimplifyResult::kFailed)
    {
        return {nullptr, false};
    }
    TESS_LOG("\nsimplified mesh:\n");
    DUMP_MESH(mesh);
    return this->tessellate(mesh, c);
}

// Stage 6: Triangulate the monotone polygons into a vertex buffer.
template <typename Sink>
size_t GrTriangulator::polysToTriangles(Poly* polys,
                                        FillRule overrideFillType,
                                        bool negateWinding,
                                        gpu::WindingFaces windingFaces,
                                        Sink* sink) const
{
    size_t vertexCount = 0;
    for (Poly* poly = polys; poly; poly = poly->fNext)
    {
        if (apply_fill_type(overrideFillType, poly))
        {
            vertexCount += emitPoly(poly, negateWinding, windingFaces, sink);
        }
    }
    return vertexCount;
}

static int get_contour_count(const RawPath& path, float tolerance)
{
    // We could theoretically be more aggressive about not counting empty
    // contours, but we need to actually match the exact number of contour
    // linked lists the tessellator will create later on.
    int contourCnt = 1;
    bool hasPoints = false;

    bool first = true;
    for (auto [verb, pts] : path)
    {
        switch (verb)
        {
            case PathVerb::move:
                if (!first)
                {
                    ++contourCnt;
                }
                [[fallthrough]];
            case PathVerb::line:
            case PathVerb::quad:
            case PathVerb::cubic:
                hasPoints = true;
                break;
            default:
                break;
        }
        first = false;
    }
    if (!hasPoints)
    {
        return 0;
    }
    return contourCnt;
}

std::tuple<Poly*, bool> GrTriangulator::pathToPolys(const RawPath& path,
                                                    float tolerance,
                                                    const AABB& clipBounds,
                                                    bool* isLinear)
{
    int contourCnt = get_contour_count(path, tolerance);
    if (contourCnt <= 0)
    {
        *isLinear = true;
        return {nullptr, true};
    }

#if 0
    if (SkPathFillType_IsInverse(fPath.getFillType()))
    {
        contourCnt++;
    }
#endif
    std::unique_ptr<VertexList[]> contours(new VertexList[contourCnt]);

    this->pathToContours(path, tolerance, clipBounds, contours.get(), isLinear);
    return this->contoursToPolys(contours.get(), contourCnt);
}

int64_t GrTriangulator::CountPoints(Poly* polys, FillRule overrideFillType)
{
    int64_t count = 0;
    for (Poly* poly = polys; poly; poly = poly->fNext)
    {
        if (apply_fill_type(overrideFillType, poly) && poly->fCount >= 3)
        {
            count += (poly->fCount - 2) * (TRIANGULATOR_WIREFRAME ? 6 : 3);
        }
    }
    return count;
}

// Stage 6: Triangulate the monotone polygons into a vertex buffer.

size_t GrTriangulator::countMaxTriangleVertices(Poly* polys,
                                                FillRule fillRule) const
{
    return math::lossless_numeric_cast<size_t>(CountPoints(polys, fillRule));
}

size_t GrTriangulator::polysToTriangles(
    Poly* polys,
    uint64_t maxVertexCount,
    FillRule fillRule,
    uint16_t pathID,
    bool reverseTriangles,
    bool negateWinding,
    gpu::WindingFaces windingFaces,
    gpu::WriteOnlyMappedMemory<gpu::TriangleVertex>* mappedMemory) const
{
    if (0 == maxVertexCount ||
        maxVertexCount > std::numeric_limits<int32_t>::max())
    {
        return 0;
    }

    // Emits triangulations into Rive's mapped triangle vertex buffer.
    class TriangleVertexBufferSink
    {
    public:
        TriangleVertexBufferSink(
            uint16_t pathID,
            bool reverseTriangles,
            gpu::WriteOnlyMappedMemory<gpu::TriangleVertex>* mappedMemory) :
            m_pathID(pathID),
            m_reverseTriangles(reverseTriangles),
            m_mappedMemory(mappedMemory)
        {}

        void emitTriangle(Vec2D a, Vec2D b, Vec2D c, int16_t riveWeight)
        {
            if (m_reverseTriangles)
            {
                std::swap(a, c);
            }
            m_mappedMemory->emplace_back(a, riveWeight, m_pathID);
            m_mappedMemory->emplace_back(b, riveWeight, m_pathID);
            m_mappedMemory->emplace_back(c, riveWeight, m_pathID);
        }

    private:
        const uint16_t m_pathID;
        const bool m_reverseTriangles;
        gpu::WriteOnlyMappedMemory<gpu::TriangleVertex>* const m_mappedMemory;
    };

    TriangleVertexBufferSink sink(pathID, reverseTriangles, mappedMemory);
    size_t actualCount =
        polysToTriangles(polys, fillRule, negateWinding, windingFaces, &sink);
    assert(actualCount <= maxVertexCount);
    return actualCount;
}

size_t GrTriangulator::polysToRetrofitCubicPatches(
    Poly* polys,
    FillRule fillRule,
    gpu::WindingFaces windingFaces,
    const RetrofitCubicPatchEmitter& emitPatch) const
{
    // Accumulates edge-adjacent, equally-wound triangles into 3-triangle strips
    // that we emit in patches instead of 1 at a time, roughly halving the patch
    // count.
    class BufferedTriStripSink
    {
    public:
        BufferedTriStripSink(const RetrofitCubicPatchEmitter& emitPatch) :
            m_emitPatch(emitPatch)
        {}

        void emitTriangle(Vec2D a, Vec2D b, Vec2D c, int16_t riveWeight)
        {
            if (a == b || a == c || b == c || riveWeight == 0)
            {
                return;
            }
            if (!tryMerge(a, b, c, riveWeight))
            {
                flush();
                reset(a, b, c, riveWeight);
            }
        }

        // Emits the buffered polygon (if any) as abs(weight) properly-wound
        // patches.
        void flush()
        {
            if (m_corners.size() != 0)
            {
                // The triangulator is designed to emit all triangles clockwise,
                // and rely on the "weight" attribute. Stencil relies on actual
                // triangle winding to know whether to increment or decrement,
                // so reverse negative-weight polygons.
                if (m_weight < 0)
                {
                    std::reverse(m_corners.begin(), m_corners.end());
                }

                // Convert the polygon vertices to strip ordering.
                // (Rotate the first 3 left by 1 position, yielding
                // {v1,v2,v0,v3,v4}).
                std::rotate(m_corners.begin(),
                            m_corners.begin() + 1,
                            m_corners.begin() + 3);

                // Stencil can't incr/decr by a variable amount, so emit
                // abs(m_weight) patches instead.
                size_t numPatches = std::abs(m_weight);
                for (size_t i = 0; i < numPatches; ++i)
                {
                    m_emitPatch(m_corners.data(), m_corners.size());
                }

                m_emittedPatchCount += numPatches;
                m_corners.clear();
            }
        }

        // Total patches emitted across all flushes.
        size_t emittedPatchCount() const { return m_emittedPatchCount; }

    private:
        // Start a fresh polygon from a single triangle.
        void reset(Vec2D a, Vec2D b, Vec2D c, int16_t weight)
        {
            m_corners.clear();
            m_corners.push_back(a);
            m_corners.push_back(b);
            m_corners.push_back(c);
            m_weight = weight;
        }

        // Merges a triangle if it fits in the patch, has the same winding, and
        // shares an edge with any side of the polygon.
        // Returns false if it can't, in which case the caller flushes and
        // starts a new polygon.
        bool tryMerge(Vec2D a, Vec2D b, Vec2D c, int16_t weight)
        {
            if (m_corners.size() == 0 || weight != m_weight ||
                m_corners.size() >= 5)
            {
                return false;
            }
            // Compare each triangle edge against each edge of the buffered
            // polygon, searching for a match.
            Vec2D tri[3] = {a, b, c};
            for (int e = 0; e < 3; ++e)
            {
                Vec2D e0 = tri[e], e1 = tri[(e + 1) % 3],
                      opp = tri[(e + 2) % 3];
                for (uint32_t i = 0; i < m_corners.size(); ++i)
                {
                    Vec2D c0 = m_corners[i];
                    Vec2D c1 = m_corners[i + 1 == m_corners.size() ? 0 : i + 1];
                    if (e0 == c1 && e1 == c0)
                    {
                        // Match! Insert opp between c0 and c1.
                        m_corners.insert(i + 1, opp);
                        return true;
                    }
                    else
                    {
                        // Not a match. Since the buffered triangles all wind in
                        // the same direction, and since the triangulator
                        // guarantees no overlap, a matching edge will always be
                        // (e0,e1)<->(c1,c0).
                        assert(e0 != c0 || e1 != c1);
                    }
                }
            }
            return false;
        }

        // Buffered polygon that we are attempting to emit as a strip of 3
        // triangles instead of a single one.
        StackVector<Vec2D, 5> m_corners;
        int16_t m_weight = 0;

        const RetrofitCubicPatchEmitter& m_emitPatch;
        size_t m_emittedPatchCount = 0;
    };

    BufferedTriStripSink sink(emitPatch);
    polysToTriangles(polys,
                     fillRule,
                     /*negateWinding=*/false,
                     windingFaces,
                     &sink);
    sink.flush(); // Flush the final buffered polygon (if any).
    return sink.emittedPatchCount();
}
} // namespace rive

#endif // SK_ENABLE_OPTIMIZE_SIZE
