/*
 * 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 "SkInstCnt.h"
#include "SkMatrix.h"
#include "SkPathRef.h"
#include "SkTDArray.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:
    SK_DECLARE_INST_COUNT(SkPath);

    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);
    }

#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); }

    /** 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();
    }

    /**
     *  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) {
        return 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) {
        return 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) {
        return 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 0 or 1
        points, the bounds is set to (0,0,0,0), and isEmpty() will return true.
        Note: this bounds may be larger than the actual shape, since curves
        do not extend as far as their control points. Additionally this bound
        can contain trailing MoveTo points (cf. isRect).
    */
    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);
    }

    /** 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();

    enum Direction {
        /** Direction either has not been or could not be computed */
        kUnknown_Direction,
        /** clockwise direction for adding closed contours */
        kCW_Direction,
        /** counter-clockwise direction for adding closed contours */
        kCCW_Direction,
    };

    /**
     *  Return the opposite of the specified direction. kUnknown is its own
     *  opposite.
     */
    static Direction OppositeDirection(Direction dir) {
        static const Direction gOppositeDir[] = {
            kUnknown_Direction, kCCW_Direction, kCW_Direction
        };
        return gOppositeDir[dir];
    }

    /**
     *  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) {
        SK_COMPILE_ASSERT(0 == kWinding_FillType, fill_type_mismatch);
        SK_COMPILE_ASSERT(1 == kEvenOdd_FillType, fill_type_mismatch);
        SK_COMPILE_ASSERT(2 == kInverseWinding_FillType, fill_type_mismatch);
        SK_COMPILE_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) {
        SK_COMPILE_ASSERT(0 == kWinding_FillType, fill_type_mismatch);
        SK_COMPILE_ASSERT(1 == kEvenOdd_FillType, fill_type_mismatch);
        SK_COMPILE_ASSERT(2 == kInverseWinding_FillType, fill_type_mismatch);
        SK_COMPILE_ASSERT(3 == kInverseEvenOdd_FillType, fill_type_mismatch);
        return (FillType)(fill & 1);
    }

    /**
     *  Tries to quickly compute the direction of the first non-degenerate
     *  contour. If it can be computed, return true and set dir to that
     *  direction. If it cannot be (quickly) determined, return false and ignore
     *  the dir parameter. If the direction was determined, it is cached to make
     *  subsequent calls return quickly.
     */
    bool cheapComputeDirection(Direction* dir) const;

    /**
     *  Returns true if the path's direction can be computed via
     *  cheapComputDirection() and if that computed direction matches the
     *  specified direction. If dir is kUnknown, returns true if the direction
     *  cannot be computed.
     */
    bool cheapIsDirection(Direction dir) const {
        Direction computedDir = kUnknown_Direction;
        (void)this->cheapComputeDirection(&computedDir);
        return computedDir == dir;
    }

    /**
     *  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. Cannot be
     *              kUnknown_Direction.
     */
    void addRect(const SkRect& rect, Direction dir = kCW_Direction);

    /**
     *  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. Cannot be
     *              kUnknown_Direction.
     */
    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. Cannot be
     *              kUnknown_Direction.
     */
    void addOval(const SkRect& oval, Direction dir = kCW_Direction);

    /**
     *  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. Cannot be
     *              kUnknown_Direction.
     */
    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. Cannot be
     *              kUnknown_Direction.
     */
    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. Cannot be
     *              kUnknown_Direction.
     * 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. Cannot be
     *               kUnknown_Direction.
     */
    void addRRect(const SkRRect& rrect, Direction dir = kCW_Direction);

    /**
     *  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 1 point (contour's moveTo pt)
        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.
            @return The verb for the current segment
        */
        Verb next(SkPoint pts[4], bool doConsumeDegerates = true) {
            if (doConsumeDegerates) {
                this->consumeDegenerateSegments();
            }
            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();
        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&);

        void setPath(const SkPath&);

        /** 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]);

        SkScalar conicWeight() const { return *fConicWeights; }

    private:
        const SkPoint*  fPts;
        const uint8_t*  fVerbs;
        const uint8_t*  fVerbStop;
        const SkScalar* fConicWeights;
        SkPoint         fMoveTo;
    };

    /**
     *  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
        // 8 free bits at 0
    };

    SkAutoTUnref<SkPathRef> fPathRef;

    int                 fLastMoveToIndex;
    uint8_t             fFillType;
    mutable uint8_t     fConvexity;
    mutable uint8_t     fDirection;
    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 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;

    /** 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
};

#endif
