LCOV - code coverage report
Current view: top level - gfx/skia/skia/include/core - SkPath.h (source / functions) Hit Total Coverage
Test: output.info Lines: 75 107 70.1 %
Date: 2017-07-14 16:53:18 Functions: 26 38 68.4 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "SkPathRef.h"
      13             : #include "SkRefCnt.h"
      14             : 
      15             : class SkReader32;
      16             : class SkWriter32;
      17             : class SkAutoPathBoundsUpdate;
      18             : class SkString;
      19             : class SkRRect;
      20             : class SkWStream;
      21             : 
      22             : /** \class SkPath
      23             : 
      24             :     The SkPath class encapsulates compound (multiple contour) geometric paths
      25             :     consisting of straight line segments, quadratic curves, and cubic curves.
      26             : 
      27             :     SkPath is not thread safe unless you've first called SkPath::updateBoundsCache().
      28             : */
      29             : class SK_API SkPath {
      30             : public:
      31             :     enum Direction {
      32             :         /** clockwise direction for adding closed contours */
      33             :         kCW_Direction,
      34             :         /** counter-clockwise direction for adding closed contours */
      35             :         kCCW_Direction,
      36             :     };
      37             : 
      38             :     SkPath();
      39             :     SkPath(const SkPath&);
      40             :     ~SkPath();
      41             : 
      42             :     SkPath& operator=(const SkPath&);
      43             :     friend  SK_API bool operator==(const SkPath&, const SkPath&);
      44             :     friend bool operator!=(const SkPath& a, const SkPath& b) {
      45             :         return !(a == b);
      46             :     }
      47             : 
      48             :     /** Return true if the paths contain an equal array of verbs and weights. Paths
      49             :      *  with equal verb counts can be readily interpolated. If the paths contain one
      50             :      *  or more conics, the conics' weights must also match.
      51             :      *
      52             :      *  @param compare  The path to compare.
      53             :      *
      54             :      *  @return true if the paths have the same verbs and weights.
      55             :      */
      56             :     bool isInterpolatable(const SkPath& compare) const;
      57             : 
      58             :     /** Interpolate between two paths with same-sized point arrays.
      59             :      *  The out path contains the verbs and weights of this path.
      60             :      *  The out points are a weighted average of this path and the ending path. 
      61             :      *
      62             :      *  @param ending  The path to interpolate between.
      63             :      *  @param weight  The weight, from 0 to 1. The output points are set to
      64             :      *                 (this->points * weight) + ending->points * (1 - weight).
      65             :      *  @return true if the paths could be interpolated.
      66             :      */
      67             :     bool interpolate(const SkPath& ending, SkScalar weight, SkPath* out) const;
      68             : 
      69             : #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
      70             :     /** Returns true if the caller is the only owner of the underlying path data */
      71             :     bool unique() const { return fPathRef->unique(); }
      72             : #endif
      73             : 
      74             :     enum FillType {
      75             :         /** Specifies that "inside" is computed by a non-zero sum of signed
      76             :             edge crossings
      77             :         */
      78             :         kWinding_FillType,
      79             :         /** Specifies that "inside" is computed by an odd number of edge
      80             :             crossings
      81             :         */
      82             :         kEvenOdd_FillType,
      83             :         /** Same as Winding, but draws outside of the path, rather than inside
      84             :         */
      85             :         kInverseWinding_FillType,
      86             :         /** Same as EvenOdd, but draws outside of the path, rather than inside
      87             :          */
      88             :         kInverseEvenOdd_FillType
      89             :     };
      90             : 
      91             :     /** Return the path's fill type. This is used to define how "inside" is
      92             :         computed. The default value is kWinding_FillType.
      93             : 
      94             :         @return the path's fill type
      95             :     */
      96          74 :     FillType getFillType() const { return (FillType)fFillType; }
      97             : 
      98             :     /** Set the path's fill type. This is used to define how "inside" is
      99             :         computed. The default value is kWinding_FillType.
     100             : 
     101             :         @param ft The new fill type for this path
     102             :     */
     103         112 :     void setFillType(FillType ft) {
     104         112 :         fFillType = SkToU8(ft);
     105         112 :     }
     106             : 
     107             :     /** Returns true if the filltype is one of the Inverse variants */
     108         836 :     bool isInverseFillType() const { return IsInverseFillType((FillType)fFillType); }
     109             : 
     110             :     /**
     111             :      *  Toggle between inverse and normal filltypes. This reverse the return
     112             :      *  value of isInverseFillType()
     113             :      */
     114           0 :     void toggleInverseFillType() {
     115           0 :         fFillType ^= 2;
     116           0 :     }
     117             : 
     118             :     enum Convexity {
     119             :         kUnknown_Convexity,
     120             :         kConvex_Convexity,
     121             :         kConcave_Convexity
     122             :     };
     123             : 
     124             :     /**
     125             :      *  Return the path's convexity, as stored in the path. If it is currently unknown,
     126             :      *  then this function will attempt to compute the convexity (and cache the result).
     127             :      */
     128         626 :     Convexity getConvexity() const {
     129         626 :         if (kUnknown_Convexity != fConvexity) {
     130         513 :             return static_cast<Convexity>(fConvexity);
     131             :         } else {
     132         113 :             return this->internalGetConvexity();
     133             :         }
     134             :     }
     135             : 
     136             :     /**
     137             :      *  Return the currently cached value for convexity, even if that is set to
     138             :      *  kUnknown_Convexity. Note: getConvexity() will automatically call
     139             :      *  ComputeConvexity and cache its return value if the current setting is
     140             :      *  kUnknown.
     141             :      */
     142           0 :     Convexity getConvexityOrUnknown() const { return (Convexity)fConvexity; }
     143             : 
     144             :     /**
     145             :      *  Store a convexity setting in the path. There is no automatic check to
     146             :      *  see if this value actually agrees with the return value that would be
     147             :      *  computed by getConvexity().
     148             :      *
     149             :      *  Note: even if this is set to a "known" value, if the path is later
     150             :      *  changed (e.g. lineTo(), addRect(), etc.) then the cached value will be
     151             :      *  reset to kUnknown_Convexity.
     152             :      */
     153             :     void setConvexity(Convexity);
     154             : 
     155             :     /**
     156             :      *  Returns true if the path is flagged as being convex. This is not a
     157             :      *  confirmed by any analysis, it is just the value set earlier.
     158             :      */
     159         626 :     bool isConvex() const {
     160         626 :         return kConvex_Convexity == this->getConvexity();
     161             :     }
     162             : 
     163             :     /**
     164             :      *  Set the isConvex flag to true or false. Convex paths may draw faster if
     165             :      *  this flag is set, though setting this to true on a path that is in fact
     166             :      *  not convex can give undefined results when drawn. Paths default to
     167             :      *  isConvex == false
     168             :      */
     169             :     SK_ATTR_DEPRECATED("use setConvexity")
     170             :     void setIsConvex(bool isConvex) {
     171             :         this->setConvexity(isConvex ? kConvex_Convexity : kConcave_Convexity);
     172             :     }
     173             : 
     174             :     /** Returns true if the path is an oval.
     175             :      *
     176             :      * @param rect      returns the bounding rect of this oval. It's a circle
     177             :      *                  if the height and width are the same.
     178             :      * @param dir       is the oval CCW (or CW if false).
     179             :      * @param start     indicates where the contour starts on the oval (see
     180             :      *                  SkPath::addOval for intepretation of the index).
     181             :      * @return true if this path is an oval.
     182             :      *              Tracking whether a path is an oval is considered an
     183             :      *              optimization for performance and so some paths that are in
     184             :      *              fact ovals can report false.
     185             :      */
     186          39 :     bool isOval(SkRect* rect, Direction* dir = nullptr,
     187             :                 unsigned* start = nullptr) const {
     188          39 :         bool isCCW = false;
     189          39 :         bool result = fPathRef->isOval(rect, &isCCW, start);
     190          39 :         if (dir && result) {
     191           0 :             *dir = isCCW ? kCCW_Direction : kCW_Direction;
     192             :         }
     193          39 :         return result;
     194             :     }
     195             : 
     196             :     /** Returns true if the path is a round rect.
     197             :      *
     198             :      * @param rrect  Returns the bounding rect and radii of this round rect.
     199             :      * @param dir    is the rrect CCW (or CW if false).
     200             :      * @param start  indicates where the contour starts on the rrect (see
     201             :      *               SkPath::addRRect for intepretation of the index).
     202             :      *
     203             :      * @return true if this path is a round rect.
     204             :      *              Tracking whether a path is a round rect is considered an
     205             :      *              optimization for performance and so some paths that are in
     206             :      *              fact round rects can report false.
     207             :      */
     208          39 :     bool isRRect(SkRRect* rrect, Direction* dir = nullptr,
     209             :                  unsigned* start = nullptr) const {
     210          39 :         bool isCCW = false;
     211          39 :         bool result = fPathRef->isRRect(rrect, &isCCW, start);
     212          39 :         if (dir && result) {
     213           0 :             *dir = isCCW ? kCCW_Direction : kCW_Direction;
     214             :         }
     215          39 :         return result;
     216             :     }
     217             : 
     218             :     /** Clear any lines and curves from the path, making it empty. This frees up
     219             :         internal storage associated with those segments.
     220             :         On Android, does not change fSourcePath.
     221             :     */
     222             :     void reset();
     223             : 
     224             :     /** Similar to reset(), in that all lines and curves are removed from the
     225             :         path. However, any internal storage for those lines/curves is retained,
     226             :         making reuse of the path potentially faster.
     227             :         On Android, does not change fSourcePath.
     228             :     */
     229             :     void rewind();
     230             : 
     231             :     /** Returns true if the path is empty (contains no lines or curves)
     232             : 
     233             :         @return true if the path is empty (contains no lines or curves)
     234             :     */
     235         113 :     bool isEmpty() const {
     236         113 :         SkDEBUGCODE(this->validate();)
     237         113 :         return 0 == fPathRef->countVerbs();
     238             :     }
     239             : 
     240             :     /** Return true if the last contour of this path ends with a close verb.
     241             :      */
     242             :     bool isLastContourClosed() const;
     243             : 
     244             :     /**
     245             :      *  Returns true if all of the points in this path are finite, meaning there
     246             :      *  are no infinities and no NaNs.
     247             :      */
     248         446 :     bool isFinite() const {
     249         446 :         SkDEBUGCODE(this->validate();)
     250         446 :         return fPathRef->isFinite();
     251             :     }
     252             : 
     253             :     /** Returns true if the path is volatile (i.e. should not be cached by devices.)
     254             :      */
     255           0 :     bool isVolatile() const {
     256           0 :         return SkToBool(fIsVolatile);
     257             :     }
     258             : 
     259             :     /** Specify whether this path is volatile. Paths are not volatile by
     260             :      default. Temporary paths that are discarded or modified after use should be
     261             :      marked as volatile. This provides a hint to the device that the path
     262             :      should not be cached. Providing this hint when appropriate can
     263             :      improve performance by avoiding unnecessary overhead and resource
     264             :      consumption on the device.
     265             :      */
     266         131 :     void setIsVolatile(bool isVolatile) {
     267         131 :         fIsVolatile = isVolatile;
     268         131 :     }
     269             : 
     270             :     /** Test a line for zero length
     271             : 
     272             :         @return true if the line is of zero length; otherwise false.
     273             :     */
     274         543 :     static bool IsLineDegenerate(const SkPoint& p1, const SkPoint& p2, bool exact) {
     275         543 :         return exact ? p1 == p2 : p1.equalsWithinTolerance(p2);
     276             :     }
     277             : 
     278             :     /** Test a quad for zero length
     279             : 
     280             :         @return true if the quad is of zero length; otherwise false.
     281             :     */
     282          10 :     static bool IsQuadDegenerate(const SkPoint& p1, const SkPoint& p2,
     283             :                                  const SkPoint& p3, bool exact) {
     284          10 :         return exact ? p1 == p2 && p2 == p3 : p1.equalsWithinTolerance(p2) &&
     285          10 :                p2.equalsWithinTolerance(p3);
     286             :     }
     287             : 
     288             :     /** Test a cubic curve for zero length
     289             : 
     290             :         @return true if the cubic is of zero length; otherwise false.
     291             :     */
     292         231 :     static bool IsCubicDegenerate(const SkPoint& p1, const SkPoint& p2,
     293             :                                   const SkPoint& p3, const SkPoint& p4, bool exact) {
     294         231 :         return exact ? p1 == p2 && p2 == p3 && p3 == p4 : p1.equalsWithinTolerance(p2) &&
     295           0 :                p2.equalsWithinTolerance(p3) &&
     296         231 :                p3.equalsWithinTolerance(p4);
     297             :     }
     298             : 
     299             :     /**
     300             :      *  Returns true if the path specifies a single line (i.e. it contains just
     301             :      *  a moveTo and a lineTo). If so, and line[] is not null, it sets the 2
     302             :      *  points in line[] to the end-points of the line. If the path is not a
     303             :      *  line, returns false and ignores line[].
     304             :      */
     305             :     bool isLine(SkPoint line[2]) const;
     306             : 
     307             :     /** Return the number of points in the path
     308             :      */
     309             :     int countPoints() const;
     310             : 
     311             :     /** Return the point at the specified index. If the index is out of range
     312             :          (i.e. is not 0 <= index < countPoints()) then the returned coordinates
     313             :          will be (0,0)
     314             :      */
     315             :     SkPoint getPoint(int index) const;
     316             : 
     317             :     /** Returns the number of points in the path. Up to max points are copied.
     318             : 
     319             :         @param points If not null, receives up to max points
     320             :         @param max The maximum number of points to copy into points
     321             :         @return the actual number of points in the path
     322             :     */
     323             :     int getPoints(SkPoint points[], int max) const;
     324             : 
     325             :     /** Return the number of verbs in the path
     326             :      */
     327             :     int countVerbs() const;
     328             : 
     329             :     /** Returns the number of verbs in the path. Up to max verbs are copied. The
     330             :         verbs are copied as one byte per verb.
     331             : 
     332             :         @param verbs If not null, receives up to max verbs
     333             :         @param max The maximum number of verbs to copy into verbs
     334             :         @return the actual number of verbs in the path
     335             :     */
     336             :     int getVerbs(uint8_t verbs[], int max) const;
     337             : 
     338             :     //! Swap contents of this and other. Guaranteed not to throw
     339             :     void swap(SkPath& other);
     340             : 
     341             :     /**
     342             :      *  Returns the bounds of the path's points. If the path contains zero points/verbs, this
     343             :      *  will return the "empty" rect [0, 0, 0, 0].
     344             :      *  Note: this bounds may be larger than the actual shape, since curves
     345             :      *  do not extend as far as their control points. Additionally this bound encompases all points,
     346             :      *  even isolated moveTos either preceeding or following the last non-degenerate contour.
     347             :     */
     348         940 :     const SkRect& getBounds() const {
     349         940 :         return fPathRef->getBounds();
     350             :     }
     351             : 
     352             :     /** Calling this will, if the internal cache of the bounds is out of date,
     353             :         update it so that subsequent calls to getBounds will be instantaneous.
     354             :         This also means that any copies or simple transformations of the path
     355             :         will inherit the cached bounds.
     356             :      */
     357           0 :     void updateBoundsCache() const {
     358             :         // for now, just calling getBounds() is sufficient
     359           0 :         this->getBounds();
     360           0 :     }
     361             : 
     362             :     /**
     363             :      *  Computes a bounds that is conservatively "snug" around the path. This assumes that the
     364             :      *  path will be filled. It does not attempt to collapse away contours that are logically
     365             :      *  empty (e.g. moveTo(x, y) + lineTo(x, y)) but will include them in the calculation.
     366             :      *
     367             :      *  It differs from getBounds() in that it will look at the snug bounds of curves, whereas
     368             :      *  getBounds() just returns the bounds of the control-points. Thus computing this may be
     369             :      *  slower than just calling getBounds().
     370             :      *
     371             :      *  If the path is empty (i.e. no points or verbs), it will return SkRect::MakeEmpty().
     372             :      */
     373             :     SkRect computeTightBounds() const;
     374             : 
     375             :     /**
     376             :      * Does a conservative test to see whether a rectangle is inside a path. Currently it only
     377             :      * will ever return true for single convex contour paths. The empty-status of the rect is not
     378             :      * considered (e.g. a rect that is a point can be inside a path). Points or line segments where
     379             :      * the rect edge touches the path border are not considered containment violations.
     380             :      */
     381             :     bool conservativelyContainsRect(const SkRect& rect) const;
     382             : 
     383             :     //  Construction methods
     384             : 
     385             :     /** Hint to the path to prepare for adding more points. This can allow the
     386             :         path to more efficiently grow its storage.
     387             : 
     388             :         @param extraPtCount The number of extra points the path should
     389             :                             preallocate for.
     390             :     */
     391             :     void incReserve(unsigned extraPtCount);
     392             : 
     393             :     /** Set the beginning of the next contour to the point (x,y).
     394             : 
     395             :         @param x    The x-coordinate of the start of a new contour
     396             :         @param y    The y-coordinate of the start of a new contour
     397             :     */
     398             :     void moveTo(SkScalar x, SkScalar y);
     399             : 
     400             :     /** Set the beginning of the next contour to the point
     401             : 
     402             :         @param p    The start of a new contour
     403             :     */
     404         126 :     void moveTo(const SkPoint& p) {
     405         126 :         this->moveTo(p.fX, p.fY);
     406         126 :     }
     407             : 
     408             :     /** Set the beginning of the next contour relative to the last point on the
     409             :         previous contour. If there is no previous contour, this is treated the
     410             :         same as moveTo().
     411             : 
     412             :         @param dx   The amount to add to the x-coordinate of the end of the
     413             :                     previous contour, to specify the start of a new contour
     414             :         @param dy   The amount to add to the y-coordinate of the end of the
     415             :                     previous contour, to specify the start of a new contour
     416             :     */
     417             :     void rMoveTo(SkScalar dx, SkScalar dy);
     418             : 
     419             :     /** Add a line from the last point to the specified point (x,y). If no
     420             :         moveTo() call has been made for this contour, the first point is
     421             :         automatically set to (0,0).
     422             : 
     423             :         @param x    The x-coordinate of the end of a line
     424             :         @param y    The y-coordinate of the end of a line
     425             :     */
     426             :     void lineTo(SkScalar x, SkScalar y);
     427             : 
     428             :     /** Add a line from the last point to the specified point. If no moveTo()
     429             :         call has been made for this contour, the first point is automatically
     430             :         set to (0,0).
     431             : 
     432             :         @param p    The end of a line
     433             :     */
     434         373 :     void lineTo(const SkPoint& p) {
     435         373 :         this->lineTo(p.fX, p.fY);
     436         373 :     }
     437             : 
     438             :     /** Same as lineTo, but the coordinates are considered relative to the last
     439             :         point on this contour. If there is no previous point, then a moveTo(0,0)
     440             :         is inserted automatically.
     441             : 
     442             :         @param dx   The amount to add to the x-coordinate of the previous point
     443             :                     on this contour, to specify a line
     444             :         @param dy   The amount to add to the y-coordinate of the previous point
     445             :                     on this contour, to specify a line
     446             :     */
     447             :     void rLineTo(SkScalar dx, SkScalar dy);
     448             : 
     449             :     /** Add a quadratic bezier from the last point, approaching control point
     450             :         (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for
     451             :         this contour, the first point is automatically set to (0,0).
     452             : 
     453             :         @param x1   The x-coordinate of the control point on a quadratic curve
     454             :         @param y1   The y-coordinate of the control point on a quadratic curve
     455             :         @param x2   The x-coordinate of the end point on a quadratic curve
     456             :         @param y2   The y-coordinate of the end point on a quadratic curve
     457             :     */
     458             :     void quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2);
     459             : 
     460             :     /** Add a quadratic bezier from the last point, approaching control point
     461             :         p1, and ending at p2. If no moveTo() call has been made for this
     462             :         contour, the first point is automatically set to (0,0).
     463             : 
     464             :         @param p1   The control point on a quadratic curve
     465             :         @param p2   The end point on a quadratic curve
     466             :     */
     467           8 :     void quadTo(const SkPoint& p1, const SkPoint& p2) {
     468           8 :         this->quadTo(p1.fX, p1.fY, p2.fX, p2.fY);
     469           8 :     }
     470             : 
     471             :     /** Same as quadTo, but the coordinates are considered relative to the last
     472             :         point on this contour. If there is no previous point, then a moveTo(0,0)
     473             :         is inserted automatically.
     474             : 
     475             :         @param dx1   The amount to add to the x-coordinate of the last point on
     476             :                 this contour, to specify the control point of a quadratic curve
     477             :         @param dy1   The amount to add to the y-coordinate of the last point on
     478             :                 this contour, to specify the control point of a quadratic curve
     479             :         @param dx2   The amount to add to the x-coordinate of the last point on
     480             :                      this contour, to specify the end point of a quadratic curve
     481             :         @param dy2   The amount to add to the y-coordinate of the last point on
     482             :                      this contour, to specify the end point of a quadratic curve
     483             :     */
     484             :     void rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2);
     485             : 
     486             :     void conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
     487             :                  SkScalar w);
     488           0 :     void conicTo(const SkPoint& p1, const SkPoint& p2, SkScalar w) {
     489           0 :         this->conicTo(p1.fX, p1.fY, p2.fX, p2.fY, w);
     490           0 :     }
     491             :     void rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
     492             :                   SkScalar w);
     493             : 
     494             :     /** Add a cubic bezier from the last point, approaching control points
     495             :         (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been
     496             :         made for this contour, the first point is automatically set to (0,0).
     497             : 
     498             :         @param x1   The x-coordinate of the 1st control point on a cubic curve
     499             :         @param y1   The y-coordinate of the 1st control point on a cubic curve
     500             :         @param x2   The x-coordinate of the 2nd control point on a cubic curve
     501             :         @param y2   The y-coordinate of the 2nd control point on a cubic curve
     502             :         @param x3   The x-coordinate of the end point on a cubic curve
     503             :         @param y3   The y-coordinate of the end point on a cubic curve
     504             :     */
     505             :     void cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
     506             :                  SkScalar x3, SkScalar y3);
     507             : 
     508             :     /** Add a cubic bezier from the last point, approaching control points p1
     509             :         and p2, and ending at p3. If no moveTo() call has been made for this
     510             :         contour, the first point is automatically set to (0,0).
     511             : 
     512             :         @param p1   The 1st control point on a cubic curve
     513             :         @param p2   The 2nd control point on a cubic curve
     514             :         @param p3   The end point on a cubic curve
     515             :     */
     516           0 :     void cubicTo(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3) {
     517           0 :         this->cubicTo(p1.fX, p1.fY, p2.fX, p2.fY, p3.fX, p3.fY);
     518           0 :     }
     519             : 
     520             :     /** Same as cubicTo, but the coordinates are considered relative to the
     521             :         current point on this contour. If there is no previous point, then a
     522             :         moveTo(0,0) is inserted automatically.
     523             : 
     524             :         @param dx1   The amount to add to the x-coordinate of the last point on
     525             :                 this contour, to specify the 1st control point of a cubic curve
     526             :         @param dy1   The amount to add to the y-coordinate of the last point on
     527             :                 this contour, to specify the 1st control point of a cubic curve
     528             :         @param dx2   The amount to add to the x-coordinate of the last point on
     529             :                 this contour, to specify the 2nd control point of a cubic curve
     530             :         @param dy2   The amount to add to the y-coordinate of the last point on
     531             :                 this contour, to specify the 2nd control point of a cubic curve
     532             :         @param dx3   The amount to add to the x-coordinate of the last point on
     533             :                      this contour, to specify the end point of a cubic curve
     534             :         @param dy3   The amount to add to the y-coordinate of the last point on
     535             :                      this contour, to specify the end point of a cubic curve
     536             :     */
     537             :     void rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
     538             :                   SkScalar x3, SkScalar y3);
     539             : 
     540             :     /**
     541             :      *  Append the specified arc to the path. If the start of the arc is different from the path's
     542             :      *  current last point, then an automatic lineTo() is added to connect the current contour
     543             :      *  to the start of the arc. However, if the path is empty, then we call moveTo() with
     544             :      *  the first point of the arc. The sweep angle is treated mod 360.
     545             :      *
     546             :      *  @param oval The bounding oval defining the shape and size of the arc
     547             :      *  @param startAngle Starting angle (in degrees) where the arc begins
     548             :      *  @param sweepAngle Sweep angle (in degrees) measured clockwise. This is treated mod 360.
     549             :      *  @param forceMoveTo If true, always begin a new contour with the arc
     550             :      */
     551             :     void arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo);
     552             : 
     553             :     /**
     554             :      *  Append a line and arc to the current path. This is the same as the PostScript call "arct".
     555             :      */
     556             :     void arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar radius);
     557             : 
     558             :     /** Append a line and arc to the current path. This is the same as the
     559             :         PostScript call "arct".
     560             :     */
     561             :     void arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius) {
     562             :         this->arcTo(p1.fX, p1.fY, p2.fX, p2.fY, radius);
     563             :     }
     564             : 
     565             :     enum ArcSize {
     566             :         /** the smaller of the two possible SVG arcs. */
     567             :         kSmall_ArcSize,
     568             :         /** the larger of the two possible SVG arcs. */
     569             :         kLarge_ArcSize,
     570             :     };
     571             : 
     572             :     /**
     573             :      *  Append an elliptical arc from the current point in the format used by SVG.
     574             :      *  The center of the ellipse is computed to satisfy the constraints below.
     575             :      *
     576             :      *  @param rx,ry The radii in the x and y directions respectively.
     577             :      *  @param xAxisRotate The angle in degrees relative to the x-axis.
     578             :      *  @param largeArc Determines whether the smallest or largest arc possible
     579             :      *         is drawn.
     580             :      *  @param sweep Determines if the arc should be swept in an anti-clockwise or
     581             :      *         clockwise direction. Note that this enum value is opposite the SVG
     582             :      *         arc sweep value.
     583             :      *  @param x,y The destination coordinates.
     584             :      */
     585             :     void arcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,
     586             :                Direction sweep, SkScalar x, SkScalar y);
     587             : 
     588           0 :     void arcTo(const SkPoint r, SkScalar xAxisRotate, ArcSize largeArc, Direction sweep,
     589             :                const SkPoint xy) {
     590           0 :         this->arcTo(r.fX, r.fY, xAxisRotate, largeArc, sweep, xy.fX, xy.fY);
     591           0 :     }
     592             : 
     593             :     /** Same as arcTo format used by SVG, but the destination coordinate is relative to the
     594             :      *  last point on this contour. If there is no previous point, then a
     595             :      *  moveTo(0,0) is inserted automatically.
     596             :      *
     597             :      *  @param rx,ry The radii in the x and y directions respectively.
     598             :      *  @param xAxisRotate The angle in degrees relative to the x-axis.
     599             :      *  @param largeArc Determines whether the smallest or largest arc possible
     600             :      *         is drawn.
     601             :      *  @param sweep Determines if the arc should be swept in an anti-clockwise or
     602             :      *         clockwise direction. Note that this enum value is opposite the SVG
     603             :      *         arc sweep value.
     604             :      *  @param dx,dy The destination coordinates relative to the last point.
     605             :      */
     606             :     void rArcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,
     607             :                 Direction sweep, SkScalar dx, SkScalar dy);
     608             : 
     609             :     /** Close the current contour. If the current point is not equal to the
     610             :         first point of the contour, a line segment is automatically added.
     611             :     */
     612             :     void close();
     613             : 
     614             :     /**
     615             :      *  Returns whether or not a fill type is inverted
     616             :      *
     617             :      *  kWinding_FillType        -> false
     618             :      *  kEvenOdd_FillType        -> false
     619             :      *  kInverseWinding_FillType -> true
     620             :      *  kInverseEvenOdd_FillType -> true
     621             :      */
     622         868 :     static bool IsInverseFillType(FillType fill) {
     623             :         static_assert(0 == kWinding_FillType, "fill_type_mismatch");
     624             :         static_assert(1 == kEvenOdd_FillType, "fill_type_mismatch");
     625             :         static_assert(2 == kInverseWinding_FillType, "fill_type_mismatch");
     626             :         static_assert(3 == kInverseEvenOdd_FillType, "fill_type_mismatch");
     627         868 :         return (fill & 2) != 0;
     628             :     }
     629             : 
     630             :     /**
     631             :      *  Returns the equivalent non-inverted fill type to the given fill type
     632             :      *
     633             :      *  kWinding_FillType        -> kWinding_FillType
     634             :      *  kEvenOdd_FillType        -> kEvenOdd_FillType
     635             :      *  kInverseWinding_FillType -> kWinding_FillType
     636             :      *  kInverseEvenOdd_FillType -> kEvenOdd_FillType
     637             :      */
     638             :     static FillType ConvertToNonInverseFillType(FillType fill) {
     639             :         static_assert(0 == kWinding_FillType, "fill_type_mismatch");
     640             :         static_assert(1 == kEvenOdd_FillType, "fill_type_mismatch");
     641             :         static_assert(2 == kInverseWinding_FillType, "fill_type_mismatch");
     642             :         static_assert(3 == kInverseEvenOdd_FillType, "fill_type_mismatch");
     643             :         return (FillType)(fill & 1);
     644             :     }
     645             : 
     646             :     /**
     647             :      *  Chop a conic into N quads, stored continguously in pts[], where
     648             :      *  N = 1 << pow2. The amount of storage needed is (1 + 2 * N)
     649             :      */
     650             :     static int ConvertConicToQuads(const SkPoint& p0, const SkPoint& p1, const SkPoint& p2,
     651             :                                    SkScalar w, SkPoint pts[], int pow2);
     652             : 
     653             :     /**
     654             :      *  Returns true if the path specifies a rectangle.
     655             :      *
     656             :      *  If this returns false, then all output parameters are ignored, and left
     657             :      *  unchanged. If this returns true, then each of the output parameters
     658             :      *  are checked for NULL. If they are not, they return their value.
     659             :      *
     660             :      *  @param rect If not null, set to the bounds of the rectangle.
     661             :      *              Note : this bounds may be smaller than the path's bounds, since it is just
     662             :      *              the bounds of the "drawable" parts of the path. e.g. a trailing MoveTo would
     663             :      *              be ignored in this rect, but not by the path's bounds
     664             :      *  @param isClosed If not null, set to true if the path is closed
     665             :      *  @param direction If not null, set to the rectangle's direction
     666             :      *  @return true if the path specifies a rectangle
     667             :      */
     668             :     bool isRect(SkRect* rect, bool* isClosed = NULL, Direction* direction = NULL) const;
     669             : 
     670             :     /** Returns true if the path specifies a pair of nested rectangles, or would draw a
     671             :         pair of nested rectangles when filled. If so, and if
     672             :         rect is not null, set rect[0] to the outer rectangle and rect[1] to the inner
     673             :         rectangle. If so, and dirs is not null, set dirs[0] to the direction of
     674             :         the outer rectangle and dirs[1] to the direction of the inner rectangle. If
     675             :         the path does not specify a pair of nested rectangles, return
     676             :         false and ignore rect and dirs.
     677             : 
     678             :         @param rect If not null, returns the path as a pair of nested rectangles
     679             :         @param dirs If not null, returns the direction of the rects
     680             :         @return true if the path describes a pair of nested rectangles
     681             :     */
     682             :     bool isNestedFillRects(SkRect rect[2], Direction dirs[2] = NULL) const;
     683             : 
     684             :     /**
     685             :      *  Add a closed rectangle contour to the path
     686             :      *  @param rect The rectangle to add as a closed contour to the path
     687             :      *  @param dir  The direction to wind the rectangle's contour.
     688             :      *
     689             :      *  Note: the contour initial point index is 0 (as defined below).
     690             :      */
     691             :     void addRect(const SkRect& rect, Direction dir = kCW_Direction);
     692             : 
     693             :     /**
     694             :      *  Add a closed rectangle contour to the path
     695             :      *  @param rect  The rectangle to add as a closed contour to the path
     696             :      *  @param dir   The direction to wind the rectangle's contour.
     697             :      *  @param start Initial point of the contour (initial moveTo), expressed as
     698             :      *               a corner index, starting in the upper-left position, clock-wise:
     699             :      *
     700             :      *  0         1
     701             :      *   *-------*
     702             :      *   |       |
     703             :      *   *-------*
     704             :      *  3         2
     705             :      */
     706             :     void addRect(const SkRect& rect, Direction dir, unsigned start);
     707             : 
     708             :     /**
     709             :      *  Add a closed rectangle contour to the path
     710             :      *
     711             :      *  @param left     The left side of a rectangle to add as a closed contour
     712             :      *                  to the path
     713             :      *  @param top      The top of a rectangle to add as a closed contour to the
     714             :      *                  path
     715             :      *  @param right    The right side of a rectangle to add as a closed contour
     716             :      *                  to the path
     717             :      *  @param bottom   The bottom of a rectangle to add as a closed contour to
     718             :      *                  the path
     719             :      *  @param dir  The direction to wind the rectangle's contour.
     720             :      *
     721             :      *  Note: the contour initial point index is 0 (as defined above).
     722             :      */
     723             :     void addRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom,
     724             :                  Direction dir = kCW_Direction);
     725             : 
     726             :     /**
     727             :      *  Add a closed oval contour to the path
     728             :      *
     729             :      *  @param oval The bounding oval to add as a closed contour to the path
     730             :      *  @param dir  The direction to wind the oval's contour.
     731             :      *
     732             :      *  Note: the contour initial point index is 1 (as defined below).
     733             :      */
     734             :     void addOval(const SkRect& oval, Direction dir = kCW_Direction);
     735             : 
     736             :     /**
     737             :      *  Add a closed oval contour to the path
     738             :      *
     739             :      *  @param oval  The bounding oval to add as a closed contour to the path
     740             :      *  @param dir   The direction to wind the oval's contour.
     741             :      *  @param start Initial point of the contour (initial moveTo), expressed
     742             :      *               as an ellipse vertex index, starting at the top, clock-wise
     743             :      *               (90/0/270/180deg order):
     744             :      *
     745             :      *        0
     746             :      *       -*-
     747             :      *     |     |
     748             :      *   3 *     * 1
     749             :      *     |     |
     750             :      *       -*-
     751             :      *        2
     752             :      */
     753             :     void addOval(const SkRect& oval, Direction dir, unsigned start);
     754             : 
     755             :     /**
     756             :      *  Add a closed circle contour to the path. The circle contour begins at
     757             :      *  the right-most point (as though 1 were passed to addOval's 'start' param).
     758             :      *
     759             :      *  @param x        The x-coordinate of the center of a circle to add as a
     760             :      *                  closed contour to the path
     761             :      *  @param y        The y-coordinate of the center of a circle to add as a
     762             :      *                  closed contour to the path
     763             :      *  @param radius   The radius of a circle to add as a closed contour to the
     764             :      *                  path
     765             :      *  @param dir  The direction to wind the circle's contour.
     766             :      */
     767             :     void addCircle(SkScalar x, SkScalar y, SkScalar radius,
     768             :                    Direction dir = kCW_Direction);
     769             : 
     770             :     /** Add the specified arc to the path as a new contour.
     771             : 
     772             :         @param oval The bounds of oval used to define the size of the arc
     773             :         @param startAngle Starting angle (in degrees) where the arc begins
     774             :         @param sweepAngle Sweep angle (in degrees) measured clockwise
     775             :     */
     776             :     void addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle);
     777             : 
     778             :     /**
     779             :      *  Add a closed round-rectangle contour to the path
     780             :      *  @param rect The bounds of a round-rectangle to add as a closed contour
     781             :      *  @param rx   The x-radius of the rounded corners on the round-rectangle
     782             :      *  @param ry   The y-radius of the rounded corners on the round-rectangle
     783             :      *  @param dir  The direction to wind the rectangle's contour.
     784             :      */
     785             :     void addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
     786             :                       Direction dir = kCW_Direction);
     787             : 
     788             :     /**
     789             :      *  Add a closed round-rectangle contour to the path. Each corner receives
     790             :      *  two radius values [X, Y]. The corners are ordered top-left, top-right,
     791             :      *  bottom-right, bottom-left.
     792             :      *  @param rect The bounds of a round-rectangle to add as a closed contour
     793             :      *  @param radii Array of 8 scalars, 4 [X,Y] pairs for each corner
     794             :      *  @param dir  The direction to wind the rectangle's contour.
     795             :      * Note: The radii here now go through the same constraint handling as the
     796             :      *       SkRRect radii (i.e., either radii at a corner being 0 implies a
     797             :      *       sqaure corner and oversized radii are proportionally scaled down).
     798             :      */
     799             :     void addRoundRect(const SkRect& rect, const SkScalar radii[],
     800             :                       Direction dir = kCW_Direction);
     801             : 
     802             :     /**
     803             :      *  Add an SkRRect contour to the path
     804             :      *  @param rrect The rounded rect to add as a closed contour
     805             :      *  @param dir   The winding direction for the new contour.
     806             :      *
     807             :      *  Note: the contour initial point index is either 6 (for dir == kCW_Direction)
     808             :      *        or 7 (for dir == kCCW_Direction), as defined below.
     809             :      *
     810             :      */
     811             :     void addRRect(const SkRRect& rrect, Direction dir = kCW_Direction);
     812             : 
     813             :     /**
     814             :      *  Add an SkRRect contour to the path
     815             :      *  @param rrect The rounded rect to add as a closed contour
     816             :      *  @param dir   The winding direction for the new contour.
     817             :      *  @param start Initial point of the contour (initial moveTo), expressed as
     818             :      *               an index of the radii minor/major points, ordered clock-wise:
     819             :      *
     820             :      *      0    1
     821             :      *      *----*
     822             :      *   7 *      * 2
     823             :      *     |      |
     824             :      *   6 *      * 3
     825             :      *      *----*
     826             :      *      5    4
     827             :      */
     828             :     void addRRect(const SkRRect& rrect, Direction dir, unsigned start);
     829             : 
     830             :     /**
     831             :      *  Add a new contour made of just lines. This is just a fast version of
     832             :      *  the following:
     833             :      *      this->moveTo(pts[0]);
     834             :      *      for (int i = 1; i < count; ++i) {
     835             :      *          this->lineTo(pts[i]);
     836             :      *      }
     837             :      *      if (close) {
     838             :      *          this->close();
     839             :      *      }
     840             :      */
     841             :     void addPoly(const SkPoint pts[], int count, bool close);
     842             : 
     843             :     enum AddPathMode {
     844             :         /** Source path contours are added as new contours.
     845             :         */
     846             :         kAppend_AddPathMode,
     847             :         /** Path is added by extending the last contour of the destination path
     848             :             with the first contour of the source path. If the last contour of
     849             :             the destination path is closed, then it will not be extended.
     850             :             Instead, the start of source path will be extended by a straight
     851             :             line to the end point of the destination path.
     852             :         */
     853             :         kExtend_AddPathMode
     854             :     };
     855             : 
     856             :     /** Add a copy of src to the path, offset by (dx,dy)
     857             :         @param src  The path to add as a new contour
     858             :         @param dx   The amount to translate the path in X as it is added
     859             :         @param dx   The amount to translate the path in Y as it is added
     860             :     */
     861             :     void addPath(const SkPath& src, SkScalar dx, SkScalar dy,
     862             :                  AddPathMode mode = kAppend_AddPathMode);
     863             : 
     864             :     /** Add a copy of src to the path
     865             :     */
     866          15 :     void addPath(const SkPath& src, AddPathMode mode = kAppend_AddPathMode) {
     867             :         SkMatrix m;
     868          15 :         m.reset();
     869          15 :         this->addPath(src, m, mode);
     870          15 :     }
     871             : 
     872             :     /** Add a copy of src to the path, transformed by matrix
     873             :         @param src  The path to add as a new contour
     874             :         @param matrix  Transform applied to src
     875             :         @param mode  Determines how path is added
     876             :     */
     877             :     void addPath(const SkPath& src, const SkMatrix& matrix, AddPathMode mode = kAppend_AddPathMode);
     878             : 
     879             :     /**
     880             :      *  Same as addPath(), but reverses the src input
     881             :      */
     882             :     void reverseAddPath(const SkPath& src);
     883             : 
     884             :     /** Offset the path by (dx,dy), returning true on success
     885             : 
     886             :         @param dx   The amount in the X direction to offset the entire path
     887             :         @param dy   The amount in the Y direction to offset the entire path
     888             :         @param dst  The translated path is written here
     889             :     */
     890             :     void offset(SkScalar dx, SkScalar dy, SkPath* dst) const;
     891             : 
     892             :     /** Offset the path by (dx,dy), returning true on success
     893             : 
     894             :         @param dx   The amount in the X direction to offset the entire path
     895             :         @param dy   The amount in the Y direction to offset the entire path
     896             :     */
     897           0 :     void offset(SkScalar dx, SkScalar dy) {
     898           0 :         this->offset(dx, dy, this);
     899           0 :     }
     900             : 
     901             :     /** Transform the points in this path by matrix, and write the answer into
     902             :         dst.
     903             : 
     904             :         @param matrix   The matrix to apply to the path
     905             :         @param dst      The transformed path is written here
     906             :     */
     907             :     void transform(const SkMatrix& matrix, SkPath* dst) const;
     908             : 
     909             :     /** Transform the points in this path by matrix
     910             : 
     911             :         @param matrix The matrix to apply to the path
     912             :     */
     913           0 :     void transform(const SkMatrix& matrix) {
     914           0 :         this->transform(matrix, this);
     915           0 :     }
     916             : 
     917             :     /** Return the last point on the path. If no points have been added, (0,0)
     918             :         is returned. If there are no points, this returns false, otherwise it
     919             :         returns true.
     920             : 
     921             :         @param lastPt   The last point on the path is returned here
     922             :     */
     923             :     bool getLastPt(SkPoint* lastPt) const;
     924             : 
     925             :     /** Set the last point on the path. If no points have been added,
     926             :         moveTo(x,y) is automatically called.
     927             : 
     928             :         @param x    The new x-coordinate for the last point
     929             :         @param y    The new y-coordinate for the last point
     930             :     */
     931             :     void setLastPt(SkScalar x, SkScalar y);
     932             : 
     933             :     /** Set the last point on the path. If no points have been added, moveTo(p)
     934             :         is automatically called.
     935             : 
     936             :         @param p    The new location for the last point
     937             :     */
     938             :     void setLastPt(const SkPoint& p) {
     939             :         this->setLastPt(p.fX, p.fY);
     940             :     }
     941             : 
     942             :     enum SegmentMask {
     943             :         kLine_SegmentMask   = 1 << 0,
     944             :         kQuad_SegmentMask   = 1 << 1,
     945             :         kConic_SegmentMask  = 1 << 2,
     946             :         kCubic_SegmentMask  = 1 << 3,
     947             :     };
     948             : 
     949             :     /**
     950             :      *  Returns a mask, where each bit corresponding to a SegmentMask is
     951             :      *  set if the path contains 1 or more segments of that type.
     952             :      *  Returns 0 for an empty path (no segments).
     953             :      */
     954         324 :     uint32_t getSegmentMasks() const { return fPathRef->getSegmentMasks(); }
     955             : 
     956             :     enum Verb {
     957             :         kMove_Verb,     //!< iter.next returns 1 point
     958             :         kLine_Verb,     //!< iter.next returns 2 points
     959             :         kQuad_Verb,     //!< iter.next returns 3 points
     960             :         kConic_Verb,    //!< iter.next returns 3 points + iter.conicWeight()
     961             :         kCubic_Verb,    //!< iter.next returns 4 points
     962             :         kClose_Verb,    //!< iter.next returns 0 points
     963             :         kDone_Verb,     //!< iter.next returns 0 points
     964             :     };
     965             : 
     966             :     /** Iterate through all of the segments (lines, quadratics, cubics) of
     967             :         each contours in a path.
     968             : 
     969             :         The iterator cleans up the segments along the way, removing degenerate
     970             :         segments and adding close verbs where necessary. When the forceClose
     971             :         argument is provided, each contour (as defined by a new starting
     972             :         move command) will be completed with a close verb regardless of the
     973             :         contour's contents.
     974             :     */
     975             :     class SK_API Iter {
     976             :     public:
     977             :         Iter();
     978             :         Iter(const SkPath&, bool forceClose);
     979             : 
     980             :         void setPath(const SkPath&, bool forceClose);
     981             : 
     982             :         /** Return the next verb in this iteration of the path. When all
     983             :             segments have been visited, return kDone_Verb.
     984             : 
     985             :             @param  pts The points representing the current verb and/or segment
     986             :             @param doConsumeDegerates If true, first scan for segments that are
     987             :                    deemed degenerate (too short) and skip those.
     988             :             @param exact if doConsumeDegenerates is true and exact is true, skip only
     989             :                    degenerate elements with lengths exactly equal to zero. If exact
     990             :                    is false, skip degenerate elements with lengths close to zero. If
     991             :                    doConsumeDegenerates is false, exact has no effect.
     992             :             @return The verb for the current segment
     993             :         */
     994        3642 :         Verb next(SkPoint pts[4], bool doConsumeDegerates = true, bool exact = false) {
     995        3642 :             if (doConsumeDegerates) {
     996         963 :                 this->consumeDegenerateSegments(exact);
     997             :             }
     998        3642 :             return this->doNext(pts);
     999             :         }
    1000             : 
    1001             :         /**
    1002             :          *  Return the weight for the current conic. Only valid if the current
    1003             :          *  segment return by next() was a conic.
    1004             :          */
    1005           0 :         SkScalar conicWeight() const { return *fConicWeights; }
    1006             : 
    1007             :         /** If next() returns kLine_Verb, then this query returns true if the
    1008             :             line was the result of a close() command (i.e. the end point is the
    1009             :             initial moveto for this contour). If next() returned a different
    1010             :             verb, this returns an undefined value.
    1011             : 
    1012             :             @return If the last call to next() returned kLine_Verb, return true
    1013             :                     if it was the result of an explicit close command.
    1014             :         */
    1015             :         bool isCloseLine() const { return SkToBool(fCloseLine); }
    1016             : 
    1017             :         /** Returns true if the current contour is closed (has a kClose_Verb)
    1018             :             @return true if the current contour is closed (has a kClose_Verb)
    1019             :         */
    1020             :         bool isClosedContour() const;
    1021             : 
    1022             :     private:
    1023             :         const SkPoint*  fPts;
    1024             :         const uint8_t*  fVerbs;
    1025             :         const uint8_t*  fVerbStop;
    1026             :         const SkScalar* fConicWeights;
    1027             :         SkPoint         fMoveTo;
    1028             :         SkPoint         fLastPt;
    1029             :         SkBool8         fForceClose;
    1030             :         SkBool8         fNeedClose;
    1031             :         SkBool8         fCloseLine;
    1032             :         SkBool8         fSegmentState;
    1033             : 
    1034             :         inline const SkPoint& cons_moveTo();
    1035             :         Verb autoClose(SkPoint pts[2]);
    1036             :         void consumeDegenerateSegments(bool exact);
    1037             :         Verb doNext(SkPoint pts[4]);
    1038             :     };
    1039             : 
    1040             :     /** Iterate through the verbs in the path, providing the associated points.
    1041             :     */
    1042             :     class SK_API RawIter {
    1043             :     public:
    1044             :         RawIter() {}
    1045          63 :         RawIter(const SkPath& path) {
    1046          63 :             setPath(path);
    1047          63 :         }
    1048             : 
    1049          63 :         void setPath(const SkPath& path) {
    1050          63 :             fRawIter.setPathRef(*path.fPathRef.get());
    1051          63 :         }
    1052             : 
    1053             :         /** Return the next verb in this iteration of the path. When all
    1054             :             segments have been visited, return kDone_Verb.
    1055             : 
    1056             :             @param  pts The points representing the current verb and/or segment
    1057             :                         This must not be NULL.
    1058             :             @return The verb for the current segment
    1059             :         */
    1060        1220 :         Verb next(SkPoint pts[4]) {
    1061        1220 :             return (Verb) fRawIter.next(pts);
    1062             :         }
    1063             : 
    1064             :         /** Return what the next verb will be, but do not visit the next segment.
    1065             : 
    1066             :             @return The verb for the next segment
    1067             :         */
    1068           0 :         Verb peek() const {
    1069           0 :             return (Verb) fRawIter.peek();
    1070             :         }
    1071             : 
    1072           0 :         SkScalar conicWeight() const {
    1073           0 :             return fRawIter.conicWeight();
    1074             :         }
    1075             : 
    1076             :     private:
    1077             :         SkPathRef::Iter fRawIter;
    1078             :         friend class SkPath;
    1079             :     };
    1080             : 
    1081             :     /**
    1082             :      *  Returns true if the point { x, y } is contained by the path, taking into
    1083             :      *  account the FillType.
    1084             :      */
    1085             :     bool contains(SkScalar x, SkScalar y) const;
    1086             : 
    1087             :     void dump(SkWStream* , bool forceClose, bool dumpAsHex) const;
    1088             :     void dump() const;
    1089             :     void dumpHex() const;
    1090             : 
    1091             :     /**
    1092             :      *  Write the path to the buffer, and return the number of bytes written.
    1093             :      *  If buffer is NULL, it still returns the number of bytes.
    1094             :      */
    1095             :     size_t writeToMemory(void* buffer) const;
    1096             :     /**
    1097             :      * Initializes the path from the buffer
    1098             :      *
    1099             :      * @param buffer Memory to read from
    1100             :      * @param length Amount of memory available in the buffer
    1101             :      * @return number of bytes read (must be a multiple of 4) or
    1102             :      *         0 if there was not enough memory available
    1103             :      */
    1104             :     size_t readFromMemory(const void* buffer, size_t length);
    1105             : 
    1106             :     /** Returns a non-zero, globally unique value corresponding to the set of verbs
    1107             :         and points in the path (but not the fill type [except on Android skbug.com/1762]).
    1108             :         Each time the path is modified, a different generation ID will be returned.
    1109             :     */
    1110             :     uint32_t getGenerationID() const;
    1111             : 
    1112             : #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
    1113             :     static const int kPathRefGenIDBitCnt = 30; // leave room for the fill type (skbug.com/1762)
    1114             : #else
    1115             :     static const int kPathRefGenIDBitCnt = 32;
    1116             : #endif
    1117             : 
    1118             :     SkDEBUGCODE(void validate() const;)
    1119             :     SkDEBUGCODE(void experimentalValidateRef() const { fPathRef->validate(); } )
    1120             : 
    1121             : private:
    1122             :     enum SerializationOffsets {
    1123             :         // 1 free bit at 29
    1124             :         kUnused1_SerializationShift = 28,    // 1 free bit
    1125             :         kDirection_SerializationShift = 26, // requires 2 bits
    1126             :         kIsVolatile_SerializationShift = 25, // requires 1 bit
    1127             :         // 1 free bit at 24
    1128             :         kConvexity_SerializationShift = 16, // requires 8 bits
    1129             :         kFillType_SerializationShift = 8,   // requires 8 bits
    1130             :         // low-8-bits are version
    1131             :     };
    1132             : 
    1133             :     enum SerializationVersions {
    1134             :         kPathPrivFirstDirection_Version = 1,
    1135             :         kPathPrivLastMoveToIndex_Version = 2,
    1136             :         kCurrent_Version = 2
    1137             :     };
    1138             : 
    1139             :     sk_sp<SkPathRef>                                   fPathRef;
    1140             :     int                                                fLastMoveToIndex;
    1141             :     uint8_t                                            fFillType;
    1142             :     mutable uint8_t                                    fConvexity;
    1143             :     mutable SkAtomic<uint8_t, sk_memory_order_relaxed> fFirstDirection;// SkPathPriv::FirstDirection
    1144             :     SkBool8                                            fIsVolatile;
    1145             : 
    1146             :     /** Resets all fields other than fPathRef to their initial 'empty' values.
    1147             :      *  Assumes the caller has already emptied fPathRef.
    1148             :      *  On Android increments fGenerationID without reseting it.
    1149             :      */
    1150             :     void resetFields();
    1151             : 
    1152             :     /** Sets all fields other than fPathRef to the values in 'that'.
    1153             :      *  Assumes the caller has already set fPathRef.
    1154             :      *  Doesn't change fGenerationID or fSourcePath on Android.
    1155             :      */
    1156             :     void copyFields(const SkPath& that);
    1157             : 
    1158             :     friend class Iter;
    1159             :     friend class SkPathPriv;
    1160             :     friend class SkPathStroker;
    1161             : 
    1162             :     /*  Append, in reverse order, the first contour of path, ignoring path's
    1163             :         last point. If no moveTo() call has been made for this contour, the
    1164             :         first point is automatically set to (0,0).
    1165             :     */
    1166             :     void reversePathTo(const SkPath&);
    1167             : 
    1168             :     // called before we add points for lineTo, quadTo, cubicTo, checking to see
    1169             :     // if we need to inject a leading moveTo first
    1170             :     //
    1171             :     //  SkPath path; path.lineTo(...);   <--- need a leading moveTo(0, 0)
    1172             :     // SkPath path; ... path.close(); path.lineTo(...) <-- need a moveTo(previous moveTo)
    1173             :     //
    1174             :     inline void injectMoveToIfNeeded();
    1175             : 
    1176             :     inline bool hasOnlyMoveTos() const;
    1177             : 
    1178             :     Convexity internalGetConvexity() const;
    1179             : 
    1180             :     bool isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts,
    1181             :                        bool* isClosed, Direction* direction) const;
    1182             : 
    1183             :     // called by stroker to see if all points are equal and worthy of a cap
    1184             :     // equivalent to a short-circuit version of getBounds().isEmpty() 
    1185             :     bool isZeroLength() const;
    1186             : 
    1187             :     /** Returns if the path can return a bound at no cost (true) or will have to
    1188             :         perform some computation (false).
    1189             :      */
    1190         113 :     bool hasComputedBounds() const {
    1191         113 :         SkDEBUGCODE(this->validate();)
    1192         113 :         return fPathRef->hasComputedBounds();
    1193             :     }
    1194             : 
    1195             : 
    1196             :     // 'rect' needs to be sorted
    1197         113 :     void setBounds(const SkRect& rect) {
    1198         226 :         SkPathRef::Editor ed(&fPathRef);
    1199             : 
    1200         113 :         ed.setBounds(rect);
    1201         113 :     }
    1202             : 
    1203             :     void setPt(int index, SkScalar x, SkScalar y);
    1204             : 
    1205             :     friend class SkAutoPathBoundsUpdate;
    1206             :     friend class SkAutoDisableOvalCheck;
    1207             :     friend class SkAutoDisableDirectionCheck;
    1208             :     friend class SkPathWriter;
    1209             :     friend class SkOpBuilder;
    1210             :     friend class SkBench_AddPathTest; // perf test reversePathTo
    1211             :     friend class PathTest_Private; // unit test reversePathTo
    1212             :     friend class ForceIsRRect_Private; // unit test isRRect
    1213             : };
    1214             : 
    1215             : #endif

Generated by: LCOV version 1.13