/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/gpu/tessellate/GrStrokeGeometry.h"

#include "include/core/SkStrokeRec.h"
#include "include/private/SkNx.h"
#include "src/core/SkGeometry.h"
#include "src/core/SkMathPriv.h"

// This is the maximum distance in pixels that we can stray from the edge of a stroke when
// converting it to flat line segments.
static constexpr float kMaxErrorFromLinearization = 1/8.f;

static inline float length(const Sk2f& n) {
    Sk2f nn = n*n;
    return SkScalarSqrt(nn[0] + nn[1]);
}

static inline Sk2f normalize(const Sk2f& v) {
    Sk2f vv = v*v;
    vv += SkNx_shuffle<1,0>(vv);
    return v * vv.rsqrt();
}

static inline void transpose(const Sk2f& a, const Sk2f& b, Sk2f* X, Sk2f* Y) {
    float transpose[4];
    a.store(transpose);
    b.store(transpose+2);
    Sk2f::Load2(transpose, X, Y);
}

static inline void normalize2(const Sk2f& v0, const Sk2f& v1, SkPoint out[2]) {
    Sk2f X, Y;
    transpose(v0, v1, &X, &Y);
    Sk2f invlength = (X*X + Y*Y).rsqrt();
    Sk2f::Store2(out, Y * invlength, -X * invlength);
}

static inline float calc_curvature_costheta(const Sk2f& leftTan, const Sk2f& rightTan) {
    Sk2f X, Y;
    transpose(leftTan, rightTan, &X, &Y);
    Sk2f invlength = (X*X + Y*Y).rsqrt();
    Sk2f dotprod = leftTan * rightTan;
    return (dotprod[0] + dotprod[1]) * invlength[0] * invlength[1];
}

static GrStrokeGeometry::Verb join_verb_from_join(SkPaint::Join join) {
    using Verb = GrStrokeGeometry::Verb;
    switch (join) {
        case SkPaint::kBevel_Join:
            return Verb::kBevelJoin;
        case SkPaint::kMiter_Join:
            return Verb::kMiterJoin;
        case SkPaint::kRound_Join:
            return Verb::kRoundJoin;
    }
    SK_ABORT("Invalid SkPaint::Join.");
}

void GrStrokeGeometry::beginPath(const SkStrokeRec& stroke, float strokeDevWidth,
                                   InstanceTallies* tallies) {
    SkASSERT(!fInsideContour);
    // Client should have already converted the stroke to device space (i.e. width=1 for hairline).
    SkASSERT(strokeDevWidth > 0);

    fCurrStrokeRadius = strokeDevWidth/2;
    fCurrStrokeJoinVerb = join_verb_from_join(stroke.getJoin());
    fCurrStrokeCapType = stroke.getCap();
    fCurrStrokeTallies = tallies;

    if (Verb::kMiterJoin == fCurrStrokeJoinVerb) {
        // We implement miters by placing a triangle-shaped cap on top of a bevel join. Convert the
        // "miter limit" to how tall that triangle cap can be.
        float m = stroke.getMiter();
        fMiterMaxCapHeightOverWidth = .5f * SkScalarSqrt(m*m - 1);
    }

    // Find the angle of curvature where the arc height above a simple line from point A to point B
    // is equal to kMaxErrorFromLinearization.
    float r = std::max(1 - kMaxErrorFromLinearization / fCurrStrokeRadius, 0.f);
    fMaxCurvatureCosTheta = 2*r*r - 1;

    fCurrContourFirstPtIdx = -1;
    fCurrContourFirstNormalIdx = -1;

    fVerbs.push_back(Verb::kBeginPath);
}

void GrStrokeGeometry::moveTo(SkPoint pt) {
    SkASSERT(!fInsideContour);
    fCurrContourFirstPtIdx = fPoints.count();
    fCurrContourFirstNormalIdx = fNormals.count();
    fPoints.push_back(pt);
    SkDEBUGCODE(fInsideContour = true);
}

void GrStrokeGeometry::lineTo(SkPoint pt) {
    SkASSERT(fInsideContour);
    this->lineTo(fCurrStrokeJoinVerb, pt);
}

