• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     */
getFillType()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     */
setFillType(FillType ft)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 */
isInverseFillType()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      */
toggleInverseFillType()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      */
getConvexity()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      */
getConvexityOrUnknown()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      */
isConvex()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      */
setIsConvex(bool isConvex)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      */
countPoints()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     */
getBounds()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      */
updateBoundsCache()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     */
moveTo(const SkPoint & p)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     */
lineTo(const SkPoint & p)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     */
quadTo(const SkPoint & p1,const SkPoint & p2)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     */
cubicTo(const SkPoint & p1,const SkPoint & p2,const SkPoint & p3)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     */
arcTo(const SkPoint p1,const SkPoint p2,SkScalar radius)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     */
addPath(const SkPath & src)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     */
offset(SkScalar dx,SkScalar dy)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     */
transform(const SkMatrix & matrix)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     */
setLastPt(const SkPoint & p)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         */
isCloseLine()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