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