void GrStrokeGeometry::lineTo(Verb leftJoinVerb, SkPoint pt) {
    Sk2f tan = Sk2f::Load(&pt) - Sk2f::Load(&fPoints.back());
    if ((tan == 0).allTrue()) {
        return;
    }

    tan = normalize(tan);
    SkVector n = SkVector::Make(tan[1], -tan[0]);

    this->recordLeftJoinIfNotEmpty(leftJoinVerb, n);
    fNormals.push_back(n);

    this->recordStroke(Verb::kLinearStroke, 0);
    fPoints.push_back(pt);
}

void GrStrokeGeometry::quadraticTo(const SkPoint P[3]) {
    SkASSERT(fInsideContour);
    this->quadraticTo(fCurrStrokeJoinVerb, P, SkFindQuadMaxCurvature(P));
}

// Wang's formula for quadratics (1985) gives us the number of evenly spaced (in the parametric
// sense) line segments that are guaranteed to be within a distance of "kMaxErrorFromLinearization"
// from the actual curve.
static inline float wangs_formula_quadratic(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2) {
    static constexpr float k = 2 / (8 * kMaxErrorFromLinearization);
    float f = SkScalarSqrt(k * length(p2 - p1*2 + p0));
    return SkScalarCeilToInt(f);
}

void GrStrokeGeometry::quadraticTo(Verb leftJoinVerb, const SkPoint P[3], float maxCurvatureT) {
    Sk2f p0 = Sk2f::Load(P);
    Sk2f p1 = Sk2f::Load(P+1);
    Sk2f p2 = Sk2f::Load(P+2);

    Sk2f tan0 = p1 - p0;
    Sk2f tan1 = p2 - p1;

    // Snap to a "lineTo" if the control point is so close to an endpoint that FP error will become
    // an issue.
    if ((tan0.abs() < SK_ScalarNearlyZero).allTrue() ||  // p0 ~= p1
        (tan1.abs() < SK_ScalarNearlyZero).allTrue()) {  // p1 ~= p2
        this->lineTo(leftJoinVerb, P[2]);
        return;
    }

    SkPoint normals[2];
    normalize2(tan0, tan1, normals);

    // Decide how many flat line segments to chop the curve into.
    int numSegments = wangs_formula_quadratic(p0, p1, p2);
    numSegments = std::min(numSegments, 1 << kMaxNumLinearSegmentsLog2);
    if (numSegments <= 1) {
        this->rotateTo(leftJoinVerb, normals[0]);
        this->lineTo(Verb::kInternalRoundJoin, P[2]);
        this->rotateTo(Verb::kInternalRoundJoin, normals[1]);
        return;
    }

    // At + B gives a vector tangent to the quadratic.
    Sk2f A = p0 - p1*2 + p2;
    Sk2f B = p1 - p0;

    // Find a line segment that crosses max curvature.
    float segmentLength = SkScalarInvert(numSegments);
    float leftT = maxCurvatureT - segmentLength/2;
    float rightT = maxCurvatureT + segmentLength/2;
    Sk2f leftTan, rightTan;
    if (leftT <= 0) {
        leftT = 0;
        leftTan = tan0;
        rightT = segmentLength;
        rightTan = A*rightT + B;
    } else if (rightT >= 1) {
        leftT = 1 - segmentLength;
        leftTan = A*leftT + B;
        rightT = 1;
        rightTan = tan1;
    } else {
        leftTan = A*leftT + B;
        rightTan = A*rightT + B;
    }

    // Check if curvature is too strong for a triangle strip on the line segment that crosses max
    // curvature. If it is, we will chop and convert the segment to a "lineTo" with round joins.
    //
    // FIXME: This is quite costly and the vast majority of curves only have moderate curvature. We
    // would benefit significantly from a quick reject that detects curves that don't need special
    // treatment for strong curvature.
    bool isCurvatureTooStrong = calc_curvature_costheta(leftTan, rightTan) < fMaxCurvatureCosTheta;
    if (isCurvatureTooStrong) {
        SkPoint ptsBuffer[5];
        const SkPoint* currQuadratic = P;

        if (leftT > 0) {
            SkChopQuadAt(currQuadratic, ptsBuffer, leftT);
            this->quadraticTo(leftJoinVerb, ptsBuffer, /*maxCurvatureT=*/1);
            if (rightT < 1) {
                rightT = (rightT - leftT) / (1 - leftT);
            }
            currQuadratic = ptsBuffer + 2;
        } else {
            this->rotateTo(leftJoinVerb, normals[0]);
        }

        if (rightT < 1) {
            SkChopQuadAt(currQuadratic, ptsBuffer, rightT);
            this->lineTo(Verb::kInternalRoundJoin, ptsBuffer[2]);
            this->quadraticTo(Verb::kInternalRoundJoin, ptsBuffer + 2, /*maxCurvatureT=*/0);
        } else {
            this->lineTo(Verb::kInternalRoundJoin, currQuadratic[2]);
            this->rotateTo(Verb::kInternalRoundJoin, normals[1]);
        }
        return;
    }

    this->recordLeftJoinIfNotEmpty(leftJoinVerb, normals[0]);
    fNormals.push_back_n(2, normals);

    this->recordStroke(Verb::kQuadraticStroke, SkNextLog2(numSegments));
    p1.store(&fPoints.push_back());
    p2.store(&fPoints.push_back());
}

