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