/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkPath_DEFINED
#define SkPath_DEFINED

#include "SkMatrix.h"
#include "SkPathRef.h"
#include "SkRefCnt.h"

class SkReader32;
class SkWriter32;
class SkAutoPathBoundsUpdate;
class SkString;
class SkRRect;
class SkWStream;

/** \class SkPath

    The SkPath class encapsulates compound (multiple contour) geometric paths
    consisting of straight line segments, quadratic curves, and cubic curves.
*/
class SK_API SkPath {
public:
    SkPath();
    SkPath(const SkPath&);
    ~SkPath();

    SkPath& operator=(const SkPath&);
    friend  SK_API bool operator==(const SkPath&, const SkPath&);
    friend bool operator!=(const SkPath& a, const SkPath& b) {
        return !(a == b);
    }

    /** Return true if the paths contain an equal array of verbs and weights. Paths
     *  with equal verb counts can be readily interpolated. If the paths contain one
     *  or more conics, the conics' weights must also match.
     *
     *  @param compare  The path to compare.
     *
     *  @return true if the paths have the same verbs and weights.
     */
    bool isInterpolatable(const SkPath& compare) const;

    /** Interpolate between two paths with same-sized point arrays.
     *  The out path contains the verbs and weights of this path.
     *  The out points are a weighted average of this path and the ending path. 
     *
     *  @param ending  The path to interpolate between.
     *  @param weight  The weight, from 0 to 1. The output points are set to
     *                 (this->points * weight) + ending->points * (1 - weight).
     *  @return true if the paths could be interpolated.
     */
    bool interpolate(const SkPath& ending, SkScalar weight, SkPath* out) const;

#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
    /** Returns true if the caller is the only owner of the underlying path data */
    bool unique() const { return fPathRef->unique(); }
#endif

    enum FillType {
        /** Specifies that "inside" is computed by a non-zero sum of signed
            edge crossings
        */
        kWinding_FillType,
        /** Specifies that "inside" is computed by an odd number of edge
            crossings
        */
        kEvenOdd_FillType,
        /** Same as Winding, but draws outside of the path, rather than inside
        */
        kInverseWinding_FillType,
        /** Same as EvenOdd, but draws outside of the path, rather than inside
         */
        kInverseEvenOdd_FillType
    };

    /** Return the path's fill type. This is used to define how "inside" is
        computed. The default value is kWinding_FillType.

        @return the path's fill type
    */
    FillType getFillType() const { return (FillType)fFillType; }

    /** Set the path's fill type. This is used to define how "inside" is
        computed. The default value is kWinding_FillType.

        @param ft The new fill type for this path
    */
    void setFillType(FillType ft) {
        fFillType = SkToU8(ft);
    }

    /** Returns true if the filltype is one of the Inverse variants */
    bool isInverseFillType() const { return IsInverseFillType((FillType)fFillType); }

    /**
     *  Toggle between inverse and normal filltypes. This reverse the return
     *  value of isInverseFillType()
     */
    void toggleInverseFillType() {
        fFillType ^= 2;
    }

    enum Convexity {
        kUnknown_Convexity,
        kConvex_Convexity,
        kConcave_Convexity
    };

    /**
     *  Return the path's convexity, as stored in the path. If it is currently unknown,
     *  then this function will attempt to compute the convexity (and cache the result).
     */
    Convexity getConvexity() const {
        if (kUnknown_Convexity != fConvexity) {
            return static_cast<Convexity>(fConvexity);
        } else {
            return this->internalGetConvexity();
        }
    }

    /**
     *  Return the currently cached value for convexity, even if that is set to
     *  kUnknown_Convexity. Note: getConvexity() will automatically call
     *  ComputeConvexity and cache its return value if the current setting is
     *  kUnknown.
     */
    Convexity getConvexityOrUnknown() const { return (Convexity)fConvexity; }

    /**
     *  Store a convexity setting in the path. There is no automatic check to
     *  see if this value actually agrees with the return value that would be
     *  computed by getConvexity().
     *
     *  Note: even if this is set to a "known" value, if the path is later
     *  changed (e.g. lineTo(), addRect(), etc.) then the cached value will be
     *  reset to kUnknown_Convexity.
     */
    void setConvexity(Convexity);

    /**
     *  Returns true if the path is flagged as being convex. This is not a
     *  confirmed by any analysis, it is just the value set earlier.
     */
    bool isConvex() const {
        return kConvex_Convexity == this->getConvexity();
    }

    /**
     *  Set the isConvex flag to true or false. Convex paths may draw faster if
     *  this flag is set, though setting this to true on a path that is in fact
     *  not convex can give undefined results when drawn. Paths default to
     *  isConvex == false
     */
    SK_ATTR_DEPRECATED("use setConvexity")
    void setIsConvex(bool isConvex) {
        this->setConvexity(isConvex ? kConvex_Convexity : kConcave_Convexity);
    }

    /** Returns true if the path is an oval.
     *
     * @param rect      returns the bounding rect of this oval. It's a circle
     *                  if the height and width are the same.
     *
     * @return true if this path is an oval.
     *              Tracking whether a path is an oval is considered an
     *              optimization for performance and so some paths that are in
     *              fact ovals can report false.
     */
    bool isOval(SkRect* rect) const { return fPathRef->isOval(rect); }