void GrStrokeGeometry::cubicTo(const SkPoint P[4]) {
    SkASSERT(fInsideContour);
    float roots[3];
    int numRoots = SkFindCubicMaxCurvature(P, roots);
    this->cubicTo(fCurrStrokeJoinVerb, P,
                  numRoots > 0 ? roots[numRoots/2] : 0,
                  numRoots > 1 ? roots[0] : kLeftMaxCurvatureNone,
                  numRoots > 2 ? roots[2] : kRightMaxCurvatureNone);
}

// Wang's formula for cubics (1985) gives us the number of evenly spaced (in the parametric sense)
// line segments that are guaranteed to be within a distance of "kMaxErrorFromLinearization"
// from the actual curve.
static inline float wangs_formula_cubic(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2,
                                        const Sk2f& p3) {
    static constexpr float k = (3 * 2) / (8 * kMaxErrorFromLinearization);
    float f = SkScalarSqrt(k * length(Sk2f::Max((p2 - p1*2 + p0).abs(),
                                                (p3 - p2*2 + p1).abs())));
    return SkScalarCeilToInt(f);
}

void GrStrokeGeometry::cubicTo(Verb leftJoinVerb, const SkPoint P[4], float maxCurvatureT,
                                 float leftMaxCurvatureT, float rightMaxCurvatureT) {
    Sk2f p0 = Sk2f::Load(P);
    Sk2f p1 = Sk2f::Load(P+1);
    Sk2f p2 = Sk2f::Load(P+2);
    Sk2f p3 = Sk2f::Load(P+3);

    Sk2f tan0 = p1 - p0;
    Sk2f tan1 = p3 - p2;

    // Snap control points to endpoints if they are so close that FP error will become an issue.
    if ((tan0.abs() < SK_ScalarNearlyZero).allTrue()) {  // p0 ~= p1
        p1 = p0;
        tan0 = p2 - p0;
        if ((tan0.abs() < SK_ScalarNearlyZero).allTrue()) {  // p0 ~= p1 ~= p2
            this->lineTo(leftJoinVerb, P[3]);
            return;
        }
    }
    if ((tan1.abs() < SK_ScalarNearlyZero).allTrue()) {  // p2 ~= p3
        p2 = p3;
        tan1 = p3 - p1;
        if ((tan1.abs() < SK_ScalarNearlyZero).allTrue() ||  // p1 ~= p2 ~= p3
            (p0 == p1).allTrue()) {  // p0 ~= p1 AND p2 ~= p3
            this->lineTo(leftJoinVerb, P[3]);
            return;
        }
    }

    SkPoint normals[2];
    normalize2(tan0, tan1, normals);

    // Decide how many flat line segments to chop the curve into.
    int numSegments = wangs_formula_cubic(p0, p1, p2, p3);
    numSegments = std::min(numSegments, 1 << kMaxNumLinearSegmentsLog2);
    if (numSegments <= 1) {
        this->rotateTo(leftJoinVerb, normals[0]);
        this->lineTo(leftJoinVerb, P[3]);
        this->rotateTo(Verb::kInternalRoundJoin, normals[1]);
        return;
    }

    // At^2 + Bt + C gives a vector tangent to the cubic. (More specifically, it's the derivative
    // minus an irrelevant scale by 3, since all we care about is the direction.)
    Sk2f A = p3 + (p1 - p2)*3 - p0;
    Sk2f B = (p0 - p1*2 + p2)*2;
    Sk2f C = p1 - p0;

    // Find a line segment that crosses max curvature.
    float segmentLength = SkScalarInvert(numSegments);
    float leftT = maxCurvatureT - segmentLength/2;
    float rightT = maxCurvatureT + segmentLength/2;
    Sk2f leftTan, rightTan;
    if (leftT <= 0) {
        leftT = 0;
        leftTan = tan0;
        rightT = segmentLength;
        rightTan = A*rightT*rightT + B*rightT + C;
    } else if (rightT >= 1) {
        leftT = 1 - segmentLength;
        leftTan = A*leftT*leftT + B*leftT + C;
        rightT = 1;
        rightTan = tan1;
    } else {
        leftTan = A*leftT*leftT + B*leftT + C;
        rightTan = A*rightT*rightT + B*rightT + C;
    }

    // Check if curvature is too strong for a triangle strip on the line segment that crosses max
    // curvature. If it is, we will chop and convert the segment to a "lineTo" with round joins.
    //
    // FIXME: This is quite costly and the vast majority of curves only have moderate curvature. We
    // would benefit significantly from a quick reject that detects curves that don't need special
    // treatment for strong curvature.
    bool isCurvatureTooStrong = calc_curvature_costheta(leftTan, rightTan) < fMaxCurvatureCosTheta;
    if (isCurvatureTooStrong) {
        SkPoint ptsBuffer[7];
        p0.store(ptsBuffer);
        p1.store(ptsBuffer + 1);
        p2.store(ptsBuffer + 2);
        p3.store(ptsBuffer + 3);
        const SkPoint* currCubic = ptsBuffer;

        if (leftT > 0) {
            SkChopCubicAt(currCubic, ptsBuffer, leftT);
            this->cubicTo(leftJoinVerb, ptsBuffer, /*maxCurvatureT=*/1,
                          (kLeftMaxCurvatureNone != leftMaxCurvatureT)
                                  ? leftMaxCurvatureT/leftT : kLeftMaxCurvatureNone,
                          kRightMaxCurvatureNone);
            if (rightT < 1) {
                rightT = (rightT - leftT) / (1 - leftT);
            }
            if (rightMaxCurvatureT < 1 && kRightMaxCurvatureNone != rightMaxCurvatureT) {
                rightMaxCurvatureT = (rightMaxCurvatureT - leftT) / (1 - leftT);
            }
            currCubic = ptsBuffer + 3;
        } else {
            this->rotateTo(leftJoinVerb, normals[0]);
        }

        if (rightT < 1) {
            SkChopCubicAt(currCubic, ptsBuffer, rightT);
            this->lineTo(Verb::kInternalRoundJoin, ptsBuffer[3]);
            currCubic = ptsBuffer + 3;
            this->cubicTo(Verb::kInternalRoundJoin, currCubic, /*maxCurvatureT=*/0,
                          kLeftMaxCurvatureNone, kRightMaxCurvatureNone);
        } else {
            this->lineTo(Verb::kInternalRoundJoin, currCubic[3]);
            this->rotateTo(Verb::kInternalRoundJoin, normals[1]);
        }
        return;
    }

    // Recurse and check the other two points of max curvature, if any.
    if (kRightMaxCurvatureNone != rightMaxCurvatureT) {
        this->cubicTo(leftJoinVerb, P, rightMaxCurvatureT, leftMaxCurvatureT,
                      kRightMaxCurvatureNone);
        return;
    }
    if (kLeftMaxCurvatureNone != leftMaxCurvatureT) {
        SkASSERT(kRightMaxCurvatureNone == rightMaxCurvatureT);
        this->cubicTo(leftJoinVerb, P, leftMaxCurvatureT, kLeftMaxCurvatureNone,
                      kRightMaxCurvatureNone);
        return;
    }

    this->recordLeftJoinIfNotEmpty(leftJoinVerb, normals[0]);
    fNormals.push_back_n(2, normals);

    this->recordStroke(Verb::kCubicStroke, SkNextLog2(numSegments));
    p1.store(&fPoints.push_back());
    p2.store(&fPoints.push_back());
    p3.store(&fPoints.push_back());
}

