• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2006 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkPath_DEFINED
9 #define SkPath_DEFINED
10 
11 #include "SkMatrix.h"
12 #include "../private/SkPathRef.h"
13 
14 class SkAutoPathBoundsUpdate;
15 class SkData;
16 class SkRRect;
17 class SkWStream;
18 
19 /** \class SkPath
20     SkPath contain geometry. SkPath may be empty, or contain one or more verbs that
21     outline a figure. SkPath always starts with a move verb to a Cartesian_Coordinate,
22     and may be followed by additional verbs that add lines or curves.
23     Adding a close verb makes the geometry into a continuous loop, a closed contour.
24     SkPath may contain any number of contours, each beginning with a move verb.
25 
26     SkPath contours may contain only a move verb, or may also contain lines,
27     quadratic beziers, conics, and cubic beziers. SkPath contours may be open or
28     closed.
29 
30     When used to draw a filled area, SkPath describes whether the fill is inside or
31     outside the geometry. SkPath also describes the winding rule used to fill
32     overlapping contours.
33 
34     Internally, SkPath lazily computes metrics likes bounds and convexity. Call
35     SkPath::updateBoundsCache to make SkPath thread safe.
36 */
37 class SK_API SkPath {
38 public:
39 
40     /** \enum SkPath::Direction
41         Direction describes whether contour is clockwise or counterclockwise.
42         When SkPath contains multiple overlapping contours, Direction together with
43         FillType determines whether overlaps are filled or form holes.
44 
45         Direction also determines how contour is measured. For instance, dashing
46         measures along SkPath to determine where to start and stop stroke; Direction
47         will change dashed results as it steps clockwise or counterclockwise.
48 
49         Closed contours like SkRect, SkRRect, circle, and oval added with
50         kCW_Direction travel clockwise; the same added with kCCW_Direction
51         travel counterclockwise.
52     */
53     enum Direction {
54         kCW_Direction,  //!< Contour travels in a clockwise direction
55         kCCW_Direction, //!< Contour travels in a counterclockwise direction
56     };
57 
58     /** By default, SkPath has no verbs, no SkPoint, and no weights.
59         SkPath::FillType is set to kWinding_FillType.
60 
61         @return  empty SkPath
62     */
63     SkPath();
64 
65     /** Copy constructor makes two paths identical by value. Internally, path and
66         the returned result share pointer values. The underlying verb array, SkPoint array
67         and weights are copied when modified.
68 
69         Creating a SkPath copy is very efficient and never allocates memory.
70         SkPath are always copied by value from the interface; the underlying shared
71         pointers are not exposed.
72 
73         @param path  SkPath to copy by value
74         @return      copy of SkPath
75     */
76     SkPath(const SkPath& path);
77 
78     /** Releases ownership of any shared data and deletes data if SkPath is sole owner.
79     */
80     ~SkPath();
81 
82     /** SkPath assignment makes two paths identical by value. Internally, assignment
83         shares pointer values. The underlying verb array, SkPoint array and weights
84         are copied when modified.
85 
86         Copying SkPath by assignment is very efficient and never allocates memory.
87         SkPath are always copied by value from the interface; the underlying shared
88         pointers are not exposed.
89 
90         @param path  verb array, SkPoint array, weights, and SkPath::FillType to copy
91         @return      SkPath copied by value
92     */
93     SkPath& operator=(const SkPath& path);
94 
95     /** Compares a and b; returns true if SkPath::FillType, verb array, SkPoint array, and weights
96         are equivalent.
97 
98         @param a  SkPath to compare
99         @param b  SkPath to compare
100         @return   true if SkPath pair are equivalent
101     */
102     friend SK_API bool operator==(const SkPath& a, const SkPath& b);
103 
104     /** Compares a and b; returns true if SkPath::FillType, verb array, SkPoint array, and weights
105         are not equivalent.
106 
107         @param a  SkPath to compare
108         @param b  SkPath to compare
109         @return   true if SkPath pair are not equivalent
110     */
111     friend bool operator!=(const SkPath& a, const SkPath& b) {
112         return !(a == b);
113     }
114 
115     /** Return true if SkPath contain equal verbs and equal weights.
116         If SkPath contain one or more conics, the weights must match.
117 
118         conicTo() may add different verbs depending on conic weight, so it is not
119         trivial to interpolate a pair of SkPath containing conics with different
120         conic weight values.
121 
122         @param compare  SkPath to compare
123         @return         true if SkPath verb array and weights are equivalent
124     */
125     bool isInterpolatable(const SkPath& compare) const;
126 
127     /** Interpolate between SkPath with SkPoint array of equal size.
128         Copy verb array and weights to out, and set out SkPoint array to a weighted
129         average of this SkPoint array and ending SkPoint array, using the formula: (Path Point * weight) + ending Point * (1 - weight).
130 
131         weight is most useful when between zero (ending SkPoint array) and
132         one (this Point_Array); will work with values outside of this
133         range.
134 
135         interpolate() returns false and leaves out unchanged if SkPoint array is not
136         the same size as ending SkPoint array. Call isInterpolatable() to check SkPath
137         compatibility prior to calling interpolate().
138 
139         @param ending  SkPoint array averaged with this SkPoint array
140         @param weight  contribution of this SkPoint array, and
141                        one minus contribution of ending SkPoint array
142         @param out     SkPath replaced by interpolated averages
143         @return        true if SkPath contain same number of SkPoint
144     */
145     bool interpolate(const SkPath& ending, SkScalar weight, SkPath* out) const;
146 
147 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
148     /** To be deprecated soon.
149         Only valid for Android framework.
150     */
unique()151     bool unique() const { return fPathRef->unique(); }
152 #endif
153 
154     /** \enum SkPath::FillType
155         FillType selects the rule used to fill SkPath. SkPath set to kWinding_FillType
156         fills if the sum of contour edges is not zero, where clockwise edges add one, and
157         counterclockwise edges subtract one. SkPath set to kEvenOdd_FillType fills if the
158         number of contour edges is odd. Each FillType has an inverse variant that
159         reverses the rule:
160         kInverseWinding_FillType fills where the sum of contour edges is zero;
161         kInverseEvenOdd_FillType fills where the number of contour edges is even.
162     */
163     enum FillType {
164         /** Specifies fill as area is enclosed by a non-zero sum of contour directions. */
165         kWinding_FillType,
166 
167         /** Specifies fill as area enclosed by an odd number of contours. */
168         kEvenOdd_FillType,
169 
170         /** Specifies fill as area is enclosed by a zero sum of contour directions. */
171         kInverseWinding_FillType,
172 
173         /** Specifies fill as area enclosed by an even number of contours. */
174         kInverseEvenOdd_FillType,
175     };
176 
177     /** Returns FillType, the rule used to fill SkPath. FillType of a new SkPath is
178         kWinding_FillType.
179 
180         @return  one of: kWinding_FillType, kEvenOdd_FillType,  kInverseWinding_FillType,
181                  kInverseEvenOdd_FillType
182     */
getFillType()183     FillType getFillType() const { return (FillType)fFillType; }
184 
185     /** Sets FillType, the rule used to fill SkPath. While there is no check
186         that ft is legal, values outside of FillType are not supported.
187 
188         @param ft  one of: kWinding_FillType, kEvenOdd_FillType,  kInverseWinding_FillType,
189                    kInverseEvenOdd_FillType
190     */
setFillType(FillType ft)191     void setFillType(FillType ft) {
192         fFillType = SkToU8(ft);
193     }
194 
195     /** Returns if FillType describes area outside SkPath geometry. The inverse fill area
196         extends indefinitely.
197 
198         @return  true if FillType is kInverseWinding_FillType or kInverseEvenOdd_FillType
199     */
isInverseFillType()200     bool isInverseFillType() const { return IsInverseFillType((FillType)fFillType); }
201 
202     /** Replace FillType with its inverse. The inverse of FillType describes the area
203         unmodified by the original FillType.
204     */
toggleInverseFillType()205     void toggleInverseFillType() {
206         fFillType ^= 2;
207     }
208 
209     /** \enum SkPath::Convexity
210         SkPath is convex if it contains one contour and contour loops no more than
211         360 degrees, and contour angles all have same Direction. Convex SkPath
212         may have better performance and require fewer resources on GPU surface.
213 
214         SkPath is concave when either at least one Direction change is clockwise and
215         another is counterclockwise, or the sum of the changes in Direction is not 360
216         degrees.
217 
218         Initially SkPath Convexity is kUnknown_Convexity. SkPath Convexity is computed
219         if needed by destination SkSurface.
220     */
221     enum Convexity : uint8_t {
222         kUnknown_Convexity, //!< Indicates Convexity has not been determined.
223 
224         /** SkPath has one contour made of a simple geometry without indentations. */
225         kConvex_Convexity,
226         kConcave_Convexity, //!< SkPath has more than one contour, or a geometry with indentations.
227     };
228 
229     /** Computes SkPath::Convexity if required, and returns stored value.
230         SkPath::Convexity is computed if stored value is kUnknown_Convexity,
231         or if SkPath has been altered since SkPath::Convexity was computed or set.
232 
233         @return  computed or stored SkPath::Convexity
234     */
getConvexity()235     Convexity getConvexity() const {
236         for (Convexity convexity = fConvexity.load(); kUnknown_Convexity != convexity; ) {
237             return convexity;
238         }
239         return this->internalGetConvexity();
240     }
241 
242     /** Returns last computed SkPath::Convexity, or kUnknown_Convexity if
243         SkPath has been altered since SkPath::Convexity was computed or set.
244 
245         @return  stored SkPath::Convexity
246     */
getConvexityOrUnknown()247     Convexity getConvexityOrUnknown() const { return (Convexity)fConvexity; }
248 
249     /** Stores convexity so that it is later returned by getConvexity() or getConvexityOrUnknown().
250         convexity may differ from getConvexity(), although setting an incorrect value may
251         cause incorrect or inefficient drawing.
252 
253         If convexity is kUnknown_Convexity: getConvexity() will
254         compute SkPath::Convexity, and getConvexityOrUnknown() will return kUnknown_Convexity.
255 
256         If convexity is kConvex_Convexity or kConcave_Convexity, getConvexity()
257         and getConvexityOrUnknown() will return convexity until the path is
258         altered.
259 
260         @param convexity  one of: kUnknown_Convexity, kConvex_Convexity, or kConcave_Convexity
261     */
262     void setConvexity(Convexity convexity);
263 
264     /** Computes SkPath::Convexity if required, and returns true if value is kConvex_Convexity.
265         If setConvexity() was called with kConvex_Convexity or kConcave_Convexity, and
266         the path has not been altered, SkPath::Convexity is not recomputed.
267 
268         @return  true if SkPath::Convexity stored or computed is kConvex_Convexity
269     */
isConvex()270     bool isConvex() const {
271         return kConvex_Convexity == this->getConvexity();
272     }
273 
274     /** Returns true if this path is recognized as an oval or circle.
275 
276         bounds receives bounds of oval.
277 
278         bounds is unmodified if oval is not found.
279 
280         @param bounds  storage for bounding SkRect of oval; may be nullptr
281         @return        true if SkPath is recognized as an oval or circle
282     */
283     bool isOval(SkRect* bounds) const;
284 
285     /** Returns true if this path is recognized as a SkRRect (but not an oval/circle or rect).
286 
287         rrect receives bounds of SkRRect.
288 
289         rrect is unmodified if SkRRect is not found.
290 
291         @param rrect  storage for bounding SkRect of SkRRect; may be nullptr
292         @return       true if SkPath contains only SkRRect
293     */
294     bool isRRect(SkRRect* rrect) const;
295 
296     /** Sets SkPath to its initial state.
297         Removes verb array, SkPoint array, and weights, and sets FillType to kWinding_FillType.
298         Internal storage associated with SkPath is released.
299     */
300     void reset();
301 
302     /** Sets SkPath to its initial state, preserving internal storage.
303         Removes verb array, SkPoint array, and weights, and sets FillType to kWinding_FillType.
304         Internal storage associated with SkPath is retained.
305 
306         Use rewind() instead of reset() if SkPath storage will be reused and performance
307         is critical.
308     */
309     void rewind();
310 
311     /** Empty SkPath may have FillType but has no SkPoint, SkPath::Verb, or conic weight.
312         SkPath() constructs empty SkPath; reset() and (rewind) make SkPath empty.
313 
314         @return  true if the path contains no SkPath::Verb array
315     */
isEmpty()316     bool isEmpty() const {
317         SkDEBUGCODE(this->validate();)
318         return 0 == fPathRef->countVerbs();
319     }
320 
321     /** Contour is closed if SkPath SkPath::Verb array was last modified by close(). When stroked,
322         closed contour draws SkPaint::Join instead of SkPaint::Cap at first and last SkPoint.
323 
324         @return  true if the last contour ends with a kClose_Verb
325     */
326     bool isLastContourClosed() const;
327 
328     /** Returns true for finite SkPoint array values between negative SK_ScalarMax and
329         positive SK_ScalarMax. Returns false for any SkPoint array value of
330         SK_ScalarInfinity, SK_ScalarNegativeInfinity, or SK_ScalarNaN.
331 
332         @return  true if all SkPoint values are finite
333     */
isFinite()334     bool isFinite() const {
335         SkDEBUGCODE(this->validate();)
336         return fPathRef->isFinite();
337     }
338 
339     /** Returns true if the path is volatile; it will not be altered or discarded
340         by the caller after it is drawn. SkPath by default have volatile set false, allowing
341         SkSurface to attach a cache of data which speeds repeated drawing. If true, SkSurface
342         may not speed repeated drawing.
343 
344         @return  true if caller will alter SkPath after drawing
345     */
isVolatile()346     bool isVolatile() const {
347         return SkToBool(fIsVolatile);
348     }
349 
350     /** Specify whether SkPath is volatile; whether it will be altered or discarded
351         by the caller after it is drawn. SkPath by default have volatile set false, allowing
352         SkBaseDevice to attach a cache of data which speeds repeated drawing.
353 
354         Mark temporary paths, discarded or modified after use, as volatile
355         to inform SkBaseDevice that the path need not be cached.
356 
357         Mark animating SkPath volatile to improve performance.
358         Mark unchanging SkPath non-volatile to improve repeated rendering.
359 
360         raster surface SkPath draws are affected by volatile for some shadows.
361         GPU surface SkPath draws are affected by volatile for some shadows and concave geometries.
362 
363         @param isVolatile  true if caller will alter SkPath after drawing
364     */
setIsVolatile(bool isVolatile)365     void setIsVolatile(bool isVolatile) {
366         fIsVolatile = isVolatile;
367     }
368 
369     /** Test if line between SkPoint pair is degenerate.
370         Line with no length or that moves a very short distance is degenerate; it is
371         treated as a point.
372 
373         exact changes the equality test. If true, returns true only if p1 equals p2.
374         If false, returns true if p1 equals or nearly equals p2.
375 
376         @param p1     line start point
377         @param p2     line end point
378         @param exact  if false, allow nearly equals
379         @return       true if line is degenerate; its length is effectively zero
380     */
381     static bool IsLineDegenerate(const SkPoint& p1, const SkPoint& p2, bool exact);
382 
383     /** Test if quad is degenerate.
384         Quad with no length or that moves a very short distance is degenerate; it is
385         treated as a point.
386 
387         @param p1     quad start point
388         @param p2     quad control point
389         @param p3     quad end point
390         @param exact  if true, returns true only if p1, p2, and p3 are equal;
391                       if false, returns true if p1, p2, and p3 are equal or nearly equal
392         @return       true if quad is degenerate; its length is effectively zero
393     */
394     static bool IsQuadDegenerate(const SkPoint& p1, const SkPoint& p2,
395                                  const SkPoint& p3, bool exact);
396 
397     /** Test if cubic is degenerate.
398         Cubic with no length or that moves a very short distance is degenerate; it is
399         treated as a point.
400 
401         @param p1     cubic start point
402         @param p2     cubic control point 1
403         @param p3     cubic control point 2
404         @param p4     cubic end point
405         @param exact  if true, returns true only if p1, p2, p3, and p4 are equal;
406                       if false, returns true if p1, p2, p3, and p4 are equal or nearly equal
407         @return       true if cubic is degenerate; its length is effectively zero
408     */
409     static bool IsCubicDegenerate(const SkPoint& p1, const SkPoint& p2,
410                                   const SkPoint& p3, const SkPoint& p4, bool exact);
411 
412     /** Returns true if SkPath contains only one line;
413         SkPath::Verb array has two entries: kMove_Verb, kLine_Verb.
414         If SkPath contains one line and line is not nullptr, line is set to
415         line start point and line end point.
416         Returns false if SkPath is not one line; line is unaltered.
417 
418         @param line  storage for line. May be nullptr
419         @return      true if SkPath contains exactly one line
420     */
421     bool isLine(SkPoint line[2]) const;
422 
423     /** Returns the number of points in SkPath.
424         SkPoint count is initially zero.
425 
426         @return  SkPath SkPoint array length
427     */
428     int countPoints() const;
429 
430     /** Returns SkPoint at index in SkPoint array. Valid range for index is
431         0 to countPoints() - 1.
432         Returns (0, 0) if index is out of range.
433 
434         @param index  SkPoint array element selector
435         @return       SkPoint array value or (0, 0)
436     */
437     SkPoint getPoint(int index) const;
438 
439     /** Returns number of points in SkPath. Up to max points are copied.
440         points may be nullptr; then, max must be zero.
441         If max is greater than number of points, excess points storage is unaltered.
442 
443         @param points  storage for SkPath SkPoint array. May be nullptr
444         @param max     maximum to copy; must be greater than or equal to zero
445         @return        SkPath SkPoint array length
446     */
447     int getPoints(SkPoint points[], int max) const;
448 
449     /** Returns the number of verbs: kMove_Verb, kLine_Verb, kQuad_Verb, kConic_Verb,
450         kCubic_Verb, and kClose_Verb; added to SkPath.
451 
452         @return  length of verb array
453     */
454     int countVerbs() const;
455 
456     /** Returns the number of verbs in the path. Up to max verbs are copied. The
457         verbs are copied as one byte per verb.
458 
459         @param verbs  storage for verbs, may be nullptr
460         @param max    maximum number to copy into verbs
461         @return       the actual number of verbs in the path
462     */
463     int getVerbs(uint8_t verbs[], int max) const;
464 
465     /** Exchanges the verb array, SkPoint array, weights, and SkPath::FillType with other.
466         Cached state is also exchanged. swap() internally exchanges pointers, so
467         it is lightweight and does not allocate memory.
468 
469         swap() usage has largely been replaced by operator=(const SkPath& path).
470         SkPath do not copy their content on assignment until they are written to,
471         making assignment as efficient as swap().
472 
473         @param other  SkPath exchanged by value
474     */
475     void swap(SkPath& other);
476 
477     /** Returns minimum and maximum x and y values of SkPoint array.
478         Returns (0, 0, 0, 0) if SkPath contains no points. Returned bounds width and height may
479         be larger or smaller than area affected when SkPath is drawn.
480 
481         SkRect returned includes all SkPoint added to SkPath, including SkPoint associated with
482         kMove_Verb that define empty contours.
483 
484         @return  bounds of all SkPoint in SkPoint array
485     */
getBounds()486     const SkRect& getBounds() const {
487         return fPathRef->getBounds();
488     }
489 
490     /** Update internal bounds so that subsequent calls to getBounds() are instantaneous.
491         Unaltered copies of SkPath may also access cached bounds through getBounds().
492 
493         For now, identical to calling getBounds() and ignoring the returned value.
494 
495         Call to prepare SkPath subsequently drawn from multiple threads,
496         to avoid a race condition where each draw separately computes the bounds.
497     */
updateBoundsCache()498     void updateBoundsCache() const {
499         // for now, just calling getBounds() is sufficient
500         this->getBounds();
501     }
502 
503     /** Returns minimum and maximum x and y values of the lines and curves in SkPath.
504         Returns (0, 0, 0, 0) if SkPath contains no points.
505         Returned bounds width and height may be larger or smaller than area affected
506         when SkPath is drawn.
507 
508         Includes SkPoint associated with kMove_Verb that define empty
509         contours.
510 
511         Behaves identically to getBounds() when SkPath contains
512         only lines. If SkPath contains curves, computed bounds includes
513         the maximum extent of the quad, conic, or cubic; is slower than getBounds();
514         and unlike getBounds(), does not cache the result.
515 
516         @return  tight bounds of curves in SkPath
517     */
518     SkRect computeTightBounds() const;
519 
520     /** Returns true if rect is contained by SkPath.
521         May return false when rect is contained by SkPath.
522 
523         For now, only returns true if SkPath has one contour and is convex.
524         rect may share points and edges with SkPath and be contained.
525         Returns true if rect is empty, that is, it has zero width or height; and
526         the SkPoint or line described by rect is contained by SkPath.
527 
528         @param rect  SkRect, line, or SkPoint checked for containment
529         @return      true if rect is contained
530     */
531     bool conservativelyContainsRect(const SkRect& rect) const;
532 
533     /** grows SkPath verb array and SkPoint array to contain extraPtCount additional SkPoint.
534         May improve performance and use less memory by
535         reducing the number and size of allocations when creating SkPath.
536 
537         @param extraPtCount  number of additional SkPoint to allocate
538     */
539     void incReserve(unsigned extraPtCount);
540 
541     /** Adds beginning of contour at SkPoint (x, y).
542 
543         @param x  x-coordinate of contour start
544         @param y  y-coordinate of contour start
545     */
546     void moveTo(SkScalar x, SkScalar y);
547 
548     /** Adds beginning of contour at SkPoint p.
549 
550         @param p  contour start
551     */
moveTo(const SkPoint & p)552     void moveTo(const SkPoint& p) {
553         this->moveTo(p.fX, p.fY);
554     }
555 
556     /** Adds beginning of contour relative to last point.
557         If SkPath is empty, starts contour at (dx, dy).
558         Otherwise, start contour at last point offset by (dx, dy).
559         Function name stands for "relative move to".
560 
561         @param dx  offset from last point x to contour start x
562         @param dy  offset from last point y to contour start y
563     */
564     void rMoveTo(SkScalar dx, SkScalar dy);
565 
566     /** Adds line from last point to (x, y). If SkPath is empty, or last SkPath::Verb is
567         kClose_Verb, last point is set to (0, 0) before adding line.
568 
569         lineTo() appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.
570         lineTo() then appends kLine_Verb to verb array and (x, y) to SkPoint array.
571 
572         @param x  end of added line in x
573         @param y  end of added line in y
574     */
575     void lineTo(SkScalar x, SkScalar y);
576 
577     /** Adds line from last point to SkPoint p. If SkPath is empty, or last SkPath::Verb is
578         kClose_Verb, last point is set to (0, 0) before adding line.
579 
580         lineTo() first appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.
581         lineTo() then appends kLine_Verb to verb array and SkPoint p to SkPoint array.
582 
583         @param p  end SkPoint of added line
584     */
lineTo(const SkPoint & p)585     void lineTo(const SkPoint& p) {
586         this->lineTo(p.fX, p.fY);
587     }
588 
589     /** Adds line from last point to vector (dx, dy). If SkPath is empty, or last SkPath::Verb is
590         kClose_Verb, last point is set to (0, 0) before adding line.
591 
592         Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
593         then appends kLine_Verb to verb array and line end to SkPoint array.
594         Line end is last point plus vector (dx, dy).
595         Function name stands for "relative line to".
596 
597         @param dx  offset from last point x to line end x
598         @param dy  offset from last point y to line end y
599     */
600     void rLineTo(SkScalar dx, SkScalar dy);
601 
602     /** Adds quad from last point towards (x1, y1), to (x2, y2).
603         If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
604         before adding quad.
605 
606         Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
607         then appends kQuad_Verb to verb array; and (x1, y1), (x2, y2)
608         to SkPoint array.
609 
610         @param x1  control SkPoint of quad in x
611         @param y1  control SkPoint of quad in y
612         @param x2  end SkPoint of quad in x
613         @param y2  end SkPoint of quad in y
614     */
615     void quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2);
616 
617     /** Adds quad from last point towards SkPoint p1, to SkPoint p2.
618         If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
619         before adding quad.
620 
621         Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
622         then appends kQuad_Verb to verb array; and SkPoint p1, p2
623         to SkPoint array.
624 
625         @param p1  control SkPoint of added quad
626         @param p2  end SkPoint of added quad
627     */
quadTo(const SkPoint & p1,const SkPoint & p2)628     void quadTo(const SkPoint& p1, const SkPoint& p2) {
629         this->quadTo(p1.fX, p1.fY, p2.fX, p2.fY);
630     }
631 
632     /** Adds quad from last point towards vector (dx1, dy1), to vector (dx2, dy2).
633         If SkPath is empty, or last SkPath::Verb
634         is kClose_Verb, last point is set to (0, 0) before adding quad.
635 
636         Appends kMove_Verb to verb array and (0, 0) to SkPoint array,
637         if needed; then appends kQuad_Verb to verb array; and appends quad
638         control and quad end to SkPoint array.
639         Quad control is last point plus vector (dx1, dy1).
640         Quad end is last point plus vector (dx2, dy2).
641         Function name stands for "relative quad to".
642 
643         @param dx1  offset from last point x to quad control x
644         @param dy1  offset from last point x to quad control y
645         @param dx2  offset from last point x to quad end x
646         @param dy2  offset from last point x to quad end y
647     */
648     void rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2);
649 
650     /** Adds conic from last point towards (x1, y1), to (x2, y2), weighted by w.
651         If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
652         before adding conic.
653 
654         Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.
655 
656         If w is finite and not one, appends kConic_Verb to verb array;
657         and (x1, y1), (x2, y2) to SkPoint array; and w to conic weights.
658 
659         If w is one, appends kQuad_Verb to verb array, and
660         (x1, y1), (x2, y2) to SkPoint array.
661 
662         If w is not finite, appends kLine_Verb twice to verb array, and
663         (x1, y1), (x2, y2) to SkPoint array.
664 
665         @param x1  control SkPoint of conic in x
666         @param y1  control SkPoint of conic in y
667         @param x2  end SkPoint of conic in x
668         @param y2  end SkPoint of conic in y
669         @param w   weight of added conic
670     */
671     void conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
672                  SkScalar w);
673 
674     /** Adds conic from last point towards SkPoint p1, to SkPoint p2, weighted by w.
675         If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
676         before adding conic.
677 
678         Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.
679 
680         If w is finite and not one, appends kConic_Verb to verb array;
681         and SkPoint p1, p2 to SkPoint array; and w to conic weights.
682 
683         If w is one, appends kQuad_Verb to verb array, and SkPoint p1, p2
684         to SkPoint array.
685 
686         If w is not finite, appends kLine_Verb twice to verb array, and
687         SkPoint p1, p2 to SkPoint array.
688 
689         @param p1  control SkPoint of added conic
690         @param p2  end SkPoint of added conic
691         @param w   weight of added conic
692     */
conicTo(const SkPoint & p1,const SkPoint & p2,SkScalar w)693     void conicTo(const SkPoint& p1, const SkPoint& p2, SkScalar w) {
694         this->conicTo(p1.fX, p1.fY, p2.fX, p2.fY, w);
695     }
696 
697     /** Adds conic from last point towards vector (dx1, dy1), to vector (dx2, dy2),
698         weighted by w. If SkPath is empty, or last SkPath::Verb
699         is kClose_Verb, last point is set to (0, 0) before adding conic.
700 
701         Appends kMove_Verb to verb array and (0, 0) to SkPoint array,
702         if needed.
703 
704         If w is finite and not one, next appends kConic_Verb to verb array,
705         and w is recorded as conic weight; otherwise, if w is one, appends
706         kQuad_Verb to verb array; or if w is not finite, appends kLine_Verb
707         twice to verb array.
708 
709         In all cases appends SkPoint control and end to SkPoint array.
710         control is last point plus vector (dx1, dy1).
711         end is last point plus vector (dx2, dy2).
712 
713         Function name stands for "relative conic to".
714 
715         @param dx1  offset from last point x to conic control x
716         @param dy1  offset from last point x to conic control y
717         @param dx2  offset from last point x to conic end x
718         @param dy2  offset from last point x to conic end y
719         @param w    weight of added conic
720     */
721     void rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
722                   SkScalar w);
723 
724     /** Adds cubic from last point towards (x1, y1), then towards (x2, y2), ending at
725         (x3, y3). If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to
726         (0, 0) before adding cubic.
727 
728         Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
729         then appends kCubic_Verb to verb array; and (x1, y1), (x2, y2), (x3, y3)
730         to SkPoint array.
731 
732         @param x1  first control SkPoint of cubic in x
733         @param y1  first control SkPoint of cubic in y
734         @param x2  second control SkPoint of cubic in x
735         @param y2  second control SkPoint of cubic in y
736         @param x3  end SkPoint of cubic in x
737         @param y3  end SkPoint of cubic in y
738     */
739     void cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
740                  SkScalar x3, SkScalar y3);
741 
742     /** Adds cubic from last point towards SkPoint p1, then towards SkPoint p2, ending at
743         SkPoint p3. If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to
744         (0, 0) before adding cubic.
745 
746         Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
747         then appends kCubic_Verb to verb array; and SkPoint p1, p2, p3
748         to SkPoint array.
749 
750         @param p1  first control SkPoint of cubic
751         @param p2  second control SkPoint of cubic
752         @param p3  end SkPoint of cubic
753     */
cubicTo(const SkPoint & p1,const SkPoint & p2,const SkPoint & p3)754     void cubicTo(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3) {
755         this->cubicTo(p1.fX, p1.fY, p2.fX, p2.fY, p3.fX, p3.fY);
756     }
757 
758     /** Adds cubic from last point towards vector (dx1, dy1), then towards
759         vector (dx2, dy2), to vector (dx3, dy3).
760         If SkPath is empty, or last SkPath::Verb
761         is kClose_Verb, last point is set to (0, 0) before adding cubic.
762 
763         Appends kMove_Verb to verb array and (0, 0) to SkPoint array,
764         if needed; then appends kCubic_Verb to verb array; and appends cubic
765         control and cubic end to SkPoint array.
766         Cubic control is last point plus vector (dx1, dy1).
767         Cubic end is last point plus vector (dx2, dy2).
768         Function name stands for "relative cubic to".
769 
770         @param x1  offset from last point x to first cubic control x
771         @param y1  offset from last point x to first cubic control y
772         @param x2  offset from last point x to second cubic control x
773         @param y2  offset from last point x to second cubic control y
774         @param x3  offset from last point x to cubic end x
775         @param y3  offset from last point x to cubic end y
776     */
777     void rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
778                   SkScalar x3, SkScalar y3);
779 
780     /** Append arc to SkPath. Arc added is part of ellipse
781         bounded by oval, from startAngle through sweepAngle. Both startAngle and
782         sweepAngle are measured in degrees, where zero degrees is aligned with the
783         positive x-axis, and positive sweeps extends arc clockwise.
784 
785         arcTo() adds line connecting SkPath last SkPoint to initial arc SkPoint if forceMoveTo
786         is false and SkPath is not empty. Otherwise, added contour begins with first point
787         of arc. Angles greater than -360 and less than 360 are treated modulo 360.
788 
789         @param oval         bounds of ellipse containing arc
790         @param startAngle   starting angle of arc in degrees
791         @param sweepAngle   sweep, in degrees. Positive is clockwise; treated modulo 360
792         @param forceMoveTo  true to start a new contour with arc
793     */
794     void arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo);
795 
796     /** Append arc to SkPath, after appending line if needed. Arc is implemented by conic
797         weighted to describe part of circle. Arc is contained by tangent from
798         last SkPath point (x0, y0) to (x1, y1), and tangent from (x1, y1) to (x2, y2). Arc
799         is part of circle sized to radius, positioned so it touches both tangent lines.
800 
801         @param x1      x common to pair of tangents
802         @param y1      y common to pair of tangents
803         @param x2      x end of second tangent
804         @param y2      y end of second tangent
805         @param radius  distance from arc to circle center
806     */
807     void arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar radius);
808 
809     /** Append arc to SkPath, after appending line if needed. Arc is implemented by conic
810         weighted to describe part of circle. Arc is contained by tangent from
811         last SkPath point to p1, and tangent from p1 to p2. Arc
812         is part of circle sized to radius, positioned so it touches both tangent lines.
813 
814         If last SkPath SkPoint does not start arc, arcTo() appends connecting line to SkPath.
815         The length of vector from p1 to p2 does not affect arc.
816 
817         Arc sweep is always less than 180 degrees. If radius is zero, or if
818         tangents are nearly parallel, arcTo() appends line from last SkPath SkPoint to p1.
819 
820         arcTo() appends at most one line and one conic.
821         arcTo() implements the functionality of PostScript_Arct and HTML_Canvas_ArcTo.
822 
823         @param p1      SkPoint common to pair of tangents
824         @param p2      end of second tangent
825         @param radius  distance from arc to circle center
826     */
arcTo(const SkPoint p1,const SkPoint p2,SkScalar radius)827     void arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius) {
828         this->arcTo(p1.fX, p1.fY, p2.fX, p2.fY, radius);
829     }
830 
831     /** \enum SkPath::ArcSize
832         Four oval parts with radii (rx, ry) start at last SkPath SkPoint and ends at (x, y).
833         ArcSize and Direction select one of the four oval parts.
834     */
835     enum ArcSize {
836         kSmall_ArcSize, //!< smaller of arc pair
837         kLarge_ArcSize, //!< larger of arc pair
838     };
839 
840     /** Append arc to SkPath. Arc is implemented by one or more conics weighted to
841         describe part of oval with radii (rx, ry) rotated by xAxisRotate degrees. Arc
842         curves from last SkPath SkPoint to (x, y), choosing one of four possible routes:
843         clockwise or counterclockwise, and smaller or larger.
844 
845         Arc sweep is always less than 360 degrees. arcTo() appends line to (x, y) if
846         either radii are zero, or if last SkPath SkPoint equals (x, y). arcTo() scales radii
847         (rx, ry) to fit last SkPath SkPoint and (x, y) if both are greater than zero but
848         too small.
849 
850         arcTo() appends up to four conic curves.
851         arcTo() implements the functionality of svg arc, although SVG "sweep-flag" value
852         is opposite the integer value of sweep; SVG "sweep-flag" uses 1 for clockwise,
853         while kCW_Direction  cast to int is zero.
854 
855         @param rx           radius in x before x-axis rotation
856         @param ry           radius in y before x-axis rotation
857         @param xAxisRotate  x-axis rotation in degrees; positive values are clockwise
858         @param largeArc     chooses smaller or larger arc
859         @param sweep        chooses clockwise or counterclockwise arc
860         @param x            end of arc
861         @param y            end of arc
862     */
863     void arcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,
864                Direction sweep, SkScalar x, SkScalar y);
865 
866     /** Append arc to SkPath. Arc is implemented by one or more conic weighted to describe part of oval
867         with radii (r.fX, r.fY) rotated by xAxisRotate degrees. Arc curves from last SkPath SkPoint to
868         (xy.fX, xy.fY), choosing one of four possible routes: clockwise or counterclockwise,
869         and smaller or larger.
870 
871         Arc sweep is always less than 360 degrees. arcTo() appends line to xy if either radii are zero,
872         or if last SkPath SkPoint equals (x, y). arcTo() scales radii r to fit last SkPath SkPoint and
873         xy if both are greater than zero but too small to describe an arc.
874 
875         arcTo() appends up to four conic curves.
876         arcTo() implements the functionality of svg arc, although SVG "sweep-flag" value is
877         opposite the integer value of sweep; SVG "sweep-flag" uses 1 for clockwise, while
878         kCW_Direction cast to int is zero.
879 
880         @param r            radii in x and y before x-axis rotation
881         @param xAxisRotate  x-axis rotation in degrees; positive values are clockwise
882         @param largeArc     chooses smaller or larger arc
883         @param sweep        chooses clockwise or counterclockwise arc
884         @param xy           end of arc
885     */
arcTo(const SkPoint r,SkScalar xAxisRotate,ArcSize largeArc,Direction sweep,const SkPoint xy)886     void arcTo(const SkPoint r, SkScalar xAxisRotate, ArcSize largeArc, Direction sweep,
887                const SkPoint xy) {
888         this->arcTo(r.fX, r.fY, xAxisRotate, largeArc, sweep, xy.fX, xy.fY);
889     }
890 
891     /** Append arc to SkPath, relative to last SkPath SkPoint. Arc is implemented by one or
892         more conic, weighted to describe part of oval with radii (rx, ry) rotated by
893         xAxisRotate degrees. Arc curves from last SkPath SkPoint (x0, y0) to end SkPoint:
894         (x0 + dx, y0 + dy), choosing one of four possible routes: clockwise or
895         counterclockwise, and smaller or larger. If SkPath is empty, the start arc SkPoint
896         is (0, 0).
897 
898         Arc sweep is always less than 360 degrees. arcTo() appends line to end SkPoint
899         if either radii are zero, or if last SkPath SkPoint equals end SkPoint.
900         arcTo() scales radii (rx, ry) to fit last SkPath SkPoint and end SkPoint if both are
901         greater than zero but too small to describe an arc.
902 
903         arcTo() appends up to four conic curves.
904         arcTo() implements the functionality of svg arc, although SVG "sweep-flag" value is
905         opposite the integer value of sweep; SVG "sweep-flag" uses 1 for clockwise, while
906         kCW_Direction cast to int is zero.
907 
908         @param rx           radius in x before x-axis rotation
909         @param ry           radius in y before x-axis rotation
910         @param xAxisRotate  x-axis rotation in degrees; positive values are clockwise
911         @param largeArc     chooses smaller or larger arc
912         @param sweep        chooses clockwise or counterclockwise arc
913         @param dx           x offset end of arc from last SkPath SkPoint
914         @param dy           y offset end of arc from last SkPath SkPoint
915     */
916     void rArcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,
917                 Direction sweep, SkScalar dx, SkScalar dy);
918 
919     /** Append kClose_Verb to SkPath. A closed contour connects the first and last SkPoint
920         with line, forming a continuous loop. Open and closed contour draw the same
921         with SkPaint::kFill_Style. With SkPaint::kStroke_Style, open contour draws
922         SkPaint::Cap at contour start and end; closed contour draws
923         SkPaint::Join at contour start and end.
924 
925         close() has no effect if SkPath is empty or last SkPath SkPath::Verb is kClose_Verb.
926     */
927     void close();
928 
929     /** Returns true if fill is inverted and SkPath with fill represents area outside
930         of its geometric bounds.
931 
932         @param fill  one of: kWinding_FillType, kEvenOdd_FillType,
933                      kInverseWinding_FillType, kInverseEvenOdd_FillType
934         @return      true if SkPath fills outside its bounds
935     */
IsInverseFillType(FillType fill)936     static bool IsInverseFillType(FillType fill) {
937         static_assert(0 == kWinding_FillType, "fill_type_mismatch");
938         static_assert(1 == kEvenOdd_FillType, "fill_type_mismatch");
939         static_assert(2 == kInverseWinding_FillType, "fill_type_mismatch");
940         static_assert(3 == kInverseEvenOdd_FillType, "fill_type_mismatch");
941         return (fill & 2) != 0;
942     }
943 
944     /** Returns equivalent SkPath::FillType representing SkPath fill inside its bounds.
945         .
946 
947         @param fill  one of: kWinding_FillType, kEvenOdd_FillType,
948                      kInverseWinding_FillType, kInverseEvenOdd_FillType
949         @return      fill, or kWinding_FillType or kEvenOdd_FillType if fill is inverted
950     */
ConvertToNonInverseFillType(FillType fill)951     static FillType ConvertToNonInverseFillType(FillType fill) {
952         static_assert(0 == kWinding_FillType, "fill_type_mismatch");
953         static_assert(1 == kEvenOdd_FillType, "fill_type_mismatch");
954         static_assert(2 == kInverseWinding_FillType, "fill_type_mismatch");
955         static_assert(3 == kInverseEvenOdd_FillType, "fill_type_mismatch");
956         return (FillType)(fill & 1);
957     }
958 
959     /** Approximates conic with quad array. Conic is constructed from start SkPoint p0,
960         control SkPoint p1, end SkPoint p2, and weight w.
961         Quad array is stored in pts; this storage is supplied by caller.
962         Maximum quad count is 2 to the pow2.
963         Every third point in array shares last SkPoint of previous quad and first SkPoint of
964         next quad. Maximum pts storage size is given by: (1 + 2 * (1 << pow2)) * sizeof(SkPoint).
965 
966         Returns quad count used the approximation, which may be smaller
967         than the number requested.
968 
969         conic weight determines the amount of influence conic control point has on the curve.
970         w less than one represents an elliptical section. w greater than one represents
971         a hyperbolic section. w equal to one represents a parabolic section.
972 
973         Two quad curves are sufficient to approximate an elliptical conic with a sweep
974         of up to 90 degrees; in this case, set pow2 to one.
975 
976         @param p0    conic start SkPoint
977         @param p1    conic control SkPoint
978         @param p2    conic end SkPoint
979         @param w     conic weight
980         @param pts   storage for quad array
981         @param pow2  quad count, as power of two, normally 0 to 5 (1 to 32 quad curves)
982         @return      number of quad curves written to pts
983     */
984     static int ConvertConicToQuads(const SkPoint& p0, const SkPoint& p1, const SkPoint& p2,
985                                    SkScalar w, SkPoint pts[], int pow2);
986 
987     /** Returns true if SkPath is equivalent to SkRect when filled.
988         If false: rect, isClosed, and direction are unchanged.
989         If true: rect, isClosed, and direction are written to if not nullptr.
990 
991         rect may be smaller than the SkPath bounds. SkPath bounds may include kMove_Verb points
992         that do not alter the area drawn by the returned rect.
993 
994         @param rect       storage for bounds of SkRect; may be nullptr
995         @param isClosed   storage set to true if SkPath is closed; may be nullptr
996         @param direction  storage set to SkRect direction; may be nullptr
997         @return           true if SkPath contains SkRect
998     */
999     bool isRect(SkRect* rect, bool* isClosed = nullptr, Direction* direction = nullptr) const;
1000 
1001     /** Returns true if SkPath is equivalent to nested SkRect pair when filled.
1002         If false, rect and dirs are unchanged.
1003         If true, rect and dirs are written to if not nullptr:
1004         setting rect[0] to outer SkRect, and rect[1] to inner SkRect;
1005         setting dirs[0] to SkPath::Direction of outer SkRect, and dirs[1] to SkPath::Direction of inner
1006         SkRect.
1007 
1008         @param rect  storage for SkRect pair; may be nullptr
1009         @param dirs  storage for SkPath::Direction pair; may be nullptr
1010         @return      true if SkPath contains nested SkRect pair
1011     */
1012     bool isNestedFillRects(SkRect rect[2], Direction dirs[2] = nullptr) const;
1013 
1014     /** Add SkRect to SkPath, appending kMove_Verb, three kLine_Verb, and kClose_Verb,
1015         starting with top-left corner of SkRect; followed by top-right, bottom-right,
1016         and bottom-left if dir is kCW_Direction; or followed by bottom-left,
1017         bottom-right, and top-right if dir is kCCW_Direction.
1018 
1019         @param rect  SkRect to add as a closed contour
1020         @param dir   SkPath::Direction to wind added contour
1021     */
1022     void addRect(const SkRect& rect, Direction dir = kCW_Direction);
1023 
1024     /** Add SkRect to SkPath, appending kMove_Verb, three kLine_Verb, and kClose_Verb.
1025         If dir is kCW_Direction, SkRect corners are added clockwise; if dir is
1026         kCCW_Direction, SkRect corners are added counterclockwise.
1027         start determines the first corner added.
1028 
1029         @param rect   SkRect to add as a closed contour
1030         @param dir    SkPath::Direction to wind added contour
1031         @param start  initial corner of SkRect to add
1032     */
1033     void addRect(const SkRect& rect, Direction dir, unsigned start);
1034 
1035     /** Add SkRect (left, top, right, bottom) to SkPath,
1036         appending kMove_Verb, three kLine_Verb, and kClose_Verb,
1037         starting with top-left corner of SkRect; followed by top-right, bottom-right,
1038         and bottom-left if dir is kCW_Direction; or followed by bottom-left,
1039         bottom-right, and top-right if dir is kCCW_Direction.
1040 
1041         @param left    smaller x of SkRect
1042         @param top     smaller y of SkRect
1043         @param right   larger x of SkRect
1044         @param bottom  larger y of SkRect
1045         @param dir     SkPath::Direction to wind added contour
1046     */
1047     void addRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom,
1048                  Direction dir = kCW_Direction);
1049 
1050     /** Add oval to path, appending kMove_Verb, four kConic_Verb, and kClose_Verb.
1051         Oval is upright ellipse bounded by SkRect oval with radii equal to half oval width
1052         and half oval height. Oval begins at (oval.fRight, oval.centerY()) and continues
1053         clockwise if dir is kCW_Direction, counterclockwise if dir is kCCW_Direction.
1054 
1055         This form is identical to addOval(oval, dir, 1).
1056 
1057         @param oval  bounds of ellipse added
1058         @param dir   SkPath::Direction to wind ellipse
1059     */
1060     void addOval(const SkRect& oval, Direction dir = kCW_Direction);
1061 
1062     /** Add oval to SkPath, appending kMove_Verb, four kConic_Verb, and kClose_Verb.
1063         Oval is upright ellipse bounded by SkRect oval with radii equal to half oval width
1064         and half oval height. Oval begins at start and continues
1065         clockwise if dir is kCW_Direction, counterclockwise if dir is kCCW_Direction.
1066 
1067         @param oval   bounds of ellipse added
1068         @param dir    SkPath::Direction to wind ellipse
1069         @param start  index of initial point of ellipse
1070     */
1071     void addOval(const SkRect& oval, Direction dir, unsigned start);
1072 
1073     /** Add circle centered at (x, y) of size radius to SkPath, appending kMove_Verb,
1074         four kConic_Verb, and kClose_Verb. Circle begins at: (x + radius, y), continuing
1075         clockwise if dir is kCW_Direction, and counterclockwise if dir is kCCW_Direction.
1076 
1077         Has no effect if radius is zero or negative.
1078 
1079         @param x       center of circle
1080         @param y       center of circle
1081         @param radius  distance from center to edge
1082         @param dir     SkPath::Direction to wind circle
1083     */
1084     void addCircle(SkScalar x, SkScalar y, SkScalar radius,
1085                    Direction dir = kCW_Direction);
1086 
1087     /** Append arc to SkPath, as the start of new contour. Arc added is part of ellipse
1088         bounded by oval, from startAngle through sweepAngle. Both startAngle and
1089         sweepAngle are measured in degrees, where zero degrees is aligned with the
1090         positive x-axis, and positive sweeps extends arc clockwise.
1091 
1092         If sweepAngle <= -360, or sweepAngle >= 360; and startAngle modulo 90 is nearly
1093         zero, append oval instead of arc. Otherwise, sweepAngle values are treated
1094         modulo 360, and arc may or may not draw depending on numeric rounding.
1095 
1096         @param oval        bounds of ellipse containing arc
1097         @param startAngle  starting angle of arc in degrees
1098         @param sweepAngle  sweep, in degrees. Positive is clockwise; treated modulo 360
1099     */
1100     void addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle);
1101 
1102     /** Append SkRRect to SkPath, creating a new closed contour. SkRRect has bounds
1103         equal to rect; each corner is 90 degrees of an ellipse with radii (rx, ry). If
1104         dir is kCW_Direction, SkRRect starts at top-left of the lower-left corner and
1105         winds clockwise. If dir is kCCW_Direction, SkRRect starts at the bottom-left
1106         of the upper-left corner and winds counterclockwise.
1107 
1108         If either rx or ry is too large, rx and ry are scaled uniformly until the
1109         corners fit. If rx or ry is less than or equal to zero, addRoundRect() appends
1110         SkRect rect to SkPath.
1111 
1112         After appending, SkPath may be empty, or may contain: SkRect, oval, or RoundRect.
1113 
1114         @param rect  bounds of SkRRect
1115         @param rx    x-radius of rounded corners on the SkRRect
1116         @param ry    y-radius of rounded corners on the SkRRect
1117         @param dir   SkPath::Direction to wind SkRRect
1118     */
1119     void addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
1120                       Direction dir = kCW_Direction);
1121 
1122     /** Append SkRRect to SkPath, creating a new closed contour. SkRRect has bounds
1123         equal to rect; each corner is 90 degrees of an ellipse with radii from the
1124         array.
1125 
1126         @param rect   bounds of SkRRect
1127         @param radii  array of 8 SkScalar values, a radius pair for each corner
1128         @param dir    SkPath::Direction to wind SkRRect
1129     */
1130     void addRoundRect(const SkRect& rect, const SkScalar radii[],
1131                       Direction dir = kCW_Direction);
1132 
1133     /** Add rrect to SkPath, creating a new closed contour. If
1134         dir is kCW_Direction, rrect starts at top-left of the lower-left corner and
1135         winds clockwise. If dir is kCCW_Direction, rrect starts at the bottom-left
1136         of the upper-left corner and winds counterclockwise.
1137 
1138         After appending, SkPath may be empty, or may contain: SkRect, oval, or SkRRect.
1139 
1140         @param rrect  bounds and radii of rounded rectangle
1141         @param dir    SkPath::Direction to wind SkRRect
1142     */
1143     void addRRect(const SkRRect& rrect, Direction dir = kCW_Direction);
1144 
1145     /** Add rrect to SkPath, creating a new closed contour. If dir is kCW_Direction, rrect
1146         winds clockwise; if dir is kCCW_Direction, rrect winds counterclockwise.
1147         start determines the first point of rrect to add.
1148 
1149         @param rrect  bounds and radii of rounded rectangle
1150         @param dir    SkPath::Direction to wind SkRRect
1151         @param start  index of initial point of SkRRect
1152     */
1153     void addRRect(const SkRRect& rrect, Direction dir, unsigned start);
1154 
1155     /** Add contour created from line array, adding (count - 1) line segments.
1156         Contour added starts at pts[0], then adds a line for every additional SkPoint
1157         in pts array. If close is true,appends kClose_Verb to SkPath, connecting
1158         pts[count - 1] and pts[0].
1159 
1160         If count is zero, append kMove_Verb to path.
1161         Has no effect if count is less than one.
1162 
1163         @param pts    array of line sharing end and start SkPoint
1164         @param count  length of SkPoint array
1165         @param close  true to add line connecting contour end and start
1166     */
1167     void addPoly(const SkPoint pts[], int count, bool close);
1168 
1169     /** \enum SkPath::AddPathMode
1170         AddPathMode chooses how addPath() appends. Adding one SkPath to another can extend
1171         the last contour or start a new contour.
1172     */
1173     enum AddPathMode {
1174         /** Since SkPath verb array begins with kMove_Verb if src is not empty, this
1175             starts a new contour.
1176         */
1177         kAppend_AddPathMode,
1178 
1179         /** is not empty, add line from last point to added SkPath first SkPoint. Skip added
1180             SkPath initial kMove_Verb, then append remining verbs, SkPoint, and conic weights.
1181         */
1182         kExtend_AddPathMode,
1183     };
1184 
1185     /** Append src to SkPath, offset by (dx, dy).
1186 
1187         If mode is kAppend_AddPathMode, src verb array, SkPoint array, and conic weights are
1188         added unaltered. If mode is kExtend_AddPathMode, add line before appending
1189         verbs, SkPoint, and conic weights.
1190 
1191         @param src   SkPath verbs, SkPoint, and conic weights to add
1192         @param dx    offset added to src SkPoint array x coordinates
1193         @param dy    offset added to src SkPoint array y coordinates
1194         @param mode  kAppend_AddPathMode or kExtend_AddPathMode
1195     */
1196     void addPath(const SkPath& src, SkScalar dx, SkScalar dy,
1197                  AddPathMode mode = kAppend_AddPathMode);
1198 
1199     /** Append src to SkPath.
1200 
1201         If mode is kAppend_AddPathMode, src verb array, SkPoint array, and conic weights are
1202         added unaltered. If mode is kExtend_AddPathMode, add line before appending
1203         verbs, SkPoint, and conic weights.
1204 
1205         @param src   SkPath verbs, SkPoint, and conic weights to add
1206         @param mode  kAppend_AddPathMode or kExtend_AddPathMode
1207     */
1208     void addPath(const SkPath& src, AddPathMode mode = kAppend_AddPathMode) {
1209         SkMatrix m;
1210         m.reset();
1211         this->addPath(src, m, mode);
1212     }
1213 
1214     /** Append src to SkPath, transformed by matrix. Transformed curves may have different
1215         verbs, SkPoint, and conic weights.
1216 
1217         If mode is kAppend_AddPathMode, src verb array, SkPoint array, and conic weights are
1218         added unaltered. If mode is kExtend_AddPathMode, add line before appending
1219         verbs, SkPoint, and conic weights.
1220 
1221         @param src     SkPath verbs, SkPoint, and conic weights to add
1222         @param matrix  transform applied to src
1223         @param mode    kAppend_AddPathMode or kExtend_AddPathMode
1224     */
1225     void addPath(const SkPath& src, const SkMatrix& matrix, AddPathMode mode = kAppend_AddPathMode);
1226 
1227     /** Append src to SkPath, from back to front.
1228         Reversed src always appends a new contour to SkPath.
1229 
1230         @param src  SkPath verbs, SkPoint, and conic weights to add
1231     */
1232     void reverseAddPath(const SkPath& src);
1233 
1234     /** Offset SkPoint array by (dx, dy). Offset SkPath replaces dst.
1235         If dst is nullptr, SkPath is replaced by offset data.
1236 
1237         @param dx   offset added to SkPoint array x coordinates
1238         @param dy   offset added to SkPoint array y coordinates
1239         @param dst  overwritten, translated copy of SkPath; may be nullptr
1240     */
1241     void offset(SkScalar dx, SkScalar dy, SkPath* dst) const;
1242 
1243     /** Offset SkPoint array by (dx, dy). SkPath is replaced by offset data.
1244 
1245         @param dx  offset added to SkPoint array x coordinates
1246         @param dy  offset added to SkPoint array y coordinates
1247     */
offset(SkScalar dx,SkScalar dy)1248     void offset(SkScalar dx, SkScalar dy) {
1249         this->offset(dx, dy, this);
1250     }
1251 
1252     /** Transform verb array, SkPoint array, and weight by matrix.
1253         transform may change verbs and increase their number.
1254         Transformed SkPath replaces dst; if dst is nullptr, original data
1255         is replaced.
1256 
1257         @param matrix  SkMatrix to apply to SkPath
1258         @param dst     overwritten, transformed copy of SkPath; may be nullptr
1259     */
1260     void transform(const SkMatrix& matrix, SkPath* dst) const;
1261 
1262     /** Transform verb array, SkPoint array, and weight by matrix.
1263         transform may change verbs and increase their number.
1264         SkPath is replaced by transformed data.
1265 
1266         @param matrix  SkMatrix to apply to SkPath
1267     */
transform(const SkMatrix & matrix)1268     void transform(const SkMatrix& matrix) {
1269         this->transform(matrix, this);
1270     }
1271 
1272     /** Returns last point on SkPath in lastPt. Returns false if SkPoint array is empty,
1273         storing (0, 0) if lastPt is not nullptr.
1274 
1275         @param lastPt  storage for final SkPoint in SkPoint array; may be nullptr
1276         @return        true if SkPoint array contains one or more SkPoint
1277     */
1278     bool getLastPt(SkPoint* lastPt) const;
1279 
1280     /** Set last point to (x, y). If SkPoint array is empty, append kMove_Verb to
1281         verb array and (x, y) to SkPoint array.
1282 
1283         @param x  set x-coordinate of last point
1284         @param y  set y-coordinate of last point
1285     */
1286     void setLastPt(SkScalar x, SkScalar y);
1287 
1288     /** Set the last point on the path. If no points have been added, moveTo(p)
1289         is automatically called.
1290 
1291         @param p  set value of last point
1292     */
setLastPt(const SkPoint & p)1293     void setLastPt(const SkPoint& p) {
1294         this->setLastPt(p.fX, p.fY);
1295     }
1296 
1297     /** \enum SkPath::SegmentMask
1298         SegmentMask constants correspond to each drawing Verb type in SkPath; for
1299         instance, if SkPath only contains lines, only the kLine_SegmentMask bit is set.
1300     */
1301     enum SegmentMask {
1302         kLine_SegmentMask  = 1 << 0, //!< Set if verb array contains kLine_Verb.
1303 
1304         /** Set if verb array contains kQuad_Verb. Note that conicTo() may add a quad. */
1305         kQuad_SegmentMask  = 1 << 1,
1306         kConic_SegmentMask = 1 << 2, //!< Set if verb array contains kConic_Verb.
1307         kCubic_SegmentMask = 1 << 3, //!< Set if verb array contains kCubic_Verb.
1308     };
1309 
1310     /** Returns a mask, where each set bit corresponds to a SegmentMask constant
1311         if SkPath contains one or more verbs of that type.
1312         Returns zero if SkPath contains no lines, or curves: quads, conics, or cubics.
1313 
1314         getSegmentMasks() returns a cached result; it is very fast.
1315 
1316         @return  SegmentMask bits or zero
1317     */
getSegmentMasks()1318     uint32_t getSegmentMasks() const { return fPathRef->getSegmentMasks(); }
1319 
1320     /** \enum SkPath::Verb
1321         Verb instructs SkPath how to interpret one or more SkPoint and optional conic weight;
1322         manage contour, and terminate SkPath.
1323     */
1324     enum Verb {
1325         kMove_Verb,  //!< Starts new contour at next SkPoint.
1326 
1327         /** Adds line from last point to next SkPoint.
1328             Line is a straight segment from SkPoint to SkPoint.
1329         */
1330         kLine_Verb,
1331 
1332         /** Adds quad from last point, using control SkPoint, and end SkPoint.
1333             Quad is a parabolic section within tangents from last point to control SkPoint,
1334             and control SkPoint to end SkPoint.
1335         */
1336         kQuad_Verb,
1337 
1338         /** Adds conic from last point, using control SkPoint, end SkPoint, and conic weight.
1339             Conic is a elliptical, parabolic, or hyperbolic section within tangents
1340             from last point to control SkPoint, and control SkPoint to end SkPoint, constrained
1341             by conic weight. conic weight less than one is elliptical; equal to one is
1342             parabolic (and identical to Quad); greater than one hyperbolic.
1343         */
1344         kConic_Verb,
1345 
1346         /** Adds cubic from last point, using two control SkPoint, and end SkPoint.
1347             Cubic is a third-order Bezier_Curve section within tangents from last point
1348             to first control SkPoint, and from second control SkPoint to end SkPoint.
1349         */
1350         kCubic_Verb,
1351         kClose_Verb, //!< Closes contour, connecting last point to kMove_Verb SkPoint.
1352         kDone_Verb,  //!< Terminates SkPath. Not in verb array, but returned by SkPath iterator.
1353     };
1354 
1355     /** \class SkPath::Iter
1356     */
1357     class SK_API Iter {
1358     public:
1359 
1360         /** Initializes SkPath::Iter with an empty SkPath. next() on SkPath::Iter returns kDone_Verb.
1361             Call setPath to initialize SkPath::Iter at a later time.
1362 
1363             @return  SkPath::Iter of empty SkPath
1364         */
1365         Iter();
1366 
1367         /** Sets SkPath::Iter to return elements of verb array, SkPoint array, and conic weight in path.
1368             If forceClose is true, SkPath::Iter will add kLine_Verb and kClose_Verb after each
1369             open contour. path is not altered.
1370 
1371             @param path        SkPath to iterate
1372             @param forceClose  true if open contours generate kClose_Verb
1373             @return            SkPath::Iter of path
1374         */
1375         Iter(const SkPath& path, bool forceClose);
1376 
1377         /** Sets SkPath::Iter to return elements of verb array, SkPoint array, and conic weight in path.
1378             If forceClose is true, SkPath::Iter will add kLine_Verb and kClose_Verb after each
1379             open contour. path is not altered.
1380 
1381             @param path        SkPath to iterate
1382             @param forceClose  true if open contours generate kClose_Verb
1383         */
1384         void setPath(const SkPath& path, bool forceClose);
1385 
1386         /** Returns next SkPath::Verb in verb array, and advances SkPath::Iter.
1387             When verb array is exhausted, returns kDone_Verb.
1388 
1389             Zero to four SkPoint are stored in pts, depending on the returned SkPath::Verb.
1390 
1391             If doConsumeDegenerates is true, skip consecutive kMove_Verb entries, returning
1392             only the last in the series; and skip very small lines, quads, and conics; and
1393             skip kClose_Verb following kMove_Verb.
1394             if doConsumeDegenerates is true and exact is true, only skip lines, quads, and
1395             conics with zero lengths.
1396 
1397             @param pts                   storage for SkPoint data describing returned SkPath::Verb
1398             @param doConsumeDegenerates  if true, skip degenerate verbs
1399             @param exact                 skip zero length curves
1400             @return                      next SkPath::Verb from verb array
1401         */
1402         Verb next(SkPoint pts[4], bool doConsumeDegenerates = true, bool exact = false) {
1403             if (doConsumeDegenerates) {
1404                 this->consumeDegenerateSegments(exact);
1405             }
1406             return this->doNext(pts);
1407         }
1408 
1409         /** Returns conic weight if next() returned kConic_Verb.
1410 
1411             If next() has not been called, or next() did not return kConic_Verb,
1412             result is undefined.
1413 
1414             @return  conic weight for conic SkPoint returned by next()
1415         */
conicWeight()1416         SkScalar conicWeight() const { return *fConicWeights; }
1417 
1418         /** Returns true if last kLine_Verb returned by next() was generated
1419             by kClose_Verb. When true, the end point returned by next() is
1420             also the start point of contour.
1421 
1422             If next() has not been called, or next() did not return kLine_Verb,
1423             result is undefined.
1424 
1425             @return  true if last kLine_Verb was generated by kClose_Verb
1426         */
isCloseLine()1427         bool isCloseLine() const { return SkToBool(fCloseLine); }
1428 
1429         /** Returns true if subsequent calls to next() return kClose_Verb before returning
1430             kMove_Verb. if true, contour SkPath::Iter is processing may end with kClose_Verb, or
1431             SkPath::Iter may have been initialized with force close set to true.
1432 
1433             @return  true if contour is closed
1434         */
1435         bool isClosedContour() const;
1436 
1437     private:
1438         const SkPoint*  fPts;
1439         const uint8_t*  fVerbs;
1440         const uint8_t*  fVerbStop;
1441         const SkScalar* fConicWeights;
1442         SkPoint         fMoveTo;
1443         SkPoint         fLastPt;
1444         SkBool8         fForceClose;
1445         SkBool8         fNeedClose;
1446         SkBool8         fCloseLine;
1447         SkBool8         fSegmentState;
1448 
1449         inline const SkPoint& cons_moveTo();
1450         Verb autoClose(SkPoint pts[2]);
1451         void consumeDegenerateSegments(bool exact);
1452         Verb doNext(SkPoint pts[4]);
1453 
1454     };
1455 
1456     /** \class SkPath::RawIter
1457     */
1458     class SK_API RawIter {
1459     public:
1460 
1461         /** Initializes RawIter with an empty SkPath. next() on RawIter returns kDone_Verb.
1462             Call setPath to initialize SkPath::Iter at a later time.
1463 
1464             @return  RawIter of empty SkPath
1465         */
RawIter()1466         RawIter() {}
1467 
1468         /** Sets RawIter to return elements of verb array, SkPoint array, and conic weight in path.
1469 
1470             @param path  SkPath to iterate
1471             @return      RawIter of path
1472         */
RawIter(const SkPath & path)1473         RawIter(const SkPath& path) {
1474             setPath(path);
1475         }
1476 
1477         /** Sets SkPath::Iter to return elements of verb array, SkPoint array, and conic weight in path.
1478 
1479             @param path  SkPath to iterate
1480         */
setPath(const SkPath & path)1481         void setPath(const SkPath& path) {
1482             fRawIter.setPathRef(*path.fPathRef.get());
1483         }
1484 
1485         /** Returns next SkPath::Verb in verb array, and advances RawIter.
1486             When verb array is exhausted, returns kDone_Verb.
1487             Zero to four SkPoint are stored in pts, depending on the returned SkPath::Verb.
1488 
1489             @param pts  storage for SkPoint data describing returned SkPath::Verb
1490             @return     next SkPath::Verb from verb array
1491         */
next(SkPoint pts[4])1492         Verb next(SkPoint pts[4]) {
1493             return (Verb) fRawIter.next(pts);
1494         }
1495 
1496         /** Returns next SkPath::Verb, but does not advance RawIter.
1497 
1498             @return  next SkPath::Verb from verb array
1499         */
peek()1500         Verb peek() const {
1501             return (Verb) fRawIter.peek();
1502         }
1503 
1504         /** Returns conic weight if next() returned kConic_Verb.
1505 
1506             If next() has not been called, or next() did not return kConic_Verb,
1507             result is undefined.
1508 
1509             @return  conic weight for conic SkPoint returned by next()
1510         */
conicWeight()1511         SkScalar conicWeight() const {
1512             return fRawIter.conicWeight();
1513         }
1514 
1515     private:
1516         SkPathRef::Iter fRawIter;
1517         friend class SkPath;
1518 
1519     };
1520 
1521     /** Returns true if the point (x, y) is contained by SkPath, taking into
1522         account FillType.
1523 
1524         @param x  x-coordinate of containment test
1525         @param y  y-coordinate of containment test
1526         @return   true if SkPoint is in SkPath
1527     */
1528     bool contains(SkScalar x, SkScalar y) const;
1529 
1530     /** Writes text representation of SkPath to stream. If stream is nullptr, writes to
1531         standard output. Set forceClose to true to get edges used to fill SkPath.
1532         Set dumpAsHex true to generate exact binary representations
1533         of floating point numbers used in SkPoint array and conic weights.
1534 
1535         @param stream      writable SkStream receiving SkPath text representation; may be nullptr
1536         @param forceClose  true if missing kClose_Verb is output
1537         @param dumpAsHex   true if SkScalar values are written as hexadecimal
1538     */
1539     void dump(SkWStream* stream, bool forceClose, bool dumpAsHex) const;
1540 
1541     /** Writes text representation of SkPath to standard output. The representation may be
1542         directly compiled as C++ code. Floating point values are written
1543         with limited precision; it may not be possible to reconstruct original SkPath
1544         from output.
1545     */
1546     void dump() const;
1547 
1548     /** Writes text representation of SkPath to standard output. The representation may be
1549         directly compiled as C++ code. Floating point values are written
1550         in hexadecimal to preserve their exact bit pattern. The output reconstructs the
1551         original SkPath.
1552 
1553         Use instead of dump() when submitting
1554     */
1555     void dumpHex() const;
1556 
1557     /** Writes SkPath to buffer, returning the number of bytes written.
1558         Pass nullptr to obtain the storage size.
1559 
1560         Writes SkPath::FillType, verb array, SkPoint array, conic weight, and
1561         additionally writes computed information like SkPath::Convexity and bounds.
1562 
1563         Use only be used in concert with readFromMemory();
1564         the format used for SkPath in memory is not guaranteed.
1565 
1566         @param buffer  storage for SkPath; may be nullptr
1567         @return        size of storage required for SkPath; always a multiple of 4
1568     */
1569     size_t writeToMemory(void* buffer) const;
1570 
1571     /** Write SkPath to buffer, returning the buffer written to, wrapped in SkData.
1572 
1573         serialize() writes SkPath::FillType, verb array, SkPoint array, conic weight, and
1574         additionally writes computed information like SkPath::Convexity and bounds.
1575 
1576         serialize() should only be used in concert with readFromMemory().
1577         The format used for SkPath in memory is not guaranteed.
1578 
1579         @return  SkPath data wrapped in SkData buffer
1580     */
1581     sk_sp<SkData> serialize() const;
1582 
1583     /** Initializes SkPath from buffer of size length. Returns zero if the buffer is
1584         data is inconsistent, or the length is too small.
1585 
1586         Reads SkPath::FillType, verb array, SkPoint array, conic weight, and
1587         additionally reads computed information like SkPath::Convexity and bounds.
1588 
1589         Used only in concert with writeToMemory();
1590         the format used for SkPath in memory is not guaranteed.
1591 
1592         @param buffer  storage for SkPath
1593         @param length  buffer size in bytes; must be multiple of 4
1594         @return        number of bytes read, or zero on failure
1595     */
1596     size_t readFromMemory(const void* buffer, size_t length);
1597 
1598     /** (see skbug.com/1762)
1599         Returns a non-zero, globally unique value. A different value is returned
1600         if verb array, SkPoint array, or conic weight changes.
1601 
1602         Setting SkPath::FillType does not change generation id.
1603 
1604         Each time the path is modified, a different generation id will be returned.
1605         SkPath::FillType does affect generation id on Android framework.
1606 
1607         @return  non-zero, globally unique value
1608     */
1609     uint32_t getGenerationID() const;
1610 
1611 #ifdef SK_SUPPORT_DIRECT_PATHREF_VALIDATION
1612     /** Returns if SkPath data is consistent. Corrupt SkPath data is detected if
1613         internal values are out of range or internal storage does not match
1614         array dimensions.
1615 
1616         @return  true if SkPath data is consistent
1617     */
isValid()1618     bool isValid() const { return this->isValidImpl() && fPathRef->isValid(); }
1619 #else
isValid()1620     bool isValid() const { return this->isValidImpl(); }
pathRefIsValid()1621     bool pathRefIsValid() const { return fPathRef->isValid(); }
1622 #endif
1623 
1624 private:
1625     sk_sp<SkPathRef>                                     fPathRef;
1626     int                                                  fLastMoveToIndex;
1627     uint8_t                                              fFillType;
1628     mutable SkAtomic<Convexity, sk_memory_order_relaxed> fConvexity;
1629     mutable SkAtomic<uint8_t, sk_memory_order_relaxed>   fFirstDirection;// SkPathPriv::FirstDirection
1630     SkBool8                                              fIsVolatile;
1631 
1632     /** Resets all fields other than fPathRef to their initial 'empty' values.
1633      *  Assumes the caller has already emptied fPathRef.
1634      *  On Android increments fGenerationID without reseting it.
1635      */
1636     void resetFields();
1637 
1638     /** Sets all fields other than fPathRef to the values in 'that'.
1639      *  Assumes the caller has already set fPathRef.
1640      *  Doesn't change fGenerationID or fSourcePath on Android.
1641      */
1642     void copyFields(const SkPath& that);
1643 
1644     size_t writeToMemoryAsRRect(void* buffer) const;
1645     size_t readAsRRect(const void*, size_t);
1646     size_t readFromMemory_LE3(const void*, size_t);
1647     size_t readFromMemory_EQ4(const void*, size_t);
1648 
1649     friend class Iter;
1650     friend class SkPathPriv;
1651     friend class SkPathStroker;
1652 
1653     /*  Append, in reverse order, the first contour of path, ignoring path's
1654         last point. If no moveTo() call has been made for this contour, the
1655         first point is automatically set to (0,0).
1656     */
1657     void reversePathTo(const SkPath&);
1658 
1659     // called before we add points for lineTo, quadTo, cubicTo, checking to see
1660     // if we need to inject a leading moveTo first
1661     //
1662     //  SkPath path; path.lineTo(...);   <--- need a leading moveTo(0, 0)
1663     // SkPath path; ... path.close(); path.lineTo(...) <-- need a moveTo(previous moveTo)
1664     //
1665     inline void injectMoveToIfNeeded();
1666 
1667     inline bool hasOnlyMoveTos() const;
1668 
1669     Convexity internalGetConvexity() const;
1670 
1671     /** Asserts if SkPath data is inconsistent.
1672         Debugging check intended for internal use only.
1673      */
1674     SkDEBUGCODE(void validate() const { SkASSERT(this->isValidImpl()); } )
1675     bool isValidImpl() const;
1676     SkDEBUGCODE(void validateRef() const { fPathRef->validate(); } )
1677 
1678     bool isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts,
1679                        bool* isClosed, Direction* direction) const;
1680 
1681     // called by stroker to see if all points (in the last contour) are equal and worthy of a cap
1682     bool isZeroLengthSincePoint(int startPtIndex) const;
1683 
1684     /** Returns if the path can return a bound at no cost (true) or will have to
1685         perform some computation (false).
1686      */
hasComputedBounds()1687     bool hasComputedBounds() const {
1688         SkDEBUGCODE(this->validate();)
1689         return fPathRef->hasComputedBounds();
1690     }
1691 
1692 
1693     // 'rect' needs to be sorted
setBounds(const SkRect & rect)1694     void setBounds(const SkRect& rect) {
1695         SkPathRef::Editor ed(&fPathRef);
1696 
1697         ed.setBounds(rect);
1698     }
1699 
1700     void setPt(int index, SkScalar x, SkScalar y);
1701 
1702     friend class SkAutoPathBoundsUpdate;
1703     friend class SkAutoDisableOvalCheck;
1704     friend class SkAutoDisableDirectionCheck;
1705     friend class SkPathWriter;
1706     friend class SkOpBuilder;
1707     friend class SkBench_AddPathTest; // perf test reversePathTo
1708     friend class PathTest_Private; // unit test reversePathTo
1709     friend class ForceIsRRect_Private; // unit test isRRect
1710     friend class FuzzPath; // for legacy access to validateRef
1711 };
1712 
1713 #endif
1714