    /** Returns true if the path is a round rect.
     *
     * @param rrect  Returns the bounding rect and radii of this round rect.
     *
     * @return true if this path is a round rect.
     *              Tracking whether a path is a round rect is considered an
     *              optimization for performance and so some paths that are in
     *              fact round rects can report false.
     */
    bool isRRect(SkRRect* rrect) const { return fPathRef->isRRect(rrect); }

    /** Clear any lines and curves from the path, making it empty. This frees up
        internal storage associated with those segments.
        On Android, does not change fSourcePath.
    */
    void reset();

    /** Similar to reset(), in that all lines and curves are removed from the
        path. However, any internal storage for those lines/curves is retained,
        making reuse of the path potentially faster.
        On Android, does not change fSourcePath.
    */
    void rewind();

    /** Returns true if the path is empty (contains no lines or curves)

        @return true if the path is empty (contains no lines or curves)
    */
    bool isEmpty() const {
        SkDEBUGCODE(this->validate();)
        return 0 == fPathRef->countVerbs();
    }

    /** Return true if the last contour of this path ends with a close verb.
     */
    bool isLastContourClosed() const;

    /**
     *  Returns true if all of the points in this path are finite, meaning there
     *  are no infinities and no NaNs.
     */
    bool isFinite() const {
        SkDEBUGCODE(this->validate();)
        return fPathRef->isFinite();
    }

    /** Returns true if the path is volatile (i.e. should not be cached by devices.)
     */
    bool isVolatile() const {
        return SkToBool(fIsVolatile);
    }

    /** Specify whether this path is volatile. Paths are not volatile by
     default. Temporary paths that are discarded or modified after use should be
     marked as volatile. This provides a hint to the device that the path
     should not be cached. Providing this hint when appropriate can
     improve performance by avoiding unnecessary overhead and resource
     consumption on the device.
     */
    void setIsVolatile(bool isVolatile) {
        fIsVolatile = isVolatile;
    }

    /** Test a line for zero length

        @return true if the line is of zero length; otherwise false.
    */
    static bool IsLineDegenerate(const SkPoint& p1, const SkPoint& p2, bool exact) {
        return exact ? p1 == p2 : p1.equalsWithinTolerance(p2);
    }

    /** Test a quad for zero length

        @return true if the quad is of zero length; otherwise false.
    */
    static bool IsQuadDegenerate(const SkPoint& p1, const SkPoint& p2,
                                 const SkPoint& p3, bool exact) {
        return exact ? p1 == p2 && p2 == p3 : p1.equalsWithinTolerance(p2) &&
               p2.equalsWithinTolerance(p3);
    }

    /** Test a cubic curve for zero length

        @return true if the cubic is of zero length; otherwise false.
    */
    static bool IsCubicDegenerate(const SkPoint& p1, const SkPoint& p2,
                                  const SkPoint& p3, const SkPoint& p4, bool exact) {
        return exact ? p1 == p2 && p2 == p3 && p3 == p4 : p1.equalsWithinTolerance(p2) &&
               p2.equalsWithinTolerance(p3) &&
               p3.equalsWithinTolerance(p4);
    }

    /**
     *  Returns true if the path specifies a single line (i.e. it contains just
     *  a moveTo and a lineTo). If so, and line[] is not null, it sets the 2
     *  points in line[] to the end-points of the line. If the path is not a
     *  line, returns false and ignores line[].
     */
    bool isLine(SkPoint line[2]) const;

    /** Return the number of points in the path
     */
    int countPoints() const;

    /** Return the point at the specified index. If the index is out of range
         (i.e. is not 0 <= index < countPoints()) then the returned coordinates
         will be (0,0)
     */
    SkPoint getPoint(int index) const;

    /** Returns the number of points in the path. Up to max points are copied.

        @param points If not null, receives up to max points
        @param max The maximum number of points to copy into points
        @return the actual number of points in the path
    */
    int getPoints(SkPoint points[], int max) const;

    /** Return the number of verbs in the path
     */
    int countVerbs() const;

    /** Returns the number of verbs in the path. Up to max verbs are copied. The
        verbs are copied as one byte per verb.

        @param verbs If not null, receives up to max verbs
        @param max The maximum number of verbs to copy into verbs
        @return the actual number of verbs in the path
    */
    int getVerbs(uint8_t verbs[], int max) const;

    //! Swap contents of this and other. Guaranteed not to throw
    void swap(SkPath& other);

    /**
     *  Returns the bounds of the path's points. If the path contains zero points/verbs, this
     *  will return the "empty" rect [0, 0, 0, 0].
     *  Note: this bounds may be larger than the actual shape, since curves
     *  do not extend as far as their control points. Additionally this bound encompases all points,
     *  even isolated moveTos either preceeding or following the last non-degenerate contour.
    */
    const SkRect& getBounds() const {
        return fPathRef->getBounds();
    }