void GrStrokeGeometry::recordStroke(Verb verb, int numSegmentsLog2) {
    SkASSERT(Verb::kLinearStroke != verb || 0 == numSegmentsLog2);
    SkASSERT(numSegmentsLog2 <= kMaxNumLinearSegmentsLog2);
    fVerbs.push_back(verb);
    if (Verb::kLinearStroke != verb) {
        SkASSERT(numSegmentsLog2 > 0);
        fParams.push_back().fNumLinearSegmentsLog2 = numSegmentsLog2;
    }
    ++fCurrStrokeTallies->fStrokes[numSegmentsLog2];
}

void GrStrokeGeometry::rotateTo(Verb leftJoinVerb, SkVector normal) {
    this->recordLeftJoinIfNotEmpty(leftJoinVerb, normal);
    fNormals.push_back(normal);
}

void GrStrokeGeometry::recordLeftJoinIfNotEmpty(Verb joinVerb, SkVector nextNormal) {
    if (fNormals.count() <= fCurrContourFirstNormalIdx) {
        // The contour is empty. Nothing to join with.
        SkASSERT(fNormals.count() == fCurrContourFirstNormalIdx);
        return;
    }

    if (Verb::kBevelJoin == joinVerb) {
        this->recordBevelJoin(Verb::kBevelJoin);
        return;
    }

    Sk2f n0 = Sk2f::Load(&fNormals.back());
    Sk2f n1 = Sk2f::Load(&nextNormal);
    Sk2f base = n1 - n0;
    if ((base.abs() * fCurrStrokeRadius < kMaxErrorFromLinearization).allTrue()) {
        // Treat any join as a bevel when the outside corners of the two adjoining strokes are
        // close enough to each other. This is important because "miterCapHeightOverWidth" becomes
        // unstable when n0 and n1 are nearly equal.
        this->recordBevelJoin(joinVerb);
        return;
    }

    // We implement miters and round joins by placing a triangle-shaped cap on top of a bevel join.
    // (For round joins this triangle cap comprises the conic control points.) Find how tall to make
    // this triangle cap, relative to its width.
    //
    // NOTE: This value would be infinite at 180 degrees, but we clamp miterCapHeightOverWidth at
    // near-infinity. 180-degree round joins still look perfectly acceptable like this (though
    // technically not pure arcs).
    Sk2f cross = base * SkNx_shuffle<1,0>(n0);
    Sk2f dot = base * n0;
    float miterCapHeight = SkScalarAbs(dot[0] + dot[1]);
    float miterCapWidth = SkScalarAbs(cross[0] - cross[1]) * 2;

    if (Verb::kMiterJoin == joinVerb) {
        if (miterCapHeight > fMiterMaxCapHeightOverWidth * miterCapWidth) {
            // This join is tighter than the miter limit. Treat it as a bevel.
            this->recordBevelJoin(Verb::kMiterJoin);
            return;
        }
        this->recordMiterJoin(miterCapHeight / miterCapWidth);
        return;
    }

    SkASSERT(Verb::kRoundJoin == joinVerb || Verb::kInternalRoundJoin == joinVerb);

    // Conic arcs become unstable when they approach 180 degrees. When the conic control point
    // begins shooting off to infinity (i.e., height/width > 32), split the conic into two.
    static constexpr float kAlmost180Degrees = 32;
    if (miterCapHeight > kAlmost180Degrees * miterCapWidth) {
        Sk2f bisect = normalize(n0 - n1);
        this->rotateTo(joinVerb, SkVector::Make(-bisect[1], bisect[0]));
        this->recordLeftJoinIfNotEmpty(joinVerb, nextNormal);
        return;
    }

    float miterCapHeightOverWidth = miterCapHeight / miterCapWidth;

    // Find the heights of this round join's conic control point as well as the arc itself.
    Sk2f X, Y;
    transpose(base * base, n0 * n1, &X, &Y);
    Sk2f r = Sk2f::Max(X + Y + Sk2f(0, 1), 0.f).sqrt();
    Sk2f heights = SkNx_fma(r, Sk2f(miterCapHeightOverWidth, -SK_ScalarRoot2Over2), Sk2f(0, 1));
    float controlPointHeight = SkScalarAbs(heights[0]);
    float curveHeight = heights[1];
    if (curveHeight * fCurrStrokeRadius < kMaxErrorFromLinearization) {
        // Treat round joins as bevels when their curvature is nearly flat.
        this->recordBevelJoin(joinVerb);
        return;
    }

    float w = curveHeight / (controlPointHeight - curveHeight);
    this->recordRoundJoin(joinVerb, miterCapHeightOverWidth, w);
}

