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