    /** Calling this will, if the internal cache of the bounds is out of date,
        update it so that subsequent calls to getBounds will be instantaneous.
        This also means that any copies or simple transformations of the path
        will inherit the cached bounds.
     */
    void updateBoundsCache() const {
        // for now, just calling getBounds() is sufficient
        this->getBounds();
    }

    /**
     * Does a conservative test to see whether a rectangle is inside a path. Currently it only
     * will ever return true for single convex contour paths. The empty-status of the rect is not
     * considered (e.g. a rect that is a point can be inside a path). Points or line segments where
     * the rect edge touches the path border are not considered containment violations.
     */
    bool conservativelyContainsRect(const SkRect& rect) const;

    //  Construction methods

    /** Hint to the path to prepare for adding more points. This can allow the
        path to more efficiently grow its storage.

        @param extraPtCount The number of extra points the path should
                            preallocate for.
    */
    void incReserve(unsigned extraPtCount);

    /** Set the beginning of the next contour to the point (x,y).

        @param x    The x-coordinate of the start of a new contour
        @param y    The y-coordinate of the start of a new contour
    */
    void moveTo(SkScalar x, SkScalar y);

    /** Set the beginning of the next contour to the point

        @param p    The start of a new contour
    */
    void moveTo(const SkPoint& p) {
        this->moveTo(p.fX, p.fY);
    }

    /** Set the beginning of the next contour relative to the last point on the
        previous contour. If there is no previous contour, this is treated the
        same as moveTo().

        @param dx   The amount to add to the x-coordinate of the end of the
                    previous contour, to specify the start of a new contour
        @param dy   The amount to add to the y-coordinate of the end of the
                    previous contour, to specify the start of a new contour
    */
    void rMoveTo(SkScalar dx, SkScalar dy);

    /** Add a line from the last point to the specified point (x,y). If no
        moveTo() call has been made for this contour, the first point is
        automatically set to (0,0).

        @param x    The x-coordinate of the end of a line
        @param y    The y-coordinate of the end of a line
    */
    void lineTo(SkScalar x, SkScalar y);

    /** Add a line from the last point to the specified point. If no moveTo()
        call has been made for this contour, the first point is automatically
        set to (0,0).

        @param p    The end of a line
    */
    void lineTo(const SkPoint& p) {
        this->lineTo(p.fX, p.fY);
    }

    /** Same as lineTo, but the coordinates are considered relative to the last
        point on this contour. If there is no previous point, then a moveTo(0,0)
        is inserted automatically.

        @param dx   The amount to add to the x-coordinate of the previous point
                    on this contour, to specify a line
        @param dy   The amount to add to the y-coordinate of the previous point
                    on this contour, to specify a line
    */
    void rLineTo(SkScalar dx, SkScalar dy);

