diff options
author | 2017-09-01 13:49:54 -0400 | |
---|---|---|
committer | 2017-09-01 19:59:19 +0000 | |
commit | b7da7239f73554abebc579a1525e1f4993fee8d8 (patch) | |
tree | 800956e66cd7be5558afc358e867ca84ce31729f /include/core/SkPath.h | |
parent | e04038462747f409417435fee3c2b2c84ed7d651 (diff) |
generated SkCanvas.h
SkCanvas.h generated from docs/SkCanvas.bmh using bookmaker.
Also added corrections to SkPaint.h, and generated SkPath.h.
Once these are functionally correct (e.g., they don't break
anything) I plan to check them in -- feel free to continue
to review them before and after the check in event.
R=brianosman@google.com
TBR=reed@google.com
Bug: skia:6898
Change-Id: I6d01e9eee422304e5ab871b3870a7ed710efd645
Reviewed-on: https://skia-review.googlesource.com/30460
Commit-Queue: Cary Clark <caryclark@skia.org>
Reviewed-by: Cary Clark <caryclark@skia.org>
Reviewed-by: Yuqian Li <liyuqian@google.com>
Diffstat (limited to 'include/core/SkPath.h')
-rw-r--r-- | include/core/SkPath.h | 1732 |
1 files changed, 1115 insertions, 617 deletions
diff --git a/include/core/SkPath.h b/include/core/SkPath.h index fb25b03426..e38b464d85 100644 --- a/include/core/SkPath.h +++ b/include/core/SkPath.h @@ -17,112 +17,199 @@ class SkRRect; class SkWStream; /** \class SkPath - - The SkPath class encapsulates compound (multiple contour) geometric paths - consisting of straight line segments, quadratic curves, and cubic curves. - - SkPath is not thread safe unless you've first called SkPath::updateBoundsCache(). */ class SK_API SkPath { public: - enum Direction { - /** clockwise direction for adding closed contours */ - kCW_Direction, - /** counter-clockwise direction for adding closed contours */ - kCCW_Direction, - }; +/** \enum SkPath::Direction + Direction describes whether contour is clockwise or counterclockwise. + When SkPath contains multiple overlapping contours, Direction together with + FillType determines whether overlaps are filled or form holes. + + Direction also determines how contour is measured. For instance, dashing + measures along SkPath to determine where to start and stop stroke; Direction + will change dashed results as it steps clockwise or counterclockwise. + + Closed contours like SkRect, SkRRect, circle, and oval added with + kCW_Direction travel clockwise; the same added with kCCW_Direction + travel counterclockwise. +*/ +enum Direction { + kCW_Direction, //!< Contour travels in a clockwise direction. + kCCW_Direction, //!< Contour travels in a counterclockwise direction. +}; + + /** By default, SkPath has no SkPath::Verb, no SkPoint, and no weights. + SkPath::FillType is set to kWinding_FillType. + + @return empty SkPath + */ SkPath(); + + /** Copy constructor makes two paths identical by value. Internally, path and + the returned result share pointer values. The underlying verb array, SkPoint arrays + and weights are copied when modified. + + Creating a SkPath copy is very efficient and never allocates memory. + SkPath are always copied by value from the interface; the underlying shared + pointers are not exposed. + + @param path SkPath to copy by value + @return copy of SkPath + */ SkPath(const SkPath& path); + + /** Releases ownership of any shared data and deletes data if SkPath is sole owner. + */ ~SkPath(); + /** SkPath assignment makes two paths identical by value. Internally, assignment + shares pointer values. The underlying verb array, SkPoint arrays and weights + are copied when modified. + + Copying SkPath by assignment is very efficient and never allocates memory. + SkPath are always copied by value from the interface; the underlying shared + pointers are not exposed. + + @param path verb array, SkPoint arrays, weights, and SkPath::FillType to copy + @return SkPath copied by value + */ SkPath& operator=(const SkPath& path); - // mac chromium dbg requires SK_API to make operator== visible + + /** Compares a and b; returns true if SkPath::FillType, verb array, SkPoint arrays, and weights + are equivalent. + + @param a SkPath to compare + @param b SkPath to compare + @return true if SkPath pair are equivalent + */ friend SK_API bool operator==(const SkPath& a, const SkPath& b); + + /** Compares a and b; returns true if SkPath::FillType, verb array, SkPoint arrays, and weights + are not equivalent. + + @param a SkPath to compare + @param b SkPath to compare + @return true if SkPath pair are not equivalent + */ friend bool operator!=(const SkPath& a, const SkPath& b) { return !(a == b); } - /** Return true if the paths contain an equal array of verbs and weights. Paths - * with equal verb counts can be readily interpolated. If the paths contain one - * or more conics, the conics' weights must also match. - * - * @param compare The path to compare. - * - * @return true if the paths have the same verbs and weights. - */ + /** Return true if SkPath contain equal SkPath::Verb and equal weights. + If SkPath contain one or more conics, the weights must match. + + conicTo() may add different SkPath::Verb depending on conic weight, so it is not + trivial to interpolate a pair of SkPath containing conics with different + conic weight values. + + @param compare SkPath to compare + @return true if SkPath verb array and weights are equivalent + */ bool isInterpolatable(const SkPath& compare) const; - /** Interpolate between two paths with same-sized point arrays. - * The out path contains the verbs and weights of this path. - * The out points are a weighted average of this path and the ending path. - * - * @param ending The path to interpolate between. - * @param weight The weight, from 0 to 1. The output points are set to - * (this->points * weight) + ending->points * (1 - weight). - * @return true if the paths could be interpolated. - */ + /** Interpolate between SkPath with equal sized point arrays. + Copy verb array and weights to out, + and set out SkPoint arrays to a weighted average of this SkPoint arrays and ending + SkPoint arrays, using the formula: + + @param ending SkPoint arrays averaged with this SkPoint arrays + @param weight contribution of ending SkPoint arrays, and + one minus contribution of this SkPoint arrays + @param out SkPath replaced by interpolated averages + @return true if SkPath contain same number of SkPoint + */ bool interpolate(const SkPath& ending, SkScalar weight, SkPath* out) const; #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK - /** Returns true if the caller is the only owner of the underlying path data */ + /** To be deprecated; only valid for Android framework. + + @return true if SkPath has one owner + */ bool unique() const { return fPathRef->unique(); } #endif + /** \enum SkPath::FillType + FillType selects the rule used to fill SkPath. SkPath set to kWinding_FillType + fills if the sum of contour edges is not zero, where clockwise edges add one, and + counterclockwise edges subtract one. SkPath set to kEvenOdd_FillType fills if the + number of contour edges is odd. Each FillType has an inverse variant that + reverses the rule: + kInverseWinding_FillType fills where the sum of contour edges is zero; + kInverseEvenOdd_FillType fills where the number of contour edges is even. + */ enum FillType { - /** Specifies that "inside" is computed by a non-zero sum of signed - edge crossings - */ + /** Specifies fill as area is enclosed by a non-zero sum of contour Direction. */ kWinding_FillType, - /** Specifies that "inside" is computed by an odd number of edge - crossings - */ + + /** Specifies fill as area enclosed by an odd number of contours. */ kEvenOdd_FillType, - /** Same as Winding, but draws outside of the path, rather than inside - */ + + /** Specifies fill as area is enclosed by a zero sum of contour Direction. */ kInverseWinding_FillType, - /** Same as EvenOdd, but draws outside of the path, rather than inside - */ + + /** Specifies fill as area enclosed by an even number of contours. */ kInverseEvenOdd_FillType, }; - /** Return the path's fill type. This is used to define how "inside" is - computed. The default value is kWinding_FillType. + /** Returns FillType, the rule used to fill SkPath. FillType of a new SkPath is + kWinding_FillType. - @return the path's fill type + @return one of: kWinding_FillType, kEvenOdd_FillType, kInverseWinding_FillType, + kInverseEvenOdd_FillType */ FillType getFillType() const { return (FillType)fFillType; } - /** Set the path's fill type. This is used to define how "inside" is - computed. The default value is kWinding_FillType. + /** Sets FillType, the rule used to fill SkPath. While there is no check + that ft is legal, values outside of FillType are not supported. - @param ft The new fill type for this path + @param ft one of: kWinding_FillType, kEvenOdd_FillType, kInverseWinding_FillType, + kInverseEvenOdd_FillType */ void setFillType(FillType ft) { fFillType = SkToU8(ft); } - /** Returns true if the filltype is one of the Inverse variants */ + /** Returns if FillType describes area outside SkPath geometry. The inverse fill area + extends indefinitely. + + @return true if FillType is kInverseWinding_FillType or kInverseEvenOdd_FillType + */ bool isInverseFillType() const { return IsInverseFillType((FillType)fFillType); } - /** - * Toggle between inverse and normal filltypes. This reverse the return - * value of isInverseFillType() - */ + /** Replace FillType with its inverse. The inverse of FillType describes the area + unmodified by the original FillType. + */ void toggleInverseFillType() { fFillType ^= 2; } + /** \enum SkPath::Convexity + SkPath is convex if it contains one contour and contour loops no more than + 360 degrees, and contour angles all have same Direction. Convex SkPath + may have better performance and require fewer resources on GPU surface. + + SkPath is concave when either at least one Direction change is clockwise and + another is counterclockwise, or the sum of the changes in Direction is not 360 + degrees. + + Initially SkPath Convexity is kUnknown_Convexity. SkPath Convexity is computed + if needed by destination SkSurface. + */ enum Convexity { - kUnknown_Convexity, + kUnknown_Convexity, //!< Indicates Convexity has not been determined. + + /** SkPath has one contour made of a simple geometry without indentations. */ kConvex_Convexity, - kConcave_Convexity, + kConcave_Convexity, //!< SkPath has more than one contour, or a geometry with indentations. }; - /** - * Return the path's convexity, as stored in the path. If it is currently unknown, - * then this function will attempt to compute the convexity (and cache the result). - */ + /** Computes SkPath::Convexity if required, and returns stored value. + SkPath::Convexity is computed if stored value is kUnknown_Convexity, + or if SkPath has been altered since SkPath::Convexity was computed or set. + + @return computed or stored SkPath::Convexity + */ Convexity getConvexity() const { if (kUnknown_Convexity != fConvexity) { return static_cast<Convexity>(fConvexity); @@ -131,56 +218,63 @@ public: } } - /** - * Return the currently cached value for convexity, even if that is set to - * kUnknown_Convexity. Note: getConvexity() will automatically call - * ComputeConvexity and cache its return value if the current setting is - * kUnknown. - */ + /** Returns last computed SkPath::Convexity, or kUnknown_Convexity if + SkPath has been altered since SkPath::Convexity was computed or set. + + @return stored SkPath::Convexity + */ Convexity getConvexityOrUnknown() const { return (Convexity)fConvexity; } - /** - * Store a convexity setting in the path. There is no automatic check to - * see if this value actually agrees with the return value that would be - * computed by getConvexity(). - * - * Note: even if this is set to a "known" value, if the path is later - * changed (e.g. lineTo(), addRect(), etc.) then the cached value will be - * reset to kUnknown_Convexity. - */ + /** Stores convexity so that it is later returned by getConvexity() or getConvexityOrUnknown(). + convexity may differ from getConvexity(), although setting an incorrect value may + cause incorrect or inefficient drawing. + + If convexity is kUnknown_Convexity: getConvexity() will + compute SkPath::Convexity, and getConvexityOrUnknown() will return kUnknown_Convexity. + + If convexity is kConvex_Convexity or kConcave_Convexity, getConvexity() + and getConvexityOrUnknown() will return convexity until the path is + altered. + + @param convexity one of: kUnknown_Convexity, kConvex_Convexity, or kConcave_Convexity + */ void setConvexity(Convexity convexity); - /** - * Returns true if the path is flagged as being convex. This is not a - * confirmed by any analysis, it is just the value set earlier. - */ + /** Computes SkPath::Convexity if required, and returns true if value is kConvex_Convexity. + If setConvexity() was called with kConvex_Convexity or kConcave_Convexity, and + the path has not been altered, SkPath::Convexity is not recomputed. + + @return true if SkPath::Convexity stored or computed is kConvex_Convexity + */ bool isConvex() const { return kConvex_Convexity == this->getConvexity(); } - /** - * Set the isConvex flag to true or false. Convex paths may draw faster if - * this flag is set, though setting this to true on a path that is in fact - * not convex can give undefined results when drawn. Paths default to - * isConvex == false - */ + /** Deprecated. Use setConvexity(). + */ SK_ATTR_DEPRECATED("use setConvexity") void setIsConvex(bool isConvex) { this->setConvexity(isConvex ? kConvex_Convexity : kConcave_Convexity); } - /** Returns true if the path is an oval. - * - * @param rect returns the bounding rect of this oval. It's a circle - * if the height and width are the same. - * @param dir is the oval CCW (or CW if false). - * @param start indicates where the contour starts on the oval (see - * SkPath::addOval for intepretation of the index). - * @return true if this path is an oval. - * Tracking whether a path is an oval is considered an - * optimization for performance and so some paths that are in - * fact ovals can report false. - */ + /** Returns true if constructed by addCircle(), addOval(); and in some cases, + addRoundRect(), addRRect(). SkPath constructed with conicTo() or rConicTo() will not + return true though SkPath draws oval. + + rect receives bounds of oval. + dir receives SkPath::Direction of oval: kCW_Direction if clockwise, kCCW_Direction if + counterclockwise. + start receives start of oval: 0 for top, 1 for right, 2 for bottom, 3 for left. + + rect, dir, and start are unmodified if oval is not found. + + Triggers performance optimizations on some GPU surface implementations. + + @param rect storage for bounding SkRect of oval; may be nullptr + @param dir storage for SkPath::Direction; may be nullptr + @param start storage for start of oval; may be nullptr + @return true if SkPath was constructed by method that reduces to oval + */ bool isOval(SkRect* rect, Direction* dir = nullptr, unsigned* start = nullptr) const { bool isCCW = false; @@ -191,18 +285,24 @@ public: return result; } - /** Returns true if the path is a round rect. - * - * @param rrect Returns the bounding rect and radii of this round rect. - * @param dir is the rrect CCW (or CW if false). - * @param start indicates where the contour starts on the rrect (see - * SkPath::addRRect for intepretation of the index). - * - * @return true if this path is a round rect. - * Tracking whether a path is a round rect is considered an - * optimization for performance and so some paths that are in - * fact round rects can report false. - */ + /** Returns true if constructed by addRoundRect(), addRRect(); and if construction + is not empty, not SkRect, and not oval. SkPath constructed with other calls + will not return true though SkPath draws SkRRect. + + rrect receives bounds of SkRRect. + dir receives SkPath::Direction of oval: kCW_Direction if clockwise, kCCW_Direction if + counterclockwise. + start receives start of SkRRect: 0 for top, 1 for right, 2 for bottom, 3 for left. + + rrect, dir, and start are unmodified if SkRRect is not found. + + Triggers performance optimizations on some GPU surface implementations. + + @param rrect storage for bounding SkRect of SkRRect; may be nullptr + @param dir storage for SkPath::Direction; may be nullptr + @param start storage for start of SkRRect; may be nullptr + @return true if SkPath contains only SkRRect + */ bool isRRect(SkRRect* rrect, Direction* dir = nullptr, unsigned* start = nullptr) const { bool isCCW = false; @@ -213,69 +313,105 @@ public: return result; } - /** Clear any lines and curves from the path, making it empty. This frees up - internal storage associated with those segments. - On Android, does not change fSourcePath. + /** Sets SkPath to its initial state. + Removes verb array, SkPoint arrays, and weights, and sets FillType to kWinding_FillType. + Internal storage associated with SkPath is released. */ void reset(); - /** Similar to reset(), in that all lines and curves are removed from the - path. However, any internal storage for those lines/curves is retained, - making reuse of the path potentially faster. - On Android, does not change fSourcePath. + /** Sets SkPath to its initial state, preserving internal storage. + Removes verb array, SkPoint arrays, and weights, and sets FillType to kWinding_FillType. + Internal storage associated with SkPath is retained. + + Use rewind() instead of reset() if SkPath storage will be reused and performance + is critical. */ void rewind(); - /** Returns true if the path is empty (contains no lines or curves) + /** Empty SkPath may have FillType but has no SkPoint, SkPath::Verb, or conic weight. + SkPath() constructs empty SkPath; reset() and (rewind) make SkPath empty. - @return true if the path is empty (contains no lines or curves) + @return true if the path contains no SkPath::Verb array */ bool isEmpty() const { SkDEBUGCODE(this->validate();) return 0 == fPathRef->countVerbs(); } - /** Return true if the last contour of this path ends with a close verb. - */ + /** Contour is closed if SkPath SkPath::Verb array was last modified by close(). When stroked, + closed contour draws SkPaint::Join instead of SkPaint::Cap at first and last SkPoint. + + @return true if the last contour ends with a kClose_Verb + */ bool isLastContourClosed() const; - /** - * Returns true if all of the points in this path are finite, meaning there - * are no infinities and no NaNs. - */ + /** Returns true for finite SkPoint array values between negative SK_ScalarMax and + positive SK_ScalarMax. Returns false for any SkPoint array value of + SK_ScalarInfinity, SK_ScalarNegativeInfinity, or SK_ScalarNaN. + + @return true if all SkPoint values are finite + */ bool isFinite() const { SkDEBUGCODE(this->validate();) return fPathRef->isFinite(); } - /** Returns true if the path is volatile (i.e. should not be cached by devices.) - */ + /** Returns true if the path is volatile; it will not be altered or discarded + by the caller after it is drawn. SkPath by default have volatile set false, allowing + SkSurface to attach a cache of data which speeds repeated drawing. If true, SkSurface + may not speed repeated drawing. + + @return true if caller will alter SkPath after drawing + */ bool isVolatile() const { return SkToBool(fIsVolatile); } - /** Specify whether this path is volatile. Paths are not volatile by - default. Temporary paths that are discarded or modified after use should be - marked as volatile. This provides a hint to the device that the path - should not be cached. Providing this hint when appropriate can - improve performance by avoiding unnecessary overhead and resource - consumption on the device. - */ + /** Specify whether SkPath is volatile; whether it will be altered or discarded + by the caller after it is drawn. SkPath by default have volatile set false, allowing + SkBaseDevice to attach a cache of data which speeds repeated drawing. + + Mark temporary paths, discarded or modified after use, as volatile + to inform SkBaseDevice that the path need not be cached. + + Mark animating SkPath volatile to improve performance. + Mark unchanging SkPath non-volatile to improve repeated rendering. + + raster surface SkPath draws are affected by volatile for some shadows. + GPU surface SkPath draws are affected by volatile for some shadows and concave geometries. + + @param isVolatile true if caller will alter SkPath after drawing + */ void setIsVolatile(bool isVolatile) { fIsVolatile = isVolatile; } - /** Test a line for zero length + /** Test if line between SkPoint pair is degenerate. + Line with no length or that moves a very short distance is degenerate; it is + treated as a point. + + exact changes the equality test. If true, returns true only if p1 equals p2. + If false, returns true if p1 equals or nearly equals p2. - @return true if the line is of zero length; otherwise false. + @param p1 line start point + @param p2 line end point + @param exact if false, allow nearly equals + @return true if line is degenerate; its length is effectively zero */ static bool IsLineDegenerate(const SkPoint& p1, const SkPoint& p2, bool exact) { return exact ? p1 == p2 : p1.equalsWithinTolerance(p2); } - /** Test a quad for zero length + /** Test if quad is degenerate. + Quad with no length or that moves a very short distance is degenerate; it is + treated as a point. - @return true if the quad is of zero length; otherwise false. + @param p1 Quad start point + @param p2 Quad control point + @param p3 Quad end point + @param exact if true, returns true only if p1, p2, and p3 are equal; + if false, returns true if p1, p2, and p3 are equal or nearly equal + @return true if quad is degenerate; its length is effectively zero */ static bool IsQuadDegenerate(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3, bool exact) { @@ -283,9 +419,17 @@ public: p2.equalsWithinTolerance(p3); } - /** Test a cubic curve for zero length - - @return true if the cubic is of zero length; otherwise false. + /** Test if cubic is degenerate. + Cubic with no length or that moves a very short distance is degenerate; it is + treated as a point. + + @param p1 Cubic start point + @param p2 Cubic control point 1 + @param p3 Cubic control point 2 + @param p4 Cubic end point + @param exact if true, returns true only if p1, p2, p3, and p4 are equal; + if false, returns true if p1, p2, p3, and p4 are equal or nearly equal + @return true if cubic is degenerate; its length is effectively zero */ static bool IsCubicDegenerate(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3, const SkPoint& p4, bool exact) { @@ -294,329 +438,515 @@ public: p3.equalsWithinTolerance(p4); } - /** - * Returns true if the path specifies a single line (i.e. it contains just - * a moveTo and a lineTo). If so, and line[] is not null, it sets the 2 - * points in line[] to the end-points of the line. If the path is not a - * line, returns false and ignores line[]. - */ + /** Returns true if SkPath contains only one line; + SkPath::Verb array has two entries: kMove_Verb, kLine_Verb. + If SkPath contains one line and line is not nullptr, line is set to + line start point and line end point. + Returns false if SkPath is not one line; line is unaltered. + + @param line storage for line. May be nullptr + @return true if SkPath contains exactly one line + */ bool isLine(SkPoint line[2]) const; - /** Return the number of points in the path - */ + /** Returns the number of points in SkPath. + SkPoint count is initially zero. + + @return SkPath SkPoint array length + */ int countPoints() const; - /** Return the point at the specified index. If the index is out of range - (i.e. is not 0 <= index < countPoints()) then the returned coordinates - will be (0,0) - */ + /** Returns SkPoint at index in SkPoint arrays. Valid range for index is + 0 to countPoints() - 1. + Returns (0, 0) if index is out of range. + + @param index SkPoint array element selector + @return SkPoint array value or (0, 0) + */ SkPoint getPoint(int index) const; - /** Returns the number of points in the path. Up to max points are copied. + /** Returns number of points in SkPath. Up to max points are copied. + points may be nullptr; then, max must be zero. + If max is greater than number of points, excess points storage is unaltered. - @param points If not null, receives up to max points - @param max The maximum number of points to copy into points - @return the actual number of points in the path + @param points storage for SkPath SkPoint array. May be nullptr + @param max maximum to copy; must be greater than or equal to zero + @return SkPath SkPoint array length */ int getPoints(SkPoint points[], int max) const; - /** Return the number of verbs in the path - */ + /** Returns the number of SkPath::Verb: kMove_Verb, kLine_Verb, kQuad_Verb, kConic_Verb, + kCubic_Verb, and kClose_Verb; added to SkPath. + + @return length of verb array + */ int countVerbs() const; /** Returns the number of verbs in the path. Up to max verbs are copied. The verbs are copied as one byte per verb. - @param verbs If not null, receives up to max verbs - @param max The maximum number of verbs to copy into verbs - @return the actual number of verbs in the path + @param verbs storage for verbs, may be nullptr + @param max maximum number to copy into verbs + @return the actual number of verbs in the path */ int getVerbs(uint8_t verbs[], int max) const; - //! Swap contents of this and other. Guaranteed not to throw + /** Exchanges the verb array, SkPoint arrays, weights, and SkPath::FillType with other. + Cached state is also exchanged. swap() internally exchanges pointers, so + it is lightweight and does not allocate memory. + + swap() usage has largely been replaced by operator=(const SkPath& path). + SkPath do not copy their content on assignment until they are written to, + making assignment as efficient as swap(). + + @param other SkPath exchanged by value + */ void swap(SkPath& other); - /** - * Returns the bounds of the path's points. If the path contains zero points/verbs, this - * will return the "empty" rect [0, 0, 0, 0]. - * Note: this bounds may be larger than the actual shape, since curves - * do not extend as far as their control points. Additionally this bound encompases all points, - * even isolated moveTos either preceeding or following the last non-degenerate contour. + /** Returns minimum and maximum x and y values of SkPoint arrays. + Returns (0, 0, 0, 0) if SkPath contains no points. Returned bounds width and height may + be larger or smaller than area affected when SkPath is drawn. + + SkRect returned includes all SkPoint added to SkPath, including SkPoint associated with + kMove_Verb that define empty contours. + + @return bounds of all SkPoint in SkPoint arrays */ const SkRect& getBounds() const { return fPathRef->getBounds(); } - /** Calling this will, if the internal cache of the bounds is out of date, - update it so that subsequent calls to getBounds will be instantaneous. - This also means that any copies or simple transformations of the path - will inherit the cached bounds. - */ + /** Update internal bounds so that subsequent calls to getBounds() are instantaneous. + Unaltered copies of SkPath may also access cached bounds through getBounds(). + + For now, identical to calling getBounds() and ignoring the returned value. + + Call to prepare SkPath subsequently drawn from multiple threads, + to avoid a race condition where each draw separately computes the bounds. + */ void updateBoundsCache() const { // for now, just calling getBounds() is sufficient this->getBounds(); } - /** - * Computes a bounds that is conservatively "snug" around the path. This assumes that the - * path will be filled. It does not attempt to collapse away contours that are logically - * empty (e.g. moveTo(x, y) + lineTo(x, y)) but will include them in the calculation. - * - * It differs from getBounds() in that it will look at the snug bounds of curves, whereas - * getBounds() just returns the bounds of the control-points. Thus computing this may be - * slower than just calling getBounds(). - * - * If the path is empty (i.e. no points or verbs), it will return SkRect::MakeEmpty(). - */ + /** Returns minimum and maximum x and y values of the lines and curves in SkPath. + Returns (0, 0, 0, 0) if SkPath contains no points. + Returned bounds width and height may be larger or smaller than area affected + when SkPath is drawn. + + Includes SkPoint associated with kMove_Verb that define empty + contours. + + Behaves identically to getBounds() when SkPath contains + only lines. If SkPath contains curves, computed bounds includes + the maximum extent of the quad, conic, or cubic; is slower than getBounds(); + and unlike getBounds(), does not cache the result. + + @return tight bounds of curves in SkPath + */ SkRect computeTightBounds() const; - /** - * Does a conservative test to see whether a rectangle is inside a path. Currently it only - * will ever return true for single convex contour paths. The empty-status of the rect is not - * considered (e.g. a rect that is a point can be inside a path). Points or line segments where - * the rect edge touches the path border are not considered containment violations. - */ - bool conservativelyContainsRect(const SkRect& rect) const; + /** Returns true if rect is contained by SkPath. + May return false when rect is contained by SkPath. + + For now, only returns true if SkPath has one contour and is convex. + rect may share points and edges with SkPath and be contained. + Returns true if rect is empty, that is, it has zero width or height; and + the SkPoint or line described by rect is contained by SkPath. - // Construction methods + @param rect SkRect, line, or SkPoint checked for containment + @return true if rect is contained + */ + bool conservativelyContainsRect(const SkRect& rect) const; - /** Hint to the path to prepare for adding more points. This can allow the - path to more efficiently grow its storage. + /** grows SkPath verb array and SkPoint arrays to contain extraPtCount additional SkPoint. + May improve performance and use less memory by + reducing the number and size of allocations when creating SkPath. - @param extraPtCount The number of extra points the path should - preallocate for. + @param extraPtCount number of additional SkPoint to allocate */ void incReserve(unsigned extraPtCount); - /** Set the beginning of the next contour to the point (x,y). + /** Adds beginning of contour at SkPoint (x, y). - @param x The x-coordinate of the start of a new contour - @param y The y-coordinate of the start of a new contour + @param x x-coordinate of contour start + @param y y-coordinate of contour start */ void moveTo(SkScalar x, SkScalar y); - /** Set the beginning of the next contour to the point + /** Adds beginning of contour at SkPoint p. - @param p The start of a new contour + @param p contour start */ void moveTo(const SkPoint& p) { this->moveTo(p.fX, p.fY); } - /** Set the beginning of the next contour relative to the last point on the - previous contour. If there is no previous contour, this is treated the - same as moveTo(). + /** Adds beginning of contour relative to last point. + If SkPath is empty, starts contour at (dx, dy). + Otherwise, start contour at last point offset by (dx, dy). + Function name stands for "relative move to". - @param dx The amount to add to the x-coordinate of the end of the - previous contour, to specify the start of a new contour - @param dy The amount to add to the y-coordinate of the end of the - previous contour, to specify the start of a new contour + @param dx offset from last point x to contour start x + @param dy offset from last point y to contour start y */ void rMoveTo(SkScalar dx, SkScalar dy); - /** Add a line from the last point to the specified point (x,y). If no - moveTo() call has been made for this contour, the first point is - automatically set to (0,0). + /** Adds line from last point to (x, y). If SkPath is empty, or last SkPath::Verb is + kClose_Verb, last point is set to (0, 0) before adding line. - @param x The x-coordinate of the end of a line - @param y The y-coordinate of the end of a line + lineTo() appends kMove_Verb to verb array and (0, 0) to SkPoint arrays, if needed. + lineTo() then appends kLine_Verb to verb array and (x, y) to SkPoint arrays. + + @param x end of added line in x + @param y end of added line in y */ void lineTo(SkScalar x, SkScalar y); - /** Add a line from the last point to the specified point. If no moveTo() - call has been made for this contour, the first point is automatically - set to (0,0). + /** Adds line from last point to SkPoint p. If SkPath is empty, or last SkPath::Verb is + kClose_Verb, last point is set to (0, 0) before adding line. + + lineTo() first appends kMove_Verb to verb array and (0, 0) to SkPoint arrays, if needed. + lineTo() then appends kLine_Verb to verb array and SkPoint p to SkPoint arrays. - @param p The end of a line + @param p end SkPoint of added line */ void lineTo(const SkPoint& p) { this->lineTo(p.fX, p.fY); } - /** Same as lineTo, but the coordinates are considered relative to the last - point on this contour. If there is no previous point, then a moveTo(0,0) - is inserted automatically. + /** Adds line from last point to SkVector (dx, dy). If SkPath is empty, or last SkPath::Verb is + kClose_Verb, last point is set to (0, 0) before adding line. + + Appends kMove_Verb to verb array and (0, 0) to SkPoint arrays, if needed; + then appends kLine_Verb to verb array and line end to SkPoint arrays. + Line end is last point plus SkVector (dx, dy). + Function name stands for "relative line to". - @param dx The amount to add to the x-coordinate of the previous point - on this contour, to specify a line - @param dy The amount to add to the y-coordinate of the previous point - on this contour, to specify a line + @param dx offset from last point x to line end x + @param dy offset from last point y to line end y */ void rLineTo(SkScalar dx, SkScalar dy); - /** Add a quadratic bezier from the last point, approaching control point - (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for - this contour, the first point is automatically set to (0,0). + /** Adds quad from last point towards (x1, y1), to (x2, y2). + If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0) + before adding quad. - @param x1 The x-coordinate of the control point on a quadratic curve - @param y1 The y-coordinate of the control point on a quadratic curve - @param x2 The x-coordinate of the end point on a quadratic curve - @param y2 The y-coordinate of the end point on a quadratic curve + Appends kMove_Verb to verb array and (0, 0) to SkPoint arrays, if needed; + then appends kQuad_Verb to verb array; and (x1, y1), (x2, y2) + to SkPoint arrays. + + @param x1 control SkPoint of quad in x + @param y1 control SkPoint of quad in y + @param x2 end SkPoint of quad in x + @param y2 end SkPoint of quad in y */ void quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2); - /** Add a quadratic bezier from the last point, approaching control point - p1, and ending at p2. If no moveTo() call has been made for this - contour, the first point is automatically set to (0,0). + /** Adds quad from last point towards SkPoint p1, to SkPoint p2. + If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0) + before adding quad. + + Appends kMove_Verb to verb array and (0, 0) to SkPoint arrays, if needed; + then appends kQuad_Verb to verb array; and SkPoint p1, p2 + to SkPoint arrays. - @param p1 The control point on a quadratic curve - @param p2 The end point on a quadratic curve + @param p1 control SkPoint of added quad + @param p2 end SkPoint of added quad */ void quadTo(const SkPoint& p1, const SkPoint& p2) { this->quadTo(p1.fX, p1.fY, p2.fX, p2.fY); } - /** Same as quadTo, but the coordinates are considered relative to the last - point on this contour. If there is no previous point, then a moveTo(0,0) - is inserted automatically. - - @param dx1 The amount to add to the x-coordinate of the last point on - this contour, to specify the control point of a quadratic curve - @param dy1 The amount to add to the y-coordinate of the last point on - this contour, to specify the control point of a quadratic curve - @param dx2 The amount to add to the x-coordinate of the last point on - this contour, to specify the end point of a quadratic curve - @param dy2 The amount to add to the y-coordinate of the last point on - this contour, to specify the end point of a quadratic curve + /** Adds quad from last point towards SkVector (dx1, dy1), to SkVector (dx2, dy2). + If SkPath is empty, or last SkPath::Verb + is kClose_Verb, last point is set to (0, 0) before adding quad. + + Appends kMove_Verb to verb array and (0, 0) to SkPoint arrays, + if needed; then appends kQuad_Verb to verb array; and appends quad + control and quad end to SkPoint arrays. + Quad control is last point plus SkVector (dx1, dy1). + Quad end is last point plus SkVector (dx2, dy2). + Function name stands for "relative quad to". + + @param dx1 offset from last point x to quad control x + @param dy1 offset from last point x to quad control y + @param dx2 offset from last point x to quad end x + @param dy2 offset from last point x to quad end y */ void rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2); + /** Adds conic from last point towards (x1, y1), to (x2, y2), weighted by w. + If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0) + before adding conic. + + Appends kMove_Verb to verb array and (0, 0) to SkPoint arrays, if needed. + + If w is finite and not one, appends kConic_Verb to verb array; + and (x1, y1), (x2, y2) to SkPoint arrays; and w to conic weights. + + If w is one, appends kQuad_Verb to verb array, and + (x1, y1), (x2, y2) to SkPoint arrays. + + If w is not finite, appends kLine_Verb twice to verb array, and + (x1, y1), (x2, y2) to SkPoint arrays. + + @param x1 control SkPoint of conic in x + @param y1 control SkPoint of conic in y + @param x2 end SkPoint of conic in x + @param y2 end SkPoint of conic in y + @param w weight of added conic + */ void conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar w); + + /** Adds conic from last point towards SkPoint p1, to SkPoint p2, weighted by w. + If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0) + before adding conic. + + Appends kMove_Verb to verb array and (0, 0) to SkPoint arrays, if needed. + + If w is finite and not one, appends kConic_Verb to verb array; + and SkPoint p1, p2 to SkPoint arrays; and w to conic weights. + + If w is one, appends kQuad_Verb to verb array, and SkPoint p1, p2 + to SkPoint arrays. + + If w is not finite, appends kLine_Verb twice to verb array, and + SkPoint p1, p2 to SkPoint arrays. + + @param p1 control SkPoint of added conic + @param p2 end SkPoint of added conic + @param w weight of added conic + */ void conicTo(const SkPoint& p1, const SkPoint& p2, SkScalar w) { this->conicTo(p1.fX, p1.fY, p2.fX, p2.fY, w); } + + /** Adds conic from last point towards SkVector (dx1, dy1), to SkVector (dx2, dy2), + weighted by w. If SkPath is empty, or last SkPath::Verb + is kClose_Verb, last point is set to (0, 0) before adding conic. + + Appends kMove_Verb to verb array and (0, 0) to SkPoint arrays, + if needed. + + If w is finite and not one, next appends kConic_Verb to verb array, + and w is recorded as conic weight; otherwise, if w is one, appends + kQuad_Verb to verb array; or if w is not finite, appends kLine_Verb + twice to verb array. + + In all cases appends SkPoint control and end to SkPoint arrays. + control is last point plus SkVector (dx1, dy1). + end is last point plus SkVector (dx2, dy2). + + Function name stands for "relative conic to". + + @param dx1 offset from last point x to conic control x + @param dy1 offset from last point x to conic control y + @param dx2 offset from last point x to conic end x + @param dy2 offset from last point x to conic end y + @param w weight of added conic + */ void rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2, SkScalar w); - /** Add a cubic bezier from the last point, approaching control points - (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been - made for this contour, the first point is automatically set to (0,0). + /** Adds cubic from last point towards (x1, y1), then towards (x2, y2), ending at + (x3, y3). If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to + (0, 0) before adding cubic. - @param x1 The x-coordinate of the 1st control point on a cubic curve - @param y1 The y-coordinate of the 1st control point on a cubic curve - @param x2 The x-coordinate of the 2nd control point on a cubic curve - @param y2 The y-coordinate of the 2nd control point on a cubic curve - @param x3 The x-coordinate of the end point on a cubic curve - @param y3 The y-coordinate of the end point on a cubic curve + Appends kMove_Verb to verb array and (0, 0) to SkPoint arrays, if needed; + then appends kCubic_Verb to verb array; and (x1, y1), (x2, y2), (x3, y3) + to SkPoint arrays. + + @param x1 first control SkPoint of cubic in x + @param y1 first control SkPoint of cubic in y + @param x2 second control SkPoint of cubic in x + @param y2 second control SkPoint of cubic in y + @param x3 end SkPoint of cubic in x + @param y3 end SkPoint of cubic in y */ void cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3); - /** Add a cubic bezier from the last point, approaching control points p1 - and p2, and ending at p3. If no moveTo() call has been made for this - contour, the first point is automatically set to (0,0). + /** Adds cubic from last point towards SkPoint p1, then towards SkPoint p2, ending at + SkPoint p3. If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to + (0, 0) before adding cubic. + + Appends kMove_Verb to verb array and (0, 0) to SkPoint arrays, if needed; + then appends kCubic_Verb to verb array; and SkPoint p1, p2, p3 + to SkPoint arrays. - @param p1 The 1st control point on a cubic curve - @param p2 The 2nd control point on a cubic curve - @param p3 The end point on a cubic curve + @param p1 first control SkPoint of cubic + @param p2 second control SkPoint of cubic + @param p3 end SkPoint of cubic */ void cubicTo(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3) { this->cubicTo(p1.fX, p1.fY, p2.fX, p2.fY, p3.fX, p3.fY); } - /** Same as cubicTo, but the coordinates are considered relative to the - current point on this contour. If there is no previous point, then a - moveTo(0,0) is inserted automatically. - - @param x1 The amount to add to the x-coordinate of the last point on - this contour, to specify the 1st control point of a cubic curve - @param y1 The amount to add to the y-coordinate of the last point on - this contour, to specify the 1st control point of a cubic curve - @param x2 The amount to add to the x-coordinate of the last point on - this contour, to specify the 2nd control point of a cubic curve - @param y2 The amount to add to the y-coordinate of the last point on - this contour, to specify the 2nd control point of a cubic curve - @param x3 The amount to add to the x-coordinate of the last point on - this contour, to specify the end point of a cubic curve - @param y3 The amount to add to the y-coordinate of the last point on - this contour, to specify the end point of a cubic curve + /** Adds cubic from last point towards SkVector (dx1, dy1), then towards + SkVector (dx2, dy2), to SkVector (dx3, dy3). + If SkPath is empty, or last SkPath::Verb + is kClose_Verb, last point is set to (0, 0) before adding cubic. + + Appends kMove_Verb to verb array and (0, 0) to SkPoint arrays, + if needed; then appends kCubic_Verb to verb array; and appends cubic + control and cubic end to SkPoint arrays. + Cubic control is last point plus SkVector (dx1, dy1). + Cubic end is last point plus SkVector (dx2, dy2). + Function name stands for "relative cubic to". + + @param x1 offset from last point x to first cubic control x + @param y1 offset from last point x to first cubic control y + @param x2 offset from last point x to second cubic control x + @param y2 offset from last point x to second cubic control y + @param x3 offset from last point x to cubic end x + @param y3 offset from last point x to cubic end y */ void rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3); - /** - * Append the specified arc to the path. If the start of the arc is different from the path's - * current last point, then an automatic lineTo() is added to connect the current contour - * to the start of the arc. However, if the path is empty, then we call moveTo() with - * the first point of the arc. The sweep angle is treated mod 360. - * - * @param oval The bounding oval defining the shape and size of the arc - * @param startAngle Starting angle (in degrees) where the arc begins - * @param sweepAngle Sweep angle (in degrees) measured clockwise. This is treated mod 360. - * @param forceMoveTo If true, always begin a new contour with the arc - */ + /** Append arc to SkPath. Arc added is part of ellipse + bounded by oval, from startAngle through sweepAngle. Both startAngle and + sweepAngle are measured in degrees, where zero degrees is aligned with the + positive x-axis, and positive sweeps extends arc clockwise. + + arcTo() adds line connecting SkPath last SkPoint to initial arc SkPoint if forceMoveTo + is false and SkPath is not empty. Otherwise, added contour begins with first point + of arc. Angles greater than -360 and less than 360 are treated modulo 360. + + @param oval bounds of ellipse containing arc + @param startAngle starting angle of arc in degrees + @param sweepAngle sweep, in degrees. Positive is clockwise; treated modulo 360 + @param forceMoveTo true to start a new contour with arc + */ void arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo); - /** - * Append a line and arc to the current path. This is the same as the PostScript call "arct". - */ + /** Append arc to SkPath, after appending line if needed. Arc is implemented by conic + weighted to describe part of circle. Arc is contained by tangent from + last SkPath point (x0, y0) to (x1, y1), and tangent from (x1, y1) to (x2, y2). Arc + is part of circle sized to radius, positioned so it touches both tangent lines. + + @param x1 x common to pair of tangents + @param y1 y common to pair of tangents + @param x2 x end of second tangent + @param y2 y end of second tangent + @param radius distance from arc to circle center + */ void arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar radius); - /** Append a line and arc to the current path. This is the same as the - PostScript call "arct". + /** Append arc to SkPath, after appending line if needed. Arc is implemented by conic + weighted to describe part of circle. Arc is contained by tangent from + last SkPath point to p1, and tangent from p1 to p2. Arc + is part of circle sized to radius, positioned so it touches both tangent lines. + + If last SkPath SkPoint does not start arc, arcTo() appends connecting line to SkPath. + The length of SkVector from p1 to p2 does not affect arc. + + Arc sweep is always less than 180 degrees. If radius is zero, or if + tangents are nearly parallel, arcTo() appends line from last SkPath SkPoint to p1. + + arcTo() appends at most one line and one conic. + arcTo() implements the functionality of PostScript_Arct and HTML_Canvas_ArcTo. + + @param p1 SkPoint common to pair of tangents + @param p2 end of second tangent + @param radius distance from arc to circle center */ void arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius) { this->arcTo(p1.fX, p1.fY, p2.fX, p2.fY, radius); } + /** \enum SkPath::ArcSize + Four oval parts with radii (rx, ry) start at last SkPath SkPoint and ends at (x, y). + ArcSize and Direction select one of the four oval parts. + */ enum ArcSize { - /** the smaller of the two possible SVG arcs. */ - kSmall_ArcSize, - /** the larger of the two possible SVG arcs. */ - kLarge_ArcSize, + kSmall_ArcSize, //!< Smaller of arc pair. + kLarge_ArcSize, //!< Larger of arc pair. }; - /** - * Append an elliptical arc from the current point in the format used by SVG. - * The center of the ellipse is computed to satisfy the constraints below. - * - * @param rx,ry The radii in the x and y directions respectively. - * @param xAxisRotate The angle in degrees relative to the x-axis. - * @param largeArc Determines whether the smallest or largest arc possible - * is drawn. - * @param sweep Determines if the arc should be swept in an anti-clockwise or - * clockwise direction. Note that this enum value is opposite the SVG - * arc sweep value. - * @param x,y The destination coordinates. - */ + /** Append arc to SkPath. Arc is implemented by one or more conics weighted to describe part of oval + with radii (rx, ry) rotated by xAxisRotate degrees. Arc curves from last SkPath SkPoint to (x, y), + choosing one of four possible routes: clockwise or counterclockwise, and smaller or larger. + + Arc sweep is always less than 360 degrees. arcTo() appends line to (x, y) if either radii are zero, + or if last SkPath SkPoint equals (x, y). arcTo() scales radii (rx, ry) to fit last SkPath SkPoint and + (x, y) if both are greater than zero but too small. + + arcTo() appends up to four conic curves. + arcTo() implements the functionality of svg arc, although SVG "sweep-flag" value is + opposite the integer value of sweep; SVG "sweep-flag" uses 1 for clockwise, while kCW_Direction + cast to int is zero. + + @param rx radius in x before x-axis rotation + @param ry radius in y before x-axis rotation + @param xAxisRotate x-axis rotation in degrees; positive values are clockwise + @param largeArc chooses smaller or larger arc + @param sweep chooses clockwise or counterclockwise arc + @param x end of arc + @param y end of arc + */ void arcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc, Direction sweep, SkScalar x, SkScalar y); + /** Append arc to SkPath. Arc is implemented by one or more conic weighted to describe part of oval + with radii (r.fX, r.fY) rotated by xAxisRotate degrees. Arc curves from last SkPath SkPoint to + (xy.fX, xy.fY), choosing one of four possible routes: clockwise or counterclockwise, + and smaller or larger. + + Arc sweep is always less than 360 degrees. arcTo() appends line to xy if either radii are zero, + or if last SkPath SkPoint equals (x, y). arcTo() scales radii r to fit last SkPath SkPoint and + xy if both are greater than zero but too small to describe an arc. + + arcTo() appends up to four conic curves. + arcTo() implements the functionality of svg arc, although SVG "sweep-flag" value is + opposite the integer value of sweep; SVG "sweep-flag" uses 1 for clockwise, while + kCW_Direction cast to int is zero. + + @param r radii in x and y before x-axis rotation + @param xAxisRotate x-axis rotation in degrees; positive values are clockwise + @param largeArc chooses smaller or larger arc + @param sweep chooses clockwise or counterclockwise arc + @param xy end of arc + */ void arcTo(const SkPoint r, SkScalar xAxisRotate, ArcSize largeArc, Direction sweep, const SkPoint xy) { this->arcTo(r.fX, r.fY, xAxisRotate, largeArc, sweep, xy.fX, xy.fY); } - /** Same as arcTo format used by SVG, but the destination coordinate is relative to the - * last point on this contour. If there is no previous point, then a - * moveTo(0,0) is inserted automatically. - * - * @param rx,ry The radii in the x and y directions respectively. - * @param xAxisRotate The angle in degrees relative to the x-axis. - * @param largeArc Determines whether the smallest or largest arc possible - * is drawn. - * @param sweep Determines if the arc should be swept in an anti-clockwise or - * clockwise direction. Note that this enum value is opposite the SVG - * arc sweep value. - * @param dx,dy The destination coordinates relative to the last point. - */ + /** Append arc to SkPath, relative to last SkPath SkPoint. Arc is implemented by one or + more conic, weighted to describe part of oval with radii (rx, ry) rotated by + xAxisRotate degrees. Arc curves from last SkPath SkPoint (x0, y0) to end SkPoint + + @param rx radius in x before x-axis rotation + @param ry radius in y before x-axis rotation + @param xAxisRotate x-axis rotation in degrees; positive values are clockwise + @param largeArc chooses smaller or larger arc + @param sweep chooses clockwise or counterclockwise arc + @param dx x offset end of arc from last SkPath SkPoint + @param dy y offset end of arc from last SkPath SkPoint + */ void rArcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc, Direction sweep, SkScalar dx, SkScalar dy); - /** Close the current contour. If the current point is not equal to the - first point of the contour, a line segment is automatically added. + /** Append kClose_Verb to SkPath. A closed contour connects the first and last SkPoint + with line, forming a continuous loop. Open and closed contour draw the same + with SkPaint::kFill_Style. With SkPaint::kStroke_Style, open contour draws + SkPaint::Cap at contour start and end; closed contour draws + SkPaint::Join at contour start and end. + + close() has no effect if SkPath is empty or last SkPath SkPath::Verb is kClose_Verb. */ void close(); - /** - * Returns whether or not a fill type is inverted - * - * kWinding_FillType -> false - * kEvenOdd_FillType -> false - * kInverseWinding_FillType -> true - * kInverseEvenOdd_FillType -> true - */ + /** Returns true if fill is inverted and SkPath with fill represents area outside + of its geometric bounds. + + @param fill one of: kWinding_FillType, kEvenOdd_FillType, + kInverseWinding_FillType, kInverseEvenOdd_FillType + @return true if SkPath fills outside its bounds + */ static bool IsInverseFillType(FillType fill) { static_assert(0 == kWinding_FillType, "fill_type_mismatch"); static_assert(1 == kEvenOdd_FillType, "fill_type_mismatch"); @@ -625,14 +955,13 @@ public: return (fill & 2) != 0; } - /** - * Returns the equivalent non-inverted fill type to the given fill type - * - * kWinding_FillType -> kWinding_FillType - * kEvenOdd_FillType -> kEvenOdd_FillType - * kInverseWinding_FillType -> kWinding_FillType - * kInverseEvenOdd_FillType -> kEvenOdd_FillType - */ + /** Returns equivalent SkPath::FillType representing SkPath fill inside its bounds. + . + + @param fill one of: kWinding_FillType, kEvenOdd_FillType, + kInverseWinding_FillType, kInverseEvenOdd_FillType + @return fill, or kWinding_FillType or kEvenOdd_FillType if fill is inverted + */ static FillType ConvertToNonInverseFillType(FillType fill) { static_assert(0 == kWinding_FillType, "fill_type_mismatch"); static_assert(1 == kEvenOdd_FillType, "fill_type_mismatch"); @@ -641,225 +970,235 @@ public: return (FillType)(fill & 1); } - /** - * Chop a conic into N quads, stored continguously in pts[], where - * N = 1 << pow2. The amount of storage needed is (1 + 2 * N) - */ + /** Approximates conic with quad array. Conic is constructed from start SkPoint p0, + control SkPoint p1, end SkPoint p2, and weight w. + Quad array is stored in pts; this storage is supplied by caller. + Maximum quad count is 2 to the pow2. + Every third point in array shares last SkPoint of previous quad and first SkPoint of + next quad. Maximum pts storage size is given by: + + @param p0 Conic start SkPoint + @param p1 Conic control SkPoint + @param p2 Conic end SkPoint + @param w Conic weight + @param pts storage for quad array + @param pow2 Quad count, as power of two, normally 0 to 5 (1 to 32 quad curves) + @return number of quad curves written to pts + */ static int ConvertConicToQuads(const SkPoint& p0, const SkPoint& p1, const SkPoint& p2, SkScalar w, SkPoint pts[], int pow2); - /** - * Returns true if the path specifies a rectangle. - * - * If this returns false, then all output parameters are ignored, and left - * unchanged. If this returns true, then each of the output parameters - * are checked for NULL. If they are not, they return their value. - * - * @param rect If not null, set to the bounds of the rectangle. - * Note : this bounds may be smaller than the path's bounds, since it is just - * the bounds of the "drawable" parts of the path. e.g. a trailing MoveTo would - * be ignored in this rect, but not by the path's bounds - * @param isClosed If not null, set to true if the path is closed - * @param direction If not null, set to the rectangle's direction - * @return true if the path specifies a rectangle - */ + /** Returns true if SkPath is equivalent to SkRect when filled. + If false: rect, isClosed, and direction are unchanged. + If true: rect, isClosed, and direction are written to if not nullptr. + + rect may be smaller than the SkPath bounds. SkPath bounds may include kMove_Verb points + that do not alter the area drawn by the returned rect. + + @param rect storage for bounds of SkRect; may be nullptr + @param isClosed storage set to true if SkPath is closed; may be nullptr + @param direction storage set to SkRect direction; may be nullptr + @return true if SkPath contains SkRect + */ bool isRect(SkRect* rect, bool* isClosed = nullptr, Direction* direction = nullptr) const; - /** Returns true if the path specifies a pair of nested rectangles, or would draw a - pair of nested rectangles when filled. If so, and if - rect is not null, set rect[0] to the outer rectangle and rect[1] to the inner - rectangle. If so, and dirs is not null, set dirs[0] to the direction of - the outer rectangle and dirs[1] to the direction of the inner rectangle. If - the path does not specify a pair of nested rectangles, return - false and ignore rect and dirs. + /** Returns true if SkPath is equivalent to nested SkRect pair when filled. + If false, rect and dirs are unchanged. + If true, rect and dirs are written to if not nullptr: + setting rect[0] to outer SkRect, and rect[1] to inner SkRect; + setting dirs[0] to SkPath::Direction of outer SkRect, and dirs[1] to SkPath::Direction of inner + SkRect. - @param rect If not null, returns the path as a pair of nested rectangles - @param dirs If not null, returns the direction of the rects - @return true if the path describes a pair of nested rectangles + @param rect storage for SkRect pair; may be nullptr + @param dirs storage for SkPath::Direction pair; may be nullptr + @return true if SkPath contains nested SkRect pair */ bool isNestedFillRects(SkRect rect[2], Direction dirs[2] = nullptr) const; - /** - * Add a closed rectangle contour to the path - * @param rect The rectangle to add as a closed contour to the path - * @param dir The direction to wind the rectangle's contour. - * - * Note: the contour initial point index is 0 (as defined below). - */ + /** Add SkRect to SkPath, appending kMove_Verb, three kLine_Verb, and kClose_Verb, + starting with top-left corner of SkRect; followed by top-right, bottom-right, + and bottom-left if dir is kCW_Direction; or followed by bottom-left, + bottom-right, and top-right if dir is kCCW_Direction. + + @param rect SkRect to add as a closed contour + @param dir SkPath::Direction to wind added contour + */ void addRect(const SkRect& rect, Direction dir = kCW_Direction); - /** - * Add a closed rectangle contour to the path - * @param rect The rectangle to add as a closed contour to the path - * @param dir The direction to wind the rectangle's contour. - * @param start Initial point of the contour (initial moveTo), expressed as - * a corner index, starting in the upper-left position, clock-wise: - * - * 0 1 - * *-------* - * | | - * *-------* - * 3 2 - */ + /** Add SkRect to SkPath, appending kMove_Verb, three kLine_Verb, and kClose_Verb. + If dir is kCW_Direction, SkRect corners are added clockwise; if dir is + kCCW_Direction, SkRect corners are added counterclockwise. + start determines the first corner added. + + @param rect SkRect to add as a closed contour + @param dir SkPath::Direction to wind added contour + @param start initial corner of SkRect to add + */ void addRect(const SkRect& rect, Direction dir, unsigned start); - /** - * Add a closed rectangle contour to the path - * - * @param left The left side of a rectangle to add as a closed contour - * to the path - * @param top The top of a rectangle to add as a closed contour to the - * path - * @param right The right side of a rectangle to add as a closed contour - * to the path - * @param bottom The bottom of a rectangle to add as a closed contour to - * the path - * @param dir The direction to wind the rectangle's contour. - * - * Note: the contour initial point index is 0 (as defined above). - */ + /** Add SkRect (left, top, right, bottom) to SkPath, + appending kMove_Verb, three kLine_Verb, and kClose_Verb, + starting with top-left corner of SkRect; followed by top-right, bottom-right, + and bottom-left if dir is kCW_Direction; or followed by bottom-left, + bottom-right, and top-right if dir is kCCW_Direction. + + @param left smaller x of SkRect + @param top smaller y of SkRect + @param right larger x of SkRect + @param bottom larger y of SkRect + @param dir SkPath::Direction to wind added contour + */ void addRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom, Direction dir = kCW_Direction); - /** - * Add a closed oval contour to the path - * - * @param oval The bounding oval to add as a closed contour to the path - * @param dir The direction to wind the oval's contour. - * - * Note: the contour initial point index is 1 (as defined below). - */ + /** Add oval to path, appending kMove_Verb, four kConic_Verb, and kClose_Verb. + Oval is upright ellipse bounded by SkRect oval with radii equal to half oval width + and half oval height. Oval begins at (oval.fRight, oval.centerY()) and continues + clockwise if dir is kCW_Direction, counterclockwise if dir is kCCW_Direction. + + This form is identical to addOval(oval, dir, 1). + + @param oval bounds of ellipse added + @param dir SkPath::Direction to wind ellipse + */ void addOval(const SkRect& oval, Direction dir = kCW_Direction); - /** - * Add a closed oval contour to the path - * - * @param oval The bounding oval to add as a closed contour to the path - * @param dir The direction to wind the oval's contour. - * @param start Initial point of the contour (initial moveTo), expressed - * as an ellipse vertex index, starting at the top, clock-wise - * (90/0/270/180deg order): - * - * 0 - * -*- - * | | - * 3 * * 1 - * | | - * -*- - * 2 - */ + /** Add oval to SkPath, appending kMove_Verb, four kConic_Verb, and kClose_Verb. + Oval is upright ellipse bounded by SkRect oval with radii equal to half oval width + and half oval height. Oval begins at start and continues + clockwise if dir is kCW_Direction, counterclockwise if dir is kCCW_Direction. + + @param oval bounds of ellipse added + @param dir SkPath::Direction to wind ellipse + @param start index of initial point of ellipse + */ void addOval(const SkRect& oval, Direction dir, unsigned start); - /** - * Add a closed circle contour to the path. The circle contour begins at - * the right-most point (as though 1 were passed to addOval's 'start' param). - * - * @param x The x-coordinate of the center of a circle to add as a - * closed contour to the path - * @param y The y-coordinate of the center of a circle to add as a - * closed contour to the path - * @param radius The radius of a circle to add as a closed contour to the - * path - * @param dir The direction to wind the circle's contour. - */ + /** Add circle centered at (x, y) of size radius to SkPath, appending kMove_Verb, + four kConic_Verb, and kClose_Verb. Circle begins at + + @param x center of circle + @param y center of circle + @param radius distance from center to edge + @param dir SkPath::Direction to wind circle + */ void addCircle(SkScalar x, SkScalar y, SkScalar radius, Direction dir = kCW_Direction); - /** Add the specified arc to the path as a new contour. + /** Append arc to SkPath, as the start of new contour. Arc added is part of ellipse + bounded by oval, from startAngle through sweepAngle. Both startAngle and + sweepAngle are measured in degrees, where zero degrees is aligned with the + positive x-axis, and positive sweeps extends arc clockwise. + + If sweepAngle <= -360, or sweepAngle >= 360; and startAngle modulo 90 is nearly + zero, append oval instead of arc. Otherwise, sweepAngle values are treated + modulo 360, and arc may or may not draw depending on numeric rounding. - @param oval The bounds of oval used to define the size of the arc - @param startAngle Starting angle (in degrees) where the arc begins - @param sweepAngle Sweep angle (in degrees) measured clockwise + @param oval bounds of ellipse containing arc + @param startAngle starting angle of arc in degrees + @param sweepAngle sweep, in degrees. Positive is clockwise; treated modulo 360 */ void addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle); - /** - * Add a closed round-rectangle contour to the path - * @param rect The bounds of a round-rectangle to add as a closed contour - * @param rx The x-radius of the rounded corners on the round-rectangle - * @param ry The y-radius of the rounded corners on the round-rectangle - * @param dir The direction to wind the rectangle's contour. - */ + /** Append SkRRect to SkPath, creating a new closed contour. SkRRect has bounds + equal to rect; each corner is 90 degrees of an ellipse with radii (rx, ry). If + dir is kCW_Direction, SkRRect starts at top-left of the lower-left corner and + winds clockwise. If dir is kCCW_Direction, SkRRect starts at the bottom-left + of the upper-left corner and winds counterclockwise. + + If either rx or ry is too large, rx and ry are scaled uniformly until the + corners fit. If rx or ry is less than or equal to zero, addRoundRect() appends + SkRect rect to SkPath. + + After appending, SkPath may be empty, or may contain: SkRect, oval, or RoundRect. + + @param rect bounds of SkRRect + @param rx x-radius of rounded corners on the SkRRect + @param ry y-radius of rounded corners on the SkRRect + @param dir SkPath::Direction to wind SkRRect + */ void addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, Direction dir = kCW_Direction); - /** - * Add a closed round-rectangle contour to the path. Each corner receives - * two radius values [X, Y]. The corners are ordered top-left, top-right, - * bottom-right, bottom-left. - * @param rect The bounds of a round-rectangle to add as a closed contour - * @param radii Array of 8 scalars, 4 [X,Y] pairs for each corner - * @param dir The direction to wind the rectangle's contour. - * Note: The radii here now go through the same constraint handling as the - * SkRRect radii (i.e., either radii at a corner being 0 implies a - * sqaure corner and oversized radii are proportionally scaled down). - */ + /** Append SkRRect to SkPath, creating a new closed contour. SkRRect has bounds + equal to rect; each corner is 90 degrees of an ellipse with radii from the + array. + + @param rect bounds of SkRRect + @param radii array of 8 SkScalar values, a radius pair for each corner + @param dir SkPath::Direction to wind SkRRect + */ void addRoundRect(const SkRect& rect, const SkScalar radii[], Direction dir = kCW_Direction); - /** - * Add an SkRRect contour to the path - * @param rrect The rounded rect to add as a closed contour - * @param dir The winding direction for the new contour. - * - * Note: the contour initial point index is either 6 (for dir == kCW_Direction) - * or 7 (for dir == kCCW_Direction), as defined below. - * - */ + /** Add rrect to SkPath, creating a new closed contour. If + dir is kCW_Direction, rrect starts at top-left of the lower-left corner and + winds clockwise. If dir is kCCW_Direction, rrect starts at the bottom-left + of the upper-left corner and winds counterclockwise. + + After appending, SkPath may be empty, or may contain: SkRect, oval, or SkRRect. + + @param rrect bounds and radii of rounded rectangle + @param dir SkPath::Direction to wind SkRRect + */ void addRRect(const SkRRect& rrect, Direction dir = kCW_Direction); - /** - * Add an SkRRect contour to the path - * @param rrect The rounded rect to add as a closed contour - * @param dir The winding direction for the new contour. - * @param start Initial point of the contour (initial moveTo), expressed as - * an index of the radii minor/major points, ordered clock-wise: - * - * 0 1 - * *----* - * 7 * * 2 - * | | - * 6 * * 3 - * *----* - * 5 4 - */ + /** Add rrect to SkPath, creating a new closed contour. If dir is kCW_Direction, rrect + winds clockwise; if dir is kCCW_Direction, rrect winds counterclockwise. + start determines the first point of rrect to add. + + @param rrect bounds and radii of rounded rectangle + @param dir SkPath::Direction to wind SkRRect + @param start index of initial point of SkRRect + */ void addRRect(const SkRRect& rrect, Direction dir, unsigned start); - /** - * Add a new contour made of just lines. This is just a fast version of - * the following: - * this->moveTo(pts[0]); - * for (int i = 1; i < count; ++i) { - * this->lineTo(pts[i]); - * } - * if (close) { - * this->close(); - * } - */ + /** Add contour created from line array, adding + + @param pts array of line sharing end and start SkPoint + @param count length of SkPoint array + @param close true to add line connecting contour end and start + */ void addPoly(const SkPoint pts[], int count, bool close); + /** \enum SkPath::AddPathMode + AddPathMode chooses how addPath() appends. Adding one SkPath to another can extend + the last contour or start a new contour. + */ enum AddPathMode { - /** Source path contours are added as new contours. + /** Since SkPath verb array begins with kMove_Verb if src is not empty, this + starts a new contour. */ kAppend_AddPathMode, - /** Path is added by extending the last contour of the destination path - with the first contour of the source path. If the last contour of - the destination path is closed, then it will not be extended. - Instead, the start of source path will be extended by a straight - line to the end point of the destination path. + + /** is not empty, add line from last point to added SkPath first SkPoint. Skip added + SkPath initial kMove_Verb, then append remining Verb, SkPoint, and conic weights. */ kExtend_AddPathMode, }; - /** Add a copy of src to the path, offset by (dx,dy) - @param src The path to add as a new contour - @param dx The amount to translate the path in X as it is added - @param dx The amount to translate the path in Y as it is added + /** Append src to SkPath, offset by (dx, dy). + + If mode is kAppend_AddPathMode, src verb array, SkPoint arrays, and conic weights are + added unaltered. If mode is kExtend_AddPathMode, add line before appending + SkPath::Verb, SkPoint, and conic weights. + + @param src SkPath SkPath::Verb, SkPoint, and conic weights to add + @param dx offset added to src SkPoint arrays x coordinates + @param dy offset added to src SkPoint arrays y coordinates + @param mode kAppend_AddPathMode or kExtend_AddPathMode */ void addPath(const SkPath& src, SkScalar dx, SkScalar dy, AddPathMode mode = kAppend_AddPathMode); - /** Add a copy of src to the path + /** Append src to SkPath. + + If mode is kAppend_AddPathMode, src verb array, SkPoint arrays, and conic weights are + added unaltered. If mode is kExtend_AddPathMode, add line before appending + SkPath::Verb, SkPoint, and conic weights. + + @param src SkPath SkPath::Verb, SkPoint, and conic weights to add + @param mode kAppend_AddPathMode or kExtend_AddPathMode */ void addPath(const SkPath& src, AddPathMode mode = kAppend_AddPathMode) { SkMatrix m; @@ -867,127 +1206,198 @@ public: this->addPath(src, m, mode); } - /** Add a copy of src to the path, transformed by matrix - @param src The path to add as a new contour - @param matrix Transform applied to src - @param mode Determines how path is added + /** Append src to SkPath, transformed by matrix. Transformed curves may have different + SkPath::Verb, SkPoint, and conic weights. + + If mode is kAppend_AddPathMode, src verb array, SkPoint arrays, and conic weights are + added unaltered. If mode is kExtend_AddPathMode, add line before appending + SkPath::Verb, SkPoint, and conic weights. + + @param src SkPath SkPath::Verb, SkPoint, and conic weights to add + @param matrix transform applied to src + @param mode kAppend_AddPathMode or kExtend_AddPathMode */ void addPath(const SkPath& src, const SkMatrix& matrix, AddPathMode mode = kAppend_AddPathMode); - /** - * Same as addPath(), but reverses the src input - */ + /** Append src to SkPath, from back to front. + Reversed src always appends a new contour to SkPath. + + @param src SkPath SkPath::Verb, SkPoint, and conic weights to add + */ void reverseAddPath(const SkPath& src); - /** Offset the path by (dx,dy), returning true on success + /** Offset SkPoint arrays by (dx, dy). Offset SkPath replaces dst. + If dst is nullptr, SkPath is replaced by offset data. - @param dx The amount in the X direction to offset the entire path - @param dy The amount in the Y direction to offset the entire path - @param dst The translated path is written here + @param dx offset added to SkPoint arrays x coordinates + @param dy offset added to SkPoint arrays y coordinates + @param dst overwritten, translated copy of SkPath; may be nullptr */ void offset(SkScalar dx, SkScalar dy, SkPath* dst) const; - /** Offset the path by (dx,dy), returning true on success + /** Offset SkPoint arrays by (dx, dy). Offset SkPath replaces dst. + If dst is nullptr, SkPath is replaced by offset data. - @param dx The amount in the X direction to offset the entire path - @param dy The amount in the Y direction to offset the entire path + @param dx offset added to SkPoint arrays x coordinates + @param dy offset added to SkPoint arrays y coordinates + @param dst overwritten, translated copy of SkPath; may be nullptr */ void offset(SkScalar dx, SkScalar dy) { this->offset(dx, dy, this); } - /** Transform the points in this path by matrix, and write the answer into - dst. + /** Transform verb array, SkPoint arrays, and weight by matrix. + transform may change SkPath::Verb and increase their number. + Transformed SkPath replaces dst; if dst is nullptr, original data + is replaced. - @param matrix The matrix to apply to the path - @param dst The transformed path is written here + @param matrix SkMatrix to apply to SkPath + @param dst overwritten, transformed copy of SkPath; may be nullptr */ void transform(const SkMatrix& matrix, SkPath* dst) const; - /** Transform the points in this path by matrix + /** Transform verb array, SkPoint arrays, and weight by matrix. + transform may change SkPath::Verb and increase their number. + Transformed SkPath replaces dst; if dst is nullptr, original data + is replaced. - @param matrix The matrix to apply to the path + @param matrix SkMatrix to apply to SkPath + @param dst overwritten, transformed copy of SkPath; may be nullptr */ void transform(const SkMatrix& matrix) { this->transform(matrix, this); } - /** Return the last point on the path. If no points have been added, (0,0) - is returned. If there are no points, this returns false, otherwise it - returns true. + /** Returns last point on SkPath in lastPt. Returns false if SkPoint arrays is empty, + storing (0, 0) if lastPt is not nullptr. - @param lastPt The last point on the path is returned here + @param lastPt storage for final SkPoint in SkPoint arrays; may be nullptr + @return true if SkPoint arrays contains one or more SkPoint */ bool getLastPt(SkPoint* lastPt) const; - /** Set the last point on the path. If no points have been added, - moveTo(x,y) is automatically called. + /** Set last point to (x, y). If SkPoint arrays is empty, append kMove_Verb to + verb array and (x, y) to SkPoint arrays. - @param x The new x-coordinate for the last point - @param y The new y-coordinate for the last point + @param x set x-coordinate of last point + @param y set y-coordinate of last point */ void setLastPt(SkScalar x, SkScalar y); /** Set the last point on the path. If no points have been added, moveTo(p) is automatically called. - @param p The new location for the last point + @param p set value of last point */ void setLastPt(const SkPoint& p) { this->setLastPt(p.fX, p.fY); } + /** \enum SkPath::SegmentMask + SegmentMask constants correspond to each drawing Verb type in SkPath; for + instance, if SkPath only contains lines, only the kLine_SegmentMask bit is set. + */ enum SegmentMask { - kLine_SegmentMask = 1 << 0, - kQuad_SegmentMask = 1 << 1, - kConic_SegmentMask = 1 << 2, - kCubic_SegmentMask = 1 << 3, + kLine_SegmentMask = 1 << 0, //!< Set if verb array contains kLine_Verb. + + /** Set if verb array contains kQuad_Verb. Note that conicTo() may add a quad. */ + kQuad_SegmentMask = 1 << 1, + kConic_SegmentMask = 1 << 2, //!< Set if verb array contains kConic_Verb. + kCubic_SegmentMask = 1 << 3, //!< Set if verb array contains kCubic_Verb. }; - /** - * Returns a mask, where each bit corresponding to a SegmentMask is - * set if the path contains 1 or more segments of that type. - * Returns 0 for an empty path (no segments). - */ + /** Returns a mask, where each set bit corresponds to a SegmentMask constant + if SkPath contains one or more SkPath::Verb of that type. + Returns zero if SkPath contains no lines, or curves: quads, conics, or cubics. + + getSegmentMasks() returns a cached result; it is very fast. + + @return SegmentMask bits or zero + */ uint32_t getSegmentMasks() const { return fPathRef->getSegmentMasks(); } + /** \enum SkPath::Verb + Verb instructs SkPath how to interpret one or more SkPoint and optional conic weight; + manage contour, and terminate SkPath. + */ enum Verb { - kMove_Verb, //!< iter.next returns 1 point - kLine_Verb, //!< iter.next returns 2 points - kQuad_Verb, //!< iter.next returns 3 points - kConic_Verb, //!< iter.next returns 3 points + iter.conicWeight() - kCubic_Verb, //!< iter.next returns 4 points - kClose_Verb, //!< iter.next returns 0 points - kDone_Verb, //!< iter.next returns 0 points - }; + kMove_Verb, //!< Starts new contour at next SkPoint. + + /** Adds line from last point to next SkPoint. + Line is a straight segment from SkPoint to SkPoint. + */ + kLine_Verb, + + /** Adds quad from last point, using control SkPoint, and end SkPoint. + Quad is a parabolic section within tangents from last point to control SkPoint, + and control SkPoint to end SkPoint. + */ + kQuad_Verb, + + /** Adds conic from last point, using control SkPoint, end SkPoint, and conic weight. + Conic is a elliptical, parabolic, or hyperbolic section within tangents + from last point to control SkPoint, and control SkPoint to end SkPoint, constrained + by conic weight. conic weight less than one is elliptical; equal to one is + parabolic (and identical to Quad); greater than one hyperbolic. + */ + kConic_Verb, - /** Iterate through all of the segments (lines, quadratics, cubics) of - each contours in a path. + /** Adds cubic from last point, using two control SkPoint, and end SkPoint. + Cubic is a third-order Bezier section within tangents from last point to + first control SkPoint, and from second control SkPoint to end SkPoint. + */ + kCubic_Verb, + kClose_Verb, //!< Closes contour, connecting last point to kMove_Verb SkPoint. + kDone_Verb, //!< Terminates SkPath. Not in verb array, but returned by SkPath iterator. + }; - The iterator cleans up the segments along the way, removing degenerate - segments and adding close verbs where necessary. When the forceClose - argument is provided, each contour (as defined by a new starting - move command) will be completed with a close verb regardless of the - contour's contents. + /** \class SkPath::Iter */ class SK_API Iter { - public: + + public: + + /** Initializes iter with an empty SkPath. next() on iter returns kDone_Verb. + Call setPath to initialize iter at a later time. + + @return Iter of empty SkPath + */ Iter(); + + /** Sets iter to return elements of verb array, SkPoint arrays, and conic weight in path. + If forceClose is true, iter will add kLine_Verb and kClose_Verb after each + open contour. path is not altered. + + @param path SkPath to iterate + @param forceClose true if open contours generate kClose_Verb + @return Iter of path + */ Iter(const SkPath& path, bool forceClose); + /** Sets iter to return elements of verb array, SkPoint arrays, and conic weight in path. + If forceClose is true, iter will add kLine_Verb and kClose_Verb after each + open contour. path is not altered. + + @param path SkPath to iterate + @param forceClose true if open contours generate kClose_Verb + */ void setPath(const SkPath& path, bool forceClose); - /** Return the next verb in this iteration of the path. When all - segments have been visited, return kDone_Verb. - - @param pts The points representing the current verb and/or segment - @param doConsumeDegerates If true, first scan for segments that are - deemed degenerate (too short) and skip those. - @param exact if doConsumeDegenerates is true and exact is true, skip only - degenerate elements with lengths exactly equal to zero. If exact - is false, skip degenerate elements with lengths close to zero. If - doConsumeDegenerates is false, exact has no effect. - @return The verb for the current segment + /** Returns next SkPath::Verb in verb array, and advances iter. + When verb array is exhausted, returns kDone_Verb. + + Zero to four points are stored in pts, depending on the returned SkPath::Verb. + + If doConsumeDegenerates is true, skip consecutive kMove_Verb entries, returning + only the last in the series; and skip very small lines, quads, and conics; and + skip kClose_Verb following kMove_Verb. + if doConsumeDegenerates is true and exact is true, only skip lines, quads, and + conics with zero lengths. + + @param pts storage for SkPoint data describing returned SkPath::Verb + @param doConsumeDegenerates if true, skip degenerate verbs + @param exact skip zero length curves + @return next SkPath::Verb from verb array */ Verb next(SkPoint pts[4], bool doConsumeDegenerates = true, bool exact = false) { if (doConsumeDegenerates) { @@ -996,24 +1406,31 @@ public: return this->doNext(pts); } - /** - * Return the weight for the current conic. Only valid if the current - * segment return by next() was a conic. - */ + /** Returns conic weight if next() returned kConic_Verb. + + If next() has not been called, or next() did not return kConic_Verb, + result is undefined. + + @return conic weight for conic points returned by next() + */ SkScalar conicWeight() const { return *fConicWeights; } - /** If next() returns kLine_Verb, then this query returns true if the - line was the result of a close() command (i.e. the end point is the - initial moveto for this contour). If next() returned a different - verb, this returns an undefined value. + /** Returns true if last kLine_Verb returned by next() was generated + by kClose_Verb. When true, the end point returned by next() is + also the start point of contour. + + If next() has not been called, or next() did not return kLine_Verb, + result is undefined. - @return If the last call to next() returned kLine_Verb, return true - if it was the result of an explicit close command. + @return true if last kLine_Verb was generated by kClose_Verb */ bool isCloseLine() const { return SkToBool(fCloseLine); } - /** Returns true if the current contour is closed (has a kClose_Verb) - @return true if the current contour is closed (has a kClose_Verb) + /** Returns true if subsequent calls to next() return kClose_Verb before returning + kMove_Verb. if true, contour iter is processing may end with kClose_Verb, or + iter may have been initialized with force close set to true. + + @return true if contour is closed */ bool isClosedContour() const; @@ -1033,40 +1450,65 @@ public: Verb autoClose(SkPoint pts[2]); void consumeDegenerateSegments(bool exact); Verb doNext(SkPoint pts[4]); + }; - /** Iterate through the verbs in the path, providing the associated points. + /** \class SkPath::RawIter */ class SK_API RawIter { - public: + + public: + + /** Initializes RawIter with an empty SkPath. next() on RawIter returns kDone_Verb. + Call setPath to initialize iter at a later time. + + @return RawIter of empty SkPath + */ RawIter() {} + + /** Sets RawIter to return elements of verb array, SkPoint arrays, and conic weight in path. + + @param path SkPath to iterate + @return RawIter of path + */ RawIter(const SkPath& path) { setPath(path); } + /** Sets iter to return elements of verb array, SkPoint arrays, and conic weight in path. + + @param path SkPath to iterate + */ void setPath(const SkPath& path) { fRawIter.setPathRef(*path.fPathRef.get()); } - /** Return the next verb in this iteration of the path. When all - segments have been visited, return kDone_Verb. + /** Returns next SkPath::Verb in verb array, and advances RawIter. + When verb array is exhausted, returns kDone_Verb. + Zero to four points are stored in pts, depending on the returned SkPath::Verb. - @param pts The points representing the current verb and/or segment - This must not be NULL. - @return The verb for the current segment + @param pts storage for SkPoint data describing returned SkPath::Verb + @return next SkPath::Verb from verb array */ Verb next(SkPoint pts[4]) { return (Verb) fRawIter.next(pts); } - /** Return what the next verb will be, but do not visit the next segment. + /** Returns next SkPath::Verb, but does not advance RawIter. - @return The verb for the next segment + @return next SkPath::Verb from verb array */ Verb peek() const { return (Verb) fRawIter.peek(); } + /** Returns conic weight if next() returned kConic_Verb. + + If next() has not been called, or next() did not return kConic_Verb, + result is undefined. + + @return conic weight for conic points returned by next() + */ SkScalar conicWeight() const { return fRawIter.conicWeight(); } @@ -1074,42 +1516,98 @@ public: private: SkPathRef::Iter fRawIter; friend class SkPath; + }; - /** - * Returns true if the point { x, y } is contained by the path, taking into - * account the FillType. - */ + /** Returns true if the point (x, y) is contained by SkPath, taking into + account FillType. + + @param x x-coordinate of containment test + @param y y-coordinate of containment test + @return true if SkPoint is in SkPath + */ bool contains(SkScalar x, SkScalar y) const; + /** Writes text representation of SkPath to stream. If stream is nullptr, dump() writes to + standard output. Set forceClose to true to get + edges used to fill SkPath. Set dumpAsHex true to get exact binary representations + of floating point numbers used in SkPoint arrays and conic weights. + + @param stream writable SkFlattenable receiving SkPath text representation; may be nullptr + @param forceClose true if missing kClose_Verb is output + @param dumpAsHex true if SkScalar values are written as hexadecimal + */ void dump(SkWStream* stream, bool forceClose, bool dumpAsHex) const; + + /** Writes text representation of SkPath to stream. If stream is nullptr, dump() writes to + standard output. Set forceClose to true to get + edges used to fill SkPath. Set dumpAsHex true to get exact binary representations + of floating point numbers used in SkPoint arrays and conic weights. + + @param stream writable SkFlattenable receiving SkPath text representation; may be nullptr + @param forceClose true if missing kClose_Verb is output + @param dumpAsHex true if SkScalar values are written as hexadecimal + */ void dump() const; + + /** Writes text representation of SkPath to standard output. The representation may be + directly compiled as C++ code. Floating point values are written + in hexadecimal to preserve their exact bit pattern. The output reconstructs the + original SkPath. + + Use instead of dump() when submitting + */ void dumpHex() const; - /** - * Write the path to the buffer, and return the number of bytes written. - * If buffer is NULL, it still returns the number of bytes. - */ + /** Writes SkPath to buffer, returning the number of bytes written. + Pass nullptr to obtain the storage size. + + Writes SkPath::FillType, verb array, SkPoint arrays, conic weight, and + additionally writes computed information like SkPath::Convexity and bounds. + + Use only be used in concert with readFromMemory(); + the format used for SkPath in memory is not guaranteed. + + @param buffer storage for SkPath; may be nullptr + @return size of storage required for SkPath; always a multiple of 4 + */ size_t writeToMemory(void* buffer) const; - /** - * Write the path to a buffer. Can recreate the path by calling readFromMemory(). - */ + /** Write SkPath to buffer, returning the buffer written to, wrapped in data. + + serialize() writes SkPath::FillType, verb array, SkPoint arrays, conic weight, and + additionally writes computed information like SkPath::Convexity and bounds. + + serialize() should only be used in concert with readFromMemory(). + The format used for SkPath in memory is not guaranteed. + + @return SkPath data wrapped in data buffer + */ sk_sp<SkData> serialize() const; - /** - * Initializes the path from the buffer - * - * @param buffer Memory to read from - * @param length Amount of memory available in the buffer - * @return number of bytes read (must be a multiple of 4) or - * 0 if there was not enough memory available - */ + /** Initializes SkPath from buffer of size length. Returns zero if the buffer is + data is inconsistent, or the length is too small. + + Reads SkPath::FillType, verb array, SkPoint arrays, conic weight, and + additionally reads computed information like SkPath::Convexity and bounds. + + Used only in concert with writeToMemory(); + the format used for SkPath in memory is not guaranteed. + + @param buffer storage for SkPath + @param length buffer size in bytes; must be multiple of 4 + @return number of bytes read, or zero on failure + */ size_t readFromMemory(const void* buffer, size_t length); - /** Returns a non-zero, globally unique value corresponding to the set of verbs - and points in the path (but not the fill type [except on Android skbug.com/1762]). - Each time the path is modified, a different generation ID will be returned. + /** Returns a non-zero, globally unique value. A different value is returned + if verb array, SkPoint arrays, or conic weight changes. + + Setting SkPath::FillType does not change generation id. + + Each time the path is modified, a different generation id will be returned. + + @return non-zero, globally unique value */ uint32_t getGenerationID() const; |