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

#ifndef SkPathBuilder_DEFINED
#define SkPathBuilder_DEFINED

#include "include/core/SkMatrix.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathIter.h"
#include "include/core/SkPathTypes.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSpan.h"
#include "include/core/SkTypes.h"
#include "include/private/SkPathRef.h"
#include "include/private/SkTArray.h"

#include <cstdint>
#include <optional>
#include <tuple>

class SkPathData;
class SkRRect;
struct SkPathRaw;
class SkString;

// todo: add this flag to clients
#ifndef SK_SUPPORT_LEGACY_PATHBUILDER_SETLASTPT
#define SK_SUPPORT_LEGACY_PATHBUILDER_SETLASTPT
#endif

class SK_API SkPathBuilder {
    using PointsArray       = skia_private::STArray<32, SkPoint>;
    using VerbsArray        = skia_private::STArray<32, SkPathVerb>;
    using ConicWeightsArray = skia_private::STArray<16, float>;
public:
    /** Constructs an empty SkPathBuilder. By default, SkPathBuilder has no verbs, no SkPoint, and
        no weights. FillType is set to kWinding.

        @return  empty SkPathBuilder
    */
    SkPathBuilder();

    SkPathBuilder(const SkPathBuilder&);
    SkPathBuilder& operator=(const SkPathBuilder&);
    SkPathBuilder(SkPathBuilder&&);
    SkPathBuilder& operator=(SkPathBuilder&&);
    ~SkPathBuilder();

    /** Constructs an empty SkPathBuilder with the given FillType. By default, SkPathBuilder has no
        verbs, no SkPoint, and no weights.

        @param fillType  SkPathFillType to set on the SkPathBuilder.
        @return          empty SkPathBuilder
    */
    explicit SkPathBuilder(SkPathFillType fillType);

    /** Constructs an SkPathBuilder that is a copy of an existing SkPath.
        Copies the FillType and replays all of the verbs from the SkPath into the SkPathBuilder.

        @param path  SkPath to copy
        @return      SkPathBuilder
    */
    explicit SkPathBuilder(const SkPath& path);

    /** Sets an SkPathBuilder to be a copy of an existing SkPath.
        Copies the FillType and replays all of the verbs from the SkPath into the SkPathBuilder.

        @param path  SkPath to copy
        @return      SkPathBuilder
    */
    SkPathBuilder& operator=(const SkPath&);

    bool operator==(const SkPathBuilder&) const;
    bool operator!=(const SkPathBuilder& o) const { return !(*this == o); }

    /** Returns SkPathFillType, the rule used to fill SkPath.

        @return  current SkPathFillType setting
    */
    SkPathFillType fillType() const { return fFillType; }

    /** Returns minimum and maximum axes values of SkPoint array.
        Returns (0, 0, 0, 0) if SkPathBuilder contains no points.

        SkRect returned includes all SkPoint added to SkPathBuilder, including SkPoint associated
        with kMove_Verb that define empty contours.

        If any of the points are non-finite, returns {}.

        @return  bounds of all SkPoint in SkPoint array, or {}.
    */
    std::optional<SkRect> computeFiniteBounds() const;

    /** Like computeFiniteBounds() but returns a 'tight' bounds, meaning when there are curve
     *  segments, this computes the X/Y limits of the curve itself, not the curve's control
     *  point(s). For a polygon, this returns the same as computeFiniteBounds().
    */
    std::optional<SkRect> computeTightBounds() const;

    // DEPRECATED -- returns "empty" if the bounds are non-finite
    SkRect computeBounds() const {
        if (auto bounds = this->computeFiniteBounds()) {
            return *bounds;
        }
        return SkRect::MakeEmpty();
    }

    /** Returns an SkPath representing the current state of the SkPathBuilder. The builder is
        unchanged after returning the path.

        @param mx if present, applied to the points after they are copied into the resulting path.
        @return  SkPath representing the current state of the builder.
     */
    SkPath snapshot(const SkMatrix* mx = nullptr) const;

    /** Returns an SkPath representing the current state of the SkPathBuilder. The builder is
        reset to empty after returning the path.

        @param mx if present, applied to the points after they are copied into the resulting path.
        @return  SkPath representing the current state of the builder.
     */
    SkPath detach(const SkMatrix* mx = nullptr);

    sk_sp<SkPathData> snapshotData() const;
    sk_sp<SkPathData> detachData();

    /** Sets SkPathFillType, the rule used to fill SkPath. While there is no
        check that ft is legal, values outside of SkPathFillType are not supported.

        @param ft  SkPathFillType to be used by SKPaths generated from this builder.
        @return    reference to SkPathBuilder
    */
    SkPathBuilder& setFillType(SkPathFillType ft) { fFillType = ft; return *this; }

    /** Specifies whether SkPath is volatile; whether it will be altered or discarded
        by the caller after it is drawn. SkPath by default have volatile set false, allowing
        Skia to attach a cache of data which speeds repeated drawing.

        Mark temporary paths, discarded or modified after use, as volatile
        to inform Skia that the path need not be cached.

        Mark animating SkPath volatile to improve performance.
        Mark unchanging SkPath non-volatile to improve repeated rendering.

        raster surface SkPath draws are affected by volatile for some shadows.
        GPU surface SkPath draws are affected by volatile for some shadows and concave geometries.

        @param isVolatile  true if caller will alter SkPath after drawing
        @return            reference to SkPathBuilder
    */
    SkPathBuilder& setIsVolatile(bool isVolatile) { fIsVolatile = isVolatile; return *this; }