void GrStrokeGeometry::recordBevelJoin(Verb originalJoinVerb) {
    if (!IsInternalJoinVerb(originalJoinVerb)) {
        fVerbs.push_back(Verb::kBevelJoin);
        ++fCurrStrokeTallies->fTriangles;
    } else {
        fVerbs.push_back(Verb::kInternalBevelJoin);
        fCurrStrokeTallies->fTriangles += 2;
    }
}

void GrStrokeGeometry::recordMiterJoin(float miterCapHeightOverWidth) {
    fVerbs.push_back(Verb::kMiterJoin);
    fParams.push_back().fMiterCapHeightOverWidth = miterCapHeightOverWidth;
    fCurrStrokeTallies->fTriangles += 2;
}

void GrStrokeGeometry::recordRoundJoin(Verb joinVerb, float miterCapHeightOverWidth,
                                         float conicWeight) {
    fVerbs.push_back(joinVerb);
    fParams.push_back().fConicWeight = conicWeight;
    fParams.push_back().fMiterCapHeightOverWidth = miterCapHeightOverWidth;
    if (Verb::kRoundJoin == joinVerb) {
        ++fCurrStrokeTallies->fTriangles;
        ++fCurrStrokeTallies->fConics;
    } else {
        SkASSERT(Verb::kInternalRoundJoin == joinVerb);
        fCurrStrokeTallies->fTriangles += 2;
        fCurrStrokeTallies->fConics += 2;
    }
}