    /** Add a quadratic bezier from the last point, approaching control point
        (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for
        this contour, the first point is automatically set to (0,0).

        @param x1   The x-coordinate of the control point on a quadratic curve
        @param y1   The y-coordinate of the control point on a quadratic curve
        @param x2   The x-coordinate of the end point on a quadratic curve
        @param y2   The y-coordinate of the end point on a quadratic curve
    */
    void quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2);

    /** Add a quadratic bezier from the last point, approaching control point
        p1, and ending at p2. If no moveTo() call has been made for this
        contour, the first point is automatically set to (0,0).

        @param p1   The control point on a quadratic curve
        @param p2   The end point on a quadratic curve
    */
    void quadTo(const SkPoint& p1, const SkPoint& p2) {
        this->quadTo(p1.fX, p1.fY, p2.fX, p2.fY);
    }

    /** Same as quadTo, but the coordinates are considered relative to the last
        point on this contour. If there is no previous point, then a moveTo(0,0)
        is inserted automatically.

        @param dx1   The amount to add to the x-coordinate of the last point on
                this contour, to specify the control point of a quadratic curve
        @param dy1   The amount to add to the y-coordinate of the last point on
                this contour, to specify the control point of a quadratic curve
        @param dx2   The amount to add to the x-coordinate of the last point on
                     this contour, to specify the end point of a quadratic curve
        @param dy2   The amount to add to the y-coordinate of the last point on
                     this contour, to specify the end point of a quadratic curve
    */
    void rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2);

    void conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
                 SkScalar w);
    void conicTo(const SkPoint& p1, const SkPoint& p2, SkScalar w) {
        this->conicTo(p1.fX, p1.fY, p2.fX, p2.fY, w);
    }
    void rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
                  SkScalar w);

    /** Add a cubic bezier from the last point, approaching control points
        (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been
        made for this contour, the first point is automatically set to (0,0).

        @param x1   The x-coordinate of the 1st control point on a cubic curve
        @param y1   The y-coordinate of the 1st control point on a cubic curve
        @param x2   The x-coordinate of the 2nd control point on a cubic curve
        @param y2   The y-coordinate of the 2nd control point on a cubic curve
        @param x3   The x-coordinate of the end point on a cubic curve
        @param y3   The y-coordinate of the end point on a cubic curve
    */
    void cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
                 SkScalar x3, SkScalar y3);

    /** Add a cubic bezier from the last point, approaching control points p1
        and p2, and ending at p3. If no moveTo() call has been made for this
        contour, the first point is automatically set to (0,0).

        @param p1   The 1st control point on a cubic curve
        @param p2   The 2nd control point on a cubic curve
        @param p3   The end point on a cubic curve
    */
    void cubicTo(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3) {
        this->cubicTo(p1.fX, p1.fY, p2.fX, p2.fY, p3.fX, p3.fY);
    }

    /** Same as cubicTo, but the coordinates are considered relative to the
        current point on this contour. If there is no previous point, then a
        moveTo(0,0) is inserted automatically.

        @param dx1   The amount to add to the x-coordinate of the last point on
                this contour, to specify the 1st control point of a cubic curve
        @param dy1   The amount to add to the y-coordinate of the last point on
                this contour, to specify the 1st control point of a cubic curve
        @param dx2   The amount to add to the x-coordinate of the last point on
                this contour, to specify the 2nd control point of a cubic curve
        @param dy2   The amount to add to the y-coordinate of the last point on
                this contour, to specify the 2nd control point of a cubic curve
        @param dx3   The amount to add to the x-coordinate of the last point on
                     this contour, to specify the end point of a cubic curve
        @param dy3   The amount to add to the y-coordinate of the last point on
                     this contour, to specify the end point of a cubic curve
    */
    void rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
                  SkScalar x3, SkScalar y3);

    /**
     *  Append the specified arc to the path. If the start of the arc is different from the path's
     *  current last point, then an automatic lineTo() is added to connect the current contour
     *  to the start of the arc. However, if the path is empty, then we call moveTo() with
     *  the first point of the arc. The sweep angle is treated mod 360.
     *
     *  @param oval The bounding oval defining the shape and size of the arc
     *  @param startAngle Starting angle (in degrees) where the arc begins
     *  @param sweepAngle Sweep angle (in degrees) measured clockwise. This is treated mod 360.
     *  @param forceMoveTo If true, always begin a new contour with the arc
     */
    void arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo);

    /**
     *  Append a line and arc to the current path. This is the same as the PostScript call "arct".
     */
    void arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar radius);

    /** Append a line and arc to the current path. This is the same as the
        PostScript call "arct".
    */
    void arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius) {
        this->arcTo(p1.fX, p1.fY, p2.fX, p2.fY, radius);
    }

    enum ArcSize {
        /** the smaller of the two possible SVG arcs. */
        kSmall_ArcSize,
        /** the larger of the two possible SVG arcs. */
        kLarge_ArcSize,
    };

    enum Direction {
        /** clockwise direction for adding closed contours */
        kCW_Direction,
        /** counter-clockwise direction for adding closed contours */
        kCCW_Direction,
    };

    /**
     *  Append an elliptical arc from the current point in the format used by SVG.
     *  The center of the ellipse is computed to satisfy the constraints below.
     *
     *  @param rx,ry The radii in the x and y directions respectively.
     *  @param xAxisRotate The angle in degrees relative to the x-axis.
     *  @param largeArc Determines whether the smallest or largest arc possible
     *         is drawn.
     *  @param sweep Determines if the arc should be swept in an anti-clockwise or
     *         clockwise direction. Note that this enum value is opposite the SVG
     *         arc sweep value.
     *  @param x,y The destination coordinates.
     */
    void arcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,
               Direction sweep, SkScalar x, SkScalar y);

    void arcTo(const SkPoint r, SkScalar xAxisRotate, ArcSize largeArc, Direction sweep,
               const SkPoint xy) {
        this->arcTo(r.fX, r.fY, xAxisRotate, largeArc, sweep, xy.fX, xy.fY);
    }

    /** Same as arcTo format used by SVG, but the destination coordinate is relative to the
     *  last point on this contour. If there is no previous point, then a
     *  moveTo(0,0) is inserted automatically.
     *
     *  @param rx,ry The radii in the x and y directions respectively.
     *  @param xAxisRotate The angle in degrees relative to the x-axis.
     *  @param largeArc Determines whether the smallest or largest arc possible
     *         is drawn.
     *  @param sweep Determines if the arc should be swept in an anti-clockwise or
     *         clockwise direction. Note that this enum value is opposite the SVG
     *         arc sweep value.
     *  @param dx,dy The destination coordinates relative to the last point.
     */
    void rArcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,
                Direction sweep, SkScalar dx, SkScalar dy);

    /** Close the current contour. If the current point is not equal to the
        first point of the contour, a line segment is automatically added.
    */
    void close();

    /**
     *  Returns whether or not a fill type is inverted
     *
     *  kWinding_FillType        -> false
     *  kEvenOdd_FillType        -> false
     *  kInverseWinding_FillType -> true
     *  kInverseEvenOdd_FillType -> true
     */
    static bool IsInverseFillType(FillType fill) {
        static_assert(0 == kWinding_FillType, "fill_type_mismatch");
        static_assert(1 == kEvenOdd_FillType, "fill_type_mismatch");
        static_assert(2 == kInverseWinding_FillType, "fill_type_mismatch");
        static_assert(3 == kInverseEvenOdd_FillType, "fill_type_mismatch");
        return (fill & 2) != 0;
    }

    /**
     *  Returns the equivalent non-inverted fill type to the given fill type
     *
     *  kWinding_FillType        -> kWinding_FillType
     *  kEvenOdd_FillType        -> kEvenOdd_FillType
     *  kInverseWinding_FillType -> kWinding_FillType
     *  kInverseEvenOdd_FillType -> kEvenOdd_FillType
     */
    static FillType ConvertToNonInverseFillType(FillType fill) {
        static_assert(0 == kWinding_FillType, "fill_type_mismatch");
        static_assert(1 == kEvenOdd_FillType, "fill_type_mismatch");
        static_assert(2 == kInverseWinding_FillType, "fill_type_mismatch");
        static_assert(3 == kInverseEvenOdd_FillType, "fill_type_mismatch");
        return (FillType)(fill & 1);
    }

    /**
     *  Chop a conic into N quads, stored continguously in pts[], where
     *  N = 1 << pow2. The amount of storage needed is (1 + 2 * N)
     */
    static int ConvertConicToQuads(const SkPoint& p0, const SkPoint& p1, const SkPoint& p2,
                                   SkScalar w, SkPoint pts[], int pow2);

    /**
     *  Returns true if the path specifies a rectangle.
     *
     *  If this returns false, then all output parameters are ignored, and left
     *  unchanged. If this returns true, then each of the output parameters
     *  are checked for NULL. If they are not, they return their value.
     *
     *  @param rect If not null, set to the bounds of the rectangle.
     *              Note : this bounds may be smaller than the path's bounds, since it is just
     *              the bounds of the "drawable" parts of the path. e.g. a trailing MoveTo would
     *              be ignored in this rect, but not by the path's bounds
     *  @param isClosed If not null, set to true if the path is closed
     *  @param direction If not null, set to the rectangle's direction
     *  @return true if the path specifies a rectangle
     */
    bool isRect(SkRect* rect, bool* isClosed = NULL, Direction* direction = NULL) const;

    /** Returns true if the path specifies a pair of nested rectangles, or would draw a
        pair of nested rectangles when filled. If so, and if
        rect is not null, set rect[0] to the outer rectangle and rect[1] to the inner
        rectangle. If so, and dirs is not null, set dirs[0] to the direction of
        the outer rectangle and dirs[1] to the direction of the inner rectangle. If
        the path does not specify a pair of nested rectangles, return
        false and ignore rect and dirs.

        @param rect If not null, returns the path as a pair of nested rectangles
        @param dirs If not null, returns the direction of the rects
        @return true if the path describes a pair of nested rectangles
    */
    bool isNestedFillRects(SkRect rect[2], Direction dirs[2] = NULL) const;

    /**
     *  Add a closed rectangle contour to the path
     *  @param rect The rectangle to add as a closed contour to the path
     *  @param dir  The direction to wind the rectangle's contour.
     *
     *  Note: the contour initial point index is 0 (as defined below).
     */
    void addRect(const SkRect& rect, Direction dir = kCW_Direction);

    /**
     *  Add a closed rectangle contour to the path
     *  @param rect  The rectangle to add as a closed contour to the path
     *  @param dir   The direction to wind the rectangle's contour.
     *  @param start Initial point of the contour (initial moveTo), expressed as
     *               a corner index, starting in the upper-left position, clock-wise:
     *
     *  0         1
     *   *-------*
     *   |       |
     *   *-------*
     *  3         2
     */
    void addRect(const SkRect& rect, Direction dir, unsigned start);

    /**
     *  Add a closed rectangle contour to the path
     *
     *  @param left     The left side of a rectangle to add as a closed contour
     *                  to the path
     *  @param top      The top of a rectangle to add as a closed contour to the
     *                  path
     *  @param right    The right side of a rectangle to add as a closed contour
     *                  to the path
     *  @param bottom   The bottom of a rectangle to add as a closed contour to
     *                  the path
     *  @param dir  The direction to wind the rectangle's contour.
     *
     *  Note: the contour initial point index is 0 (as defined above).
     */
    void addRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom,
                 Direction dir = kCW_Direction);

    /**
     *  Add a closed oval contour to the path
     *
     *  @param oval The bounding oval to add as a closed contour to the path
     *  @param dir  The direction to wind the oval's contour.
     *
     *  Note: the contour initial point index is 1 (as defined below).
     */
    void addOval(const SkRect& oval, Direction dir = kCW_Direction);

    /**
     *  Add a closed oval contour to the path
     *
     *  @param oval  The bounding oval to add as a closed contour to the path
     *  @param dir   The direction to wind the oval's contour.
     *  @param start Initial point of the contour (initial moveTo), expressed
     *               as an ellipse vertex index, starting at the top, clock-wise
     *               (90/0/270/180deg order):
     *
     *        0
     *       -*-
     *     |     |
     *   3 *     * 1
     *     |     |
     *       -*-
     *        2
     */
    void addOval(const SkRect& oval, Direction dir, unsigned start);

    /**
     *  Add a closed circle contour to the path
     *
     *  @param x        The x-coordinate of the center of a circle to add as a
     *                  closed contour to the path
     *  @param y        The y-coordinate of the center of a circle to add as a
     *                  closed contour to the path
     *  @param radius   The radius of a circle to add as a closed contour to the
     *                  path
     *  @param dir  The direction to wind the circle's contour.
     */
    void addCircle(SkScalar x, SkScalar y, SkScalar radius,
                   Direction dir = kCW_Direction);

    /** Add the specified arc to the path as a new contour.

        @param oval The bounds of oval used to define the size of the arc
        @param startAngle Starting angle (in degrees) where the arc begins
        @param sweepAngle Sweep angle (in degrees) measured clockwise
    */
    void addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle);

    /**
     *  Add a closed round-rectangle contour to the path
     *  @param rect The bounds of a round-rectangle to add as a closed contour
     *  @param rx   The x-radius of the rounded corners on the round-rectangle
     *  @param ry   The y-radius of the rounded corners on the round-rectangle
     *  @param dir  The direction to wind the rectangle's contour.
     */
    void addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
                      Direction dir = kCW_Direction);

    /**
     *  Add a closed round-rectangle contour to the path. Each corner receives
     *  two radius values [X, Y]. The corners are ordered top-left, top-right,
     *  bottom-right, bottom-left.
     *  @param rect The bounds of a round-rectangle to add as a closed contour
     *  @param radii Array of 8 scalars, 4 [X,Y] pairs for each corner
     *  @param dir  The direction to wind the rectangle's contour.
     * Note: The radii here now go through the same constraint handling as the
     *       SkRRect radii (i.e., either radii at a corner being 0 implies a
     *       sqaure corner and oversized radii are proportionally scaled down).
     */
    void addRoundRect(const SkRect& rect, const SkScalar radii[],
                      Direction dir = kCW_Direction);

    /**
     *  Add an SkRRect contour to the path
     *  @param rrect The rounded rect to add as a closed contour
     *  @param dir   The winding direction for the new contour.
     *
     *  Note: the contour initial point index is either 6 (for dir == kCW_Direction)
     *        or 7 (for dir == kCCW_Direction), as defined below.
     *
     */
    void addRRect(const SkRRect& rrect, Direction dir = kCW_Direction);

    /**
     *  Add an SkRRect contour to the path
     *  @param rrect The rounded rect to add as a closed contour
     *  @param dir   The winding direction for the new contour.
     *  @param start Initial point of the contour (initial moveTo), expressed as
     *               an index of the radii minor/major points, ordered clock-wise:
     *
     *      0    1
     *      *----*
     *   7 *      * 2
     *     |      |
     *   6 *      * 3
     *      *----*
     *      5    4
     */
    void addRRect(const SkRRect& rrect, Direction dir, unsigned start);

    /**
     *  Add a new contour made of just lines. This is just a fast version of
     *  the following:
     *      this->moveTo(pts[0]);
     *      for (int i = 1; i < count; ++i) {
     *          this->lineTo(pts[i]);
     *      }
     *      if (close) {
     *          this->close();
     *      }
     */
    void addPoly(const SkPoint pts[], int count, bool close);

    enum AddPathMode {
        /** Source path contours are added as new contours.
        */
        kAppend_AddPathMode,
        /** Path is added by extending the last contour of the destination path
            with the first contour of the source path. If the last contour of
            the destination path is closed, then it will not be extended.
            Instead, the start of source path will be extended by a straight
            line to the end point of the destination path.
        */
        kExtend_AddPathMode
    };

    /** Add a copy of src to the path, offset by (dx,dy)
        @param src  The path to add as a new contour
        @param dx   The amount to translate the path in X as it is added
        @param dx   The amount to translate the path in Y as it is added
    */
    void addPath(const SkPath& src, SkScalar dx, SkScalar dy,
                 AddPathMode mode = kAppend_AddPathMode);

    /** Add a copy of src to the path
    */
    void addPath(const SkPath& src, AddPathMode mode = kAppend_AddPathMode) {
        SkMatrix m;
        m.reset();
        this->addPath(src, m, mode);
    }

    /** Add a copy of src to the path, transformed by matrix
        @param src  The path to add as a new contour
        @param matrix  Transform applied to src
        @param mode  Determines how path is added
    */
    void addPath(const SkPath& src, const SkMatrix& matrix, AddPathMode mode = kAppend_AddPathMode);

    /**
     *  Same as addPath(), but reverses the src input
     */
    void reverseAddPath(const SkPath& src);

    /** Offset the path by (dx,dy), returning true on success

        @param dx   The amount in the X direction to offset the entire path
        @param dy   The amount in the Y direction to offset the entire path
        @param dst  The translated path is written here
    */
    void offset(SkScalar dx, SkScalar dy, SkPath* dst) const;

    /** Offset the path by (dx,dy), returning true on success

        @param dx   The amount in the X direction to offset the entire path
        @param dy   The amount in the Y direction to offset the entire path
    */
    void offset(SkScalar dx, SkScalar dy) {
        this->offset(dx, dy, this);
    }

    /** Transform the points in this path by matrix, and write the answer into
        dst.

        @param matrix   The matrix to apply to the path
        @param dst      The transformed path is written here
    */
    void transform(const SkMatrix& matrix, SkPath* dst) const;

    /** Transform the points in this path by matrix

        @param matrix The matrix to apply to the path
    */
    void transform(const SkMatrix& matrix) {
        this->transform(matrix, this);
    }

    /** Return the last point on the path. If no points have been added, (0,0)
        is returned. If there are no points, this returns false, otherwise it
        returns true.

        @param lastPt   The last point on the path is returned here
    */
    bool getLastPt(SkPoint* lastPt) const;

    /** Set the last point on the path. If no points have been added,
        moveTo(x,y) is automatically called.

        @param x    The new x-coordinate for the last point
        @param y    The new y-coordinate for the last point
    */
    void setLastPt(SkScalar x, SkScalar y);

    /** Set the last point on the path. If no points have been added, moveTo(p)
        is automatically called.

        @param p    The new location for the last point
    */
    void setLastPt(const SkPoint& p) {
        this->setLastPt(p.fX, p.fY);
    }

    enum SegmentMask {
        kLine_SegmentMask   = 1 << 0,
        kQuad_SegmentMask   = 1 << 1,
        kConic_SegmentMask  = 1 << 2,
        kCubic_SegmentMask  = 1 << 3,
    };

    /**
     *  Returns a mask, where each bit corresponding to a SegmentMask is
     *  set if the path contains 1 or more segments of that type.
     *  Returns 0 for an empty path (no segments).
     */
    uint32_t getSegmentMasks() const { return fPathRef->getSegmentMasks(); }

    enum Verb {
        kMove_Verb,     //!< iter.next returns 1 point
        kLine_Verb,     //!< iter.next returns 2 points
        kQuad_Verb,     //!< iter.next returns 3 points
        kConic_Verb,    //!< iter.next returns 3 points + iter.conicWeight()
        kCubic_Verb,    //!< iter.next returns 4 points
        kClose_Verb,    //!< iter.next returns 0 points
        kDone_Verb,     //!< iter.next returns 0 points
    };

    /** Iterate through all of the segments (lines, quadratics, cubics) of
        each contours in a path.

        The iterator cleans up the segments along the way, removing degenerate
        segments and adding close verbs where necessary. When the forceClose
        argument is provided, each contour (as defined by a new starting
        move command) will be completed with a close verb regardless of the
        contour's contents.
    */
    class SK_API Iter {
    public:
        Iter();
        Iter(const SkPath&, bool forceClose);

        void setPath(const SkPath&, bool forceClose);

        /** Return the next verb in this iteration of the path. When all
            segments have been visited, return kDone_Verb.

            @param  pts The points representing the current verb and/or segment
            @param doConsumeDegerates If true, first scan for segments that are
                   deemed degenerate (too short) and skip those.
            @param exact if doConsumeDegenerates is true and exact is true, skip only
                   degenerate elements with lengths exactly equal to zero. If exact
                   is false, skip degenerate elements with lengths close to zero. If
                   doConsumeDegenerates is false, exact has no effect.
            @return The verb for the current segment
        */
        Verb next(SkPoint pts[4], bool doConsumeDegerates = true, bool exact = false) {
            if (doConsumeDegerates) {
                this->consumeDegenerateSegments(exact);
            }
            return this->doNext(pts);
        }

        /**
         *  Return the weight for the current conic. Only valid if the current
         *  segment return by next() was a conic.
         */
        SkScalar conicWeight() const { return *fConicWeights; }

        /** If next() returns kLine_Verb, then this query returns true if the
            line was the result of a close() command (i.e. the end point is the
            initial moveto for this contour). If next() returned a different
            verb, this returns an undefined value.

            @return If the last call to next() returned kLine_Verb, return true
                    if it was the result of an explicit close command.
        */
        bool isCloseLine() const { return SkToBool(fCloseLine); }

        /** Returns true if the current contour is closed (has a kClose_Verb)
            @return true if the current contour is closed (has a kClose_Verb)
        */
        bool isClosedContour() const;

    private:
        const SkPoint*  fPts;
        const uint8_t*  fVerbs;
        const uint8_t*  fVerbStop;
        const SkScalar* fConicWeights;
        SkPoint         fMoveTo;
        SkPoint         fLastPt;
        SkBool8         fForceClose;
        SkBool8         fNeedClose;
        SkBool8         fCloseLine;
        SkBool8         fSegmentState;

        inline const SkPoint& cons_moveTo();
        Verb autoClose(SkPoint pts[2]);
        void consumeDegenerateSegments(bool exact);
        Verb doNext(SkPoint pts[4]);
    };

    /** Iterate through the verbs in the path, providing the associated points.
    */
    class SK_API RawIter {
    public:
        RawIter() {}
        RawIter(const SkPath& path) {
            setPath(path);
        }

        void setPath(const SkPath& path) {
            fRawIter.setPathRef(*path.fPathRef.get());
        }

        /** Return the next verb in this iteration of the path. When all
            segments have been visited, return kDone_Verb.

            @param  pts The points representing the current verb and/or segment
                        This must not be NULL.
            @return The verb for the current segment
        */
        Verb next(SkPoint pts[4]) {
            return (Verb) fRawIter.next(pts);
        }

        /** Return what the next verb will be, but do not visit the next segment.

            @return The verb for the next segment
        */
        Verb peek() const {
            return (Verb) fRawIter.peek();
        }

        SkScalar conicWeight() const {
            return fRawIter.conicWeight();
        }

    private:
        SkPathRef::Iter fRawIter;
        friend class SkPath;
    };

    /**
     *  Returns true if the point { x, y } is contained by the path, taking into
     *  account the FillType.
     */
    bool contains(SkScalar x, SkScalar y) const;

    void dump(SkWStream* , bool forceClose, bool dumpAsHex) const;
    void dump() const;
    void dumpHex() const;

    /**
     *  Write the path to the buffer, and return the number of bytes written.
     *  If buffer is NULL, it still returns the number of bytes.
     */
    size_t writeToMemory(void* buffer) const;
    /**
     * Initializes the path from the buffer
     *
     * @param buffer Memory to read from
     * @param length Amount of memory available in the buffer
     * @return number of bytes read (must be a multiple of 4) or
     *         0 if there was not enough memory available
     */
    size_t readFromMemory(const void* buffer, size_t length);

    /** Returns a non-zero, globally unique value corresponding to the set of verbs
        and points in the path (but not the fill type [except on Android skbug.com/1762]).
        Each time the path is modified, a different generation ID will be returned.
    */
    uint32_t getGenerationID() const;