    /** Sets SkPathBuilder to its initial state.
        Removes verb array, SkPoint array, and weights, and sets FillType to kWinding.
        Internal storage associated with SkPathBuilder is preserved.

        @return  reference to SkPathBuilder
    */
    SkPathBuilder& reset();

    /** Specifies the beginning of contour. If the previous verb was a "move" verb,
     *  then this just replaces the point value of that move, otherwise it appends a new
     *  "move" verb to the builder using the point.
     *
     *  Thus, each contour can only have 1 move verb in it (the last one specified).
     */
    SkPathBuilder& moveTo(SkPoint point);

    SkPathBuilder& moveTo(SkScalar x, SkScalar y) {
        return this->moveTo(SkPoint::Make(x, y));
    }

    /** Adds line from last point to SkPoint p. If SkPathBuilder is empty, or last SkPath::Verb is
        kClose_Verb, last point is set to (0, 0) before adding line.

        lineTo() first appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.
        lineTo() then appends kLine_Verb to verb array and SkPoint p to SkPoint array.

        @param p  end SkPoint of added line
        @return   reference to SkPathBuilder
    */
    SkPathBuilder& lineTo(SkPoint pt);

    /** Adds line from last point to (x, y). If SkPathBuilder is empty, or last SkPath::Verb is
        kClose_Verb, last point is set to (0, 0) before adding line.

        lineTo() appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.
        lineTo() then appends kLine_Verb to verb array and (x, y) to SkPoint array.

        @param x  end of added line on x-axis
        @param y  end of added line on y-axis
        @return   reference to SkPathBuilder
    */
    SkPathBuilder& lineTo(SkScalar x, SkScalar y) { return this->lineTo(SkPoint::Make(x, y)); }

    /** Adds quad from last point towards SkPoint p1, to SkPoint p2.
        If SkPathBuilder is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
        before adding quad.

        Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
        then appends kQuad_Verb to verb array; and SkPoint p1, p2
        to SkPoint array.

        @param p1  control SkPoint of added quad
        @param p2  end SkPoint of added quad
        @return    reference to SkPathBuilder
    */
    SkPathBuilder& quadTo(SkPoint pt1, SkPoint pt2);

