Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef SkPath_DEFINED
     18 #define SkPath_DEFINED
     19 
     20 #include "SkMatrix.h"
     21 #include "SkTDArray.h"
     22 
     23 #ifdef ANDROID
     24 #define GEN_ID_INC              fGenerationID++
     25 #define GEN_ID_PTR_INC(ptr)     ptr->fGenerationID++
     26 #else
     27 #define GEN_ID_INC
     28 #define GEN_ID_PTR_INC(ptr)
     29 #endif
     30 
     31 class SkReader32;
     32 class SkWriter32;
     33 class SkAutoPathBoundsUpdate;
     34 class SkString;
     35 
     36 /** \class SkPath
     37 
     38     The SkPath class encapsulates compound (multiple contour) geometric paths
     39     consisting of straight line segments, quadratic curves, and cubic curves.
     40 */
     41 class SK_API SkPath {
     42 public:
     43     SkPath();
     44     SkPath(const SkPath&);
     45     ~SkPath();
     46 
     47     SkPath& operator=(const SkPath&);
     48 
     49     friend bool operator==(const SkPath&, const SkPath&);
     50     friend bool operator!=(const SkPath& a, const SkPath& b) {
     51         return !(a == b);
     52     }
     53 
     54     enum FillType {
     55         /** Specifies that "inside" is computed by a non-zero sum of signed
     56             edge crossings
     57         */
     58         kWinding_FillType,
     59         /** Specifies that "inside" is computed by an odd number of edge
     60             crossings
     61         */
     62         kEvenOdd_FillType,
     63         /** Same as Winding, but draws outside of the path, rather than inside
     64         */
     65         kInverseWinding_FillType,
     66         /** Same as EvenOdd, but draws outside of the path, rather than inside
     67          */
     68         kInverseEvenOdd_FillType
     69     };
     70 
     71     /** Return the path's fill type. This is used to define how "inside" is
     72         computed. The default value is kWinding_FillType.
     73 
     74         @return the path's fill type
     75     */
     76     FillType getFillType() const { return (FillType)fFillType; }
     77 
     78     /** Set the path's fill type. This is used to define how "inside" is
     79         computed. The default value is kWinding_FillType.
     80 
     81         @param ft The new fill type for this path
     82     */
     83     void setFillType(FillType ft) {
     84         fFillType = SkToU8(ft);
     85         GEN_ID_INC;
     86     }
     87 
     88     /** Returns true if the filltype is one of the Inverse variants */
     89     bool isInverseFillType() const { return (fFillType & 2) != 0; }
     90 
     91     /**
     92      *  Toggle between inverse and normal filltypes. This reverse the return
     93      *  value of isInverseFillType()
     94      */
     95     void toggleInverseFillType() {
     96         fFillType ^= 2;
     97         GEN_ID_INC;
     98      }
     99 
    100     enum Convexity {
    101         kUnknown_Convexity,
    102         kConvex_Convexity,
    103         kConcave_Convexity
    104     };
    105 
    106     /**
    107      *  Return the path's convexity, as stored in the path. If it is currently
    108      *  unknown, and the computeIfUnknown bool is true, then this will first
    109      *  call ComputeConvexity() and then return that (cached) value.
    110      */
    111     Convexity getConvexity() const {
    112         if (kUnknown_Convexity == fConvexity) {
    113             fConvexity = (uint8_t)ComputeConvexity(*this);
    114         }
    115         return (Convexity)fConvexity;
    116     }
    117 
    118     /**
    119      *  Return the currently cached value for convexity, even if that is set to
    120      *  kUnknown_Convexity. Note: getConvexity() will automatically call
    121      *  ComputeConvexity and cache its return value if the current setting is
    122      *  kUnknown.
    123      */
    124     Convexity getConvexityOrUnknown() const { return (Convexity)fConvexity; }
    125 
    126     /**
    127      *  Store a convexity setting in the path. There is no automatic check to
    128      *  see if this value actually agress with the return value from
    129      *  ComputeConvexity().
    130      *
    131      *  Note: even if this is set to a "known" value, if the path is later
    132      *  changed (e.g. lineTo(), addRect(), etc.) then the cached value will be
    133      *  reset to kUnknown_Convexity.
    134      */
    135     void setConvexity(Convexity);
    136 
    137     /**
    138      *  Compute the convexity of the specified path. This does not look at the
    139      *  value stored in the path, but computes it directly from the path's data.
    140      *
    141      *  This never returns kUnknown_Convexity.
    142      *
    143      *  If there is more than one contour, this returns kConcave_Convexity.
    144      *  If the contour is degenerate (e.g. there are fewer than 3 non-degenerate
    145      *  segments), then this returns kConvex_Convexity.
    146      *  The contour is treated as if it were closed, even if there is no kClose
    147      *  verb.
    148      */
    149     static Convexity ComputeConvexity(const SkPath&);
    150 
    151     /**
    152      *  DEPRECATED: use getConvexity()
    153      *  Returns true if the path is flagged as being convex. This is not a
    154      *  confirmed by any analysis, it is just the value set earlier.
    155      */
    156     bool isConvex() const {
    157         return kConvex_Convexity == this->getConvexity();
    158     }
    159 
    160     /**
    161      *  DEPRECATED: use setConvexity()
    162      *  Set the isConvex flag to true or false. Convex paths may draw faster if
    163      *  this flag is set, though setting this to true on a path that is in fact
    164      *  not convex can give undefined results when drawn. Paths default to
    165      *  isConvex == false
    166      */
    167     void setIsConvex(bool isConvex) {
    168         this->setConvexity(isConvex ? kConvex_Convexity : kConcave_Convexity);
    169     }
    170 
    171     /** Clear any lines and curves from the path, making it empty. This frees up
    172         internal storage associated with those segments.
    173         This does NOT change the fill-type setting nor isConvex
    174     */
    175     void reset();
    176 
    177     /** Similar to reset(), in that all lines and curves are removed from the
    178         path. However, any internal storage for those lines/curves is retained,
    179         making reuse of the path potentially faster.
    180         This does NOT change the fill-type setting nor isConvex
    181     */
    182     void rewind();
    183 
    184     /** Returns true if the path is empty (contains no lines or curves)
    185 
    186         @return true if the path is empty (contains no lines or curves)
    187     */
    188     bool isEmpty() const;
    189 
    190     /** Returns true if the path specifies a rectangle. If so, and if rect is
    191         not null, set rect to the bounds of the path. If the path does not
    192         specify a rectangle, return false and ignore rect.
    193 
    194         @param rect If not null, returns the bounds of the path if it specifies
    195                     a rectangle
    196         @return true if the path specifies a rectangle
    197     */
    198     bool isRect(SkRect* rect) const;
    199 
    200     /** Return the number of points in the path
    201      */
    202     int countPoints() const {
    203         return this->getPoints(NULL, 0);
    204     }
    205 
    206     /** Return the point at the specified index. If the index is out of range
    207          (i.e. is not 0 <= index < countPoints()) then the returned coordinates
    208          will be (0,0)
    209      */
    210     SkPoint getPoint(int index) const;
    211 
    212     /** Returns the number of points in the path. Up to max points are copied.
    213 
    214         @param points If not null, receives up to max points
    215         @param max The maximum number of points to copy into points
    216         @return the actual number of points in the path
    217     */
    218     int getPoints(SkPoint points[], int max) const;
    219 
    220     //! Swap contents of this and other. Guaranteed not to throw
    221     void swap(SkPath& other);
    222 
    223     /** Returns the bounds of the path's points. If the path contains 0 or 1
    224         points, the bounds is set to (0,0,0,0), and isEmpty() will return true.
    225         Note: this bounds may be larger than the actual shape, since curves
    226         do not extend as far as their control points.
    227     */
    228     const SkRect& getBounds() const {
    229         if (fBoundsIsDirty) {
    230             this->computeBounds();
    231         }
    232         return fBounds;
    233     }
    234 
    235     /** Calling this will, if the internal cache of the bounds is out of date,
    236         update it so that subsequent calls to getBounds will be instanteous.
    237         This also means that any copies or simple transformations of the path
    238         will inherit the cached bounds.
    239      */
    240     void updateBoundsCache() const {
    241         // for now, just calling getBounds() is sufficient
    242         this->getBounds();
    243     }
    244 
    245     //  Construction methods
    246 
    247     /** Hint to the path to prepare for adding more points. This can allow the
    248         path to more efficiently grow its storage.
    249 
    250         @param extraPtCount The number of extra points the path should
    251                             preallocate for.
    252     */
    253     void incReserve(unsigned extraPtCount);
    254 
    255     /** Set the beginning of the next contour to the point (x,y).
    256 
    257         @param x    The x-coordinate of the start of a new contour
    258         @param y    The y-coordinate of the start of a new contour
    259     */
    260     void moveTo(SkScalar x, SkScalar y);
    261 
    262     /** Set the beginning of the next contour to the point
    263 
    264         @param p    The start of a new contour
    265     */
    266     void moveTo(const SkPoint& p) {
    267         this->moveTo(p.fX, p.fY);
    268     }
    269 
    270     /** Set the beginning of the next contour relative to the last point on the
    271         previous contour. If there is no previous contour, this is treated the
    272         same as moveTo().
    273 
    274         @param dx   The amount to add to the x-coordinate of the end of the
    275                     previous contour, to specify the start of a new contour
    276         @param dy   The amount to add to the y-coordinate of the end of the
    277                     previous contour, to specify the start of a new contour
    278     */
    279     void rMoveTo(SkScalar dx, SkScalar dy);
    280 
    281     /** Add a line from the last point to the specified point (x,y). If no
    282         moveTo() call has been made for this contour, the first point is
    283         automatically set to (0,0).
    284 
    285         @param x    The x-coordinate of the end of a line
    286         @param y    The y-coordinate of the end of a line
    287     */
    288     void lineTo(SkScalar x, SkScalar y);
    289 
    290     /** Add a line from the last point to the specified point. If no moveTo()
    291         call has been made for this contour, the first point is automatically
    292         set to (0,0).
    293 
    294         @param p    The end of a line
    295     */
    296     void lineTo(const SkPoint& p) {
    297         this->lineTo(p.fX, p.fY);
    298     }
    299 
    300     /** Same as lineTo, but the coordinates are considered relative to the last
    301         point on this contour. If there is no previous point, then a moveTo(0,0)
    302         is inserted automatically.
    303 
    304         @param dx   The amount to add to the x-coordinate of the previous point
    305                     on this contour, to specify a line
    306         @param dy   The amount to add to the y-coordinate of the previous point
    307                     on this contour, to specify a line
    308     */
    309     void rLineTo(SkScalar dx, SkScalar dy);
    310 
    311     /** Add a quadratic bezier from the last point, approaching control point
    312         (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for
    313         this contour, the first point is automatically set to (0,0).
    314 
    315         @param x1   The x-coordinate of the control point on a quadratic curve
    316         @param y1   The y-coordinate of the control point on a quadratic curve
    317         @param x2   The x-coordinate of the end point on a quadratic curve
    318         @param y2   The y-coordinate of the end point on a quadratic curve
    319     */
    320     void quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2);
    321 
    322     /** Add a quadratic bezier from the last point, approaching control point
    323         p1, and ending at p2. If no moveTo() call has been made for this
    324         contour, the first point is automatically set to (0,0).
    325 
    326         @param p1   The control point on a quadratic curve
    327         @param p2   The end point on a quadratic curve
    328     */
    329     void quadTo(const SkPoint& p1, const SkPoint& p2) {
    330         this->quadTo(p1.fX, p1.fY, p2.fX, p2.fY);
    331     }
    332 
    333     /** Same as quadTo, but the coordinates are considered relative to the last
    334         point on this contour. If there is no previous point, then a moveTo(0,0)
    335         is inserted automatically.
    336 
    337         @param dx1   The amount to add to the x-coordinate of the last point on
    338                 this contour, to specify the control point of a quadratic curve
    339         @param dy1   The amount to add to the y-coordinate of the last point on
    340                 this contour, to specify the control point of a quadratic curve
    341         @param dx2   The amount to add to the x-coordinate of the last point on
    342                      this contour, to specify the end point of a quadratic curve
    343         @param dy2   The amount to add to the y-coordinate of the last point on
    344                      this contour, to specify the end point of a quadratic curve
    345     */
    346     void rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2);
    347 
    348     /** Add a cubic bezier from the last point, approaching control points
    349         (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been
    350         made for this contour, the first point is automatically set to (0,0).
    351 
    352         @param x1   The x-coordinate of the 1st control point on a cubic curve
    353         @param y1   The y-coordinate of the 1st control point on a cubic curve
    354         @param x2   The x-coordinate of the 2nd control point on a cubic curve
    355         @param y2   The y-coordinate of the 2nd control point on a cubic curve
    356         @param x3   The x-coordinate of the end point on a cubic curve
    357         @param y3   The y-coordinate of the end point on a cubic curve
    358     */
    359     void cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
    360                  SkScalar x3, SkScalar y3);
    361 
    362     /** Add a cubic bezier from the last point, approaching control points p1
    363         and p2, and ending at p3. If no moveTo() call has been made for this
    364         contour, the first point is automatically set to (0,0).
    365 
    366         @param p1   The 1st control point on a cubic curve
    367         @param p2   The 2nd control point on a cubic curve
    368         @param p3   The end point on a cubic curve
    369     */
    370     void cubicTo(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3) {
    371         this->cubicTo(p1.fX, p1.fY, p2.fX, p2.fY, p3.fX, p3.fY);
    372     }
    373 
    374     /** Same as cubicTo, but the coordinates are considered relative to the
    375         current point on this contour. If there is no previous point, then a
    376         moveTo(0,0) is inserted automatically.
    377 
    378         @param dx1   The amount to add to the x-coordinate of the last point on
    379                 this contour, to specify the 1st control point of a cubic curve
    380         @param dy1   The amount to add to the y-coordinate of the last point on
    381                 this contour, to specify the 1st control point of a cubic curve
    382         @param dx2   The amount to add to the x-coordinate of the last point on
    383                 this contour, to specify the 2nd control point of a cubic curve
    384         @param dy2   The amount to add to the y-coordinate of the last point on
    385                 this contour, to specify the 2nd control point of a cubic curve
    386         @param dx3   The amount to add to the x-coordinate of the last point on
    387                      this contour, to specify the end point of a cubic curve
    388         @param dy3   The amount to add to the y-coordinate of the last point on
    389                      this contour, to specify the end point of a cubic curve
    390     */
    391     void    rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
    392                      SkScalar x3, SkScalar y3);
    393 
    394     /** Append the specified arc to the path as a new contour. If the start of
    395         the path is different from the path's current last point, then an
    396         automatic lineTo() is added to connect the current contour to the start
    397         of the arc. However, if the path is empty, then we call moveTo() with
    398         the first point of the arc. The sweep angle is treated mod 360.
    399 
    400         @param oval The bounding oval defining the shape and size of the arc
    401         @param startAngle Starting angle (in degrees) where the arc begins
    402         @param sweepAngle Sweep angle (in degrees) measured clockwise. This is
    403                           treated mod 360.
    404         @param forceMoveTo If true, always begin a new contour with the arc
    405     */
    406     void    arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
    407                   bool forceMoveTo);
    408 
    409     /** Append a line and arc to the current path. This is the same as the
    410         PostScript call "arct".
    411     */
    412     void arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
    413                SkScalar radius);
    414 
    415     /** Append a line and arc to the current path. This is the same as the
    416         PostScript call "arct".
    417     */
    418     void arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius) {
    419         this->arcTo(p1.fX, p1.fY, p2.fX, p2.fY, radius);
    420     }
    421 
    422     /** Close the current contour. If the current point is not equal to the
    423         first point of the contour, a line segment is automatically added.
    424     */
    425     void close();
    426 
    427     enum Direction {
    428         /** clockwise direction for adding closed contours */
    429         kCW_Direction,
    430         /** counter-clockwise direction for adding closed contours */
    431         kCCW_Direction
    432     };
    433 
    434     /** Add a closed rectangle contour to the path
    435         @param rect The rectangle to add as a closed contour to the path
    436         @param dir  The direction to wind the rectangle's contour
    437     */
    438     void    addRect(const SkRect& rect, Direction dir = kCW_Direction);
    439 
    440     /** Add a closed rectangle contour to the path
    441 
    442         @param left     The left side of a rectangle to add as a closed contour
    443                         to the path
    444         @param top      The top of a rectangle to add as a closed contour to the
    445                         path
    446         @param right    The right side of a rectangle to add as a closed contour
    447                         to the path
    448         @param bottom   The bottom of a rectangle to add as a closed contour to
    449                         the path
    450         @param dir      The direction to wind the rectangle's contour
    451     */
    452     void addRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom,
    453                  Direction dir = kCW_Direction);
    454 
    455     /** Add a closed oval contour to the path
    456 
    457         @param oval The bounding oval to add as a closed contour to the path
    458         @param dir  The direction to wind the oval's contour
    459     */
    460     void addOval(const SkRect& oval, Direction dir = kCW_Direction);
    461 
    462     /** Add a closed circle contour to the path
    463 
    464         @param x        The x-coordinate of the center of a circle to add as a
    465                         closed contour to the path
    466         @param y        The y-coordinate of the center of a circle to add as a
    467                         closed contour to the path
    468         @param radius   The radius of a circle to add as a closed contour to the
    469                         path
    470         @param dir      The direction to wind the circle's contour
    471     */
    472     void addCircle(SkScalar x, SkScalar y, SkScalar radius,
    473                    Direction dir = kCW_Direction);
    474 
    475     /** Add the specified arc to the path as a new contour.
    476 
    477         @param oval The bounds of oval used to define the size of the arc
    478         @param startAngle Starting angle (in degrees) where the arc begins
    479         @param sweepAngle Sweep angle (in degrees) measured clockwise
    480     */
    481     void addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle);
    482 
    483     /** Add a closed round-rectangle contour to the path
    484         @param rect The bounds of a round-rectangle to add as a closed contour
    485         @param rx   The x-radius of the rounded corners on the round-rectangle
    486         @param ry   The y-radius of the rounded corners on the round-rectangle
    487         @param dir  The direction to wind the round-rectangle's contour
    488     */
    489     void    addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
    490                          Direction dir = kCW_Direction);
    491 
    492     /** Add a closed round-rectangle contour to the path. Each corner receives
    493         two radius values [X, Y]. The corners are ordered top-left, top-right,
    494         bottom-right, bottom-left.
    495         @param rect The bounds of a round-rectangle to add as a closed contour
    496         @param radii Array of 8 scalars, 4 [X,Y] pairs for each corner
    497         @param dir  The direction to wind the round-rectangle's contour
    498         */
    499     void addRoundRect(const SkRect& rect, const SkScalar radii[],
    500                       Direction dir = kCW_Direction);
    501 
    502     /** Add a copy of src to the path, offset by (dx,dy)
    503         @param src  The path to add as a new contour
    504         @param dx   The amount to translate the path in X as it is added
    505         @param dx   The amount to translate the path in Y as it is added
    506     */
    507     void    addPath(const SkPath& src, SkScalar dx, SkScalar dy);
    508 
    509     /** Add a copy of src to the path
    510     */
    511     void addPath(const SkPath& src) {
    512         SkMatrix m;
    513         m.reset();
    514         this->addPath(src, m);
    515     }
    516 
    517     /** Add a copy of src to the path, transformed by matrix
    518         @param src  The path to add as a new contour
    519     */
    520     void addPath(const SkPath& src, const SkMatrix& matrix);
    521 
    522     /** Offset the path by (dx,dy), returning true on success
    523 
    524         @param dx   The amount in the X direction to offset the entire path
    525         @param dy   The amount in the Y direction to offset the entire path
    526         @param dst  The translated path is written here
    527     */
    528     void offset(SkScalar dx, SkScalar dy, SkPath* dst) const;
    529 
    530     /** Offset the path by (dx,dy), returning true on success
    531 
    532         @param dx   The amount in the X direction to offset the entire path
    533         @param dy   The amount in the Y direction to offset the entire path
    534     */
    535     void offset(SkScalar dx, SkScalar dy) {
    536         this->offset(dx, dy, this);
    537     }
    538 
    539     /** Transform the points in this path by matrix, and write the answer into
    540         dst.
    541 
    542         @param matrix   The matrix to apply to the path
    543         @param dst      The transformed path is written here
    544     */
    545     void transform(const SkMatrix& matrix, SkPath* dst) const;
    546 
    547     /** Transform the points in this path by matrix
    548 
    549         @param matrix The matrix to apply to the path
    550     */
    551     void transform(const SkMatrix& matrix) {
    552         this->transform(matrix, this);
    553     }
    554 
    555     /** Return the last point on the path. If no points have been added, (0,0)
    556         is returned.
    557 
    558         @param lastPt   The last point on the path is returned here
    559     */
    560     void getLastPt(SkPoint* lastPt) const;
    561 
    562     /** Set the last point on the path. If no points have been added,
    563         moveTo(x,y) is automatically called.
    564 
    565         @param x    The new x-coordinate for the last point
    566         @param y    The new y-coordinate for the last point
    567     */
    568     void setLastPt(SkScalar x, SkScalar y);
    569 
    570     /** Set the last point on the path. If no points have been added, moveTo(p)
    571         is automatically called.
    572 
    573         @param p    The new location for the last point
    574     */
    575     void setLastPt(const SkPoint& p) {
    576         this->setLastPt(p.fX, p.fY);
    577     }
    578 
    579     enum Verb {
    580         kMove_Verb,     //!< iter.next returns 1 point
    581         kLine_Verb,     //!< iter.next returns 2 points
    582         kQuad_Verb,     //!< iter.next returns 3 points
    583         kCubic_Verb,    //!< iter.next returns 4 points
    584         kClose_Verb,    //!< iter.next returns 1 point (the last point)
    585         kDone_Verb      //!< iter.next returns 0 points
    586     };
    587 
    588     /** Iterate through all of the segments (lines, quadratics, cubics) of
    589         each contours in a path.
    590     */
    591     class SK_API Iter {
    592     public:
    593                 Iter();
    594                 Iter(const SkPath&, bool forceClose);
    595 
    596         void setPath(const SkPath&, bool forceClose);
    597 
    598         /** Return the next verb in this iteration of the path. When all
    599             segments have been visited, return kDone_Verb.
    600 
    601             @param  pts The points representing the current verb and/or segment
    602             @return The verb for the current segment
    603         */
    604         Verb next(SkPoint pts[4]);
    605 
    606         /** If next() returns kLine_Verb, then this query returns true if the
    607             line was the result of a close() command (i.e. the end point is the
    608             initial moveto for this contour). If next() returned a different
    609             verb, this returns an undefined value.
    610 
    611             @return If the last call to next() returned kLine_Verb, return true
    612                     if it was the result of an explicit close command.
    613         */
    614         bool isCloseLine() const { return SkToBool(fCloseLine); }
    615 
    616         /** Returns true if the current contour is closed (has a kClose_Verb)
    617             @return true if the current contour is closed (has a kClose_Verb)
    618         */
    619         bool isClosedContour() const;
    620 
    621     private:
    622         const SkPoint*  fPts;
    623         const uint8_t*  fVerbs;
    624         const uint8_t*  fVerbStop;
    625         SkPoint         fMoveTo;
    626         SkPoint         fLastPt;
    627         SkBool8         fForceClose;
    628         SkBool8         fNeedClose;
    629         SkBool8         fNeedMoveTo;
    630         SkBool8         fCloseLine;
    631 
    632         bool cons_moveTo(SkPoint pts[1]);
    633         Verb autoClose(SkPoint pts[2]);
    634     };
    635 
    636     void dump(bool forceClose, const char title[] = NULL) const;
    637     void dump() const;
    638 
    639     void flatten(SkWriter32&) const;
    640     void unflatten(SkReader32&);
    641 
    642     /** Subdivide the path so that no segment is longer that dist.
    643         If bendLines is true, then turn all line segments into curves.
    644         If dst == null, then the original path itself is modified (not const!)
    645     */
    646     void subdivide(SkScalar dist, bool bendLines, SkPath* dst = NULL) const;
    647 
    648 #ifdef ANDROID
    649     uint32_t getGenerationID() const;
    650 #endif
    651 
    652     SkDEBUGCODE(void validate() const;)
    653 
    654 private:
    655     SkTDArray<SkPoint>  fPts;
    656     SkTDArray<uint8_t>  fVerbs;
    657     mutable SkRect      fBounds;
    658     mutable uint8_t     fBoundsIsDirty;
    659     uint8_t             fFillType;
    660     mutable uint8_t     fConvexity;
    661 #ifdef ANDROID
    662     uint32_t            fGenerationID;
    663 #endif
    664 
    665     // called, if dirty, by getBounds()
    666     void computeBounds() const;
    667 
    668     friend class Iter;
    669     void cons_moveto();
    670 
    671     friend class SkPathStroker;
    672     /*  Append the first contour of path, ignoring path's initial point. If no
    673         moveTo() call has been made for this contour, the first point is
    674         automatically set to (0,0).
    675     */
    676     void pathTo(const SkPath& path);
    677 
    678     /*  Append, in reverse order, the first contour of path, ignoring path's
    679         last point. If no moveTo() call has been made for this contour, the
    680         first point is automatically set to (0,0).
    681     */
    682     void reversePathTo(const SkPath&);
    683 
    684     friend const SkPoint* sk_get_path_points(const SkPath&, int index);
    685     friend class SkAutoPathBoundsUpdate;
    686 };
    687 
    688 #endif
    689 
    690