#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
    static const int kPathRefGenIDBitCnt = 30; // leave room for the fill type (skbug.com/1762)
#else
    static const int kPathRefGenIDBitCnt = 32;
#endif

    SkDEBUGCODE(void validate() const;)
    SkDEBUGCODE(void experimentalValidateRef() const { fPathRef->validate(); } )

private:
    enum SerializationOffsets {
        // 1 free bit at 29
        kUnused1_SerializationShift = 28,    // 1 free bit
        kDirection_SerializationShift = 26, // requires 2 bits
        kIsVolatile_SerializationShift = 25, // requires 1 bit
        // 1 free bit at 24
        kConvexity_SerializationShift = 16, // requires 8 bits
        kFillType_SerializationShift = 8,   // requires 8 bits
        // low-8-bits are version
    };

    enum SerializationVersions {
        kPathPrivFirstDirection_Version = 1,
        kPathPrivLastMoveToIndex_Version = 2,
        kCurrent_Version = 2
    };

    SkAutoTUnref<SkPathRef>                            fPathRef;
    int                                                fLastMoveToIndex;
    uint8_t                                            fFillType;
    mutable uint8_t                                    fConvexity;
    mutable SkAtomic<uint8_t, sk_memory_order_relaxed> fFirstDirection;// SkPathPriv::FirstDirection
    mutable SkBool8                                    fIsVolatile;

    /** Resets all fields other than fPathRef to their initial 'empty' values.
     *  Assumes the caller has already emptied fPathRef.
     *  On Android increments fGenerationID without reseting it.
     */
    void resetFields();

    /** Sets all fields other than fPathRef to the values in 'that'.
     *  Assumes the caller has already set fPathRef.
     *  Doesn't change fGenerationID or fSourcePath on Android.
     */
    void copyFields(const SkPath& that);

    friend class Iter;
    friend class SkPathPriv;
    friend class SkPathStroker;

    /*  Append, in reverse order, the first contour of path, ignoring path's
        last point. If no moveTo() call has been made for this contour, the
        first point is automatically set to (0,0).
    */
    void reversePathTo(const SkPath&);

    // called before we add points for lineTo, quadTo, cubicTo, checking to see
    // if we need to inject a leading moveTo first
    //
    //  SkPath path; path.lineTo(...);   <--- need a leading moveTo(0, 0)
    // SkPath path; ... path.close(); path.lineTo(...) <-- need a moveTo(previous moveTo)
    //
    inline void injectMoveToIfNeeded();

    inline bool hasOnlyMoveTos() const;

    Convexity internalGetConvexity() const;

    bool isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts,
                       bool* isClosed, Direction* direction) const;

    // called by stroker to see if all points are equal and worthy of a cap
    // equivalent to a short-circuit version of getBounds().isEmpty() 
    bool isZeroLength() const;

    /** Returns if the path can return a bound at no cost (true) or will have to
        perform some computation (false).
     */
    bool hasComputedBounds() const {
        SkDEBUGCODE(this->validate();)
        return fPathRef->hasComputedBounds();
    }


    // 'rect' needs to be sorted
    void setBounds(const SkRect& rect) {
        SkPathRef::Editor ed(&fPathRef);

        ed.setBounds(rect);
    }

    void setPt(int index, SkScalar x, SkScalar y);

    friend class SkAutoPathBoundsUpdate;
    friend class SkAutoDisableOvalCheck;
    friend class SkAutoDisableDirectionCheck;
    friend class SkBench_AddPathTest; // perf test reversePathTo
    friend class PathTest_Private; // unit test reversePathTo
    friend class ForceIsRRect_Private; // unit test isRRect
};

#endif