    /** Adds quad from last point towards (x1, y1), to (x2, y2).
        If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
        before adding quad.

        Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
        then appends kQuad_Verb to verb array; and (x1, y1), (x2, y2)
        to SkPoint array.

        @param x1  control SkPoint of quad on x-axis
        @param y1  control SkPoint of quad on y-axis
        @param x2  end SkPoint of quad on x-axis
        @param y2  end SkPoint of quad on y-axis
        @return    reference to SkPath

        example: https://fiddle.skia.org/c/@Path_quadTo
    */
    SkPathBuilder& quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
        return this->quadTo(SkPoint::Make(x1, y1), SkPoint::Make(x2, y2));
    }

    /** Adds quad from last point towards the first SkPoint in pts, to the second.
        If SkPathBuilder is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
        before adding quad.

        Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
        then appends kQuad_Verb to verb array; and the SkPoints to SkPoint array.

        @param pts  control point and endpoint of added quad.
        @return     reference to SkPathBuilder
    */
    SkPathBuilder& quadTo(const SkPoint pts[2]) { return this->quadTo(pts[0], pts[1]); }

    /** Adds conic from last point towards pt1, to pt2, weighted by w.
        If SkPathBuilder is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
        before adding conic.

        Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.

        If w is finite, positive, and not one, appends kConic_Verb to verb array;
        and pt1, pt2 to SkPoint array; and w to conic weights.

        If w is one, appends kQuad_Verb to verb array, and
        pt1, pt2 to SkPoint array.

        If w is zero, this is the same as lineTo(pt2)

        If w is not finite, appends kLine_Verb twice to verb array, and
        pt1, pt2 to SkPoint array.

        @param pt1  control SkPoint of conic
        @param pt2  end SkPoint of conic
        @param w   weight of added conic
        @return    reference to SkPathBuilder
    */
    SkPathBuilder& conicTo(SkPoint pt1, SkPoint pt2, SkScalar w);

    /** Adds conic from last point towards (x1, y1), to (x2, y2), weighted by w.
        If SkPathBuilder is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
        before adding conic.

        Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.

        If w is finite and not one, appends kConic_Verb to verb array;
        and (x1, y1), (x2, y2) to SkPoint array; and w to conic weights.

        If w is one, appends kQuad_Verb to verb array, and
        (x1, y1), (x2, y2) to SkPoint array.

        If w is not finite, appends kLine_Verb twice to verb array, and
        (x1, y1), (x2, y2) to SkPoint array.

        @param x1  control SkPoint of conic on x-axis
        @param y1  control SkPoint of conic on y-axis
        @param x2  end SkPoint of conic on x-axis
        @param y2  end SkPoint of conic on y-axis
        @param w   weight of added conic
        @return    reference to SkPathBuilder
    */
    SkPathBuilder& conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar w) {
        return this->conicTo(SkPoint::Make(x1, y1), SkPoint::Make(x2, y2), w);
    }

    /** Adds conic from last point towards SkPoint p1, to SkPoint p2, weighted by w.
        If SkPathBuilder is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
        before adding conic.

        Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.

        If w is finite and not one, appends kConic_Verb to verb array;
        and SkPoint p1, p2 to SkPoint array; and w to conic weights.

        If w is one, appends kQuad_Verb to verb array, and SkPoint p1, p2
        to SkPoint array.

        If w is not finite, appends kLine_Verb twice to verb array, and
        SkPoint p1, p2 to SkPoint array.

        @param p1  control SkPoint of added conic
        @param p2  end SkPoint of added conic
        @param w   weight of added conic
        @return    reference to SkPathBuilder
    */
    SkPathBuilder& conicTo(const SkPoint pts[2], SkScalar w) {
        return this->conicTo(pts[0], pts[1], w);
    }

    /** Adds cubic from last point towards SkPoint p1, then towards SkPoint p2, ending at
        SkPoint p3. If SkPathBuilder is empty, or last SkPath::Verb is kClose_Verb, last point is
        set to (0, 0) before adding cubic.

        Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
        then appends kCubic_Verb to verb array; and SkPoint p1, p2, p3
        to SkPoint array.

        @param p1  first control SkPoint of cubic
        @param p2  second control SkPoint of cubic
        @param p3  end SkPoint of cubic
        @return    reference to SkPathBuilder
    */
    SkPathBuilder& cubicTo(SkPoint pt1, SkPoint pt2, SkPoint pt3);

    /** Adds cubic from last point towards (x1, y1), then towards (x2, y2), ending at
        (x3, y3). If SkPathBuilder is empty, or last SkPath::Verb is kClose_Verb, last point is set
        to (0, 0) before adding cubic.

        Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
        then appends kCubic_Verb to verb array; and (x1, y1), (x2, y2), (x3, y3)
        to SkPoint array.

        @param x1  first control SkPoint of cubic on x-axis
        @param y1  first control SkPoint of cubic on y-axis
        @param x2  second control SkPoint of cubic on x-axis
        @param y2  second control SkPoint of cubic on y-axis
        @param x3  end SkPoint of cubic on x-axis
        @param y3  end SkPoint of cubic on y-axis
        @return    reference to SkPathBuilder
    */
    SkPathBuilder& cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3) {
        return this->cubicTo(SkPoint::Make(x1, y1), SkPoint::Make(x2, y2), SkPoint::Make(x3, y3));
    }

    /** Adds cubic from last point towards the first SkPoint, then towards the second, ending at
        the third. If SkPathBuilder is empty, or last SkPath::Verb is kClose_Verb, last point is
        set to (0, 0) before adding cubic.

        Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
        then appends kCubic_Verb to verb array; and SkPoint p1, p2, p3
        to SkPoint array.

        @param pts  first and second control SkPoints of cubic, and end SkPoint.
        @return     reference to SkPathBuilder
    */
    SkPathBuilder& cubicTo(const SkPoint pts[3]) {
        return this->cubicTo(pts[0], pts[1], pts[2]);
    }

    /** Appends kClose_Verb to SkPathBuilder. A closed contour connects the first and last SkPoint
        with line, forming a continuous loop. Open and closed contour draw the same
        with SkPaint::kFill_Style. With SkPaint::kStroke_Style, open contour draws
        SkPaint::Cap at contour start and end; closed contour draws
        SkPaint::Join at contour start and end.

        close() has no effect if SkPathBuilder is empty or last SkPath SkPath::Verb is kClose_Verb.

        @return  reference to SkPathBuilder
    */
    SkPathBuilder& close();

    /** Append a series of lineTo(...)

        @param pts    span of SkPoint
        @return reference to SkPathBuilder.
    */
    SkPathBuilder& polylineTo(SkSpan<const SkPoint> pts);

    // Relative versions of segments, relative to the previous position.

    /** Adds beginning of contour relative to last point.
        If SkPathBuilder is empty, starts contour at (dx, dy).
        Otherwise, start contour at last point offset by (dx, dy).
        Function name stands for "relative move to".

        @param pt  vector offset from last point to contour start
        @return    reference to SkPathBuilder

        example: https://fiddle.skia.org/c/@Path_rMoveTo
    */
    SkPathBuilder& rMoveTo(SkVector pt);

    /** Adds beginning of contour relative to last point.
        If SkPathBuilder is empty, starts contour at (dx, dy).
        Otherwise, start contour at last point offset by (dx, dy).
        Function name stands for "relative move to".

        @param dx  offset from last point to contour start on x-axis
        @param dy  offset from last point to contour start on y-axis
        @return    reference to SkPathBuilder

        example: https://fiddle.skia.org/c/@Path_rMoveTo
    */
    SkPathBuilder& rMoveTo(SkScalar dx, SkScalar dy) { return this->rMoveTo({dx, dy}); }

    /** Adds line from last point to vector given by pt. If SkPathBuilder is empty, or last
        SkPath::Verb is kClose_Verb, last point is set to (0, 0) before adding line.

        Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
        then appends kLine_Verb to verb array and line end to SkPoint array.
        Line end is last point plus vector given by pt.
        Function name stands for "relative line to".

        @param pt  vector offset from last point to line end
        @return    reference to SkPathBuilder
    */
    SkPathBuilder& rLineTo(SkVector pt);

    /** Adds line from last point to vector (dx, dy). If SkPathBuilder is empty, or last
        SkPath::Verb is kClose_Verb, last point is set to (0, 0) before adding line.

        Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
        then appends kLine_Verb to verb array and line end to SkPoint array.
        Line end is last point plus vector (dx, dy).
        Function name stands for "relative line to".

        @param dx  offset from last point to line end on x-axis
        @param dy  offset from last point to line end on y-axis
        @return    reference to SkPathBuilder
    */
    SkPathBuilder& rLineTo(SkScalar dx, SkScalar dy) { return this->rLineTo({dx, dy}); }

    /** Adds quad from last point towards vector pt1, to vector pt2.
        If SkPathBuilder is empty, or last SkPath::Verb
        is kClose_Verb, last point is set to (0, 0) before adding quad.

        Appends kMove_Verb to verb array and (0, 0) to SkPoint array,
        if needed; then appends kQuad_Verb to verb array; and appends quad
        control and quad end to SkPoint array.
        Quad control is last point plus vector pt1.
        Quad end is last point plus vector pt2.
        Function name stands for "relative quad to".

        @param pt1  offset vector from last point to quad control
        @param pt2  offset vector from last point to quad end
        @return     reference to SkPathBuilder
    */
    SkPathBuilder& rQuadTo(SkVector pt1, SkVector pt2);

    /** Adds quad from last point towards vector (dx1, dy1), to vector (dx2, dy2).
        If SkPathBuilder is empty, or last SkPath::Verb
        is kClose_Verb, last point is set to (0, 0) before adding quad.

        Appends kMove_Verb to verb array and (0, 0) to SkPoint array,
        if needed; then appends kQuad_Verb to verb array; and appends quad
        control and quad end to SkPoint array.
        Quad control is last point plus vector (dx1, dy1).
        Quad end is last point plus vector (dx2, dy2).
        Function name stands for "relative quad to".

        @param dx1  offset from last point to quad control on x-axis
        @param dy1  offset from last point to quad control on y-axis
        @param dx2  offset from last point to quad end on x-axis
        @param dy2  offset from last point to quad end on y-axis
        @return     reference to SkPathBuilder
    */
    SkPathBuilder& rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2) {
        return this->rQuadTo({dx1, dy1}, {dx2, dy2});
    }

    /** Adds conic from last point towards vector p1, to vector p2,
        weighted by w. If SkPathBuilder is empty, or last SkPath::Verb
        is kClose_Verb, last point is set to (0, 0) before adding conic.

        Appends kMove_Verb to verb array and (0, 0) to SkPoint array,
        if needed.

        If w is finite and not one, next appends kConic_Verb to verb array,
        and w is recorded as conic weight; otherwise, if w is one, appends
        kQuad_Verb to verb array; or if w is not finite, appends kLine_Verb
        twice to verb array.

        In all cases appends SkPoint control and end to SkPoint array.
        control is last point plus vector p1.
        end is last point plus vector p2.

        Function name stands for "relative conic to".

        @param p1  offset vector from last point to conic control
        @param p2  offset vector from last point to conic end
        @param w   weight of added conic
        @return    reference to SkPathBuilder
    */
    SkPathBuilder& rConicTo(SkVector p1, SkVector p2, SkScalar w);

    /** Adds conic from last point towards vector (dx1, dy1), to vector (dx2, dy2),
        weighted by w. If SkPathBuilder is empty, or last SkPath::Verb
        is kClose_Verb, last point is set to (0, 0) before adding conic.

        Appends kMove_Verb to verb array and (0, 0) to SkPoint array,
        if needed.

        If w is finite and not one, next appends kConic_Verb to verb array,
        and w is recorded as conic weight; otherwise, if w is one, appends
        kQuad_Verb to verb array; or if w is not finite, appends kLine_Verb
        twice to verb array.

        In all cases appends SkPoint control and end to SkPoint array.
        control is last point plus vector (dx1, dy1).
        end is last point plus vector (dx2, dy2).

        Function name stands for "relative conic to".

        @param dx1  offset from last point to conic control on x-axis
        @param dy1  offset from last point to conic control on y-axis
        @param dx2  offset from last point to conic end on x-axis
        @param dy2  offset from last point to conic end on y-axis
        @param w    weight of added conic
        @return     reference to SkPathBuilder
    */
    SkPathBuilder& rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2, SkScalar w) {
        return this->rConicTo({dx1, dy1}, {dx2, dy2}, w);
    }

    /** Adds cubic from last point towards vector pt1, then towards
        vector pt2, to vector pt3.
        If SkPathBuilder is empty, or last SkPath::Verb
        is kClose_Verb, last point is set to (0, 0) before adding cubic.

        Appends kMove_Verb to verb array and (0, 0) to SkPoint array,
        if needed; then appends kCubic_Verb to verb array; and appends cubic
        control and cubic end to SkPoint array.
        Cubic control is last point plus vector (dx1, dy1).
        Cubic end is last point plus vector (dx2, dy2).
        Function name stands for "relative cubic to".

        @param pt1  offset vector from last point to first cubic control
        @param pt2  offset vector from last point to second cubic control
        @param pt3  offset vector from last point to cubic end
        @return    reference to SkPathBuilder
    */
    SkPathBuilder& rCubicTo(SkVector pt1, SkVector pt2, SkVector pt3);

    /** Adds cubic from last point towards vector (dx1, dy1), then towards
        vector (dx2, dy2), to vector (dx3, dy3).
        If SkPathBuilder is empty, or last SkPath::Verb
        is kClose_Verb, last point is set to (0, 0) before adding cubic.

        Appends kMove_Verb to verb array and (0, 0) to SkPoint array,
        if needed; then appends kCubic_Verb to verb array; and appends cubic
        control and cubic end to SkPoint array.
        Cubic control is last point plus vector (dx1, dy1).
        Cubic end is last point plus vector (dx2, dy2).
        Function name stands for "relative cubic to".

        @param dx1  offset from last point to first cubic control on x-axis
        @param dy1  offset from last point to first cubic control on y-axis
        @param dx2  offset from last point to second cubic control on x-axis
        @param dy2  offset from last point to second cubic control on y-axis
        @param dx3  offset from last point to cubic end on x-axis
        @param dy3  offset from last point to cubic end on y-axis
        @return    reference to SkPathBuilder
    */
    SkPathBuilder& rCubicTo(SkScalar dx1, SkScalar dy1,
                            SkScalar dx2, SkScalar dy2,
                            SkScalar dx3, SkScalar dy3) {
        return this->rCubicTo({dx1, dy1}, {dx2, dy2}, {dx3, dy3});
    }

    // Arcs

    enum ArcSize {
        kSmall_ArcSize, //!< smaller of arc pair
        kLarge_ArcSize, //!< larger of arc pair
    };

    /** Appends arc to SkPathBuilder, relative to last SkPath SkPoint. Arc is implemented by one or
        more conic, weighted to describe part of oval with radii (rx, ry) rotated by
        xAxisRotate degrees. Arc curves from last SkPathBuilder SkPoint to relative end SkPoint:
        (dx, dy), choosing one of four possible routes: clockwise or
        counterclockwise, and smaller or larger. If SkPathBuilder is empty, the start arc SkPoint
        is (0, 0).

        Arc sweep is always less than 360 degrees. arcTo() appends line to end SkPoint
        if either radii are zero, or if last SkPath SkPoint equals end SkPoint.
        arcTo() scales radii (rx, ry) to fit last SkPath SkPoint and end SkPoint if both are
        greater than zero but too small to describe an arc.

        arcTo() appends up to four conic curves.
        arcTo() implements the functionality of svg arc, although SVG "sweep-flag" value is
        opposite the integer value of sweep; SVG "sweep-flag" uses 1 for clockwise, while
        kCW_Direction cast to int is zero.

        @param r            radii on axes before x-axis rotation
        @param xAxisRotate  x-axis rotation in degrees; positive values are clockwise
        @param largeArc     chooses smaller or larger arc
        @param sweep        chooses clockwise or counterclockwise arc
        @param dxdy         offset end of arc from last SkPath point
        @return             reference to SkPath
    */
    SkPathBuilder& rArcTo(SkPoint r, SkScalar xAxisRotate, ArcSize largeArc,
                          SkPathDirection sweep, SkVector dxdy);

    /** Appends arc to the builder. Arc added is part of ellipse
        bounded by oval, from startAngle through sweepAngle. Both startAngle and
        sweepAngle are measured in degrees, where zero degrees is aligned with the
        positive x-axis, and positive sweeps extends arc clockwise.

        arcTo() adds line connecting the builder's last point to initial arc point if forceMoveTo
        is false and the builder is not empty. Otherwise, added contour begins with first point
        of arc. Angles greater than -360 and less than 360 are treated modulo 360.

        @param oval          bounds of ellipse containing arc
        @param startAngleDeg starting angle of arc in degrees
        @param sweepAngleDeg sweep, in degrees. Positive is clockwise; treated modulo 360
        @param forceMoveTo   true to start a new contour with arc
        @return              reference to the builder
    */
    SkPathBuilder& arcTo(const SkRect& oval, SkScalar startAngleDeg, SkScalar sweepAngleDeg,
                         bool forceMoveTo);

    /** Appends arc to SkPath, after appending line if needed. Arc is implemented by conic
        weighted to describe part of circle. Arc is contained by tangent from
        last SkPath point to p1, and tangent from p1 to p2. Arc
        is part of circle sized to radius, positioned so it touches both tangent lines.

        If last SkPath SkPoint does not start arc, arcTo() appends connecting line to SkPath.
        The length of vector from p1 to p2 does not affect arc.

        Arc sweep is always less than 180 degrees. If radius is zero, or if
        tangents are nearly parallel, arcTo() appends line from last SkPath SkPoint to p1.

        arcTo() appends at most one line and one conic.
        arcTo() implements the functionality of PostScript arct and HTML Canvas arcTo.

        @param p1      SkPoint common to pair of tangents
        @param p2      end of second tangent
        @param radius  distance from arc to circle center
        @return        reference to SkPath
    */
    SkPathBuilder& arcTo(SkPoint p1, SkPoint p2, SkScalar radius);

    /** Appends arc to SkPath. Arc is implemented by one or more conic weighted to describe
        part of oval with radii (r.fX, r.fY) rotated by xAxisRotate degrees. Arc curves
        from last SkPath SkPoint to (xy.fX, xy.fY), choosing one of four possible routes:
        clockwise or counterclockwise,
        and smaller or larger.

        Arc sweep is always less than 360 degrees. arcTo() appends line to xy if either
        radii are zero, or if last SkPath SkPoint equals (xy.fX, xy.fY). arcTo() scales radii r to
        fit last SkPath SkPoint and xy if both are greater than zero but too small to describe
        an arc.

        arcTo() appends up to four conic curves.
        arcTo() implements the functionality of SVG arc, although SVG sweep-flag value is
        opposite the integer value of sweep; SVG sweep-flag uses 1 for clockwise, while
        kCW_Direction cast to int is zero.

        @param r            radii on axes before x-axis rotation
        @param xAxisRotate  x-axis rotation in degrees; positive values are clockwise
        @param largeArc     chooses smaller or larger arc
        @param sweep        chooses clockwise or counterclockwise arc
        @param xy           end of arc
        @return             reference to SkPath
    */
    SkPathBuilder& arcTo(SkPoint r, SkScalar xAxisRotate, ArcSize largeArc, SkPathDirection sweep,
                         SkPoint xy);

    /** Appends arc to the builder, as the start of new contour. Arc added is part of ellipse
        bounded by oval, from startAngle through sweepAngle. Both startAngle and
        sweepAngle are measured in degrees, where zero degrees is aligned with the
        positive x-axis, and positive sweeps extends arc clockwise.

        If sweepAngle <= -360, or sweepAngle >= 360; and startAngle modulo 90 is nearly
        zero, append oval instead of arc. Otherwise, sweepAngle values are treated
        modulo 360, and arc may or may not draw depending on numeric rounding.

        @param oval          bounds of ellipse containing arc
        @param startAngleDeg starting angle of arc in degrees
        @param sweepAngleDeg sweep, in degrees. Positive is clockwise; treated modulo 360
        @return              reference to this builder
    */
    SkPathBuilder& addArc(const SkRect& oval, SkScalar startAngleDeg, SkScalar sweepAngleDeg);

    SkPathBuilder& addLine(SkPoint a, SkPoint b) {
        return this->moveTo(a).lineTo(b);
    }

    /** Adds a new contour to the SkPathBuilder, defined by the rect, and wound in the
        specified direction. The verbs added to the path will be:

        kMove, kLine, kLine, kLine, kClose

        start specifies which corner to begin the contour:
            0: upper-left  corner
            1: upper-right corner
            2: lower-right corner
            3: lower-left  corner

        This start point also acts as the implied beginning of the subsequent,
        contour, if it does not have an explicit moveTo(). e.g.

            path.addRect(...)
            // if we don't say moveTo() here, we will use the rect's start point
            path.lineTo(...)

        @param rect   SkRect to add as a closed contour
        @param dir    SkPath::Direction to orient the new contour
        @param start  initial corner of SkRect to add
        @return       reference to SkPathBuilder
     */
    SkPathBuilder& addRect(const SkRect&, SkPathDirection, unsigned startIndex);

    /** Adds a new contour to the SkPathBuilder, defined by the rect, and wound in the
        specified direction. The verbs added to the path will be:

        kMove, kLine, kLine, kLine, kClose

        The contour starts at the upper-left corner of the rect, which also acts as the implied
        beginning of the subsequent contour, if it does not have an explicit moveTo(). e.g.

            path.addRect(...)
            // if we don't say moveTo() here, we will use the rect's upper-left corner
            path.lineTo(...)

        @param rect   SkRect to add as a closed contour
        @param dir    SkPath::Direction to orient the new contour
        @return       reference to SkPathBuilder
     */
    SkPathBuilder& addRect(const SkRect& rect, SkPathDirection dir = SkPathDirection::kDefault) {
        return this->addRect(rect, dir, 0);
    }

    /** Adds oval to SkPathBuilder, appending kMove_Verb, four kConic_Verb, and kClose_Verb.
        Oval is upright ellipse bounded by SkRect oval with radii equal to half oval width
        and half oval height. Oval begins at (oval.fRight, oval.centerY()) and continues
        clockwise if dir is kCW_Direction, counterclockwise if dir is kCCW_Direction.

        @param oval  bounds of ellipse added
        @param dir   SkPath::Direction to wind ellipse
        @return      reference to SkPathBuilder
    */
    SkPathBuilder& addOval(const SkRect&, SkPathDirection, unsigned startIndex);

    /** Appends SkRRect to SkPathBuilder, creating a new closed contour. If dir is kCW_Direction,
        SkRRect winds clockwise. If dir is kCCW_Direction, SkRRect winds counterclockwise.

        After appending, SkPathBuilder may be empty, or may contain: SkRect, oval, or SkRRect.

        @param rrect  SkRRect to add
        @param dir    SkPath::Direction to wind SkRRect
        @param start  index of initial point of SkRRect
        @return       reference to SkPathBuilder
    */
    SkPathBuilder& addRRect(const SkRRect& rrect, SkPathDirection, unsigned start);

    /** Appends SkRRect to SkPathBuilder, creating a new closed contour. If dir is kCW_Direction,
        SkRRect starts at top-left of the lower-left corner and winds clockwise. If dir is
        kCCW_Direction, SkRRect starts at the bottom-left of the upper-left corner and winds
        counterclockwise.

        After appending, SkPathBuilder may be empty, or may contain: SkRect, oval, or SkRRect.

        @param rrect  SkRRect to add
        @param dir    SkPath::Direction to wind SkRRect
        @return       reference to SkPathBuilder
    */
    SkPathBuilder& addRRect(const SkRRect& rrect, SkPathDirection dir = SkPathDirection::kDefault) {
        // legacy start indices: 6 (CW) and 7 (CCW)
        return this->addRRect(rrect, dir, dir == SkPathDirection::kCW ? 6 : 7);
    }

    /** Adds oval to SkPathBuilder, appending kMove_Verb, four kConic_Verb, and kClose_Verb.
        Oval is upright ellipse bounded by SkRect oval with radii equal to half oval width
        and half oval height. Oval begins at start and continues
        clockwise if dir is kCW_Direction, counterclockwise if dir is kCCW_Direction.

        @param oval   bounds of ellipse added
        @param dir    SkPath::Direction to wind ellipse
        @return       reference to SkPath

        example: https://fiddle.skia.org/c/@Path_addOval_2
    */
    SkPathBuilder& addOval(const SkRect& oval, SkPathDirection dir = SkPathDirection::kDefault) {
        // legacy start index: 1
        return this->addOval(oval, dir, 1);
    }

    /** Adds circle with center and radius to SkPathBuilder, appending kMove_Verb,
        four kConic_Verb, and kClose_Verb. Circle begins at: (center.fX + radius, center.fY).

        Has no effect if radius is zero or negative.

        @param center  center of circle
        @param radius  distance from center to edge
        @param dir     SkPath::Direction to wind circle
        @return        reference to SkPathBuilder
    */
    SkPathBuilder& addCircle(SkPoint center, float radius,
                             SkPathDirection dir = SkPathDirection::kDefault);
    SkPathBuilder& addCircle(float x, float y, float radius,
                             SkPathDirection dir = SkPathDirection::kDefault) {
        return this->addCircle({x, y}, radius, dir);
    }

    /** Adds contour created from line array, adding (pts.size() - 1) line segments.
        Contour added starts at pts[0], then adds a line for every additional SkPoint
        in pts array. If close is true, appends kClose_Verb to SkPath, connecting
        pts[count - 1] and pts[0].

        @param pts    array of line sharing end and start SkPoint
        @param close  true to add line connecting contour end and start
        @return       reference to SkPath
    */
    SkPathBuilder& addPolygon(SkSpan<const SkPoint> pts, bool close);

    /** Appends src to SkPathBuilder, offset by (dx, dy).

        If mode is kAppend_AddPathMode, src verb array, SkPoint array, and conic weights are
        added unaltered. If mode is kExtend_AddPathMode, add line before appending
        verbs, SkPoint, and conic weights.

        @param src   SkPath verbs, SkPoint, and conic weights to add
        @param dx    offset added to src SkPoint array x-axis coordinates
        @param dy    offset added to src SkPoint array y-axis coordinates
        @param mode  kAppend_AddPathMode or kExtend_AddPathMode
        @return      reference to SkPathBuilder
    */
    SkPathBuilder& addPath(const SkPath& src, SkScalar dx, SkScalar dy,
                           SkPath::AddPathMode mode = SkPath::kAppend_AddPathMode);

    /** Appends src to SkPathBuilder.

        If mode is kAppend_AddPathMode, src verb array, SkPoint array, and conic weights are
        added unaltered. If mode is kExtend_AddPathMode, add line before appending
        verbs, SkPoint, and conic weights.

        @param src   SkPath verbs, SkPoint, and conic weights to add
        @param mode  kAppend_AddPathMode or kExtend_AddPathMode
        @return      reference to SkPathBuilder
    */
    SkPathBuilder& addPath(const SkPath& src,
                           SkPath::AddPathMode mode = SkPath::kAppend_AddPathMode) {
        return this->addPath(src, SkMatrix::I(), mode);
    }

    /** Appends src to SkPathBuilder, transformed by matrix. Transformed curves may have different
        verbs, SkPoint, and conic weights.

        If mode is kAppend_AddPathMode, src verb array, SkPoint array, and conic weights are
        added unaltered. If mode is kExtend_AddPathMode, add line before appending
        verbs, SkPoint, and conic weights.

        @param src     SkPath verbs, SkPoint, and conic weights to add
        @param matrix  transform applied to src
        @param mode    kAppend_AddPathMode or kExtend_AddPathMode
        @return        reference to SkPathBuilder
    */
    SkPathBuilder& addPath(const SkPath& src, const SkMatrix& matrix,
                           SkPath::AddPathMode mode = SkPath::AddPathMode::kAppend_AddPathMode);

    // Performance hint, to reserve extra storage for subsequent calls to lineTo, quadTo, etc.

    /** Grows SkPathBuilder verb array and SkPoint array to contain additional space.
        May improve performance and use less memory by
        reducing the number and size of allocations when creating SkPathBuilder.

        @param extraPtCount     number of additional SkPoint to allocate
        @param extraVerbCount   number of additional verbs
        @param extraConicCount  number of additional conic weights
    */
    void incReserve(int extraPtCount, int extraVerbCount, int extraConicCount);

    /** Grows SkPathBuilder verb array and SkPoint array to contain additional space.
        May improve performance and use less memory by
        reducing the number and size of allocations when creating SkPathBuilder.

        @param extraPtCount    number of additional SkPoints and verbs to allocate
    */
    void incReserve(int extraPtCount) {
        this->incReserve(extraPtCount, extraPtCount, 0);
    }

    /** Offsets SkPoint array by (dx, dy).

        @param dx   offset added to SkPoint array x-axis coordinates
        @param dy   offset added to SkPoint array y-axis coordinates
    */
    SkPathBuilder& offset(SkScalar dx, SkScalar dy);

    /** Transforms verb array, SkPoint array, and weight by matrix.
        transform may change verbs and increase their number.

        @param matrix  SkMatrix to apply to SkPath
        @param pc      whether to apply perspective clipping
    */
    SkPathBuilder& transform(const SkMatrix& matrix);

    /*
     *  Returns true if the builder is empty, or all of its points are finite.
     */
    bool isFinite() const;

    /** Replaces SkPathFillType with its inverse. The inverse of SkPathFillType describes the area
        unmodified by the original SkPathFillType.
    */
    SkPathBuilder& toggleInverseFillType() {
        fFillType = SkPathFillType_ToggleInverse(fFillType);
        return *this;
    }

    /** Returns if SkPath is empty.
        Empty SkPathBuilder may have FillType but has no SkPoint, SkPath::Verb, or conic weight.
        SkPathBuilder() constructs empty SkPathBuilder; reset() and rewind() make SkPath empty.

        @return  true if the path contains no SkPath::Verb array
    */
    bool isEmpty() const { return fVerbs.empty(); }

    /** Returns last point on SkPathBuilder. Returns nullopt if SkPoint array is empty.

        @return  last SkPoint if SkPoint array contains one or more SkPoint, otherwise nullopt

        example: https://fiddle.skia.org/c/@Path_getLastPt
    */
    std::optional<SkPoint> getLastPt() const;

    /** Change the point at the specified index (see countPoints()).
     *  If index is out of range, the call does nothing.
     *
     *  @param index which point to replace
     *  @param p the new point value
     */
    void setPoint(size_t index, SkPoint p);

    /** Change the last point in the builder.
     *  If the builder is empty, the call does nothing.
     *
     *  @param p the new point value
     */
    void setLastPoint(SkPoint p) {
        this->setPoint(this->points().size() - 1, p);
    }

