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