
/*
 * 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 "SkTDArray.h"

#ifdef SK_BUILD_FOR_ANDROID
#define GEN_ID_INC              fGenerationID++
#define GEN_ID_PTR_INC(ptr)     ptr->fGenerationID++
#else
#define GEN_ID_INC
#define GEN_ID_PTR_INC(ptr)
#endif

class SkReader32;
class SkWriter32;
class SkAutoPathBoundsUpdate;
class SkString;

/** \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 bool operator==(const SkPath&, const SkPath&);
    friend bool operator!=(const SkPath& a, const SkPath& b) {
        return !(a == b);
    }

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

    /** Returns true if the filltype is one of the Inverse variants */
    bool isInverseFillType() const { return (fFillType & 2) != 0; }

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

    enum Convexity {
        kUnknown_Convexity,
        kConvex_Convexity,
        kConcave_Convexity
    };

    /**
     *  Return the path's convexity, as stored in the path. If it is currently
     *  unknown, and the computeIfUnknown bool is true, then this will first
     *  call ComputeConvexity() and then return that (cached) value.
     */
    Convexity getConvexity() const {
        if (kUnknown_Convexity == fConvexity) {
            fConvexity = (uint8_t)ComputeConvexity(*this);
        }
        return (Convexity)fConvexity;
    }

    /**
     *  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 agress with the return value from
     *  ComputeConvexity().
     *
     *  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);

    /**
     *  Compute the convexity of the specified path. This does not look at the
     *  value stored in the path, but computes it directly from the path's data.
     *
     *  This never returns kUnknown_Convexity.
     *
     *  If there is more than one contour, this returns kConcave_Convexity.
     *  If the contour is degenerate (e.g. there are fewer than 3 non-degenerate
     *  segments), then this returns kConvex_Convexity.
     *  The contour is treated as if it were closed, even if there is no kClose
     *  verb.
     */
    static Convexity ComputeConvexity(const SkPath&);

    /**
     *  DEPRECATED: use getConvexity()
     *  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();
    }

    /**
     *  DEPRECATED: use setConvexity()
     *  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
     */
    void setIsConvex(bool isConvex) {
        this->setConvexity(isConvex ? kConvex_Convexity : kConcave_Convexity);
    }

    /** Clear any lines and curves from the path, making it empty. This frees up
        internal storage associated with those segments.
        This does NOT change the fill-type setting nor isConvex
    */
    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.
        This does NOT change the fill-type setting nor isConvex
    */
    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;

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

    /** 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, SK_ScalarNearlyZero) &&
               p2.equalsWithinTolerance(p3, SK_ScalarNearlyZero);
    }

    /** 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, SK_ScalarNearlyZero) &&
               p2.equalsWithinTolerance(p3, SK_ScalarNearlyZero) &&
               p3.equalsWithinTolerance(p4, SK_ScalarNearlyZero);
    }

    /** Returns true if the path specifies a rectangle. If so, and if rect is
        not null, set rect to the bounds of the path. If the path does not
        specify a rectangle, return false and ignore rect.
     
        @param rect If not null, returns the bounds of the path if it specifies
                    a rectangle
        @return true if the path specifies a rectangle
    */
    bool isRect(SkRect* rect) const;

    /** Return the number of points in the path
     */
    int countPoints() const {
        return this->getPoints(NULL, 0);
    }

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

    //! 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.
    */
    const SkRect& getBounds() const {
        if (fBoundsIsDirty) {
            this->computeBounds();
        }
        return fBounds;
    }

    /** Calling this will, if the internal cache of the bounds is out of date,
        update it so that subsequent calls to getBounds will be instanteous.
        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();
    }

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

    /** 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 as a new contour. If the start of
        the path 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 {
        /** clockwise direction for adding closed contours */
        kCW_Direction,
        /** counter-clockwise direction for adding closed contours */
        kCCW_Direction
    };

    /**
     *  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.
     */
    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.
     */
    bool cheapIsDirection(Direction dir) const {
        Direction computedDir;
        return this->cheapComputeDirection(&computedDir) && computedDir == dir;
    }

    /** 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
    */
    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
    */
    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
    */
    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
    */
    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 round-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 round-rectangle's contour
        */
    void addRoundRect(const SkRect& rect, const SkScalar radii[],
                      Direction dir = kCW_Direction);

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

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

    /** Add a copy of src to the path, transformed by matrix
        @param src  The path to add as a new contour
    */
    void addPath(const SkPath& src, const SkMatrix& matrix);

    /**
     *  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,
        kCubic_SegmentMask  = 1 << 2
    };

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

    enum Verb {
        kMove_Verb,     //!< iter.next returns 1 point
        kLine_Verb,     //!< iter.next returns 2 points
        kQuad_Verb,     //!< iter.next returns 3 points
        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
            @return The verb for the current segment
        */
        Verb next(SkPoint pts[4]);

        /** 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;
        SkPoint         fMoveTo;
        SkPoint         fLastPt;
        SkBool8         fForceClose;
        SkBool8         fNeedClose;
        SkBool8         fCloseLine;
        SkBool8         fSegmentState;

        bool cons_moveTo(SkPoint pts[1]);
        Verb autoClose(SkPoint pts[2]);
        void consumeDegenerateSegments();
    };

    /** 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
            @return The verb for the current segment
        */
        Verb next(SkPoint pts[4]);

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

    void dump(bool forceClose, const char title[] = NULL) const;
    void dump() const;

    void flatten(SkWriter32&) const;
    void unflatten(SkReader32&);

#ifdef SK_BUILD_FOR_ANDROID
    uint32_t getGenerationID() const;
    const SkPath* getSourcePath() const;
    void setSourcePath(const SkPath* path);
#endif

    SkDEBUGCODE(void validate() const;)

private:
    SkTDArray<SkPoint>  fPts;
    SkTDArray<uint8_t>  fVerbs;
    mutable SkRect      fBounds;
    int                 fLastMoveToIndex;
    uint8_t             fFillType;
    uint8_t             fSegmentMask;
    mutable uint8_t     fBoundsIsDirty;
    mutable uint8_t     fConvexity;
#ifdef SK_BUILD_FOR_ANDROID
    uint32_t            fGenerationID;
    const SkPath*       fSourcePath;
#endif

    // called, if dirty, by getBounds()
    void computeBounds() const;

    friend class Iter;

    friend class SkPathStroker;
    /*  Append the first contour of path, ignoring path's initial point. If no
        moveTo() call has been made for this contour, the first point is
        automatically set to (0,0).
    */
    void pathTo(const SkPath& path);

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

    friend class SkAutoPathBoundsUpdate;
};

#endif