#ifdef SK_SUPPORT_LEGACY_PATHBUILDER_SETLASTPT
    /** DEPRECATED: use setLastPoint() or setPoint()
        Sets the last point on the path. If SkPoint array is empty, this behaves like moveTo().

        @param pt the new value for the last point in the path
    */
    void setLastPt(SkPoint pt);
    void setLastPt(float x, float y) { this->setLastPt({x, y}); }
#endif

    /** Returns the number of points in SkPathBuilder.
        SkPoint count is initially zero.

        @return  SkPathBuilder SkPoint array length
    */
    int countPoints() const { return fPts.size(); }

    /** Returns if SkPathFillType describes area outside SkPath geometry. The inverse fill area
        extends indefinitely.

        @return  true if FillType is kInverseWinding or kInverseEvenOdd
    */
    bool isInverseFillType() const { return SkPathFillType_IsInverse(fFillType); }

    SkSpan<const SkPoint> points() const {
        return fPts;
    }
    SkSpan<const SkPathVerb> verbs() const {
        return fVerbs;
    }
    SkSpan<const float> conicWeights() const {
        return fConicWeights;
    }

    enum class Reserve {
        // Reserves the exact amount of storage needed for pathraw (never overallocates).
        kExact,
        // Allows the storage buffers to overallocate, based on their internal growth policy.
        kGrow
    };
    SkPathBuilder& addRaw(const SkPathRaw&, Reserve);

    SkPathIter iter() const;

    enum class DumpFormat {
        kDecimal,
        kHex,
    };
    SkString dumpToString(DumpFormat = DumpFormat::kDecimal) const;
    void dump(DumpFormat) const;
    // can't use default argument easily in debugger, so we name this
    // helper explicitly.
    void dump() const { this->dump(DumpFormat::kDecimal); }

    bool contains(SkPoint) const;

private:
    PointsArray fPts;
    VerbsArray fVerbs;
    ConicWeightsArray fConicWeights;

    SkPathFillType  fFillType;
    bool            fIsVolatile;
    SkPathConvexity fConvexity;

    unsigned    fSegmentMask;
    int         fLastMoveIndex; // only needed until SkPath is immutable

    SkPathIsAType fType = SkPathIsAType::kGeneral;
    SkPathIsAData fIsA {};

    // called right before we add a (non-move) verb
    void ensureMove() {
        fType = SkPathIsAType::kGeneral;
        if (fVerbs.empty()) {
            this->moveTo({0, 0});
        } else if (fVerbs.back() == SkPathVerb::kClose) {
            this->moveTo(fPts[fLastMoveIndex]);
        }
    }

    bool isZeroLengthSincePoint(int startPtIndex) const;

    SkPathBuilder& privateReverseAddPath(const SkPath&);
    SkPathBuilder& privateReversePathTo(const SkPath&);

    std::tuple<SkPoint*, SkScalar*> growForVerbsInPath(const SkPath& path);

    friend class SkPathPriv;
    friend class SkStroke;
    friend class SkPathStroker;
};

#endif