void GrStrokeGeometry::closeContour() {
    SkASSERT(fInsideContour);
    SkASSERT(fPoints.count() > fCurrContourFirstPtIdx);
    if (fPoints.back() != fPoints[fCurrContourFirstPtIdx]) {
        // Draw a line back to the beginning.
        this->lineTo(fCurrStrokeJoinVerb, fPoints[fCurrContourFirstPtIdx]);
    }
    if (fNormals.count() > fCurrContourFirstNormalIdx) {
        // Join the first and last lines.
        this->rotateTo(fCurrStrokeJoinVerb,fNormals[fCurrContourFirstNormalIdx]);
    } else {
        // This contour is empty. Add a bogus normal since the iterator always expects one.
        SkASSERT(fNormals.count() == fCurrContourFirstNormalIdx);
        fNormals.push_back({0, 0});
    }
    fVerbs.push_back(Verb::kEndContour);
    SkDEBUGCODE(fInsideContour = false);
}

void GrStrokeGeometry::capContourAndExit() {
    SkASSERT(fInsideContour);
    if (fCurrContourFirstNormalIdx >= fNormals.count()) {
        // This contour is empty. Add a normal in the direction that caps orient on empty geometry.
        SkASSERT(fNormals.count() == fCurrContourFirstNormalIdx);
        fNormals.push_back({1, 0});
    }

    this->recordCapsIfAny();
    fVerbs.push_back(Verb::kEndContour);

    SkDEBUGCODE(fInsideContour = false);
}

void GrStrokeGeometry::recordCapsIfAny() {
    SkASSERT(fInsideContour);
    SkASSERT(fCurrContourFirstNormalIdx < fNormals.count());

    if (SkPaint::kButt_Cap == fCurrStrokeCapType) {
        return;
    }

    Verb capVerb;
    if (SkPaint::kSquare_Cap == fCurrStrokeCapType) {
        if (fCurrStrokeRadius * SK_ScalarRoot2Over2 < kMaxErrorFromLinearization) {
            return;
        }
        capVerb = Verb::kSquareCap;
        fCurrStrokeTallies->fStrokes[0] += 2;
    } else {
        SkASSERT(SkPaint::kRound_Cap == fCurrStrokeCapType);
        if (fCurrStrokeRadius < kMaxErrorFromLinearization) {
            return;
        }
        capVerb = Verb::kRoundCap;
        fCurrStrokeTallies->fTriangles += 2;
        fCurrStrokeTallies->fConics += 4;
    }

    fVerbs.push_back(capVerb);
    fVerbs.push_back(Verb::kEndContour);

    fVerbs.push_back(capVerb);

    // Reserve the space first, since push_back() takes the point by reference and might
    // invalidate the reference if the array grows.
    fPoints.reserve(fPoints.count() + 1);
    fPoints.push_back(fPoints[fCurrContourFirstPtIdx]);

    // Reserve the space first, since push_back() takes the normal by reference and might
    // invalidate the reference if the array grows. (Although in this case we should be fine
    // since there is a negate operator.)
    fNormals.reserve(fNormals.count() + 1);
    fNormals.push_back(-fNormals[fCurrContourFirstNormalIdx]);
}
