aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Cary Clark <caryclark@skia.org>2017-08-29 17:36:51 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-08-30 11:06:02 +0000
commit73fa972d0bd9de7cb801323495b5d1fabd31b24f (patch)
tree3a376a200b59bfd5c434eba345cf8e978a8f8ba6
parent1a763632d21636504d78910f7dea0aa708c6365f (diff)
work on path
Work on SkPath.h documentation; fixed self-consistency bugs identified by bookmaker. Fixed a couple of minor typos in SkPath.h itself. Also brought SkPaint and SkCanvas docs up to date. TBR=reed@google.com Docs-Preview: https://skia.org/?cl=39040 Bug: skia: 6898 Change-Id: Id89d4e2fa7fb6ee2e3cbec7ea762e06308b67d8b Reviewed-on: https://skia-review.googlesource.com/39040 Commit-Queue: Cary Clark <caryclark@skia.org> Reviewed-by: Cary Clark <caryclark@google.com> Reviewed-by: Cary Clark <caryclark@skia.org>
-rw-r--r--docs/SkCanvas_Reference.bmh36
-rw-r--r--docs/SkPaint_Reference.bmh4
-rw-r--r--docs/SkPath_Reference.bmh10434
-rw-r--r--docs/undocumented.bmh3
-rw-r--r--include/core/SkPath.h14
-rw-r--r--site/user/api/SkCanvas_Reference.md140
-rw-r--r--site/user/api/SkPaint_Reference.md28
-rw-r--r--site/user/api/SkPath_Reference.md1183
-rw-r--r--tools/bookmaker/bookmaker.cpp302
-rw-r--r--tools/bookmaker/bookmaker.h18
-rw-r--r--tools/bookmaker/includeParser.cpp42
-rw-r--r--tools/bookmaker/includeWriter.cpp60
12 files changed, 6342 insertions, 5922 deletions
diff --git a/docs/SkCanvas_Reference.bmh b/docs/SkCanvas_Reference.bmh
index ca4a129a47..0168afae77 100644
--- a/docs/SkCanvas_Reference.bmh
+++ b/docs/SkCanvas_Reference.bmh
@@ -67,7 +67,7 @@ when no Surface is required, and some helpers implicitly create Raster_Surface.
# # description ##
#Legend ##
# SkCanvas() # No Surface, no dimensions. ##
-# SkCanvas(int width, int height, const SkSurfaceProps* props = NULL) # No Surface, set dimensions, Surface_Properties. ##
+# SkCanvas(int width, int height, const SkSurfaceProps* props = nullptr) # No Surface, set dimensions, Surface_Properties. ##
# SkCanvas(SkBaseDevice* device) # Existing Device. (SkBaseDevice is private.) ##
# SkCanvas(const SkBitmap& bitmap) # Uses existing Bitmap. ##
# SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props) # Uses existing Bitmap and Surface_Properties. ##
@@ -364,7 +364,7 @@ void draw(SkCanvas* canvas) {
# ------------------------------------------------------------------------------
-#Method SkCanvas(int width, int height, const SkSurfaceProps* props = NULL)
+#Method SkCanvas(int width, int height, const SkSurfaceProps* props = nullptr)
Creates Canvas of the specified dimensions without a Surface.
Used by subclasses with custom implementations for draw methods.
@@ -465,16 +465,16 @@ The actual output depends on the installed fonts.
}
#StdOut
- -----
- --x--
- --x--
- --x--
- --x--
- --x--
- --x--
- -----
- --x--
- --x--
+ -----
+ ---x-
+ ---x-
+ ---x-
+ ---x-
+ ---x-
+ ---x-
+ -----
+ ---x-
+ ---x-
-----
#StdOut ##
##
@@ -803,7 +803,7 @@ void draw(SkCanvas* canvas) {
# ------------------------------------------------------------------------------
-#Method void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = NULL)
+#Method void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = nullptr)
Returns the pixel base address, Image_Info, rowBytes, and origin if the pixels
can be read directly. The returned address is only valid
@@ -3774,7 +3774,7 @@ void draw(SkCanvas* canvas) {
drawImage, drawImageRect, and drawImageNine can be called with a bare pointer or
a smart pointer as a convenience. The pairs of calls are otherwise identical.
-#Method void drawImage(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint = NULL)
+#Method void drawImage(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint = nullptr)
Draw Image image, with its top-left corner at (left, top),
using Clip, Matrix, and optional Paint paint.
@@ -3814,7 +3814,7 @@ void draw(SkCanvas* canvas) {
# ------------------------------------------------------------------------------
#Method void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top,
- const SkPaint* paint = NULL)
+ const SkPaint* paint = nullptr)
Draw Image image, with its top-left corner at (left, top),
using Clip, Matrix, and optional Paint paint.
@@ -4362,7 +4362,7 @@ void draw(SkCanvas* canvas) {
# ------------------------------------------------------------------------------
#Method void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
- const SkPaint* paint = NULL)
+ const SkPaint* paint = nullptr)
Draw Bitmap bitmap, with its top-left corner at (left, top),
using Clip, Matrix, and optional Paint paint.
@@ -4580,7 +4580,7 @@ void draw(SkCanvas* canvas) {
# ------------------------------------------------------------------------------
#Method void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
- const SkPaint* paint = NULL)
+ const SkPaint* paint = nullptr)
Draw Bitmap bitmap stretched differentially to fit into Rect dst.
IRect center divides the bitmap into nine sections: four sides, four corners,
@@ -5843,7 +5843,7 @@ void draw(SkCanvas* canvas) {
# ------------------------------------------------------------------------------
-#Method void drawDrawable(SkDrawable* drawable, const SkMatrix* matrix = NULL)
+#Method void drawDrawable(SkDrawable* drawable, const SkMatrix* matrix = nullptr)
Draw Drawable drawable using Clip and Matrix, concatenated with
optional matrix.
diff --git a/docs/SkPaint_Reference.bmh b/docs/SkPaint_Reference.bmh
index cfb432a1dd..cc9ae93fbe 100644
--- a/docs/SkPaint_Reference.bmh
+++ b/docs/SkPaint_Reference.bmh
@@ -4713,7 +4713,7 @@ text contains an invalid UTF-8 sequence, zero is returned.
##
#Method size_t breakText(const void* text, size_t length, SkScalar maxWidth,
- SkScalar* measuredWidth = NULL) const
+ SkScalar* measuredWidth = nullptr) const
Returns the bytes of text that fit within maxWidth.
If kVerticalText_Flag is clear, the text fragment fits if its advance width is less than or
@@ -4757,7 +4757,7 @@ text contains an invalid UTF-8 sequence, zero is returned.
##
#Method int getTextWidths(const void* text, size_t byteLength, SkScalar widths[],
- SkRect bounds[] = NULL) const
+ SkRect bounds[] = nullptr) const
Retrieves the advance and bounds for each glyph in text, and returns
the glyph count in text.
diff --git a/docs/SkPath_Reference.bmh b/docs/SkPath_Reference.bmh
index 95067c71b5..a0508dff29 100644
--- a/docs/SkPath_Reference.bmh
+++ b/docs/SkPath_Reference.bmh
@@ -1,80 +1,80 @@
-#Topic Path
-#Alias Path_Reference
-#Alias Paths
-
-Path contains Lines and Curves which can be stroked or filled. Contour is
-composed of a series of connected Lines and Curves. Path may contain zero,
-one, or more Contours.
-Each Line and Curve are described by Verb, Points, and optional Weight.
-
-Each pair of connected Lines and Curves share common Point; for instance, Path
-containing two connected Lines are described the Verb sequence:
-SkPath::kMove_Verb, SkPath::kLine_Verb, SkPath::kLine_Verb; and a Point sequence
-with three entries, sharing
-the middle entry as the end of the first Line and the start of the second Line.
-
-Path components Arc, Rect, Round_Rect, Circle, and Oval are composed of
-Lines and Curves with as many Verbs and Points required
-for an exact description. Once added to Path, these components may lose their
-identity; although Path can be inspected to determine if it decribes a single
-Rect, Oval, Round_Rect, and so on.
-
-#Example
-#Height 192
-#Description
-Path contains three Contours: Line, Circle, and Quad. Line is stroked but
-not filled. Circle is stroked and filled; Circle stroke forms a loop. Quad
-is stroked and filled, but since it is not closed, Quad does not stroke a loop.
-##
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setAntiAlias(true);
- SkPath path;
- path.moveTo(124, 108);
- path.lineTo(172, 24);
- path.addCircle(50, 50, 30);
- path.moveTo(36, 148);
- path.quadTo(66, 188, 120, 136);
- canvas->drawPath(path, paint);
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setColor(SK_ColorBLUE);
- paint.setStrokeWidth(3);
- canvas->drawPath(path, paint);
-}
-##
-
-Path contains a Fill_Type which determines whether overlapping Contours
-form fills or holes. Fill_Type also determines whether area inside or outside
-Lines and Curves is filled.
-
-#Example
-#Height 192
-#Description
-Path is drawn filled, then stroked, then stroked and filled.
-##
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setAntiAlias(true);
- SkPath path;
- path.moveTo(36, 48);
- path.quadTo(66, 88, 120, 36);
- canvas->drawPath(path, paint);
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setColor(SK_ColorBLUE);
- paint.setStrokeWidth(8);
- canvas->translate(0, 50);
- canvas->drawPath(path, paint);
- paint.setStyle(SkPaint::kStrokeAndFill_Style);
- paint.setColor(SK_ColorRED);
- canvas->translate(0, 50);
- canvas->drawPath(path, paint);
-}
-##
-
-Path contents are never shared. Copying Path by value effectively creates
-a new Path independent of the original. Internally, the copy does not duplicate
-its contents until it is edited, to reduce memory use and improve performance.
-
+#Topic Path
+#Alias Path_Reference
+#Alias Paths
+
+Path contains Lines and Curves which can be stroked or filled. Contour is
+composed of a series of connected Lines and Curves. Path may contain zero,
+one, or more Contours.
+Each Line and Curve are described by Verb, Points, and optional Conic_Weight.
+
+Each pair of connected Lines and Curves share common Point; for instance, Path
+containing two connected Lines are described the Verb sequence:
+SkPath::kMove_Verb, SkPath::kLine_Verb, SkPath::kLine_Verb; and a Point sequence
+with three entries, sharing
+the middle entry as the end of the first Line and the start of the second Line.
+
+Path components Arc, Rect, Round_Rect, Circle, and Oval are composed of
+Lines and Curves with as many Verbs and Points required
+for an exact description. Once added to Path, these components may lose their
+identity; although Path can be inspected to determine if it decribes a single
+Rect, Oval, Round_Rect, and so on.
+
+#Example
+#Height 192
+#Description
+Path contains three Contours: Line, Circle, and Quad. Line is stroked but
+not filled. Circle is stroked and filled; Circle stroke forms a loop. Quad
+is stroked and filled, but since it is not closed, Quad does not stroke a loop.
+##
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ SkPath path;
+ path.moveTo(124, 108);
+ path.lineTo(172, 24);
+ path.addCircle(50, 50, 30);
+ path.moveTo(36, 148);
+ path.quadTo(66, 188, 120, 136);
+ canvas->drawPath(path, paint);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setColor(SK_ColorBLUE);
+ paint.setStrokeWidth(3);
+ canvas->drawPath(path, paint);
+}
+##
+
+Path contains a Fill_Type which determines whether overlapping Contours
+form fills or holes. Fill_Type also determines whether area inside or outside
+Lines and Curves is filled.
+
+#Example
+#Height 192
+#Description
+Path is drawn filled, then stroked, then stroked and filled.
+##
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ SkPath path;
+ path.moveTo(36, 48);
+ path.quadTo(66, 88, 120, 36);
+ canvas->drawPath(path, paint);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setColor(SK_ColorBLUE);
+ paint.setStrokeWidth(8);
+ canvas->translate(0, 50);
+ canvas->drawPath(path, paint);
+ paint.setStyle(SkPaint::kStrokeAndFill_Style);
+ paint.setColor(SK_ColorRED);
+ canvas->translate(0, 50);
+ canvas->drawPath(path, paint);
+}
+##
+
+Path contents are never shared. Copying Path by value effectively creates
+a new Path independent of the original. Internally, the copy does not duplicate
+its contents until it is edited, to reduce memory use and improve performance.
+
#Subtopic Subtopics
#ToDo not all methods are in topics ##
#ToDo subtopics are not in topics ##
@@ -90,10 +90,10 @@ its contents until it is edited, to reduce memory use and improve performance.
# Verb # How Points and Contours are defined. ##
# Verb_Array # All Verbs in Path. ##
# Verb # How Points and Contours are defined. ##
-# Weight # Strength of control Point in Conic. ##
+# Conic_Weight # Strength of control Point in Conic. ##
#Subtopic ##
-
-
+
+
#Subtopic Contour
#Alias Contours
Contour contains one or more Verbs, and as many Points as
@@ -101,27 +101,27 @@ are required to satisfy Verb_Array. First Verb in Path is always
SkPath::kMove_Verb; each SkPath::kMove_Verb that follows starts a new Contour.
#Example
-#Description
-Each SkPath::moveTo starts a new Contour, and content after SkPath::close()
-also starts a new Contour. Since SkPath::conicTo wasn't preceded by
-SkPath::moveTo, the first Point of the third Contour starts at the last Point
-of the second Contour.
-##
-#Height 192
- SkPaint paint;
- paint.setAntiAlias(true);
- canvas->drawString("1st contour", 150, 100, paint);
- canvas->drawString("2nd contour", 130, 160, paint);
- canvas->drawString("3rd contour", 40, 30, paint);
- paint.setStyle(SkPaint::kStroke_Style);
- SkPath path;
- path.moveTo(124, 108);
- path.lineTo(172, 24);
- path.moveTo(36, 148);
- path.quadTo(66, 188, 120, 136);
- path.close();
- path.conicTo(70, 20, 110, 40, 0.6f);
- canvas->drawPath(path, paint);
+#Description
+Each SkPath::moveTo starts a new Contour, and content after SkPath::close()
+also starts a new Contour. Since SkPath::conicTo wasn't preceded by
+SkPath::moveTo, the first Point of the third Contour starts at the last Point
+of the second Contour.
+##
+#Height 192
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ canvas->drawString("1st contour", 150, 100, paint);
+ canvas->drawString("2nd contour", 130, 160, paint);
+ canvas->drawString("3rd contour", 40, 30, paint);
+ paint.setStyle(SkPaint::kStroke_Style);
+ SkPath path;
+ path.moveTo(124, 108);
+ path.lineTo(172, 24);
+ path.moveTo(36, 148);
+ path.quadTo(66, 188, 120, 136);
+ path.close();
+ path.conicTo(70, 20, 110, 40, 0.6f);
+ canvas->drawPath(path, paint);
##
If final Verb in Contour is SkPath::kClose_Verb, Line connects Last_Point in
@@ -132,23 +132,23 @@ remains open. An open Contour, stroked, draws Paint_Stroke_Cap at
Last_Point and first Point.
#Example
-#Height 160
-#Description
-Path is drawn stroked, with an open Contour and a closed Contour.
-##
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setStrokeWidth(8);
- SkPath path;
- path.moveTo(36, 48);
- path.quadTo(66, 88, 120, 36);
- canvas->drawPath(path, paint);
- path.close();
- canvas->translate(0, 50);
- canvas->drawPath(path, paint);
-}
+#Height 160
+#Description
+Path is drawn stroked, with an open Contour and a closed Contour.
+##
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(8);
+ SkPath path;
+ path.moveTo(36, 48);
+ path.quadTo(66, 88, 120, 36);
+ canvas->drawPath(path, paint);
+ path.close();
+ canvas->translate(0, 50);
+ canvas->drawPath(path, paint);
+}
##
#Subtopic Zero_Length
@@ -159,33 +159,50 @@ Even if Contour length is zero, stroked Lines are drawn if Paint_Stroke_Cap
makes them visible.
#Example
-#Height 64
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setStrokeWidth(8);
- paint.setStrokeCap(SkPaint::kRound_Cap);
- SkPath path;
- path.moveTo(36, 48);
- path.lineTo(36, 48);
- canvas->drawPath(path, paint);
- path.reset();
- paint.setStrokeCap(SkPaint::kSquare_Cap);
- path.moveTo(56, 48);
- path.close();
+#Height 64
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(8);
+ paint.setStrokeCap(SkPaint::kRound_Cap);
+ SkPath path;
+ path.moveTo(36, 48);
+ path.lineTo(36, 48);
+ canvas->drawPath(path, paint);
+ path.reset();
+ paint.setStrokeCap(SkPaint::kSquare_Cap);
+ path.moveTo(56, 48);
+ path.close();
canvas->drawPath(path, paint);
##
#Subtopic Zero_Length ##
#Subtopic Contour ##
-
-# ------------------------------------------------------------------------------
+
+# ------------------------------------------------------------------------------
+
+#Class SkPath
+
+Paths contain geometry. Paths may be empty, or contain one or more Verbs that
+outline a figure. Path always starts with a move verb to a Cartesian
+coordinate, and may be followed by additional verbs that add lines or curves.
+Adding a close verb makes the geometry into a continuous loop, a closed contour.
+Paths may contain any number of contours, each beginnning with a move verb.
+
+Path contours may contain only a move verb, or may also contain lines,
+quadratic Beziers, conics, and cubic Beziers. Path contours may be open or
+closed.
+
+When used to draw a filled area, Path describes whether the fill is inside or
+outside the geometry. Path also describes the winding rule used to fill
+overlapping contours.
+
+Internally, Path lazily computes metrics likes bounds and convexity. Call
+SkPath::updateBoundsCache to make Path thread safe.
+
+#Topic Overview
-#Class SkPath
-
-#Topic Overview
-
#Subtopic Constants
#ToDo incomplete ##
#Table
@@ -201,7 +218,7 @@ makes them visible.
# Verb # Controls how Path Points are interpreted. ##
#Table ##
#Subtopic ##
-
+
#Subtopic Classes_and_Structs
#Table
#Legend
@@ -211,7 +228,7 @@ makes them visible.
# RawIter # Iterates through lines and curves, including degenerates. ##
#Table ##
#Subtopic ##
-
+
#Subtopic Constructors
#Table
#Legend
@@ -233,140 +250,141 @@ makes them visible.
# operator!=(const SkPath& a, const SkPath& b) # Compares paths for inequality. ##
#Table ##
#Subtopic ##
-
-#Subtopic Member_Functions
-#Table
-#Legend
-# function # description ##
-#Legend ##
-# ConvertConicToQuads # Approximates Conic with Quad array. ##
-# ConvertToNonInverseFillType # Returns Fill_Type representing inside geometry. ##
-# IsCubicDegenerate # Returns if Cubic is very small. ##
-# IsInverseFillType # Returns if Fill_Type represents outside geometry. ##
-# IsLineDegenerate # Returns if Line is very small. ##
-# IsQuadDegenerate # Returns if Quad is very small. ##
-# addArc # Adds one Contour containing Arc. ##
-# addCircle # Adds one Contour containing Circle. ##
-# addOval # Adds one Contour containing Oval. ##
-# addPath # Adds contents of Path. ##
-# addPoly # Adds one Contour containing connected lines. ##
-# addRRect # Adds one Contour containing Round_Rect. ##
-# addRect # Adds one Contour containing Rect. ##
-# addRoundRect # Adds one Contour containing Round_Rect with common corner radii. ##
-# arcTo # Appends Arc. ##
-# close() # Makes last Contour a loop. ##
-# computeTightBounds # Returns extent of geometry. ##
-# conicTo # Appends Conic. ##
-# conservativelyContainsRect # Returns true if Rect may be inside. ##
-# contains() # Returns if Point is in fill area. ##
-# countPoints # Returns Point_Array length. ##
-# countVerbs # Returns Verb_Array length. ##
-# cubicTo # Appends Cubic. ##
-# dump() # Sends text representation using floats to stdout. ##
-# dumpHex # Sends text representation using hexadecimal to stdout. ##
-# experimentalValidateRef # Experimental; debugging only. ##
-# getBounds # Returns maximum and minimum of Point_Array. ##
-# getConvexity # Returns geometry convexity, computing if necessary. ##
-# getConvexityOrUnknown # Returns geometry convexity if known. ##
-# getFillType # Returns Fill_Type: winding, even-odd, inverse. ##
-# getGenerationID # Returns unique ID. ##
-# getLastPt # Returns Last_Point. ##
-# getPoint # Returns entry from Point_Array. ##
-# getPoints # Returns Point_Array. ##
-# getSegmentMasks # Returns types in Verb_Array. ##
-# getVerbs # Returns Verb_Array. ##
-# incReserve # Hint to reserve space for additional data. ##
-# interpolate() # Interpolates between Path pair. ##
-# isConvex # Returns if geometry is convex. ##
-# isEmpty # Returns if verb count is zero. ##
-# isFinite # Returns if all Point values are finite. ##
-# isInterpolatable # Returns if pair contains equal counts of Verb_Array and Weights. ##
-# isInverseFillType # Returns if Fill_Type fills outside geometry. ##
-# isLastContourClosed # Returns if final Contour forms a loop. ##
-# isLine # Returns if describes Line. ##
-# isNestedFillRects # Returns if describes Rect pair, one inside the other. ##
-# isOval # Returns if describes Oval. ##
-# isRRect # Returns if describes Round_Rect. ##
-# isRect # Returns if describes Rect. ##
-# isVolatile # Returns if Device should not cache. ##
-# lineTo # Appends Line. ##
-# moveTo # Starts Contour. ##
-# offset() # Translates Point_Array. ##
-# quadTo # Appends Quad. ##
-# rArcTo # Appends Arc relative to Last_Point. ##
-# rConicTo # Appends Conic relative to Last_Point. ##
-# rCubicTo # Appends Cubic relative to Last_Point. ##
-# rLineTo # Appends Line relative to Last_Point. ##
-# rMoveTo # Starts Contour relative to Last_Point. ##
-# rQuadTo # Appends Quad relative to Last_Point. ##
-# readFromMemory # Initialize from buffer. ##
-# reset() # Removes Verb_Array, Point_Array, and Weights; frees memory. ##
-# reverseAddPath # Adds contents of Path back to front. ##
-# rewind() # Removes Verb_Array, Point_Array, and Weights; leaves memory allocated. ##
-# setConvexity # Sets if geometry is convex to avoid future computation. ##
-# setFillType # Sets Fill_Type: winding, even-odd, inverse. ##
-# setIsConvex # Deprecated. ##
-# setIsVolatile # Sets if Device should not cache. ##
-# setLastPt # Replaces Last_Point. ##
-# swap() # Exchanges Path pair. ##
-# toggleInverseFillType # Toggles Fill_Type between inside and outside geometry. ##
-# transform() # Applies Matrix to Point_Array and Weights. ##
-# unique() # Returns if data has single owner. ##
-# updateBoundsCache # Refresh result of getBounds. ##
-# writeToMemory # Copy data to buffer. ##
-#Table ##
-#Subtopic Path_Member_Functions ##
-#Topic Overview ##
-
+
+#Subtopic Member_Functions
+#Table
+#Legend
+# function # description ##
+#Legend ##
+# ConvertConicToQuads # Approximates Conic with Quad array. ##
+# ConvertToNonInverseFillType # Returns Fill_Type representing inside geometry. ##
+# IsCubicDegenerate # Returns if Cubic is very small. ##
+# IsInverseFillType # Returns if Fill_Type represents outside geometry. ##
+# IsLineDegenerate # Returns if Line is very small. ##
+# IsQuadDegenerate # Returns if Quad is very small. ##
+# addArc # Adds one Contour containing Arc. ##
+# addCircle # Adds one Contour containing Circle. ##
+# addOval # Adds one Contour containing Oval. ##
+# addPath # Adds contents of Path. ##
+# addPoly # Adds one Contour containing connected lines. ##
+# addRRect # Adds one Contour containing Round_Rect. ##
+# addRect # Adds one Contour containing Rect. ##
+# addRoundRect # Adds one Contour containing Round_Rect with common corner radii. ##
+# arcTo # Appends Arc. ##
+# close() # Makes last Contour a loop. ##
+# computeTightBounds # Returns extent of geometry. ##
+# conicTo # Appends Conic. ##
+# conservativelyContainsRect # Returns true if Rect may be inside. ##
+# contains() # Returns if Point is in fill area. ##
+# countPoints # Returns Point_Array length. ##
+# countVerbs # Returns Verb_Array length. ##
+# cubicTo # Appends Cubic. ##
+# dump() # Sends text representation using floats to stdout. ##
+# dumpHex # Sends text representation using hexadecimal to stdout. ##
+# getBounds # Returns maximum and minimum of Point_Array. ##
+# getConvexity # Returns geometry convexity, computing if necessary. ##
+# getConvexityOrUnknown # Returns geometry convexity if known. ##
+# getFillType # Returns Fill_Type: winding, even-odd, inverse. ##
+# getGenerationID # Returns unique ID. ##
+# getLastPt # Returns Last_Point. ##
+# getPoint # Returns entry from Point_Array. ##
+# getPoints # Returns Point_Array. ##
+# getSegmentMasks # Returns types in Verb_Array. ##
+# getVerbs # Returns Verb_Array. ##
+# incReserve # Hint to reserve space for additional data. ##
+# interpolate() # Interpolates between Path pair. ##
+# isConvex # Returns if geometry is convex. ##
+# isEmpty # Returns if verb count is zero. ##
+# isFinite # Returns if all Point values are finite. ##
+# isInterpolatable # Returns if pair contains equal counts of Verb_Array and Weights. ##
+# isInverseFillType # Returns if Fill_Type fills outside geometry. ##
+# isLastContourClosed # Returns if final Contour forms a loop. ##
+# isLine # Returns if describes Line. ##
+# isNestedFillRects # Returns if describes Rect pair, one inside the other. ##
+# isOval # Returns if describes Oval. ##
+# isRRect # Returns if describes Round_Rect. ##
+# isRect # Returns if describes Rect. ##
+# isValid # Returns if data is internally consistent. ##
+# isVolatile # Returns if Device should not cache. ##
+# lineTo # Appends Line. ##
+# moveTo # Starts Contour. ##
+# offset() # Translates Point_Array. ##
+# quadTo # Appends Quad. ##
+# rArcTo # Appends Arc relative to Last_Point. ##
+# rConicTo # Appends Conic relative to Last_Point. ##
+# rCubicTo # Appends Cubic relative to Last_Point. ##
+# rLineTo # Appends Line relative to Last_Point. ##
+# rMoveTo # Starts Contour relative to Last_Point. ##
+# rQuadTo # Appends Quad relative to Last_Point. ##
+# readFromMemory # Initializes from buffer. ##
+# reset() # Removes Verb_Array, Point_Array, and Weights; frees memory. ##
+# reverseAddPath # Adds contents of Path back to front. ##
+# rewind() # Removes Verb_Array, Point_Array, and Weights; leaves memory allocated. ##
+# serialize() # Copies data to buffer. ##
+# setConvexity # Sets if geometry is convex to avoid future computation. ##
+# setFillType # Sets Fill_Type: winding, even-odd, inverse. ##
+# setIsConvex # Deprecated. ##
+# setIsVolatile # Sets if Device should not cache. ##
+# setLastPt # Replaces Last_Point. ##
+# swap() # Exchanges Path pair. ##
+# toggleInverseFillType # Toggles Fill_Type between inside and outside geometry. ##
+# transform() # Applies Matrix to Point_Array and Weights. ##
+# unique() # Returns if data has single owner. ##
+# updateBoundsCache # Refreshes result of getBounds. ##
+# writeToMemory # Copies data to buffer. ##
+#Table ##
+#Subtopic Path_Member_Functions ##
+#Topic Overview ##
+
#Subtopic Verb
#Alias Verbs
-#Enum Verb
-
-#Code
- enum Verb {
- kMove_Verb
- kLine_Verb
- kQuad_Verb
- kConic_Verb
- kCubic_Verb
- kClose_Verb
- kDone_Verb
- };
-##
-
-Verb instructs Path how to interpret one or more Point and optional Weight;
+#Enum Verb
+
+#Code
+ enum Verb {
+ kMove_Verb,
+ kLine_Verb,
+ kQuad_Verb,
+ kConic_Verb,
+ kCubic_Verb,
+ kClose_Verb,
+ kDone_Verb,
+ };
+##
+
+Verb instructs Path how to interpret one or more Point and optional Conic_Weight;
manage Contour, and terminate Path.
-#Const kMove_Verb 0
- Starts new Contour at next Point.
-##
-#Const kLine_Verb 1
- Adds Line from Last_Point to next Point.
- Line is a straight segment from Point to Point.
-##
-#Const kQuad_Verb 2
- Adds Quad from Last_Point, using control Point, and end Point.
- Quad is a parabolic section within tangents from Last_Point to control Point,
- and control Point to end Point.
-##
-#Const kConic_Verb 3
- Adds Conic from Last_Point, using control Point, end Point, and Weight.
- Conic is a elliptical, parabolic, or hyperbolic section within tangents
- from Last_Point to control Point, and control Point to end Point, constrained
- by Weight. Weight less than one is elliptical; equal to one is parabolic
- (and identical to Quad); greater than one hyperbolic.
-##
-#Const kCubic_Verb 4
- Adds Cubic from Last_Point, using two control Points, and end Point.
- Cubic is a third-order Bezier section within tangents from Last_Point to
- first control Point, and from second control Point to end Point.
-##
-#Const kClose_Verb 5
- Closes Contour, connecting Last_Point to kMove_Verb Point.
-##
-#Const kDone_Verb 6
- Terminates Path. Not in Verb_Array, but returned by Path iterator.
+#Const kMove_Verb 0
+ Starts new Contour at next Point.
+##
+#Const kLine_Verb 1
+ Adds Line from Last_Point to next Point.
+ Line is a straight segment from Point to Point.
+##
+#Const kQuad_Verb 2
+ Adds Quad from Last_Point, using control Point, and end Point.
+ Quad is a parabolic section within tangents from Last_Point to control Point,
+ and control Point to end Point.
+##
+#Const kConic_Verb 3
+ Adds Conic from Last_Point, using control Point, end Point, and Conic_Weight.
+ Conic is a elliptical, parabolic, or hyperbolic section within tangents
+ from Last_Point to control Point, and control Point to end Point, constrained
+ by Conic_Weight. Conic_Weight less than one is elliptical; equal to one is
+ parabolic (and identical to Quad); greater than one hyperbolic.
+##
+#Const kCubic_Verb 4
+ Adds Cubic from Last_Point, using two control Points, and end Point.
+ Cubic is a third-order Bezier section within tangents from Last_Point to
+ first control Point, and from second control Point to end Point.
+##
+#Const kClose_Verb 5
+ Closes Contour, connecting Last_Point to kMove_Verb Point.
+##
+#Const kDone_Verb 6
+ Terminates Path. Not in Verb_Array, but returned by Path iterator.
##
Each Verb has zero or more Points stored in Path.
@@ -385,412 +403,415 @@ for consecutive entries.
# kClose_Verb # 0 # 1 # 0 ##
# kDone_Verb # -- # 0 # 0 ##
##
-
-#Example
-void draw(SkCanvas* canvas) {
- SkPath path;
- path.lineTo(20, 20);
- path.quadTo(-10, -10, 30, 30);
- path.close();
- path.cubicTo(1, 2, 3, 4, 5, 6);
- path.conicTo(0, 0, 0, 0, 2);
- uint8_t verbs[7];
- int count = path.getVerbs(verbs, (int) SK_ARRAY_COUNT(verbs));
- const char* verbStr[] = { "Move", "Line", "Quad", "Conic", "Cubic", "Close" };
- SkDebugf("verb count: %d\nverbs: ", count);
- for (int i = 0; i < count; ++i) {
- SkDebugf("k%s_Verb ", verbStr[verbs[i]]);
- }
- SkDebugf("\n");
-}
-#StdOut
-verb count: 7
-verbs: kMove_Verb kLine_Verb kQuad_Verb kClose_Verb kMove_Verb kCubic_Verb kConic_Verb
-##
-##
-
-#Enum Verb ##
-#Subtopic Verb ##
-
-# ------------------------------------------------------------------------------
-#Subtopic Direction
-#Alias Directions
-
-#Enum Direction
-
-#Code
- enum Direction {
- kCW_Direction
- kCCW_Direction
- };
-##
-
-Direction describes whether Contour is clockwise or counterclockwise.
-When Path contains multiple overlapping Contours, Direction together with
-Fill_Type determines whether overlaps are filled or form holes.
-
-Direction also determines how Contour is measured. For instance, dashing
-measures along Path to determine where to start and stop stroke; Direction
-will change dashed results as it steps clockwise or counterclockwise.
-
-Closed Contours like Rect, Round_Rect, Circle, and Oval added with
-kCW_Direction travel clockwise; the same added with kCCW_Direction
-travel counterclockwise.
-
-#Const kCW_Direction
- Contour travels in a clockwise direction.
-##
-#Const kCCW_Direction
- Contour travels in a counterclockwise direction.
-##
-
-
-#Example
-#Height 100
-void draw(SkCanvas* canvas) {
- const SkPoint arrow[] = { {40, -5}, {45, 0}, {40, 5} };
- const SkRect rect = {10, 10, 90, 90};
- SkPaint rectPaint;
- rectPaint.setAntiAlias(true);
- SkPaint textPaint(rectPaint);
- textPaint.setTextAlign(SkPaint::kCenter_Align);
- rectPaint.setStyle(SkPaint::kStroke_Style);
- SkPaint arrowPaint(rectPaint);
- SkPath arrowPath;
- arrowPath.addPoly(arrow, SK_ARRAY_COUNT(arrow), true);
- arrowPaint.setPathEffect(SkPath1DPathEffect::Make(arrowPath, 320, 0,
- SkPath1DPathEffect::kRotate_Style));
- for (auto direction : { SkPath::kCW_Direction, SkPath::kCCW_Direction } ) {
- canvas->drawRect(rect, rectPaint);
- for (unsigned start : { 0, 1, 2, 3 } ) {
- SkPath path;
- path.addRect(rect, direction, start);
- canvas->drawPath(path, arrowPaint);
- }
- canvas->drawString(SkPath::kCW_Direction == direction ? "CW" : "CCW", rect.centerX(),
- rect.centerY(), textPaint);
- canvas->translate(120, 0);
- }
-}
-##
-
-#SeeAlso arcTo rArcTo isRect isNestedFillRects addRect addOval
-
-#Enum Direction ##
-#Subtopic Direction ##
-
-# ------------------------------------------------------------------------------
-
-#Method SkPath()
-
-By default, Path has no Verbs, no Points, and no Weights.
-Fill_Type is set to kWinding_FillType.
-
-#Return empty Path. ##
-
-#Example
- SkPath path;
- SkDebugf("path is " "%s" "empty", path.isEmpty() ? "" : "not ");
-#StdOut
-path is empty
-##
-##
-
-#SeeAlso reset rewind
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method SkPath(const SkPath& path)
-
-Copy constructor makes two paths identical by value. Internally, path and
-the returned result share pointer values. The underlying Verb_Array, Point_Array
-and Weights are copied when modified.
-
-Creating a Path copy is very efficient and never allocates memory.
-Paths are always copied by value from the interface; the underlying shared
-pointers are not exposed.
-
-#Param path Path to copy by value. ##
-
-#Return Copy of Path. ##
-
-#Example
-#Description
- Modifying one path does not effect another, even if they started as copies
- of each other.
-##
- SkPath path;
- path.lineTo(20, 20);
- SkPath path2(path);
- path2.close();
- SkDebugf("path verbs: %d\n", path.countVerbs());
- SkDebugf("path2 verbs: %d\n", path2.countVerbs());
- path.reset();
- SkDebugf("after reset\n" "path verbs: %d\n", path.countVerbs());
- SkDebugf("path2 verbs: %d\n", path2.countVerbs());
-#StdOut
-path verbs: 2
-path2 verbs: 3
-after reset
-path verbs: 0
-path2 verbs: 3
-##
-##
-
-#SeeAlso operator=(const SkPath& path)
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method ~SkPath()
-
-Releases ownership of any shared data and deletes data if Path is sole owner.
-
-#Example
-#Description
-delete calls Path destructor, but copy of original in path2 is unaffected.
-##
-void draw(SkCanvas* canvas) {
- SkPath* path = new SkPath();
- path->lineTo(20, 20);
- SkPath path2(*path);
- delete path;
- SkDebugf("path2 is " "%s" "empty", path2.isEmpty() ? "" : "not ");
-}
-##
-
-#SeeAlso SkPath() SkPath(const SkPath& path) operator=(const SkPath& path)
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method SkPath& operator=(const SkPath& path)
-
-Path assignment makes two paths identical by value. Internally, assignment
-shares pointer values. The underlying Verb_Array, Point_Array and Weights
-are copied when modified.
-
-Copying Paths by assignment is very efficient and never allocates memory.
-Paths are always copied by value from the interface; the underlying shared
-pointers are not exposed.
-
-#Param path Verb_Array, Point_Array, Weights, amd Fill_Type to copy. ##
-
-#Return Path copied by value. ##
-
-#Example
-SkPath path1;
-path1.addRect({10, 20, 30, 40});
-SkPath path2 = path1;
-const SkRect& b1 = path1.getBounds();
-SkDebugf("path1 bounds = %g, %g, %g, %g\n", b1.fLeft, b1.fTop, b1.fRight, b1.fBottom);
-const SkRect& b2 = path2.getBounds();
-SkDebugf("path2 bounds = %g, %g, %g, %g\n", b2.fLeft, b2.fTop, b2.fRight, b2.fBottom);
-#StdOut
-path1 bounds = 10, 20, 30, 40
-path2 bounds = 10, 20, 30, 40
-#StdOut ##
-##
-
-#SeeAlso swap() SkPath(const SkPath& path)
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method friend SK_API bool operator==(const SkPath& a, const SkPath& b)
-
-Compares a and b; returns true if Fill_Type, Verb_Array, Point_Array, and Weights
-are equivalent.
-
-#Param a Path to compare. ##
-#Param b Path to compare. ##
-
-#Return true if Path pair are equivalent. ##
-
-#Example
-#Description
-Rewind removes Verb_Array but leaves storage; since storage is not compared,
-Path pair are equivalent.
-##
-void draw(SkCanvas* canvas) {
- auto debugster = [](const char* prefix, const SkPath& a, const SkPath& b) -> void {
- SkDebugf("%s one %c= two\n", prefix, a == b ? '=' : '!');
- };
- SkPath one;
- SkPath two;
- debugster("empty", one, two);
- one.moveTo(0, 0);
- debugster("moveTo", one, two);
- one.rewind();
- debugster("rewind", one, two);
- one.moveTo(0, 0);
- one.reset();
- debugster("reset", one, two);
-}
-#StdOut
-empty one == two
-moveTo one != two
-rewind one == two
-reset one == two
-##
-##
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method friend bool operator!=(const SkPath& a, const SkPath& b)
-
-Compares a and b; returns true if Fill_Type, Verb_Array, Point_Array, and Weights
-are not equivalent.
-
-#Param a Path to compare. ##
-#Param b Path to compare. ##
-
-#Return true if Path pair are not equivalent. ##
-
-#Example
-#Description
-Path pair are equal though their convexity is not equal.
-##
-void draw(SkCanvas* canvas) {
- auto debugster = [](const char* prefix, const SkPath& a, const SkPath& b) -> void {
- SkDebugf("%s one %c= two\n", prefix, a != b ? '!' : '=');
- };
- SkPath one;
- SkPath two;
- debugster("empty", one, two);
- one.addRect({10, 20, 30, 40});
- two.addRect({10, 20, 30, 40});
- debugster("addRect", one, two);
- one.setConvexity(SkPath::kConcave_Convexity);
- debugster("setConvexity", one, two);
- SkDebugf("convexity %c=\n", one.getConvexity() == two.getConvexity() ? '=' : '!');
-}
-#StdOut
-empty one == two
-addRect one == two
-setConvexity one == two
-convexity !=
-##
-##
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method bool isInterpolatable(const SkPath& compare) const
-
-Return true if Paths contain equal Verbs and equal Weights.
-If Paths contain one or more Conics, the Weights must match.
-
-conicTo may add different Verbs depending on Conic_Weight, so it is not
-trival to interpolate a pair of Paths containing Conics with different
-Conic_Weight values.
-
-#Param compare Path to compare. ##
-
-#Return true if Paths Verb_Array and Weights are equivalent. ##
-
-#Example
- SkPath path, path2;
- path.moveTo(20, 20);
- path.lineTo(40, 40);
- path.lineTo(20, 20);
- path.lineTo(40, 40);
- path.close();
- path2.addRect({20, 20, 40, 40});
- SkDebugf("paths are " "%s" "interpolatable", path.isInterpolatable(path2) ? "" : "not ");
-#StdOut
-paths are interpolatable
-##
-##
-
-#SeeAlso isInterpolatable
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method bool interpolate(const SkPath& ending, SkScalar weight, SkPath* out) const
-
-Interpolate between Paths with equal sized Point_Arrays.
-Copy Verb_Array and Weights to out,
-and set out Point_Array to a weighted average of this Point_Array and ending
-Point_Array, using the formula:
-#Formula
-(this->points * weight) + ending->points * (1 - weight)
-##
-
-interpolate() returns false and leaves out unchanged if Point_Array is not
-the same size as ending Point_Array. Call isInterpolatable to check Path
-compatibility prior to calling interpolate().
-
-#Param ending Point_Array averaged with this Point_Array. ##
-#Param weight Most useful when between zero (ending Point_Array) and
- one (this Point_Array); will work with values outside of this
- range.
-##
-#Param out ##
-
-#Return true if Paths contain same number of Points. ##
-
-#Example
-#Height 60
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
- SkPath path, path2;
- path.moveTo(20, 20);
- path.lineTo(40, 40);
- path.lineTo(20, 40);
- path.lineTo(40, 20);
- path.close();
- path2.addRect({20, 20, 40, 40});
- for (SkScalar i = 0; i <= 1; i += 1.f / 6) {
- SkPath interp;
- path.interpolate(path2, i, &interp);
- canvas->drawPath(interp, paint);
- canvas->translate(30, 0);
- }
-}
-##
-
-#SeeAlso isInterpolatable
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method bool unique() const
-
-#Private
-To be deprecated; only valid for Android framework.
-##
-
-#Return true if Path has one owner. ##
-
-##
-
-# ------------------------------------------------------------------------------
+
+#Example
+void draw(SkCanvas* canvas) {
+ SkPath path;
+ path.lineTo(20, 20);
+ path.quadTo(-10, -10, 30, 30);
+ path.close();
+ path.cubicTo(1, 2, 3, 4, 5, 6);
+ path.conicTo(0, 0, 0, 0, 2);
+ uint8_t verbs[7];
+ int count = path.getVerbs(verbs, (int) SK_ARRAY_COUNT(verbs));
+ const char* verbStr[] = { "Move", "Line", "Quad", "Conic", "Cubic", "Close" };
+ SkDebugf("verb count: %d\nverbs: ", count);
+ for (int i = 0; i < count; ++i) {
+ SkDebugf("k%s_Verb ", verbStr[verbs[i]]);
+ }
+ SkDebugf("\n");
+}
+#StdOut
+verb count: 7
+verbs: kMove_Verb kLine_Verb kQuad_Verb kClose_Verb kMove_Verb kCubic_Verb kConic_Verb
+##
+##
+
+#Enum Verb ##
+#Subtopic Verb ##
+
+# ------------------------------------------------------------------------------
+#Subtopic Direction
+#Alias Directions
+
+#Enum Direction
+
+#Code
+ enum Direction {
+ kCW_Direction,
+ kCCW_Direction,
+ };
+##
+
+Direction describes whether Contour is clockwise or counterclockwise.
+When Path contains multiple overlapping Contours, Direction together with
+Fill_Type determines whether overlaps are filled or form holes.
+
+Direction also determines how Contour is measured. For instance, dashing
+measures along Path to determine where to start and stop stroke; Direction
+will change dashed results as it steps clockwise or counterclockwise.
+
+Closed Contours like Rect, Round_Rect, Circle, and Oval added with
+kCW_Direction travel clockwise; the same added with kCCW_Direction
+travel counterclockwise.
+
+#Const kCW_Direction 0
+ Contour travels in a clockwise direction.
+##
+#Const kCCW_Direction 1
+ Contour travels in a counterclockwise direction.
+##
+
+
+#Example
+#Height 100
+void draw(SkCanvas* canvas) {
+ const SkPoint arrow[] = { {40, -5}, {45, 0}, {40, 5} };
+ const SkRect rect = {10, 10, 90, 90};
+ SkPaint rectPaint;
+ rectPaint.setAntiAlias(true);
+ SkPaint textPaint(rectPaint);
+ textPaint.setTextAlign(SkPaint::kCenter_Align);
+ rectPaint.setStyle(SkPaint::kStroke_Style);
+ SkPaint arrowPaint(rectPaint);
+ SkPath arrowPath;
+ arrowPath.addPoly(arrow, SK_ARRAY_COUNT(arrow), true);
+ arrowPaint.setPathEffect(SkPath1DPathEffect::Make(arrowPath, 320, 0,
+ SkPath1DPathEffect::kRotate_Style));
+ for (auto direction : { SkPath::kCW_Direction, SkPath::kCCW_Direction } ) {
+ canvas->drawRect(rect, rectPaint);
+ for (unsigned start : { 0, 1, 2, 3 } ) {
+ SkPath path;
+ path.addRect(rect, direction, start);
+ canvas->drawPath(path, arrowPaint);
+ }
+ canvas->drawString(SkPath::kCW_Direction == direction ? "CW" : "CCW", rect.centerX(),
+ rect.centerY(), textPaint);
+ canvas->translate(120, 0);
+ }
+}
+##
+
+#SeeAlso arcTo rArcTo isRect isNestedFillRects addRect addOval
+
+#Enum Direction ##
+#Subtopic Direction ##
+
+# ------------------------------------------------------------------------------
+
+#Method SkPath()
+
+By default, Path has no Verbs, no Points, and no Weights.
+Fill_Type is set to kWinding_FillType.
+
+#Return empty Path ##
+
+#Example
+ SkPath path;
+ SkDebugf("path is " "%s" "empty", path.isEmpty() ? "" : "not ");
+#StdOut
+path is empty
+##
+##
+
+#SeeAlso reset rewind
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method SkPath(const SkPath& path)
+
+Copy constructor makes two paths identical by value. Internally, path and
+the returned result share pointer values. The underlying Verb_Array, Point_Array
+and Weights are copied when modified.
+
+Creating a Path copy is very efficient and never allocates memory.
+Paths are always copied by value from the interface; the underlying shared
+pointers are not exposed.
+
+#Param path Path to copy by value ##
+
+#Return Copy of Path ##
+
+#Example
+#Description
+ Modifying one path does not effect another, even if they started as copies
+ of each other.
+##
+ SkPath path;
+ path.lineTo(20, 20);
+ SkPath path2(path);
+ path2.close();
+ SkDebugf("path verbs: %d\n", path.countVerbs());
+ SkDebugf("path2 verbs: %d\n", path2.countVerbs());
+ path.reset();
+ SkDebugf("after reset\n" "path verbs: %d\n", path.countVerbs());
+ SkDebugf("path2 verbs: %d\n", path2.countVerbs());
+#StdOut
+path verbs: 2
+path2 verbs: 3
+after reset
+path verbs: 0
+path2 verbs: 3
+##
+##
+
+#SeeAlso operator=(const SkPath& path)
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method ~SkPath()
+
+Releases ownership of any shared data and deletes data if Path is sole owner.
+
+#Example
+#Description
+delete calls Path destructor, but copy of original in path2 is unaffected.
+##
+void draw(SkCanvas* canvas) {
+ SkPath* path = new SkPath();
+ path->lineTo(20, 20);
+ SkPath path2(*path);
+ delete path;
+ SkDebugf("path2 is " "%s" "empty", path2.isEmpty() ? "" : "not ");
+}
+##
+
+#SeeAlso SkPath() SkPath(const SkPath& path) operator=(const SkPath& path)
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method SkPath& operator=(const SkPath& path)
+
+Path assignment makes two paths identical by value. Internally, assignment
+shares pointer values. The underlying Verb_Array, Point_Array and Weights
+are copied when modified.
+
+Copying Paths by assignment is very efficient and never allocates memory.
+Paths are always copied by value from the interface; the underlying shared
+pointers are not exposed.
+
+#Param path Verb_Array, Point_Array, Weights, amd Fill_Type to copy ##
+
+#Return Path copied by value ##
+
+#Example
+SkPath path1;
+path1.addRect({10, 20, 30, 40});
+SkPath path2 = path1;
+const SkRect& b1 = path1.getBounds();
+SkDebugf("path1 bounds = %g, %g, %g, %g\n", b1.fLeft, b1.fTop, b1.fRight, b1.fBottom);
+const SkRect& b2 = path2.getBounds();
+SkDebugf("path2 bounds = %g, %g, %g, %g\n", b2.fLeft, b2.fTop, b2.fRight, b2.fBottom);
+#StdOut
+path1 bounds = 10, 20, 30, 40
+path2 bounds = 10, 20, 30, 40
+#StdOut ##
+##
+
+#SeeAlso swap() SkPath(const SkPath& path)
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method bool operator==(const SkPath& a, const SkPath& b)
+
+Compares a and b; returns true if Fill_Type, Verb_Array, Point_Array, and Weights
+are equivalent.
+
+#Param a Path to compare ##
+#Param b Path to compare ##
+
+#Return true if Path pair are equivalent ##
+
+#Example
+#Description
+Rewind removes Verb_Array but leaves storage; since storage is not compared,
+Path pair are equivalent.
+##
+void draw(SkCanvas* canvas) {
+ auto debugster = [](const char* prefix, const SkPath& a, const SkPath& b) -> void {
+ SkDebugf("%s one %c= two\n", prefix, a == b ? '=' : '!');
+ };
+ SkPath one;
+ SkPath two;
+ debugster("empty", one, two);
+ one.moveTo(0, 0);
+ debugster("moveTo", one, two);
+ one.rewind();
+ debugster("rewind", one, two);
+ one.moveTo(0, 0);
+ one.reset();
+ debugster("reset", one, two);
+}
+#StdOut
+empty one == two
+moveTo one != two
+rewind one == two
+reset one == two
+##
+##
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method bool operator!=(const SkPath& a, const SkPath& b)
+
+Compares a and b; returns true if Fill_Type, Verb_Array, Point_Array, and Weights
+are not equivalent.
+
+#Param a Path to compare ##
+#Param b Path to compare ##
+
+#Return true if Path pair are not equivalent ##
+
+#Example
+#Description
+Path pair are equal though their convexity is not equal.
+##
+void draw(SkCanvas* canvas) {
+ auto debugster = [](const char* prefix, const SkPath& a, const SkPath& b) -> void {
+ SkDebugf("%s one %c= two\n", prefix, a != b ? '!' : '=');
+ };
+ SkPath one;
+ SkPath two;
+ debugster("empty", one, two);
+ one.addRect({10, 20, 30, 40});
+ two.addRect({10, 20, 30, 40});
+ debugster("addRect", one, two);
+ one.setConvexity(SkPath::kConcave_Convexity);
+ debugster("setConvexity", one, two);
+ SkDebugf("convexity %c=\n", one.getConvexity() == two.getConvexity() ? '=' : '!');
+}
+#StdOut
+empty one == two
+addRect one == two
+setConvexity one == two
+convexity !=
+##
+##
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method bool isInterpolatable(const SkPath& compare) const
+
+Return true if Paths contain equal Verbs and equal Weights.
+If Paths contain one or more Conics, the Weights must match.
+
+conicTo may add different Verbs depending on Conic_Weight, so it is not
+trival to interpolate a pair of Paths containing Conics with different
+Conic_Weight values.
+
+#Param compare Path to compare ##
+
+#Return true if Paths Verb_Array and Weights are equivalent ##
+
+#Example
+ SkPath path, path2;
+ path.moveTo(20, 20);
+ path.lineTo(40, 40);
+ path.lineTo(20, 20);
+ path.lineTo(40, 40);
+ path.close();
+ path2.addRect({20, 20, 40, 40});
+ SkDebugf("paths are " "%s" "interpolatable", path.isInterpolatable(path2) ? "" : "not ");
+#StdOut
+paths are interpolatable
+##
+##
+
+#SeeAlso isInterpolatable
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method bool interpolate(const SkPath& ending, SkScalar weight, SkPath* out) const
+
+Interpolate between Paths with equal sized Point_Arrays.
+Copy Verb_Array and Weights to out,
+and set out Point_Array to a weighted average of this Point_Array and ending
+Point_Array, using the formula:
+#Formula
+(this->points * weight) + ending->points * (1 - weight)
+##
+
+weight is most useful when between zero (ending Point_Array) and
+one (this Point_Array); will work with values outside of this
+range.
+
+interpolate() returns false and leaves out unchanged if Point_Array is not
+the same size as ending Point_Array. Call isInterpolatable to check Path
+compatibility prior to calling interpolate().
+
+#Param ending Point_Array averaged with this Point_Array ##
+#Param weight contribution of ending Point_Array, and
+ one minus contribution of this Point_Array
+##
+#Param out Path replaced by interpolated averages ##
+
+#Return true if Paths contain same number of Points ##
+
+#Example
+#Height 60
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ SkPath path, path2;
+ path.moveTo(20, 20);
+ path.lineTo(40, 40);
+ path.lineTo(20, 40);
+ path.lineTo(40, 20);
+ path.close();
+ path2.addRect({20, 20, 40, 40});
+ for (SkScalar i = 0; i <= 1; i += 1.f / 6) {
+ SkPath interp;
+ path.interpolate(path2, i, &interp);
+ canvas->drawPath(interp, paint);
+ canvas->translate(30, 0);
+ }
+}
+##
+
+#SeeAlso isInterpolatable
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method bool unique() const
+
+#Private
+To be deprecated; only valid for Android framework.
+##
+
+#Return true if Path has one owner ##
+
+##
+
+# ------------------------------------------------------------------------------
#Subtopic Fill_Type
-#Enum FillType
-
-#Code
- enum FillType {
- kWinding_FillType
- kEvenOdd_FillType
- kInverseWinding_FillType
- kInverseEvenOdd_FillType
- };
-##
+#Enum FillType
+
+#Code
+ enum FillType {
+ kWinding_FillType,
+ kEvenOdd_FillType,
+ kInverseWinding_FillType,
+ kInverseEvenOdd_FillType,
+ };
+##
Fill_Type selects the rule used to fill Path. Path set to kWinding_FillType
fills if the sum of Contour edges is not zero, where clockwise edges add one, and
@@ -808,923 +829,930 @@ one counterclockwise rectangle. The even-odd variants draw the same. The
winding variants draw the top rectangle overlap, which has a winding of 2, the
same as the outer parts of the top rectangles, which have a winding of 1.
##
-void draw(SkCanvas* canvas) {
- SkPath path;
- path.addRect({10, 10, 30, 30}, SkPath::kCW_Direction);
- path.addRect({20, 20, 40, 40}, SkPath::kCW_Direction);
- path.addRect({10, 60, 30, 80}, SkPath::kCW_Direction);
- path.addRect({20, 70, 40, 90}, SkPath::kCCW_Direction);
- SkPaint strokePaint;
- strokePaint.setStyle(SkPaint::kStroke_Style);
- SkRect clipRect = {0, 0, 51, 100};
- canvas->drawPath(path, strokePaint);
- SkPaint fillPaint;
- for (auto fillType : { SkPath::kWinding_FillType, SkPath::kEvenOdd_FillType,
- SkPath::kInverseWinding_FillType, SkPath::kInverseEvenOdd_FillType } ) {
- canvas->translate(51, 0);
- canvas->save();
- canvas->clipRect(clipRect);
- path.setFillType(fillType);
- canvas->drawPath(path, fillPaint);
- canvas->restore();
- }
+void draw(SkCanvas* canvas) {
+ SkPath path;
+ path.addRect({10, 10, 30, 30}, SkPath::kCW_Direction);
+ path.addRect({20, 20, 40, 40}, SkPath::kCW_Direction);
+ path.addRect({10, 60, 30, 80}, SkPath::kCW_Direction);
+ path.addRect({20, 70, 40, 90}, SkPath::kCCW_Direction);
+ SkPaint strokePaint;
+ strokePaint.setStyle(SkPaint::kStroke_Style);
+ SkRect clipRect = {0, 0, 51, 100};
+ canvas->drawPath(path, strokePaint);
+ SkPaint fillPaint;
+ for (auto fillType : { SkPath::kWinding_FillType, SkPath::kEvenOdd_FillType,
+ SkPath::kInverseWinding_FillType, SkPath::kInverseEvenOdd_FillType } ) {
+ canvas->translate(51, 0);
+ canvas->save();
+ canvas->clipRect(clipRect);
+ path.setFillType(fillType);
+ canvas->drawPath(path, fillPaint);
+ canvas->restore();
+ }
}
##
-
-#Const kWinding_FillType
-Specifies fill as area is enclosed by a non-zero sum of Contour Directions.
-##
-#Const kEvenOdd_FillType
-Specifies fill as area enclosed by an odd number of Contours.
-##
-#Const kInverseWinding_FillType
-Specifies fill as area is enclosed by a zero sum of Contour Directions.
-##
-#Const kInverseEvenOdd_FillType
-Specifies fill as area enclosed by an even number of Contours.
-##
-
-#Example
-#Height 230
-void draw(SkCanvas* canvas) {
- SkPath path;
- path.addRect({20, 10, 80, 70}, SkPath::kCW_Direction);
- path.addRect({40, 30, 100, 90}, SkPath::kCW_Direction);
- SkPaint strokePaint;
- strokePaint.setStyle(SkPaint::kStroke_Style);
- SkRect clipRect = {0, 0, 128, 128};
- canvas->drawPath(path, strokePaint);
- canvas->drawLine({0, 50}, {120, 50}, strokePaint);
- SkPaint textPaint;
- textPaint.setAntiAlias(true);
- textPaint.setTextAlign(SkPaint::kCenter_Align);
- SkScalar textHPos[] = { 10, 30, 60, 90, 110 };
- canvas->drawPosTextH("01210", 5, textHPos, 48, textPaint);
- textPaint.setTextSize(18);
- canvas->translate(0, 128);
- canvas->scale(.5f, .5f);
- canvas->drawString("inverse", 384, 150, textPaint);
- SkPaint fillPaint;
- for (auto fillType : { SkPath::kWinding_FillType, SkPath::kEvenOdd_FillType,
- SkPath::kInverseWinding_FillType, SkPath::kInverseEvenOdd_FillType } ) {
- canvas->save();
- canvas->clipRect(clipRect);
- path.setFillType(fillType);
- canvas->drawPath(path, fillPaint);
- canvas->restore();
- canvas->drawString(fillType & 1 ? "even-odd" : "winding", 64, 170, textPaint);
- canvas->translate(128, 0);
- }
-}
-##
-
-#SeeAlso SkPaint::Style Direction getFillType setFillType
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method FillType getFillType() const
-
-Returns FillType, the rule used to fill Path. FillType of a new Path is
-kWinding_FillType.
-
-#Return one of: kWinding_FillType, kEvenOdd_FillType, kInverseWinding_FillType,
-kInverseEvenOdd_FillType.
-##
-
-#Example
- SkPath path;
- SkDebugf("default path fill type is %s\n",
- path.getFillType() == SkPath::kWinding_FillType ? "kWinding_FillType" :
- path.getFillType() == SkPath::kEvenOdd_FillType ? "kEvenOdd_FillType" :
- path.getFillType() == SkPath::kInverseWinding_FillType ? "kInverseWinding_FillType" :
- "kInverseEvenOdd_FillType");
-#StdOut
-default path fill type is kWinding_FillType
-##
-##
-
-#SeeAlso FillType setFillType isInverseFillType
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void setFillType(FillType ft)
-
-Sets FillType, the rule used to fill Path. While setFillType does not check
-that ft is legal, values outside of FillType are not supported.
-
-#Param ft one of: kWinding_FillType, kEvenOdd_FillType, kInverseWinding_FillType,
-kInverseEvenOdd_FillType.
-##
-
-#Example
-#Description
-If empty Path is set to inverse FillType, it fills all pixels.
-##
-#Height 64
- SkPath path;
- path.setFillType(SkPath::kInverseWinding_FillType);
- SkPaint paint;
- paint.setColor(SK_ColorBLUE);
- canvas->drawPath(path, paint);
-##
-
-#SeeAlso FillType getFillType toggleInverseFillType
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method bool isInverseFillType() const
-
-Returns if FillType describes area outside Path geometry. The inverse fill area
-extends indefinitely.
-
-#Return true if FillType is kInverseWinding_FillType or kInverseEvenOdd_FillType. ##
-
-#Example
- SkPath path;
- SkDebugf("default path fill type is inverse: %s\n",
- path.isInverseFillType() ? "true" : "false");
-#StdOut
-default path fill type is inverse: false
-##
-##
-
-#SeeAlso FillType getFillType setFillType toggleInverseFillType
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void toggleInverseFillType()
-
-Replace FillType with its inverse. The inverse of FillType describes the area
-unmodified by the original FillType.
-
-#Table
-#Legend
-# FillType # toggled FillType ##
-##
-# kWinding_FillType # kInverseWinding_FillType ##
-# kEvenOdd_FillType # kInverseEvenOdd_FillType ##
-# kInverseWinding_FillType # kWinding_FillType ##
-# kInverseEvenOdd_FillType # kEvenOdd_FillType ##
-##
-
-#Example
-#Description
-Path drawn normally and through its inverse touches every pixel once.
-##
-#Height 100
-SkPath path;
-SkPaint paint;
-paint.setColor(SK_ColorRED);
+
+#Const kWinding_FillType 0
+Specifies fill as area is enclosed by a non-zero sum of Contour Directions.
+##
+#Const kEvenOdd_FillType 1
+Specifies fill as area enclosed by an odd number of Contours.
+##
+#Const kInverseWinding_FillType 2
+Specifies fill as area is enclosed by a zero sum of Contour Directions.
+##
+#Const kInverseEvenOdd_FillType 3
+Specifies fill as area enclosed by an even number of Contours.
+##
+
+#Example
+#Height 230
+void draw(SkCanvas* canvas) {
+ SkPath path;
+ path.addRect({20, 10, 80, 70}, SkPath::kCW_Direction);
+ path.addRect({40, 30, 100, 90}, SkPath::kCW_Direction);
+ SkPaint strokePaint;
+ strokePaint.setStyle(SkPaint::kStroke_Style);
+ SkRect clipRect = {0, 0, 128, 128};
+ canvas->drawPath(path, strokePaint);
+ canvas->drawLine({0, 50}, {120, 50}, strokePaint);
+ SkPaint textPaint;
+ textPaint.setAntiAlias(true);
+ textPaint.setTextAlign(SkPaint::kCenter_Align);
+ SkScalar textHPos[] = { 10, 30, 60, 90, 110 };
+ canvas->drawPosTextH("01210", 5, textHPos, 48, textPaint);
+ textPaint.setTextSize(18);
+ canvas->translate(0, 128);
+ canvas->scale(.5f, .5f);
+ canvas->drawString("inverse", 384, 150, textPaint);
+ SkPaint fillPaint;
+ for (auto fillType : { SkPath::kWinding_FillType, SkPath::kEvenOdd_FillType,
+ SkPath::kInverseWinding_FillType, SkPath::kInverseEvenOdd_FillType } ) {
+ canvas->save();
+ canvas->clipRect(clipRect);
+ path.setFillType(fillType);
+ canvas->drawPath(path, fillPaint);
+ canvas->restore();
+ canvas->drawString(fillType & 1 ? "even-odd" : "winding", 64, 170, textPaint);
+ canvas->translate(128, 0);
+ }
+}
+##
+
+#SeeAlso SkPaint::Style Direction getFillType setFillType
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method FillType getFillType() const
+
+Returns FillType, the rule used to fill Path. FillType of a new Path is
+kWinding_FillType.
+
+#Return one of: kWinding_FillType, kEvenOdd_FillType, kInverseWinding_FillType,
+kInverseEvenOdd_FillType
+##
+
+#Example
+ SkPath path;
+ SkDebugf("default path fill type is %s\n",
+ path.getFillType() == SkPath::kWinding_FillType ? "kWinding_FillType" :
+ path.getFillType() == SkPath::kEvenOdd_FillType ? "kEvenOdd_FillType" :
+ path.getFillType() == SkPath::kInverseWinding_FillType ? "kInverseWinding_FillType" :
+ "kInverseEvenOdd_FillType");
+#StdOut
+default path fill type is kWinding_FillType
+##
+##
+
+#SeeAlso FillType setFillType isInverseFillType
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void setFillType(FillType ft)
+
+Sets FillType, the rule used to fill Path. While there is no check
+that ft is legal, values outside of FillType are not supported.
+
+#Param ft one of: kWinding_FillType, kEvenOdd_FillType, kInverseWinding_FillType,
+kInverseEvenOdd_FillType
+##
+
+#Example
+#Description
+If empty Path is set to inverse FillType, it fills all pixels.
+##
+#Height 64
+ SkPath path;
+ path.setFillType(SkPath::kInverseWinding_FillType);
+ SkPaint paint;
+ paint.setColor(SK_ColorBLUE);
+ canvas->drawPath(path, paint);
+##
+
+#SeeAlso FillType getFillType toggleInverseFillType
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method bool isInverseFillType() const
+
+Returns if FillType describes area outside Path geometry. The inverse fill area
+extends indefinitely.
+
+#Return true if FillType is kInverseWinding_FillType or kInverseEvenOdd_FillType ##
+
+#Example
+ SkPath path;
+ SkDebugf("default path fill type is inverse: %s\n",
+ path.isInverseFillType() ? "true" : "false");
+#StdOut
+default path fill type is inverse: false
+##
+##
+
+#SeeAlso FillType getFillType setFillType toggleInverseFillType
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void toggleInverseFillType()
+
+Replace FillType with its inverse. The inverse of FillType describes the area
+unmodified by the original FillType.
+
+#Table
+#Legend
+# FillType # toggled FillType ##
+##
+# kWinding_FillType # kInverseWinding_FillType ##
+# kEvenOdd_FillType # kInverseEvenOdd_FillType ##
+# kInverseWinding_FillType # kWinding_FillType ##
+# kInverseEvenOdd_FillType # kEvenOdd_FillType ##
+##
+
+#Example
+#Description
+Path drawn normally and through its inverse touches every pixel once.
+##
+#Height 100
+SkPath path;
+SkPaint paint;
+paint.setColor(SK_ColorRED);
paint.setTextSize(80);
paint.getTextPath("ABC", 3, 20, 80, &path);
-canvas->drawPath(path, paint);
-path.toggleInverseFillType();
-paint.setColor(SK_ColorGREEN);
-canvas->drawPath(path, paint);
-##
-
-#SeeAlso FillType getFillType setFillType isInverseFillType
-
-##
-
+canvas->drawPath(path, paint);
+path.toggleInverseFillType();
+paint.setColor(SK_ColorGREEN);
+canvas->drawPath(path, paint);
+##
+
+#SeeAlso FillType getFillType setFillType isInverseFillType
+
+##
+
#Subtopic Fill_Type ##
-
-# ------------------------------------------------------------------------------
+
+# ------------------------------------------------------------------------------
#Subtopic Convexity
-
-#Enum Convexity
-
-#Code
- enum Convexity {
- kUnknown_Convexity,
- kConvex_Convexity,
- kConcave_Convexity
- };
-##
-
+
+#Enum Convexity
+
+#Code
+ enum Convexity {
+ kUnknown_Convexity,
+ kConvex_Convexity,
+ kConcave_Convexity,
+ };
+##
+
Path is convex if it contains one Contour and Contour loops no more than
360 degrees, and Contour angles all have same Direction. Convex Path
may have better performance and require fewer resources on GPU_Surface.
-Path 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 Path Convexity is kUnknown_Convexity. Path Convexity is computed
-if needed by destination Surface.
-
-#Const kUnknown_Convexity
- Indicates Convexity has not been determined.
-##
-#Const kConvex_Convexity
- Path has one Contour made of a simple geometry without indentations.
-##
-#Const kConcave_Convexity
- Path has more than one Contour, or a geometry with indentations.
-##
-
-#Example
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- SkPoint quad[] = {{70, 70}, {20, 20}, {120, 20}, {120, 120}};
- const char* labels[] = { "unknown", "convex", "concave" };
- for (SkScalar x : { 40, 100 } ) {
- SkPath path;
- quad[0].fX = x;
- path.addPoly(quad, SK_ARRAY_COUNT(quad), true);
- canvas->drawPath(path, paint);
- canvas->drawString(labels[(int) path.getConvexity()], 30, 100, paint);
- canvas->translate(100, 100);
- }
-}
-##
-
-#SeeAlso Contour Direction getConvexity getConvexityOrUnknown setConvexity isConvex
-
-#Enum Convexity ##
-
-#Method Convexity getConvexity() const
-
-Computes Convexity if required, and returns stored value.
-Convexity is computed if stored value is kUnknown_Convexity,
-or if Path has been altered since Convexity was computed or set.
-
-#Return Computed or stored Convexity. ##
-
-#Example
-void draw(SkCanvas* canvas) {
- auto debugster = [](const char* prefix, const SkPath& path) -> void {
- SkDebugf("%s path convexity is %s\n", prefix,
- SkPath::kUnknown_Convexity == path.getConvexity() ? "unknown" :
- SkPath::kConvex_Convexity == path.getConvexity() ? "convex" : "concave"); };
- SkPath path;
- debugster("initial", path);
- path.lineTo(50, 0);
- debugster("first line", path);
- path.lineTo(50, 50);
- debugster("second line", path);
- path.lineTo(100, 50);
- debugster("third line", path);
-}
-##
-
-#SeeAlso Convexity Contour Direction getConvexityOrUnknown setConvexity isConvex
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method Convexity getConvexityOrUnknown() const
-
-Returns last computed Convexity, or kUnknown_Convexity if
-Path has been altered since Convexity was computed or set.
-
-#Return Stored Convexity. ##
-
-#Example
-#Description
-Convexity is unknown unless getConvexity is called without a subsequent call
-that alters the path.
-##
-void draw(SkCanvas* canvas) {
- auto debugster = [](const char* prefix, const SkPath& path) -> void {
- SkDebugf("%s path convexity is %s\n", prefix,
- SkPath::kUnknown_Convexity == path.getConvexityOrUnknown() ? "unknown" :
- SkPath::kConvex_Convexity == path.getConvexityOrUnknown() ? "convex" : "concave"); };
- SkPath path;
- debugster("initial", path);
- path.lineTo(50, 0);
- debugster("first line", path);
- path.getConvexity();
- path.lineTo(50, 50);
- debugster("second line", path);
- path.lineTo(100, 50);
- path.getConvexity();
- debugster("third line", path);
-}
-##
-
-#SeeAlso Convexity Contour Direction getConvexity setConvexity isConvex
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void setConvexity(Convexity 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 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. ##
-
-#Example
-void draw(SkCanvas* canvas) {
- auto debugster = [](const char* prefix, const SkPath& path) -> void {
- SkDebugf("%s path convexity is %s\n", prefix,
- SkPath::kUnknown_Convexity == path.getConvexity() ? "unknown" :
- SkPath::kConvex_Convexity == path.getConvexity() ? "convex" : "concave"); };
- SkPoint quad[] = {{70, 70}, {20, 20}, {120, 20}, {120, 120}};
- SkPath path;
- path.addPoly(quad, SK_ARRAY_COUNT(quad), true);
- debugster("initial", path);
- path.setConvexity(SkPath::kConcave_Convexity);
- debugster("after forcing concave", path);
- path.setConvexity(SkPath::kUnknown_Convexity);
- debugster("after forcing unknown", path);
-}
-##
-
-#SeeAlso Convexity Contour Direction getConvexity getConvexityOrUnknown isConvex
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method bool isConvex() const
-
-Computes 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, Convexity is not recomputed.
-
-#Return true if Convexity stored or computed is kConvex_Convexity. ##
-
-#Example
-#Description
-Concave shape is erroneously considered convex after a forced call to
-setConvexity.
-##
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- SkPoint quad[] = {{70, 70}, {20, 20}, {120, 20}, {120, 120}};
- for (SkScalar x : { 40, 100 } ) {
- SkPath path;
- quad[0].fX = x;
- path.addPoly(quad, SK_ARRAY_COUNT(quad), true);
- path.setConvexity(SkPath::kConvex_Convexity);
- canvas->drawPath(path, paint);
- canvas->drawString(path.isConvex() ? "convex" : "not convex", 30, 100, paint);
- canvas->translate(100, 100);
- }
-}
-##
-
-#SeeAlso Convexity Contour Direction getConvexity getConvexityOrUnknown setConvexity
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void setIsConvex(bool isConvex)
-
-#Deprecated
-Use setConvexity.
-##
-
-##
-
-#Subtopic Convexity ##
-
-# ------------------------------------------------------------------------------
-
-#Method bool isOval(SkRect* rect, Direction* dir = nullptr,
- unsigned* start = nullptr) const
-
-Path is Oval if constructed by addCircle, addOval; and in some cases,
-addRoundRect, addRRect. Path constructed with conicTo or rConicTo will not
-return true though Path draws Oval.
-
-isOval triggers performance optimizations on some GPU_Surface implementations.
-
-#Param rect storage for bounding Rect of Oval. Oval is Circle if rect width
-equals rect height. Unwritten if Path is not Oval. May be nullptr.
-##
-#Param dir storage for Direction; kCW_Direction if clockwise, kCCW_Direction if
-counterclockwise. Unwritten if Path is not Oval. May be nullptr.
-##
-#Param start storage for start of Oval: 0 for top,
-1 for right, 2 for bottom, 3 for left. Unwritten if Path is not Oval. May be nullptr.
-##
-
-#Return true if Path was constructed by method that reduces to Oval. ##
-
-#Example
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- SkPath path;
- path.addOval({20, 20, 220, 220}, SkPath::kCW_Direction, 1);
- SkRect bounds;
- SkPath::Direction direction;
- unsigned start;
- path.isOval(&bounds, &direction, &start);
- paint.setColor(0xFF9FBFFF);
- canvas->drawRect(bounds, paint);
- paint.setColor(0x3f000000);
- canvas->drawPath(path, paint);
- paint.setColor(SK_ColorBLACK);
- canvas->rotate(start * 90, bounds.centerX(), bounds.centerY());
- char startText = '0' + start;
- paint.setTextSize(20);
- canvas->drawText(&startText, 1, bounds.centerX(), bounds.fTop + 20, paint);
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setStrokeWidth(4);
- path.reset();
- path.addArc(bounds, -90, SkPath::kCW_Direction == direction ? 90 : -90);
- path.rLineTo(20, -20);
- canvas->drawPath(path, paint);
-}
-##
-
-#SeeAlso Oval addCircle addOval
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method bool isRRect(SkRRect* rrect, Direction* dir = nullptr,
- unsigned* start = nullptr) const
-
-Path is Round_Rect if constructed by addRoundRect, addRRect; and if construction
-is not empty, not Rect, and not Oval. Path constructed with other other calls
-will not return true though Path draws Round_Rect.
-
-isRRect triggers performance optimizations on some GPU_Surface implementations.
-
-#Param rrect storage for bounding Rect of Round_Rect.
-Unwritten if Path is not Round_Rect. May be nullptr.
-##
-#Param dir storage for Direction; kCW_Direction if clockwise, kCCW_Direction if
-counterclockwise. Unwritten if Path is not Round_Rect. May be nullptr.
-##
-#Param start storage for start of Round_Rect: 0 for top,
-1 for right, 2 for bottom, 3 for left. Unwritten if Path is not Round_Rect. May be nullptr.
-##
-
-#Return true for Round_Rect Path constructed by addRoundRect or addRRect. ##
-
-#Example
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- SkPath path;
- path.addRRect(SkRRect::MakeRectXY({20, 20, 220, 220}, 30, 50), SkPath::kCCW_Direction, 3);
- SkRRect rrect;
- SkPath::Direction direction;
- unsigned start;
- path.isRRect(&rrect, &direction, &start);
- const SkRect& bounds = rrect.rect();
- paint.setColor(0xFF9FBFFF);
- canvas->drawRect(bounds, paint);
- paint.setColor(0x3f000000);
- canvas->drawPath(path, paint);
- paint.setColor(SK_ColorBLACK);
- canvas->rotate(start * 90, bounds.centerX(), bounds.centerY());
- char startText = '0' + start;
- paint.setTextSize(20);
- canvas->drawText(&startText, 1, bounds.centerX(), bounds.fTop + 20, paint);
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setStrokeWidth(4);
- path.reset();
- path.addArc(bounds, -90, SkPath::kCW_Direction == direction ? 90 : -90);
- path.rLineTo(20, -20);
- canvas->drawPath(path, paint);
-}
-##
-
-#SeeAlso Round_Rect addRoundRect addRRect
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void reset()
-
-Sets Path to its intial state.
-Removes Verb_Array, Point_Array, and Weights, and sets FillType to kWinding_FillType.
-Internal storage associated with Path is released.
-
-#Example
- SkPath path1, path2;
- path1.setFillType(SkPath::kInverseWinding_FillType);
- path1.addRect({10, 20, 30, 40});
- SkDebugf("path1 %c= path2\n", path1 == path2 ? '=' : '!');
- path1.reset();
- SkDebugf("path1 %c= path2\n", path1 == path2 ? '=' : '!');
-##
-
-#SeeAlso rewind()
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void rewind()
-
-Sets Path to its intial state, preserving internal storage.
-Removes Verb_Array, Point_Array, and Weights, and sets FillType to kWinding_FillType.
-Internal storage associated with Path is retained.
-
-Use rewind() instead of reset() if Path storage will be reused and performance
-is critical.
-
-#Example
-#Description
-Although path1 retains its internal storage, it is indistinguishable from
-a newly initialized path.
-##
- SkPath path1, path2;
- path1.setFillType(SkPath::kInverseWinding_FillType);
- path1.addRect({10, 20, 30, 40});
- SkDebugf("path1 %c= path2\n", path1 == path2 ? '=' : '!');
- path1.rewind();
- SkDebugf("path1 %c= path2\n", path1 == path2 ? '=' : '!');
-##
-
-#SeeAlso reset()
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method bool isEmpty() const
-
-Empty Path may have FillType but has no SkPoint, Verb, or Conic_Weight.
-SkPath() constructs empty Path; reset() and (rewind) make Path empty.
-
-#Return true if the path contains no Verb array. ##
-
-#Example
-void draw(SkCanvas* canvas) {
- auto debugster = [](const char* prefix, const SkPath& path) -> void {
- SkDebugf("%s path is %s" "empty\n", prefix, path.isEmpty() ? "" : "not ");
- };
- SkPath path;
- debugster("initial", path);
- path.moveTo(0, 0);
- debugster("after moveTo", path);
- path.rewind();
- debugster("after rewind", path);
- path.lineTo(0, 0);
- debugster("after lineTo", path);
- path.reset();
- debugster("after reset", path);
-}
-#StdOut
-initial path is empty
-after moveTo path is not empty
-after rewind path is empty
-after lineTo path is not empty
-after reset path is empty
-##
-##
-
-#SeeAlso SkPath() reset() rewind()
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method bool isLastContourClosed() const
-
-Contour is closed if Path Verb array was last modified by close(). When stroked,
-closed Contour draws Paint_Stroke_Join instead of Paint_Stroke_Cap at first and last Point.
-
-#Return true if the last Contour ends with a kClose_Verb. ##
-
-#Example
-#Description
-close() has no effect if Path is empty; isLastContourClosed() returns
-false until Path has geometry followed by close().
-##
-void draw(SkCanvas* canvas) {
- auto debugster = [](const char* prefix, const SkPath& path) -> void {
- SkDebugf("%s last contour is %s" "closed\n", prefix,
- path.isLastContourClosed() ? "" : "not ");
- };
- SkPath path;
- debugster("initial", path);
- path.close();
- debugster("after close", path);
- path.lineTo(0, 0);
- debugster("after lineTo", path);
- path.close();
- debugster("after close", path);
-}
-#StdOut
-initial last contour is not closed
-after close last contour is not closed
-after lineTo last contour is not closed
-after close last contour is closed
-##
-##
-
-#SeeAlso close()
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method bool isFinite() const
-
-Finite Point array values are between negative SK_ScalarMax and
-positive SK_ScalarMax. Any Point array value of
-SK_ScalarInfinity, SK_ScalarNegativeInfinity, or SK_ScalarNaN
-cause isFinite to return false.
-
-#Return true if all Point values are finite. ##
-
-#Example
-void draw(SkCanvas* canvas) {
- auto debugster = [](const char* prefix, const SkPath& path) -> void {
- SkDebugf("%s path is %s" "finite\n", prefix, path.isFinite() ? "" : "not ");
- };
- SkPath path;
- debugster("initial", path);
- path.lineTo(SK_ScalarMax, SK_ScalarMax);
- debugster("after line", path);
- SkMatrix matrix;
- matrix.setScale(2, 2);
- path.transform(matrix);
- debugster("after scale", path);
-}
-#StdOut
-initial path is finite
-after line path is finite
-after scale path is not finite
-##
-##
-
-#SeeAlso SkScalar
-##
-
-# ------------------------------------------------------------------------------
-
-#Method bool isVolatile() const
-
-Returns true if the path is volatile; it will not be altered or discarded
-by the caller after it is drawn. Paths by default have volatile set false, allowing
-Surface to attach a cache of data which speeds repeated drawing. If true, Surface
-may not speed repeated drawing.
-
-#Return true if caller will alter Path after drawing. ##
-
-#Example
- SkPath path;
- SkDebugf("volatile by default is %s\n", path.isVolatile() ? "true" : "false");
-#StdOut
-volatile by default is false
-##
-##
-
-#SeeAlso setIsVolatile
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void setIsVolatile(bool isVolatile)
-
-Specify whether Path is volatile; whether it will be altered or discarded
-by the caller after it is drawn. Paths by default have volatile set false, allowing
-Device to attach a cache of data which speeds repeated drawing.
-
-Mark temporary paths, discarded or modified after use, as volatile
-to inform Device that the path need not be cached.
-
-Mark animating Path volatile to improve performance.
-Mark unchanging Path non-volative to improve repeated rendering.
-
-Raster_Surface Path draws are affected by volatile for some shadows.
-GPU_Surface Path draws are affected by volatile for some shadows and concave geometries.
-
-#Param isVolatile true if caller will alter Path after drawing. ##
-
-#Example
-#Height 50
-#Width 50
- SkPaint paint;
- paint.setStyle(SkPaint::kStroke_Style);
- SkPath path;
- path.setIsVolatile(true);
- path.lineTo(40, 40);
- canvas->drawPath(path, paint);
- path.rewind();
- path.moveTo(0, 40);
- path.lineTo(40, 0);
- canvas->drawPath(path, paint);
-##
-
-#ToDo tie example to bench to show how volatile affects speed or dm to show resource usage ##
-
-#SeeAlso isVolatile
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method static bool IsLineDegenerate(const SkPoint& p1, const SkPoint& p2, bool exact)
-
-Test if Line between Point pair is degenerate.
-Line with no length or that moves a very short distance is degenerate; it is
-treated as a point.
-
-#Param p1 Line start point. ##
-#Param p2 Line end point. ##
-#Param exact If true, returns true only if p1 equals p2. If false, returns true
- if p1 equals or nearly equals p2.
-##
-
-#Return true if Line is degenerate; its length is effectively zero. ##
-
-#Example
-#Description
-As single precision floats, 100 and 100.000001f have the same bit representation,
-and are exactly equal. 100 and 100.0001f have different bit representations, and
-are not exactly equal, but are nearly equal.
-##
-void draw(SkCanvas* canvas) {
- SkPoint points[] = { {100, 100}, {100.000001f, 100.000001f}, {100.0001f, 100.0001f} };
- for (size_t i = 0; i < SK_ARRAY_COUNT(points) - 1; ++i) {
- for (bool exact : { false, true } ) {
- SkDebugf("line from (%1.8g,%1.8g) to (%1.8g,%1.8g) is %s" "degenerate, %s\n",
- points[i].fX, points[i].fY, points[i + 1].fX, points[i + 1].fY,
- SkPath::IsLineDegenerate(points[i], points[i + 1], exact)
- ? "" : "not ", exact ? "exactly" : "nearly");
- }
- }
-}
-#StdOut
-line from (100,100) to (100,100) is degenerate, nearly
-line from (100,100) to (100,100) is degenerate, exactly
-line from (100,100) to (100.0001,100.0001) is degenerate, nearly
-line from (100,100) to (100.0001,100.0001) is not degenerate, exactly
-#StdOut ##
-##
-
-#SeeAlso IsQuadDegenerate IsCubicDegenerate SkPoint::equalsWithinTolerance
-##
-
-# ------------------------------------------------------------------------------
-
-#Method static bool IsQuadDegenerate(const SkPoint& p1, const SkPoint& p2,
- const SkPoint& p3, bool exact)
-
-Test if Quad is degenerate.
-Quad with no length or that moves a very short distance is degenerate; it is
-treated as a point.
-
-#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. ##
-
-#Example
-#Description
-As single precision floats: 100, 100.00001f, and 100.00002f have different bit representations
-but nearly the same value. Translating all three by 1000 gives them the same bit representation;
-the fractional portion of the number can't be represented by the float and is lost.
-##
-void draw(SkCanvas* canvas) {
- auto debugster = [](const SkPath& path, bool exact) -> void {
- SkDebugf("quad (%1.8g,%1.8g), (%1.8g,%1.8g), (%1.8g,%1.8g) is %s" "degenerate, %s\n",
- path.getPoint(0).fX, path.getPoint(0).fY, path.getPoint(1).fX,
- path.getPoint(1).fY, path.getPoint(2).fX, path.getPoint(2).fY,
- SkPath::IsQuadDegenerate(path.getPoint(0), path.getPoint(1), path.getPoint(2), exact) ?
- "" : "not ", exact ? "exactly" : "nearly");
- };
- SkPath path, offset;
- path.moveTo({100, 100});
- path.quadTo({100.00001f, 100.00001f}, {100.00002f, 100.00002f});
- offset.addPath(path, 1000, 1000);
- for (bool exact : { false, true } ) {
- debugster(path, exact);
- debugster(offset, exact);
- }
-}
-#StdOut
-quad (100,100), (100.00001,100.00001), (100.00002,100.00002) is degenerate, nearly
-quad (1100,1100), (1100,1100), (1100,1100) is degenerate, nearly
-quad (100,100), (100.00001,100.00001), (100.00002,100.00002) is not degenerate, exactly
-quad (1100,1100), (1100,1100), (1100,1100) is degenerate, exactly
-#StdOut ##
-##
-
-#SeeAlso IsLineDegenerate IsCubicDegenerate SkPoint::equalsWithinTolerance
-##
-
-# ------------------------------------------------------------------------------
-
-#Method static bool IsCubicDegenerate(const SkPoint& p1, const SkPoint& p2,
- const SkPoint& p3, const SkPoint& p4, bool exact)
-
-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. ##
-
-#Example
-void draw(SkCanvas* canvas) {
- SkPoint points[] = {{1, 0}, {0, 0}, {0, 0}, {0, 0}};
- SkScalar step = 1;
- SkScalar prior, length, degenerate;
- do {
- prior = points[0].fX;
- step /= 2;
- if (SkPath::IsCubicDegenerate(points[0], points[1], points[2], points[3], false)) {
- degenerate = prior;
- points[0].fX += step;
- } else {
- length = prior;
- points[0].fX -= step;
- }
- } while (prior != points[0].fX);
- SkDebugf("%1.8g is degenerate\n", degenerate);
- SkDebugf("%1.8g is length\n", length);
-}
-#StdOut
-0.00024414062 is degenerate
-0.00024414065 is length
-#StdOut ##
-##
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method bool isLine(SkPoint line[2]) const
-
-Returns true if Path contains only one Line;
-Path_Verb array has two entries: kMove_Verb, kLine_Verb.
-If Path contains one Line and line is not nullptr, line is set to
-Line start point and Line end point.
-Returns false if Path is not one Line; line is unaltered.
-
-#Param line storage for Line. May be nullptr. ##
-
-#Return true if Path contains exactly one Line. ##
-
-#Example
-void draw(SkCanvas* canvas) {
- auto debugster = [](const char* prefix, const SkPath& path) -> void {
- SkPoint line[2];
- if (path.isLine(line)) {
- SkDebugf("%s is line (%1.8g,%1.8g) (%1.8g,%1.8g)\n", prefix,
- line[0].fX, line[0].fY, line[1].fX, line[1].fY);
- } else {
- SkDebugf("%s is not line\n", prefix);
- }
- };
- SkPath path;
- debugster("empty", path);
- path.lineTo(0, 0);
- debugster("zero line", path);
- path.rewind();
- path.moveTo(10, 10);
- path.lineTo(20, 20);
- debugster("line", path);
- path.moveTo(20, 20);
- debugster("second move", path);
-}
-#StdOut
-empty is not line
-zero line is line (0,0) (0,0)
-line is line (10,10) (20,20)
-second move is not line
-##
-##
-
-##
-
-# ------------------------------------------------------------------------------
-
+Path 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 Path Convexity is kUnknown_Convexity. Path Convexity is computed
+if needed by destination Surface.
+
+#Const kUnknown_Convexity 0
+ Indicates Convexity has not been determined.
+##
+#Const kConvex_Convexity 1
+ Path has one Contour made of a simple geometry without indentations.
+##
+#Const kConcave_Convexity 2
+ Path has more than one Contour, or a geometry with indentations.
+##
+
+#Example
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ SkPoint quad[] = {{70, 70}, {20, 20}, {120, 20}, {120, 120}};
+ const char* labels[] = { "unknown", "convex", "concave" };
+ for (SkScalar x : { 40, 100 } ) {
+ SkPath path;
+ quad[0].fX = x;
+ path.addPoly(quad, SK_ARRAY_COUNT(quad), true);
+ canvas->drawPath(path, paint);
+ canvas->drawString(labels[(int) path.getConvexity()], 30, 100, paint);
+ canvas->translate(100, 100);
+ }
+}
+##
+
+#SeeAlso Contour Direction getConvexity getConvexityOrUnknown setConvexity isConvex
+
+#Enum Convexity ##
+
+#Method Convexity getConvexity() const
+
+Computes Convexity if required, and returns stored value.
+Convexity is computed if stored value is kUnknown_Convexity,
+or if Path has been altered since Convexity was computed or set.
+
+#Return Computed or stored Convexity ##
+
+#Example
+void draw(SkCanvas* canvas) {
+ auto debugster = [](const char* prefix, const SkPath& path) -> void {
+ SkDebugf("%s path convexity is %s\n", prefix,
+ SkPath::kUnknown_Convexity == path.getConvexity() ? "unknown" :
+ SkPath::kConvex_Convexity == path.getConvexity() ? "convex" : "concave"); };
+ SkPath path;
+ debugster("initial", path);
+ path.lineTo(50, 0);
+ debugster("first line", path);
+ path.lineTo(50, 50);
+ debugster("second line", path);
+ path.lineTo(100, 50);
+ debugster("third line", path);
+}
+##
+
+#SeeAlso Convexity Contour Direction getConvexityOrUnknown setConvexity isConvex
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method Convexity getConvexityOrUnknown() const
+
+Returns last computed Convexity, or kUnknown_Convexity if
+Path has been altered since Convexity was computed or set.
+
+#Return Stored Convexity ##
+
+#Example
+#Description
+Convexity is unknown unless getConvexity is called without a subsequent call
+that alters the path.
+##
+void draw(SkCanvas* canvas) {
+ auto debugster = [](const char* prefix, const SkPath& path) -> void {
+ SkDebugf("%s path convexity is %s\n", prefix,
+ SkPath::kUnknown_Convexity == path.getConvexityOrUnknown() ? "unknown" :
+ SkPath::kConvex_Convexity == path.getConvexityOrUnknown() ? "convex" : "concave"); };
+ SkPath path;
+ debugster("initial", path);
+ path.lineTo(50, 0);
+ debugster("first line", path);
+ path.getConvexity();
+ path.lineTo(50, 50);
+ debugster("second line", path);
+ path.lineTo(100, 50);
+ path.getConvexity();
+ debugster("third line", path);
+}
+##
+
+#SeeAlso Convexity Contour Direction getConvexity setConvexity isConvex
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void setConvexity(Convexity 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 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 ##
+
+#Example
+void draw(SkCanvas* canvas) {
+ auto debugster = [](const char* prefix, const SkPath& path) -> void {
+ SkDebugf("%s path convexity is %s\n", prefix,
+ SkPath::kUnknown_Convexity == path.getConvexity() ? "unknown" :
+ SkPath::kConvex_Convexity == path.getConvexity() ? "convex" : "concave"); };
+ SkPoint quad[] = {{70, 70}, {20, 20}, {120, 20}, {120, 120}};
+ SkPath path;
+ path.addPoly(quad, SK_ARRAY_COUNT(quad), true);
+ debugster("initial", path);
+ path.setConvexity(SkPath::kConcave_Convexity);
+ debugster("after forcing concave", path);
+ path.setConvexity(SkPath::kUnknown_Convexity);
+ debugster("after forcing unknown", path);
+}
+##
+
+#SeeAlso Convexity Contour Direction getConvexity getConvexityOrUnknown isConvex
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method bool isConvex() const
+
+Computes 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, Convexity is not recomputed.
+
+#Return true if Convexity stored or computed is kConvex_Convexity ##
+
+#Example
+#Description
+Concave shape is erroneously considered convex after a forced call to
+setConvexity.
+##
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ SkPoint quad[] = {{70, 70}, {20, 20}, {120, 20}, {120, 120}};
+ for (SkScalar x : { 40, 100 } ) {
+ SkPath path;
+ quad[0].fX = x;
+ path.addPoly(quad, SK_ARRAY_COUNT(quad), true);
+ path.setConvexity(SkPath::kConvex_Convexity);
+ canvas->drawPath(path, paint);
+ canvas->drawString(path.isConvex() ? "convex" : "not convex", 30, 100, paint);
+ canvas->translate(100, 100);
+ }
+}
+##
+
+#SeeAlso Convexity Contour Direction getConvexity getConvexityOrUnknown setConvexity
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void setIsConvex(bool isConvex)
+
+Deprecated. Use setConvexity.
+
+#Deprecated
+##
+
+#NoExample
+##
+
+#SeeAlso Convexity setConvexity getConvexity
+
+##
+
+#Subtopic Convexity ##
+
+# ------------------------------------------------------------------------------
+
+#Method bool isOval(SkRect* rect, Direction* dir = nullptr,
+ unsigned* start = nullptr) const
+
+Returns true if constructed by addCircle, addOval; and in some cases,
+addRoundRect, addRRect. Path constructed with conicTo or rConicTo will not
+return true though Path draws Oval.
+
+rect receives bounds of Oval.
+dir receives 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 Rect of Oval; may be nullptr ##
+#Param dir storage for Direction; may be nullptr ##
+#Param start storage for start of Oval; may be nullptr ##
+
+#Return true if Path was constructed by method that reduces to Oval ##
+
+#Example
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ SkPath path;
+ path.addOval({20, 20, 220, 220}, SkPath::kCW_Direction, 1);
+ SkRect bounds;
+ SkPath::Direction direction;
+ unsigned start;
+ path.isOval(&bounds, &direction, &start);
+ paint.setColor(0xFF9FBFFF);
+ canvas->drawRect(bounds, paint);
+ paint.setColor(0x3f000000);
+ canvas->drawPath(path, paint);
+ paint.setColor(SK_ColorBLACK);
+ canvas->rotate(start * 90, bounds.centerX(), bounds.centerY());
+ char startText = '0' + start;
+ paint.setTextSize(20);
+ canvas->drawText(&startText, 1, bounds.centerX(), bounds.fTop + 20, paint);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(4);
+ path.reset();
+ path.addArc(bounds, -90, SkPath::kCW_Direction == direction ? 90 : -90);
+ path.rLineTo(20, -20);
+ canvas->drawPath(path, paint);
+}
+##
+
+#SeeAlso Oval addCircle addOval
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method bool isRRect(SkRRect* rrect, Direction* dir = nullptr,
+ unsigned* start = nullptr) const
+
+Returns true if constructed by addRoundRect, addRRect; and if construction
+is not empty, not Rect, and not Oval. Path constructed with other other calls
+will not return true though Path draws Round_Rect.
+
+rrect receives bounds of Round_Rect.
+dir receives Direction of Oval: kCW_Direction if clockwise, kCCW_Direction if
+counterclockwise.
+start receives start of Round_Rect: 0 for top, 1 for right, 2 for bottom, 3 for left.
+
+rrect, dir, and start are unmodified if Round_Rect is not found.
+
+Triggers performance optimizations on some GPU_Surface implementations.
+
+#Param rrect storage for bounding Rect of Round_Rect; may be nullptr ##
+#Param dir storage for Direction; may be nullptr ##
+#Param start storage for start of Round_Rect; may be nullptr ##
+
+#Return true for Round_Rect Path constructed by addRoundRect or addRRect ##
+
+#Example
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ SkPath path;
+ path.addRRect(SkRRect::MakeRectXY({20, 20, 220, 220}, 30, 50), SkPath::kCCW_Direction, 3);
+ SkRRect rrect;
+ SkPath::Direction direction;
+ unsigned start;
+ path.isRRect(&rrect, &direction, &start);
+ const SkRect& bounds = rrect.rect();
+ paint.setColor(0xFF9FBFFF);
+ canvas->drawRect(bounds, paint);
+ paint.setColor(0x3f000000);
+ canvas->drawPath(path, paint);
+ paint.setColor(SK_ColorBLACK);
+ canvas->rotate(start * 90, bounds.centerX(), bounds.centerY());
+ char startText = '0' + start;
+ paint.setTextSize(20);
+ canvas->drawText(&startText, 1, bounds.centerX(), bounds.fTop + 20, paint);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(4);
+ path.reset();
+ path.addArc(bounds, -90, SkPath::kCW_Direction == direction ? 90 : -90);
+ path.rLineTo(20, -20);
+ canvas->drawPath(path, paint);
+}
+##
+
+#SeeAlso Round_Rect addRoundRect addRRect
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void reset()
+
+Sets Path to its intial state.
+Removes Verb_Array, Point_Array, and Weights, and sets FillType to kWinding_FillType.
+Internal storage associated with Path is released.
+
+#Example
+ SkPath path1, path2;
+ path1.setFillType(SkPath::kInverseWinding_FillType);
+ path1.addRect({10, 20, 30, 40});
+ SkDebugf("path1 %c= path2\n", path1 == path2 ? '=' : '!');
+ path1.reset();
+ SkDebugf("path1 %c= path2\n", path1 == path2 ? '=' : '!');
+##
+
+#SeeAlso rewind()
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void rewind()
+
+Sets Path to its intial state, preserving internal storage.
+Removes Verb_Array, Point_Array, and Weights, and sets FillType to kWinding_FillType.
+Internal storage associated with Path is retained.
+
+Use rewind() instead of reset() if Path storage will be reused and performance
+is critical.
+
+#Example
+#Description
+Although path1 retains its internal storage, it is indistinguishable from
+a newly initialized path.
+##
+ SkPath path1, path2;
+ path1.setFillType(SkPath::kInverseWinding_FillType);
+ path1.addRect({10, 20, 30, 40});
+ SkDebugf("path1 %c= path2\n", path1 == path2 ? '=' : '!');
+ path1.rewind();
+ SkDebugf("path1 %c= path2\n", path1 == path2 ? '=' : '!');
+##
+
+#SeeAlso reset()
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method bool isEmpty() const
+
+Empty Path may have FillType but has no SkPoint, Verb, or Conic_Weight.
+SkPath() constructs empty Path; reset() and (rewind) make Path empty.
+
+#Return true if the path contains no Verb array ##
+
+#Example
+void draw(SkCanvas* canvas) {
+ auto debugster = [](const char* prefix, const SkPath& path) -> void {
+ SkDebugf("%s path is %s" "empty\n", prefix, path.isEmpty() ? "" : "not ");
+ };
+ SkPath path;
+ debugster("initial", path);
+ path.moveTo(0, 0);
+ debugster("after moveTo", path);
+ path.rewind();
+ debugster("after rewind", path);
+ path.lineTo(0, 0);
+ debugster("after lineTo", path);
+ path.reset();
+ debugster("after reset", path);
+}
+#StdOut
+initial path is empty
+after moveTo path is not empty
+after rewind path is empty
+after lineTo path is not empty
+after reset path is empty
+##
+##
+
+#SeeAlso SkPath() reset() rewind()
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method bool isLastContourClosed() const
+
+Contour is closed if Path Verb array was last modified by close(). When stroked,
+closed Contour draws Paint_Stroke_Join instead of Paint_Stroke_Cap at first and last Point.
+
+#Return true if the last Contour ends with a kClose_Verb ##
+
+#Example
+#Description
+close() has no effect if Path is empty; isLastContourClosed() returns
+false until Path has geometry followed by close().
+##
+void draw(SkCanvas* canvas) {
+ auto debugster = [](const char* prefix, const SkPath& path) -> void {
+ SkDebugf("%s last contour is %s" "closed\n", prefix,
+ path.isLastContourClosed() ? "" : "not ");
+ };
+ SkPath path;
+ debugster("initial", path);
+ path.close();
+ debugster("after close", path);
+ path.lineTo(0, 0);
+ debugster("after lineTo", path);
+ path.close();
+ debugster("after close", path);
+}
+#StdOut
+initial last contour is not closed
+after close last contour is not closed
+after lineTo last contour is not closed
+after close last contour is closed
+##
+##
+
+#SeeAlso close()
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method bool isFinite() const
+
+Returns true for finite Point array values between negative SK_ScalarMax and
+positive SK_ScalarMax. Returns false for any Point array value of
+SK_ScalarInfinity, SK_ScalarNegativeInfinity, or SK_ScalarNaN.
+
+#Return true if all Point values are finite ##
+
+#Example
+void draw(SkCanvas* canvas) {
+ auto debugster = [](const char* prefix, const SkPath& path) -> void {
+ SkDebugf("%s path is %s" "finite\n", prefix, path.isFinite() ? "" : "not ");
+ };
+ SkPath path;
+ debugster("initial", path);
+ path.lineTo(SK_ScalarMax, SK_ScalarMax);
+ debugster("after line", path);
+ SkMatrix matrix;
+ matrix.setScale(2, 2);
+ path.transform(matrix);
+ debugster("after scale", path);
+}
+#StdOut
+initial path is finite
+after line path is finite
+after scale path is not finite
+##
+##
+
+#SeeAlso SkScalar
+##
+
+# ------------------------------------------------------------------------------
+
+#Method bool isVolatile() const
+
+Returns true if the path is volatile; it will not be altered or discarded
+by the caller after it is drawn. Paths by default have volatile set false, allowing
+Surface to attach a cache of data which speeds repeated drawing. If true, Surface
+may not speed repeated drawing.
+
+#Return true if caller will alter Path after drawing ##
+
+#Example
+ SkPath path;
+ SkDebugf("volatile by default is %s\n", path.isVolatile() ? "true" : "false");
+#StdOut
+volatile by default is false
+##
+##
+
+#SeeAlso setIsVolatile
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void setIsVolatile(bool isVolatile)
+
+Specify whether Path is volatile; whether it will be altered or discarded
+by the caller after it is drawn. Paths by default have volatile set false, allowing
+Device to attach a cache of data which speeds repeated drawing.
+
+Mark temporary paths, discarded or modified after use, as volatile
+to inform Device that the path need not be cached.
+
+Mark animating Path volatile to improve performance.
+Mark unchanging Path non-volative to improve repeated rendering.
+
+Raster_Surface Path draws are affected by volatile for some shadows.
+GPU_Surface Path draws are affected by volatile for some shadows and concave geometries.
+
+#Param isVolatile true if caller will alter Path after drawing ##
+
+#Example
+#Height 50
+#Width 50
+ SkPaint paint;
+ paint.setStyle(SkPaint::kStroke_Style);
+ SkPath path;
+ path.setIsVolatile(true);
+ path.lineTo(40, 40);
+ canvas->drawPath(path, paint);
+ path.rewind();
+ path.moveTo(0, 40);
+ path.lineTo(40, 0);
+ canvas->drawPath(path, paint);
+##
+
+#ToDo tie example to bench to show how volatile affects speed or dm to show resource usage ##
+
+#SeeAlso isVolatile
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method static bool IsLineDegenerate(const SkPoint& p1, const SkPoint& p2, bool exact)
+
+Test if Line between Point pair is degenerate.
+Line with no length or that moves a very short distance is degenerate; it is
+treated as a point.
+
+#Param p1 line start point ##
+#Param p2 line end point ##
+#Param exact If true, returns true only if p1 equals p2. If false, returns true
+ if p1 equals or nearly equals p2
+##
+
+#Return true if Line is degenerate; its length is effectively zero ##
+
+#Example
+#Description
+As single precision floats, 100 and 100.000001f have the same bit representation,
+and are exactly equal. 100 and 100.0001f have different bit representations, and
+are not exactly equal, but are nearly equal.
+##
+void draw(SkCanvas* canvas) {
+ SkPoint points[] = { {100, 100}, {100.000001f, 100.000001f}, {100.0001f, 100.0001f} };
+ for (size_t i = 0; i < SK_ARRAY_COUNT(points) - 1; ++i) {
+ for (bool exact : { false, true } ) {
+ SkDebugf("line from (%1.8g,%1.8g) to (%1.8g,%1.8g) is %s" "degenerate, %s\n",
+ points[i].fX, points[i].fY, points[i + 1].fX, points[i + 1].fY,
+ SkPath::IsLineDegenerate(points[i], points[i + 1], exact)
+ ? "" : "not ", exact ? "exactly" : "nearly");
+ }
+ }
+}
+#StdOut
+line from (100,100) to (100,100) is degenerate, nearly
+line from (100,100) to (100,100) is degenerate, exactly
+line from (100,100) to (100.0001,100.0001) is degenerate, nearly
+line from (100,100) to (100.0001,100.0001) is not degenerate, exactly
+#StdOut ##
+##
+
+#SeeAlso IsQuadDegenerate IsCubicDegenerate SkPoint::equalsWithinTolerance
+##
+
+# ------------------------------------------------------------------------------
+
+#Method static bool IsQuadDegenerate(const SkPoint& p1, const SkPoint& p2,
+ const SkPoint& p3, bool exact)
+
+Test if Quad is degenerate.
+Quad with no length or that moves a very short distance is degenerate; it is
+treated as a point.
+
+#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 ##
+
+#Example
+#Description
+As single precision floats: 100, 100.00001f, and 100.00002f have different bit representations
+but nearly the same value. Translating all three by 1000 gives them the same bit representation;
+the fractional portion of the number can't be represented by the float and is lost.
+##
+void draw(SkCanvas* canvas) {
+ auto debugster = [](const SkPath& path, bool exact) -> void {
+ SkDebugf("quad (%1.8g,%1.8g), (%1.8g,%1.8g), (%1.8g,%1.8g) is %s" "degenerate, %s\n",
+ path.getPoint(0).fX, path.getPoint(0).fY, path.getPoint(1).fX,
+ path.getPoint(1).fY, path.getPoint(2).fX, path.getPoint(2).fY,
+ SkPath::IsQuadDegenerate(path.getPoint(0), path.getPoint(1), path.getPoint(2), exact) ?
+ "" : "not ", exact ? "exactly" : "nearly");
+ };
+ SkPath path, offset;
+ path.moveTo({100, 100});
+ path.quadTo({100.00001f, 100.00001f}, {100.00002f, 100.00002f});
+ offset.addPath(path, 1000, 1000);
+ for (bool exact : { false, true } ) {
+ debugster(path, exact);
+ debugster(offset, exact);
+ }
+}
+#StdOut
+quad (100,100), (100.00001,100.00001), (100.00002,100.00002) is degenerate, nearly
+quad (1100,1100), (1100,1100), (1100,1100) is degenerate, nearly
+quad (100,100), (100.00001,100.00001), (100.00002,100.00002) is not degenerate, exactly
+quad (1100,1100), (1100,1100), (1100,1100) is degenerate, exactly
+#StdOut ##
+##
+
+#SeeAlso IsLineDegenerate IsCubicDegenerate SkPoint::equalsWithinTolerance
+##
+
+# ------------------------------------------------------------------------------
+
+#Method static bool IsCubicDegenerate(const SkPoint& p1, const SkPoint& p2,
+ const SkPoint& p3, const SkPoint& p4, bool exact)
+
+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 ##
+
+#Example
+void draw(SkCanvas* canvas) {
+ SkPoint points[] = {{1, 0}, {0, 0}, {0, 0}, {0, 0}};
+ SkScalar step = 1;
+ SkScalar prior, length, degenerate;
+ do {
+ prior = points[0].fX;
+ step /= 2;
+ if (SkPath::IsCubicDegenerate(points[0], points[1], points[2], points[3], false)) {
+ degenerate = prior;
+ points[0].fX += step;
+ } else {
+ length = prior;
+ points[0].fX -= step;
+ }
+ } while (prior != points[0].fX);
+ SkDebugf("%1.8g is degenerate\n", degenerate);
+ SkDebugf("%1.8g is length\n", length);
+}
+#StdOut
+0.00024414062 is degenerate
+0.00024414065 is length
+#StdOut ##
+##
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method bool isLine(SkPoint line[2]) const
+
+Returns true if Path contains only one Line;
+Path_Verb array has two entries: kMove_Verb, kLine_Verb.
+If Path contains one Line and line is not nullptr, line is set to
+Line start point and Line end point.
+Returns false if Path is not one Line; line is unaltered.
+
+#Param line storage for Line. May be nullptr ##
+
+#Return true if Path contains exactly one Line ##
+
+#Example
+void draw(SkCanvas* canvas) {
+ auto debugster = [](const char* prefix, const SkPath& path) -> void {
+ SkPoint line[2];
+ if (path.isLine(line)) {
+ SkDebugf("%s is line (%1.8g,%1.8g) (%1.8g,%1.8g)\n", prefix,
+ line[0].fX, line[0].fY, line[1].fX, line[1].fY);
+ } else {
+ SkDebugf("%s is not line\n", prefix);
+ }
+ };
+ SkPath path;
+ debugster("empty", path);
+ path.lineTo(0, 0);
+ debugster("zero line", path);
+ path.rewind();
+ path.moveTo(10, 10);
+ path.lineTo(20, 20);
+ debugster("line", path);
+ path.moveTo(20, 20);
+ debugster("second move", path);
+}
+#StdOut
+empty is not line
+zero line is line (0,0) (0,0)
+line is line (10,10) (20,20)
+second move is not line
+##
+##
+
+##
+
+# ------------------------------------------------------------------------------
+
#Subtopic Point_Array
#Alias Point_Arrays
@@ -1735,117 +1763,117 @@ one Point for move, one Point for Line, two Points for Quad; totaling four Point
Point_Array may be read directly from Path with getPoints, or inspected with
getPoint, with Iter, or with RawIter.
-
-#Method int getPoints(SkPoint points[], int max) const
-
-Returns number of points in Path. 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 storage for Path Point array. May be nullptr. ##
-#Param max Number of points alloted in points storage; must be greater than or equal to zero. ##
-
-#Return Path Point array length. ##
-
-#Example
-void draw(SkCanvas* canvas) {
- auto debugster = [](const char* prefix, const SkPath& path, SkPoint* points, int max) -> void {
- int count = path.getPoints(points, max);
- SkDebugf("%s point count: %d ", prefix, count);
- for (int i = 0; i < SkTMin(count, max) && points; ++i) {
- SkDebugf("(%1.8g,%1.8g) ", points[i].fX, points[i].fY);
- }
- SkDebugf("\n");
- };
- SkPath path;
- path.lineTo(20, 20);
- path.lineTo(-10, -10);
- SkPoint points[3];
- debugster("no points", path, nullptr, 0);
- debugster("zero max", path, points, 0);
- debugster("too small", path, points, 2);
- debugster("just right", path, points, path.countPoints());
-}
-#StdOut
-no points point count: 3
-zero max point count: 3
-too small point count: 3 (0,0) (20,20)
-just right point count: 3 (0,0) (20,20) (-10,-10)
-##
-##
-
-#SeeAlso countPoints getPoint
-##
-
-#Method int countPoints() const
-
-Returns the number of points in Path.
-Point count is initially zero.
-
-#Return Path Point array length. ##
-
-#Example
-void draw(SkCanvas* canvas) {
- auto debugster = [](const char* prefix, const SkPath& path) -> void {
- SkDebugf("%s point count: %d\n", prefix, path.countPoints());
- };
- SkPath path;
- debugster("empty", path);
- path.lineTo(0, 0);
- debugster("zero line", path);
- path.rewind();
- path.moveTo(10, 10);
- path.lineTo(20, 20);
- debugster("line", path);
- path.moveTo(20, 20);
- debugster("second move", path);
-}
-#StdOut
-empty point count: 0
-zero line point count: 2
-line point count: 2
-second move point count: 3
-##
-##
-
-#SeeAlso getPoints
-##
-
-#Method SkPoint getPoint(int index) const
-
-Returns Point at index in Point_Array. Valid range for index is
-0 to countPoints - 1.
-If the index is out of range, getPoint returns (0, 0).
-
-#Param index Point_Array element selector. ##
-
-#Return Point_Array value or (0, 0). ##
-
-#Example
-void draw(SkCanvas* canvas) {
- auto debugster = [](const char* prefix, const SkPath& path) -> void {
- SkDebugf("%s point count: %d\n", prefix, path.countPoints());
- };
- SkPath path;
- path.lineTo(20, 20);
- path.offset(-10, -10);
- for (int i= 0; i < path.countPoints(); ++i) {
- SkDebugf("point %d: (%1.8g,%1.8g)\n", i, path.getPoint(i).fX, path.getPoint(i).fY);
- }
-}
-#StdOut
-point 0: (-10,-10)
-point 1: (10,10)
-##
-##
-
-#SeeAlso countPoints getPoints
-##
-
-
-#Subtopic Point_Array ##
-
-# ------------------------------------------------------------------------------
+
+#Method int getPoints(SkPoint points[], int max) const
+
+Returns number of points in Path. 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 storage for Path Point array. May be nullptr ##
+#Param max maximum to copy; must be greater than or equal to zero ##
+
+#Return Path Point array length ##
+
+#Example
+void draw(SkCanvas* canvas) {
+ auto debugster = [](const char* prefix, const SkPath& path, SkPoint* points, int max) -> void {
+ int count = path.getPoints(points, max);
+ SkDebugf("%s point count: %d ", prefix, count);
+ for (int i = 0; i < SkTMin(count, max) && points; ++i) {
+ SkDebugf("(%1.8g,%1.8g) ", points[i].fX, points[i].fY);
+ }
+ SkDebugf("\n");
+ };
+ SkPath path;
+ path.lineTo(20, 20);
+ path.lineTo(-10, -10);
+ SkPoint points[3];
+ debugster("no points", path, nullptr, 0);
+ debugster("zero max", path, points, 0);
+ debugster("too small", path, points, 2);
+ debugster("just right", path, points, path.countPoints());
+}
+#StdOut
+no points point count: 3
+zero max point count: 3
+too small point count: 3 (0,0) (20,20)
+just right point count: 3 (0,0) (20,20) (-10,-10)
+##
+##
+
+#SeeAlso countPoints getPoint
+##
+
+#Method int countPoints() const
+
+Returns the number of points in Path.
+Point count is initially zero.
+
+#Return Path Point array length ##
+
+#Example
+void draw(SkCanvas* canvas) {
+ auto debugster = [](const char* prefix, const SkPath& path) -> void {
+ SkDebugf("%s point count: %d\n", prefix, path.countPoints());
+ };
+ SkPath path;
+ debugster("empty", path);
+ path.lineTo(0, 0);
+ debugster("zero line", path);
+ path.rewind();
+ path.moveTo(10, 10);
+ path.lineTo(20, 20);
+ debugster("line", path);
+ path.moveTo(20, 20);
+ debugster("second move", path);
+}
+#StdOut
+empty point count: 0
+zero line point count: 2
+line point count: 2
+second move point count: 3
+##
+##
+
+#SeeAlso getPoints
+##
+
+#Method SkPoint getPoint(int index) const
+
+Returns Point at index in Point_Array. Valid range for index is
+0 to countPoints - 1.
+Returns (0, 0) if index is out of range.
+
+#Param index Point array element selector ##
+
+#Return Point array value or (0, 0) ##
+
+#Example
+void draw(SkCanvas* canvas) {
+ auto debugster = [](const char* prefix, const SkPath& path) -> void {
+ SkDebugf("%s point count: %d\n", prefix, path.countPoints());
+ };
+ SkPath path;
+ path.lineTo(20, 20);
+ path.offset(-10, -10);
+ for (int i= 0; i < path.countPoints(); ++i) {
+ SkDebugf("point %d: (%1.8g,%1.8g)\n", i, path.getPoint(i).fX, path.getPoint(i).fY);
+ }
+}
+#StdOut
+point 0: (-10,-10)
+point 1: (10,10)
+##
+##
+
+#SeeAlso countPoints getPoints
+##
+
+
+#Subtopic Point_Array ##
+
+# ------------------------------------------------------------------------------
#Subtopic Verb_Array
Verb_Array always starts with kMove_Verb.
@@ -1856,517 +1884,518 @@ returned when iterating through Verb_Array.
Verb_Array may be read directly from Path with getVerbs, or inspected with Iter,
or with RawIter.
-
-#Method int countVerbs() const
-
-Returns the number of Verbs: kMove_Verb, kLine_Verb, kQuad_Verb, kConic_Verb,
-kCubic_Verb, and kClose_Verb; added to Path.
-
-#Return Length of Verb_Array. ##
-
-#Example
-SkPath path;
-SkDebugf("empty verb count: %d\n", path.countVerbs());
-path.addRoundRect({10, 20, 30, 40}, 5, 5);
-SkDebugf("round rect verb count: %d\n", path.countVerbs());
-#StdOut
-empty verb count: 0
-round rect verb count: 10
-##
-##
-
-#SeeAlso getVerbs Iter RawIter
-
-##
-
-#Method int getVerbs(uint8_t verbs[], int max) 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 ##
-
-#Example
-void draw(SkCanvas* canvas) {
- auto debugster = [](const char* prefix, const SkPath& path, uint8_t* verbs, int max) -> void {
- int count = path.getVerbs(verbs, max);
- SkDebugf("%s verb count: %d ", prefix, count);
- const char* verbStr[] = { "move", "line", "quad", "conic", "cubic", "close" };
- for (int i = 0; i < SkTMin(count, max) && verbs; ++i) {
- SkDebugf("%s ", verbStr[verbs[i]]);
- }
- SkDebugf("\n");
- };
- SkPath path;
- path.lineTo(20, 20);
- path.lineTo(-10, -10);
- uint8_t verbs[3];
- debugster("no verbs", path, nullptr, 0);
- debugster("zero max", path, verbs, 0);
- debugster("too small", path, verbs, 2);
- debugster("just right", path, verbs, path.countVerbs());
-}
-#StdOut
-no verbs verb count: 3
-zero max verb count: 3
-too small verb count: 3 move line
-just right verb count: 3 move line line
-##
-##
-
-#SeeAlso countVerbs getPoints Iter RawIter
-##
+
+#Method int countVerbs() const
+
+Returns the number of Verbs: kMove_Verb, kLine_Verb, kQuad_Verb, kConic_Verb,
+kCubic_Verb, and kClose_Verb; added to Path.
+
+#Return length of Verb_Array ##
+
+#Example
+SkPath path;
+SkDebugf("empty verb count: %d\n", path.countVerbs());
+path.addRoundRect({10, 20, 30, 40}, 5, 5);
+SkDebugf("round rect verb count: %d\n", path.countVerbs());
+#StdOut
+empty verb count: 0
+round rect verb count: 10
+##
+##
+
+#SeeAlso getVerbs Iter RawIter
+
+##
+
+#Method int getVerbs(uint8_t verbs[], int max) 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 storage for verbs, may be nullptr ##
+#Param max maximum number to copy into verbs ##
+
+#Return the actual number of verbs in the path ##
+
+#Example
+void draw(SkCanvas* canvas) {
+ auto debugster = [](const char* prefix, const SkPath& path, uint8_t* verbs, int max) -> void {
+ int count = path.getVerbs(verbs, max);
+ SkDebugf("%s verb count: %d ", prefix, count);
+ const char* verbStr[] = { "move", "line", "quad", "conic", "cubic", "close" };
+ for (int i = 0; i < SkTMin(count, max) && verbs; ++i) {
+ SkDebugf("%s ", verbStr[verbs[i]]);
+ }
+ SkDebugf("\n");
+ };
+ SkPath path;
+ path.lineTo(20, 20);
+ path.lineTo(-10, -10);
+ uint8_t verbs[3];
+ debugster("no verbs", path, nullptr, 0);
+ debugster("zero max", path, verbs, 0);
+ debugster("too small", path, verbs, 2);
+ debugster("just right", path, verbs, path.countVerbs());
+}
+#StdOut
+no verbs verb count: 3
+zero max verb count: 3
+too small verb count: 3 move line
+just right verb count: 3 move line line
+##
+##
+
+#SeeAlso countVerbs getPoints Iter RawIter
+##
#Subtopic Verb_Array ##
-
-# ------------------------------------------------------------------------------
-
-#Method void swap(SkPath& other)
-
-Exchanges the Verb_Array, Point_Array, Weights, and Fill_Type 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).
-Paths do not copy their content on assignment util they are written to,
-making assignment as efficient as swap().
-
-#Param other Path exchanged by value. ##
-
-#Example
-SkPath path1, path2;
-path1.addRect({10, 20, 30, 40});
-path1.swap(path2);
-const SkRect& b1 = path1.getBounds();
-SkDebugf("path1 bounds = %g, %g, %g, %g\n", b1.fLeft, b1.fTop, b1.fRight, b1.fBottom);
-const SkRect& b2 = path2.getBounds();
-SkDebugf("path2 bounds = %g, %g, %g, %g\n", b2.fLeft, b2.fTop, b2.fRight, b2.fBottom);
-#StdOut
-path1 bounds = 0, 0, 0, 0
-path2 bounds = 10, 20, 30, 40
-#StdOut ##
-##
-
-#SeeAlso operator=(const SkPath& path)
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method const SkRect& getBounds() const
-
-Returns minimum and maximum x and y values of Point_Array. If Path contains
-no points, getBounds returns (0, 0, 0, 0). Returned bounds width and height may
-be larger or smaller than area affected when Path is drawn.
-
-getBounds includes all Points added to Path, including Points associated with
-kMove_Verb that define empty Contours.
-
-#Return bounds of all Points in Point_Array. ##
-
-#Example
-#Description
-Bounds of upright Circle can be predicted from center and radius.
-Bounds of rotated Circle includes control Points outside of filled area.
-##
- auto debugster = [](const char* prefix, const SkPath& path) -> void {
- const SkRect& bounds = path.getBounds();
- SkDebugf("%s bounds = %g, %g, %g, %g\n", prefix,
- bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
- };
- SkPath path;
- debugster("empty", path);
- path.addCircle(50, 45, 25);
- debugster("circle", path);
- SkMatrix matrix;
- matrix.setRotate(45, 50, 45);
- path.transform(matrix);
- debugster("rotated circle", path);
-#StdOut
-empty bounds = 0, 0, 0, 0
-circle bounds = 25, 20, 75, 70
-rotated circle bounds = 14.6447, 9.64466, 85.3553, 80.3553
-##
-##
-
-#SeeAlso computeTightBounds updateBoundsCache
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void updateBoundsCache() const
-
-Update internal bounds so that subsequent calls to getBounds are instantaneous.
-Unaltered copies of Path may also access cached bounds through getBounds.
-
-For now, updateBoundsCache is identical to getBounds, where the
-returned value is ignored.
-
-updateBoundsCache prepares a Path subsequently drawn from multiple threads,
-to avoid a race condition where each draw separately computes the bounds.
-
-#Example
- double times[2] = { 0, 0 };
- for (int i = 0; i < 10000; ++i) {
- SkPath path;
- for (int j = 1; j < 100; ++ j) {
- path.addCircle(50 + j, 45 + j, 25 + j);
- }
- if (1 & i) {
- path.updateBoundsCache();
- }
- double start = SkTime::GetNSecs();
- (void) path.getBounds();
- times[1 & i] += SkTime::GetNSecs() - start;
- }
- SkDebugf("uncached avg: %g ms\n", times[0] * 1e-6);
- SkDebugf("cached avg: %g ms\n", times[1] * 1e-6);
-#StdOut
-#Volatile
-uncached avg: 0.18048 ms
-cached avg: 0.182784 ms
-##
-##
-
-#SeeAlso getBounds
-#ToDo the results don't make sense, need to profile to figure this out ##
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method SkRect computeTightBounds() const
-
-Returns minimum and maximum x and y values of the lines and curves in Path.
-If Path contains no points, computeTightBounds returns (0, 0, 0, 0).
-Returned bounds width and height may be larger or smaller than area affected
-when Path is drawn.
-
-computeTightBounds behaves identically to getBounds when Path contains
-only lines. If Path contains curves, compute computeTightBounds includes
-the maximum extent of the Quad, Conic, or Cubic; is slower,
-and does not cache the result.
-
-Like getBounds, computeTightBounds includes Points associated with
-kMove_Verb that define empty Contours.
-
-#Return ##
-
-#Example
- auto debugster = [](const char* prefix, const SkPath& path) -> void {
- const SkRect& bounds = path.computeTightBounds();
- SkDebugf("%s bounds = %g, %g, %g, %g\n", prefix,
- bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
- };
- SkPath path;
- debugster("empty", path);
- path.addCircle(50, 45, 25);
- debugster("circle", path);
- SkMatrix matrix;
- matrix.setRotate(45, 50, 45);
- path.transform(matrix);
- debugster("rotated circle", path);
-#StdOut
-empty bounds = 0, 0, 0, 0
-circle bounds = 25, 20, 75, 70
-rotated circle bounds = 25, 20, 75, 70
-##
-##
-
-#SeeAlso getBounds
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method bool conservativelyContainsRect(const SkRect& rect) const
-
-Returns true if rect is contained by Path.
-May return false when rect is contained by Path.
-
-For now, only returns true if Path has one Contour and is convex.
-rect may share points and edges with Path and be contained.
-If rect is empty, that is, it has zero width or height; conservativelyContainsRect
-returns true if the Point or Line described by rect is contained by Path.
-
-#Param rect Rect, Line, or Point checked for containment. ##
-
-#Return true if rect is contained. ##
-
-#Example
-#Height 140
-#Description
-Rect is drawn in blue if it is contained by red Path.
-##
-void draw(SkCanvas* canvas) {
- SkPath path;
- path.addRoundRect({10, 20, 54, 120}, 10, 20);
- SkRect tests[] = {
- { 10, 40, 54, 80 },
- { 25, 20, 39, 120 },
- { 15, 25, 49, 115 },
- { 13, 27, 51, 113 },
- };
- for (unsigned i = 0; i < SK_ARRAY_COUNT(tests); ++i) {
- SkPaint paint;
- paint.setColor(SK_ColorRED);
- canvas->drawPath(path, paint);
- bool rectInPath = path.conservativelyContainsRect(tests[i]);
- paint.setColor(rectInPath ? SK_ColorBLUE : SK_ColorBLACK);
- canvas->drawRect(tests[i], paint);
- canvas->translate(64, 0);
- }
-}
-##
-
-#SeeAlso contains Op Rect Convexity
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void incReserve(unsigned extraPtCount)
-
-grows Path Verb_Array and Point_Array to contain extraPtCount additional Points.
-incReserve may improve performance and use less memory by
-reducing the number and size of allocations when creating Path.
-
-#Param extraPtCount number of additional Points to preallocate. ##
-
-#Example
-#Height 192
-void draw(SkCanvas* canvas) {
- auto addPoly = [](int sides, SkScalar size, SkPath* path) -> void {
- path->moveTo(size, 0);
- for (int i = 1; i < sides; i++) {
- SkScalar c, s = SkScalarSinCos(SK_ScalarPI * 2 * i / sides, &c);
- path->lineTo(c * size, s * size);
- }
- path->close();
- };
- SkPath path;
- path.incReserve(3 + 4 + 5 + 6 + 7 + 8 + 9);
- for (int sides = 3; sides < 10; ++sides) {
- addPoly(sides, sides, &path);
- }
- SkMatrix matrix;
- matrix.setScale(10, 10, -10, -10);
- path.transform(matrix);
- SkPaint paint;
- paint.setStyle(SkPaint::kStroke_Style);
- canvas->drawPath(path, paint);
-}
-##
-
-#SeeAlso Point_Array
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void moveTo(SkScalar x, SkScalar y)
-
-Adds beginning of Contour at Point (x, y).
-
-#Param x x-coordinate of Contour start. ##
-#Param y y-coordinate of Contour start. ##
-
-#Example
- #Width 140
- #Height 100
- void draw(SkCanvas* canvas) {
- SkRect rect = { 20, 20, 120, 80 };
- SkPath path;
- path.addRect(rect);
- path.moveTo(rect.fLeft, rect.fTop);
- path.lineTo(rect.fRight, rect.fBottom);
- path.moveTo(rect.fLeft, rect.fBottom);
- path.lineTo(rect.fRight, rect.fTop);
- SkPaint paint;
- paint.setStyle(SkPaint::kStroke_Style);
- canvas->drawPath(path, paint);
- }
-##
-
-#SeeAlso Contour lineTo rMoveTo quadTo conicTo cubicTo close()
-
-##
-
-#Method void moveTo(const SkPoint& p)
-
-Adds beginning of Contour at Point p.
-
-#Param p Contour start. ##
-
-#Example
- #Width 128
- #Height 128
-void draw(SkCanvas* canvas) {
- SkPoint data[][3] = {{{30,40},{60,60},{90,30}}, {{30,120},{60,100},{90,120}},
- {{60,100},{60,40},{70,30}}, {{60,40},{50,20},{70,30}}};
- SkPath path;
- for (unsigned i = 0; i < SK_ARRAY_COUNT(data); ++i) {
- path.moveTo(data[i][0]);
- path.lineTo(data[i][1]);
- path.lineTo(data[i][2]);
- }
- SkPaint paint;
- paint.setStyle(SkPaint::kStroke_Style);
- canvas->drawPath(path, paint);
-}
-##
-
-#SeeAlso Contour lineTo rMoveTo quadTo conicTo cubicTo close()
-
-##
-
-#Method void rMoveTo(SkScalar dx, SkScalar dy)
-
-Adds beginning of Contour relative to Last_Point.
-If Path is empty, starts Contour at (dx, dy).
-Otherwise, start Contour at Last_Point offset by (dx, dy).
-rMoveTo stands for relative move to.
-
-#Param dx offset from Last_Point x to Contour start x. ##
-#Param dy offset from Last_Point y to Contour start y. ##
-
-#Example
- #Height 100
- SkPath path;
- path.addRect({20, 20, 80, 80}, SkPath::kCW_Direction, 2);
- path.rMoveTo(25, 2);
- SkVector arrow[] = {{0, -4}, {-20, 0}, {0, -3}, {-5, 5}, {5, 5}, {0, -3}, {20, 0}};
- for (unsigned i = 0; i < SK_ARRAY_COUNT(arrow); ++i) {
- path.rLineTo(arrow[i].fX, arrow[i].fY);
- }
- SkPaint paint;
- canvas->drawPath(path, paint);
- SkPoint lastPt;
- path.getLastPt(&lastPt);
- canvas->drawString("start", lastPt.fX, lastPt.fY, paint);
-##
-
-#SeeAlso Contour lineTo moveTo quadTo conicTo cubicTo close()
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void lineTo(SkScalar x, SkScalar y)
-
-Adds Line from Last_Point to (x, y). If Path is empty, or last Verb is
-kClose_Verb, Last_Point is set to (0, 0) before adding Line.
-
-lineTo appends kMove_Verb to Verb_Array and (0, 0) to Point_Array, if needed.
-lineTo then appends kLine_Verb to Verb_Array and (x, y) to Point_Array.
-
-#Param x end of added Line in x. ##
-#Param y end of added Line in y. ##
-
-#Example
-#Height 100
-###$
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setTextSize(72);
- canvas->drawString("#", 120, 80, paint);
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setStrokeWidth(5);
- SkPath path;
- SkPoint hash[] = {{58, 28}, {43, 80}, {37, 45}, {85, 45}};
- SkVector offsets[] = {{0, 0}, {17, 0}, {0, 0}, {-5, 17}};
- unsigned o = 0;
- for (unsigned i = 0; i < SK_ARRAY_COUNT(hash); i += 2) {
- for (unsigned j = 0; j < 2; o++, j++) {
- path.moveTo(hash[i].fX + offsets[o].fX, hash[i].fY + offsets[o].fY);
- path.lineTo(hash[i + 1].fX + offsets[o].fX, hash[i + 1].fY + offsets[o].fY);
- }
- }
- canvas->drawPath(path, paint);
-}
-$$$#
-##
-
-#SeeAlso Contour moveTo rLineTo addRect
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void lineTo(const SkPoint& p)
-
-Adds Line from Last_Point to Point p. If Path is empty, or last 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 Point_Array, if needed.
-lineTo then appends kLine_Verb to Verb_Array and Point p to Point_Array.
-
-#Param p end Point of added Line. ##
-
-#Example
-#Height 100
- SkPath path;
- SkVector oxo[] = {{25, 25}, {35, 35}, {25, 35}, {35, 25},
- {40, 20}, {40, 80}, {60, 20}, {60, 80},
- {20, 40}, {80, 40}, {20, 60}, {80, 60}};
- for (unsigned i = 0; i < SK_ARRAY_COUNT(oxo); i += 2) {
- path.moveTo(oxo[i]);
- path.lineTo(oxo[i + 1]);
- }
- SkPaint paint;
- paint.setStyle(SkPaint::kStroke_Style);
- canvas->drawPath(path, paint);
-##
-
-#SeeAlso Contour moveTo rLineTo addRect
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void rLineTo(SkScalar dx, SkScalar dy)
-
-Adds Line from Last_Point to Vector (dx, dy). If Path is empty, or last Verb is
-kClose_Verb, Last_Point is set to (0, 0) before adding Line.
-
-rLineTo first appends kMove_Verb to Verb_Array and (0, 0) to Point_Array, if needed.
-rLineTo then appends kLine_Verb to Verb_Array and Line end to Point_Array.
-Line end is Last_Point plus Vector (dx, dy).
-rLineTo stands for relative line to.
-
-#Param dx offset from Last_Point x to Line end x. ##
-#Param dy offset from Last_Point y to Line end y. ##
-
-#Example
-#Height 128
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
- SkPath path;
- path.moveTo(10, 98);
- SkScalar x = 0, y = 0;
- for (int i = 10; i < 100; i += 5) {
- x += i * ((i & 2) - 1);
- y += i * (((i + 1) & 2) - 1);
- path.rLineTo(x, y);
-
- }
- canvas->drawPath(path, paint);
-}
-##
-
-#SeeAlso Contour moveTo lineTo addRect
-
-##
-
-# ------------------------------------------------------------------------------
+
+# ------------------------------------------------------------------------------
+
+#Method void swap(SkPath& other)
+
+Exchanges the Verb_Array, Point_Array, Weights, and Fill_Type 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).
+Paths do not copy their content on assignment util they are written to,
+making assignment as efficient as swap().
+
+#Param other Path exchanged by value ##
+
+#Example
+SkPath path1, path2;
+path1.addRect({10, 20, 30, 40});
+path1.swap(path2);
+const SkRect& b1 = path1.getBounds();
+SkDebugf("path1 bounds = %g, %g, %g, %g\n", b1.fLeft, b1.fTop, b1.fRight, b1.fBottom);
+const SkRect& b2 = path2.getBounds();
+SkDebugf("path2 bounds = %g, %g, %g, %g\n", b2.fLeft, b2.fTop, b2.fRight, b2.fBottom);
+#StdOut
+path1 bounds = 0, 0, 0, 0
+path2 bounds = 10, 20, 30, 40
+#StdOut ##
+##
+
+#SeeAlso operator=(const SkPath& path)
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method const SkRect& getBounds() const
+
+Returns minimum and maximum x and y values of Point_Array.
+Returns (0, 0, 0, 0) if Path contains no points. Returned bounds width and height may
+be larger or smaller than area affected when Path is drawn.
+
+Rect returned includes all Points added to Path, including Points associated with
+kMove_Verb that define empty Contours.
+
+#Return bounds of all Points in Point_Array ##
+
+#Example
+#Description
+Bounds of upright Circle can be predicted from center and radius.
+Bounds of rotated Circle includes control Points outside of filled area.
+##
+ auto debugster = [](const char* prefix, const SkPath& path) -> void {
+ const SkRect& bounds = path.getBounds();
+ SkDebugf("%s bounds = %g, %g, %g, %g\n", prefix,
+ bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
+ };
+ SkPath path;
+ debugster("empty", path);
+ path.addCircle(50, 45, 25);
+ debugster("circle", path);
+ SkMatrix matrix;
+ matrix.setRotate(45, 50, 45);
+ path.transform(matrix);
+ debugster("rotated circle", path);
+#StdOut
+empty bounds = 0, 0, 0, 0
+circle bounds = 25, 20, 75, 70
+rotated circle bounds = 14.6447, 9.64466, 85.3553, 80.3553
+##
+##
+
+#SeeAlso computeTightBounds updateBoundsCache
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void updateBoundsCache() const
+
+Update internal bounds so that subsequent calls to getBounds are instantaneous.
+Unaltered copies of Path may also access cached bounds through getBounds.
+
+For now, identical to calling getBounds and ignoring the returned value.
+
+Call to prepare Path subsequently drawn from multiple threads,
+to avoid a race condition where each draw separately computes the bounds.
+
+#Example
+ double times[2] = { 0, 0 };
+ for (int i = 0; i < 10000; ++i) {
+ SkPath path;
+ for (int j = 1; j < 100; ++ j) {
+ path.addCircle(50 + j, 45 + j, 25 + j);
+ }
+ if (1 & i) {
+ path.updateBoundsCache();
+ }
+ double start = SkTime::GetNSecs();
+ (void) path.getBounds();
+ times[1 & i] += SkTime::GetNSecs() - start;
+ }
+ SkDebugf("uncached avg: %g ms\n", times[0] * 1e-6);
+ SkDebugf("cached avg: %g ms\n", times[1] * 1e-6);
+#StdOut
+#Volatile
+uncached avg: 0.18048 ms
+cached avg: 0.182784 ms
+##
+##
+
+#SeeAlso getBounds
+#ToDo the results don't make sense, need to profile to figure this out ##
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method SkRect computeTightBounds() const
+
+Returns minimum and maximum x and y values of the lines and curves in Path.
+Returns (0, 0, 0, 0) if Path contains no points.
+Returned bounds width and height may be larger or smaller than area affected
+when Path is drawn.
+
+Includes Points associated with kMove_Verb that define empty
+Contours.
+
+Behaves identically to getBounds when Path contains
+only lines. If Path 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 Path ##
+
+#Example
+ auto debugster = [](const char* prefix, const SkPath& path) -> void {
+ const SkRect& bounds = path.computeTightBounds();
+ SkDebugf("%s bounds = %g, %g, %g, %g\n", prefix,
+ bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
+ };
+ SkPath path;
+ debugster("empty", path);
+ path.addCircle(50, 45, 25);
+ debugster("circle", path);
+ SkMatrix matrix;
+ matrix.setRotate(45, 50, 45);
+ path.transform(matrix);
+ debugster("rotated circle", path);
+#StdOut
+empty bounds = 0, 0, 0, 0
+circle bounds = 25, 20, 75, 70
+rotated circle bounds = 25, 20, 75, 70
+##
+##
+
+#SeeAlso getBounds
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method bool conservativelyContainsRect(const SkRect& rect) const
+
+Returns true if rect is contained by Path.
+May return false when rect is contained by Path.
+
+For now, only returns true if Path has one Contour and is convex.
+rect may share points and edges with Path and be contained.
+Returns true if rect is empty, that is, it has zero width or height; and
+the Point or Line described by rect is contained by Path.
+
+#Param rect Rect, Line, or Point checked for containment ##
+
+#Return true if rect is contained ##
+
+#Example
+#Height 140
+#Description
+Rect is drawn in blue if it is contained by red Path.
+##
+void draw(SkCanvas* canvas) {
+ SkPath path;
+ path.addRoundRect({10, 20, 54, 120}, 10, 20);
+ SkRect tests[] = {
+ { 10, 40, 54, 80 },
+ { 25, 20, 39, 120 },
+ { 15, 25, 49, 115 },
+ { 13, 27, 51, 113 },
+ };
+ for (unsigned i = 0; i < SK_ARRAY_COUNT(tests); ++i) {
+ SkPaint paint;
+ paint.setColor(SK_ColorRED);
+ canvas->drawPath(path, paint);
+ bool rectInPath = path.conservativelyContainsRect(tests[i]);
+ paint.setColor(rectInPath ? SK_ColorBLUE : SK_ColorBLACK);
+ canvas->drawRect(tests[i], paint);
+ canvas->translate(64, 0);
+ }
+}
+##
+
+#SeeAlso contains Op Rect Convexity
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void incReserve(unsigned extraPtCount)
+
+grows Path Verb_Array and Point_Array to contain extraPtCount additional Points.
+May improve performance and use less memory by
+reducing the number and size of allocations when creating Path.
+
+#Param extraPtCount number of additional Points to preallocate ##
+
+#Example
+#Height 192
+void draw(SkCanvas* canvas) {
+ auto addPoly = [](int sides, SkScalar size, SkPath* path) -> void {
+ path->moveTo(size, 0);
+ for (int i = 1; i < sides; i++) {
+ SkScalar c, s = SkScalarSinCos(SK_ScalarPI * 2 * i / sides, &c);
+ path->lineTo(c * size, s * size);
+ }
+ path->close();
+ };
+ SkPath path;
+ path.incReserve(3 + 4 + 5 + 6 + 7 + 8 + 9);
+ for (int sides = 3; sides < 10; ++sides) {
+ addPoly(sides, sides, &path);
+ }
+ SkMatrix matrix;
+ matrix.setScale(10, 10, -10, -10);
+ path.transform(matrix);
+ SkPaint paint;
+ paint.setStyle(SkPaint::kStroke_Style);
+ canvas->drawPath(path, paint);
+}
+##
+
+#SeeAlso Point_Array
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void moveTo(SkScalar x, SkScalar y)
+
+Adds beginning of Contour at Point (x, y).
+
+#Param x x-coordinate of Contour start ##
+#Param y y-coordinate of Contour start ##
+
+#Example
+ #Width 140
+ #Height 100
+ void draw(SkCanvas* canvas) {
+ SkRect rect = { 20, 20, 120, 80 };
+ SkPath path;
+ path.addRect(rect);
+ path.moveTo(rect.fLeft, rect.fTop);
+ path.lineTo(rect.fRight, rect.fBottom);
+ path.moveTo(rect.fLeft, rect.fBottom);
+ path.lineTo(rect.fRight, rect.fTop);
+ SkPaint paint;
+ paint.setStyle(SkPaint::kStroke_Style);
+ canvas->drawPath(path, paint);
+ }
+##
+
+#SeeAlso Contour lineTo rMoveTo quadTo conicTo cubicTo close()
+
+##
+
+#Method void moveTo(const SkPoint& p)
+
+Adds beginning of Contour at Point p.
+
+#Param p contour start ##
+
+#Example
+ #Width 128
+ #Height 128
+void draw(SkCanvas* canvas) {
+ SkPoint data[][3] = {{{30,40},{60,60},{90,30}}, {{30,120},{60,100},{90,120}},
+ {{60,100},{60,40},{70,30}}, {{60,40},{50,20},{70,30}}};
+ SkPath path;
+ for (unsigned i = 0; i < SK_ARRAY_COUNT(data); ++i) {
+ path.moveTo(data[i][0]);
+ path.lineTo(data[i][1]);
+ path.lineTo(data[i][2]);
+ }
+ SkPaint paint;
+ paint.setStyle(SkPaint::kStroke_Style);
+ canvas->drawPath(path, paint);
+}
+##
+
+#SeeAlso Contour lineTo rMoveTo quadTo conicTo cubicTo close()
+
+##
+
+#Method void rMoveTo(SkScalar dx, SkScalar dy)
+
+Adds beginning of Contour relative to Last_Point.
+If Path 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 offset from Last_Point x to Contour start x ##
+#Param dy offset from Last_Point y to Contour start y ##
+
+#Example
+ #Height 100
+ SkPath path;
+ path.addRect({20, 20, 80, 80}, SkPath::kCW_Direction, 2);
+ path.rMoveTo(25, 2);
+ SkVector arrow[] = {{0, -4}, {-20, 0}, {0, -3}, {-5, 5}, {5, 5}, {0, -3}, {20, 0}};
+ for (unsigned i = 0; i < SK_ARRAY_COUNT(arrow); ++i) {
+ path.rLineTo(arrow[i].fX, arrow[i].fY);
+ }
+ SkPaint paint;
+ canvas->drawPath(path, paint);
+ SkPoint lastPt;
+ path.getLastPt(&lastPt);
+ canvas->drawString("start", lastPt.fX, lastPt.fY, paint);
+##
+
+#SeeAlso Contour lineTo moveTo quadTo conicTo cubicTo close()
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void lineTo(SkScalar x, SkScalar y)
+
+Adds Line from Last_Point to (x, y). If Path is empty, or last Verb is
+kClose_Verb, Last_Point is set to (0, 0) before adding Line.
+
+lineTo appends kMove_Verb to Verb_Array and (0, 0) to Point_Array, if needed.
+lineTo then appends kLine_Verb to Verb_Array and (x, y) to Point_Array.
+
+#Param x end of added Line in x ##
+#Param y end of added Line in y ##
+
+#Example
+#Height 100
+###$
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setTextSize(72);
+ canvas->drawString("#", 120, 80, paint);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(5);
+ SkPath path;
+ SkPoint hash[] = {{58, 28}, {43, 80}, {37, 45}, {85, 45}};
+ SkVector offsets[] = {{0, 0}, {17, 0}, {0, 0}, {-5, 17}};
+ unsigned o = 0;
+ for (unsigned i = 0; i < SK_ARRAY_COUNT(hash); i += 2) {
+ for (unsigned j = 0; j < 2; o++, j++) {
+ path.moveTo(hash[i].fX + offsets[o].fX, hash[i].fY + offsets[o].fY);
+ path.lineTo(hash[i + 1].fX + offsets[o].fX, hash[i + 1].fY + offsets[o].fY);
+ }
+ }
+ canvas->drawPath(path, paint);
+}
+$$$#
+##
+
+#SeeAlso Contour moveTo rLineTo addRect
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void lineTo(const SkPoint& p)
+
+Adds Line from Last_Point to Point p. If Path is empty, or last 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 Point_Array, if needed.
+lineTo then appends kLine_Verb to Verb_Array and Point p to Point_Array.
+
+#Param p end Point of added Line ##
+
+#Example
+#Height 100
+ SkPath path;
+ SkVector oxo[] = {{25, 25}, {35, 35}, {25, 35}, {35, 25},
+ {40, 20}, {40, 80}, {60, 20}, {60, 80},
+ {20, 40}, {80, 40}, {20, 60}, {80, 60}};
+ for (unsigned i = 0; i < SK_ARRAY_COUNT(oxo); i += 2) {
+ path.moveTo(oxo[i]);
+ path.lineTo(oxo[i + 1]);
+ }
+ SkPaint paint;
+ paint.setStyle(SkPaint::kStroke_Style);
+ canvas->drawPath(path, paint);
+##
+
+#SeeAlso Contour moveTo rLineTo addRect
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void rLineTo(SkScalar dx, SkScalar dy)
+
+Adds Line from Last_Point to Vector (dx, dy). If Path is empty, or last Verb is
+kClose_Verb, Last_Point is set to (0, 0) before adding Line.
+
+Appends kMove_Verb to Verb_Array and (0, 0) to Point_Array, if needed;
+then appends kLine_Verb to Verb_Array and Line end to Point_Array.
+Line end is Last_Point plus Vector (dx, dy).
+Function name stands for relative line to.
+
+#Param dx offset from Last_Point x to Line end x ##
+#Param dy offset from Last_Point y to Line end y ##
+
+#Example
+#Height 128
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ SkPath path;
+ path.moveTo(10, 98);
+ SkScalar x = 0, y = 0;
+ for (int i = 10; i < 100; i += 5) {
+ x += i * ((i & 2) - 1);
+ y += i * (((i + 1) & 2) - 1);
+ path.rLineTo(x, y);
+
+ }
+ canvas->drawPath(path, paint);
+}
+##
+
+#SeeAlso Contour moveTo lineTo addRect
+
+##
+
+# ------------------------------------------------------------------------------
#Topic Quad
+#Substitute quads
+#Alias Quads
Quad describes a quadratic Bezier, a second-order curve identical to a section
of a parabola. Quad begins at a start Point, curves towards a control Point,
@@ -2374,19 +2403,19 @@ and then curves to an end Point.
#Example
#Height 110
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
- SkPoint quadPts[] = {{20, 90}, {120, 10}, {220, 90}};
- canvas->drawLine(quadPts[0], quadPts[1], paint);
- canvas->drawLine(quadPts[1], quadPts[2], paint);
- SkPath path;
- path.moveTo(quadPts[0]);
- path.quadTo(quadPts[1], quadPts[2]);
- paint.setStrokeWidth(3);
- canvas->drawPath(path, paint);
-}
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ SkPoint quadPts[] = {{20, 90}, {120, 10}, {220, 90}};
+ canvas->drawLine(quadPts[0], quadPts[1], paint);
+ canvas->drawLine(quadPts[1], quadPts[2], paint);
+ SkPath path;
+ path.moveTo(quadPts[0]);
+ path.quadTo(quadPts[1], quadPts[2]);
+ paint.setStrokeWidth(3);
+ canvas->drawPath(path, paint);
+}
##
Quad is a special case of Conic where Conic_Weight is set to one.
@@ -2397,140 +2426,141 @@ tangent to the line between control Point and end Point.
#Example
#Height 160
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
- SkPoint quadPts[] = {{20, 150}, {120, 10}, {220, 150}};
- SkColor colors[] = { 0xff88ff00, 0xff0088bb, 0xff6600cc, 0xffbb3377 };
- for (unsigned i = 0; i < SK_ARRAY_COUNT(colors); ++i) {
- paint.setColor(0x7fffffff & colors[i]);
- paint.setStrokeWidth(1);
- canvas->drawLine(quadPts[0], quadPts[1], paint);
- canvas->drawLine(quadPts[1], quadPts[2], paint);
- SkPath path;
- path.moveTo(quadPts[0]);
- path.quadTo(quadPts[1], quadPts[2]);
- paint.setStrokeWidth(3);
- paint.setColor(colors[i]);
- canvas->drawPath(path, paint);
- quadPts[1].fY += 30;
- }
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ SkPoint quadPts[] = {{20, 150}, {120, 10}, {220, 150}};
+ SkColor colors[] = { 0xff88ff00, 0xff0088bb, 0xff6600cc, 0xffbb3377 };
+ for (unsigned i = 0; i < SK_ARRAY_COUNT(colors); ++i) {
+ paint.setColor(0x7fffffff & colors[i]);
+ paint.setStrokeWidth(1);
+ canvas->drawLine(quadPts[0], quadPts[1], paint);
+ canvas->drawLine(quadPts[1], quadPts[2], paint);
+ SkPath path;
+ path.moveTo(quadPts[0]);
+ path.quadTo(quadPts[1], quadPts[2]);
+ paint.setStrokeWidth(3);
+ paint.setColor(colors[i]);
+ canvas->drawPath(path, paint);
+ quadPts[1].fY += 30;
+ }
}
##
-
-#Method void quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2)
-
- Adds Quad from Last_Point towards (x1, y1), to (x2, y2).
- If Path is empty, or last Verb is kClose_Verb, Last_Point is set to (0, 0)
- before adding Quad.
-
- quadTo appends kMove_Verb to Verb_Array and (0, 0) to Point_Array, if needed.
- quadTo then appends kQuad_Verb to Verb_Array; and (x1, y1), (x2, y2)
- to Point_Array.
-
- #Param x1 control Point of Quad in x. ##
- #Param y1 control Point of Quad in y. ##
- #Param x2 end Point of Quad in x. ##
- #Param y2 end Point of Quad in y. ##
-
- #Example
- void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
- SkPath path;
- path.moveTo(0, -10);
- for (int i = 0; i < 128; i += 16) {
- path.quadTo( 10 + i, -10 - i, 10 + i, 0);
- path.quadTo( 14 + i, 14 + i, 0, 14 + i);
- path.quadTo(-18 - i, 18 + i, -18 - i, 0);
- path.quadTo(-22 - i, -22 - i, 0, -22 - i);
- }
- path.offset(128, 128);
+
+#Method void quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2)
+
+ Adds Quad from Last_Point towards (x1, y1), to (x2, y2).
+ If Path is empty, or last Verb is kClose_Verb, Last_Point is set to (0, 0)
+ before adding Quad.
+
+ Appends kMove_Verb to Verb_Array and (0, 0) to Point_Array, if needed;
+ then appends kQuad_Verb to Verb_Array; and (x1, y1), (x2, y2)
+ to Point_Array.
+
+ #Param x1 control Point of Quad in x ##
+ #Param y1 control Point of Quad in y ##
+ #Param x2 end Point of Quad in x ##
+ #Param y2 end Point of Quad in y ##
+
+ #Example
+ void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ SkPath path;
+ path.moveTo(0, -10);
+ for (int i = 0; i < 128; i += 16) {
+ path.quadTo( 10 + i, -10 - i, 10 + i, 0);
+ path.quadTo( 14 + i, 14 + i, 0, 14 + i);
+ path.quadTo(-18 - i, 18 + i, -18 - i, 0);
+ path.quadTo(-22 - i, -22 - i, 0, -22 - i);
+ }
+ path.offset(128, 128);
+ canvas->drawPath(path, paint);
+ }
+ ##
+
+ #SeeAlso Contour moveTo conicTo rQuadTo
+
+##
+
+#Method void quadTo(const SkPoint& p1, const SkPoint& p2)
+
+ Adds Quad from Last_Point towards Point p1, to Point p2.
+ If Path is empty, or last Verb is kClose_Verb, Last_Point is set to (0, 0)
+ before adding Quad.
+
+ Appends kMove_Verb to Verb_Array and (0, 0) to Point_Array, if needed;
+ then appends kQuad_Verb to Verb_Array; and Points p1, p2
+ to Point_Array.
+
+ #Param p1 control Point of added Quad ##
+ #Param p2 end Point of added Quad ##
+
+ #Example
+ void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setAntiAlias(true);
+ SkPath path;
+ SkPoint pts[] = {{128, 10}, {10, 214}, {236, 214}};
+ path.moveTo(pts[1]);
+ for (int i = 0; i < 3; ++i) {
+ path.quadTo(pts[i % 3], pts[(i + 2) % 3]);
+ }
+ canvas->drawPath(path, paint);
+ }
+ ##
+
+ #SeeAlso Contour moveTo conicTo rQuadTo
+
+##
+
+#Method void rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2)
+
+ Adds Quad from Last_Point towards Vector (dx1, dy1), to Vector (dx2, dy2).
+ If Path is empty, or last Verb
+ is kClose_Verb, Last_Point is set to (0, 0) before adding Quad.
+
+ Appends kMove_Verb to Verb_Array and (0, 0) to Point_Array,
+ if needed; then appends kQuad_Verb to Verb_Array; and appends Quad
+ control and Quad end to Point_Array.
+ Quad control is Last_Point plus Vector (dx1, dy1).
+ Quad end is Last_Point plus Vector (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 ##
+
+ #Example
+ void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ SkPath path;
+ path.moveTo(128, 20);
+ path.rQuadTo(-6, 10, -7, 10);
+ for (int i = 1; i < 32; i += 4) {
+ path.rQuadTo(10 + i, 10 + i, 10 + i * 4, 10);
+ path.rQuadTo(-10 - i, 10 + i, -10 - (i + 2) * 4, 10);
+ }
+ path.quadTo(92, 220, 128, 215);
canvas->drawPath(path, paint);
- }
- ##
-
- #SeeAlso Contour moveTo conicTo rQuadTo
-
-##
-
-#Method void quadTo(const SkPoint& p1, const SkPoint& p2)
-
- Adds Quad from Last_Point towards Point p1, to Point p2.
- If Path is empty, or last Verb is kClose_Verb, Last_Point is set to (0, 0)
- before adding Quad.
-
- quadTo appends kMove_Verb to Verb_Array and (0, 0) to Point_Array, if needed.
- quadTo then appends kQuad_Verb to Verb_Array; and Points p1, p2
- to Point_Array.
-
- #Param p1 control Point of added Quad. ##
- #Param p2 end Point of added Quad. ##
-
- #Example
- void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setAntiAlias(true);
- SkPath path;
- SkPoint pts[] = {{128, 10}, {10, 214}, {236, 214}};
- path.moveTo(pts[1]);
- for (int i = 0; i < 3; ++i) {
- path.quadTo(pts[i % 3], pts[(i + 2) % 3]);
- }
- canvas->drawPath(path, paint);
- }
- ##
-
- #SeeAlso Contour moveTo conicTo rQuadTo
-
-##
-
-#Method void rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2)
-
- Adds Quad from Last_Point towards Vector (dx1, dy1), to Vector (dx2, dy2).
- If Path is empty, or last Verb
- is kClose_Verb, Last_Point is set to (0, 0) before adding Quad.
-
- rQuadTo first appends kMove_Verb to Verb_Array and (0, 0) to Point_Array,
- if needed. rQuadTo then appends kQuad_Verb to Verb_Array; and appends Quad
- control and Quad end to Point_Array.
- Quad control is Last_Point plus Vector (dx1, dy1).
- Quad end is Last_Point plus Vector (dx2, dy2).
- rQuadTo 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. ##
-
- #Example
- void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setAntiAlias(true);
- SkPath path;
- path.moveTo(128, 20);
- path.rQuadTo(-6, 10, -7, 10);
- for (int i = 1; i < 32; i += 4) {
- path.rQuadTo(10 + i, 10 + i, 10 + i * 4, 10);
- path.rQuadTo(-10 - i, 10 + i, -10 - (i + 2) * 4, 10);
- }
- path.quadTo(92, 220, 128, 215);
- canvas->drawPath(path, paint);
- }
- ##
-
- #SeeAlso Contour moveTo conicTo quadTo
-
-##
-
+ }
+ ##
+
+ #SeeAlso Contour moveTo conicTo quadTo
+
+##
+
#Topic Quad ##
-
-# ------------------------------------------------------------------------------
-
+
+# ------------------------------------------------------------------------------
+
#Topic Conic
+#Substitute conics
#Alias Conics
Conic describes a conical section: a piece of an ellipse, or a piece of a
@@ -2538,11 +2568,13 @@ parabola, or a piece of a hyperbola. Conic begins at a start Point,
curves towards a control Point, and then curves to an end Point. The influence
of the control Point is determined by Conic_Weight.
-Each Conic in Path adds two Points and one Weight. Weights in Path may be
-inspected with Iter, or with RawIter.
+Each Conic in Path adds two Points and one Conic_Weight. Conic_Weights in Path
+may be inspected with Iter, or with RawIter.
#Subtopic Weight
+#Substitute weights
#Alias Weights
+#Alias Conic_Weights
Weight determines both the strength of the control Point and the type of Conic.
If Weight is exactly one, then Conic is identical to Quad; it is always a
@@ -2552,31 +2584,31 @@ parabolic segment.
#Example
#Description
-When Conic weight is one, Quad is added to path; the two are identical.
-##
-void draw(SkCanvas* canvas) {
- const char* verbNames[] = { "move", "line", "quad", "conic", "cubic", "close", "done" };
- const int pointCount[] = { 1 , 2 , 3 , 3 , 4 , 1 , 0 };
- SkPath path;
- path.conicTo(20, 30, 50, 60, 1);
- SkPath::Iter iter(path, false);
- SkPath::Verb verb;
- do {
- SkPoint points[4];
- verb = iter.next(points);
- SkDebugf("%s ", verbNames[(int) verb]);
- for (int i = 0; i < pointCount[(int) verb]; ++i) {
- SkDebugf("{%g, %g}, ", points[i].fX, points[i].fY);
- }
- if (SkPath::kConic_Verb == verb) {
- SkDebugf("weight = %g", iter.conicWeight());
- }
- SkDebugf("\n");
- } while (SkPath::kDone_Verb != verb);
+When Conic_Weight is one, Quad is added to path; the two are identical.
+##
+void draw(SkCanvas* canvas) {
+ const char* verbNames[] = { "move", "line", "quad", "conic", "cubic", "close", "done" };
+ const int pointCount[] = { 1 , 2 , 3 , 3 , 4 , 1 , 0 };
+ SkPath path;
+ path.conicTo(20, 30, 50, 60, 1);
+ SkPath::Iter iter(path, false);
+ SkPath::Verb verb;
+ do {
+ SkPoint points[4];
+ verb = iter.next(points);
+ SkDebugf("%s ", verbNames[(int) verb]);
+ for (int i = 0; i < pointCount[(int) verb]; ++i) {
+ SkDebugf("{%g, %g}, ", points[i].fX, points[i].fY);
+ }
+ if (SkPath::kConic_Verb == verb) {
+ SkDebugf("weight = %g", iter.conicWeight());
+ }
+ SkDebugf("\n");
+ } while (SkPath::kDone_Verb != verb);
}
#StdOut
-move {0, 0},
-quad {0, 0}, {20, 30}, {50, 60},
+move {0, 0},
+quad {0, 0}, {20, 30}, {50, 60},
done
##
##
@@ -2591,29 +2623,29 @@ A 90 degree circular arc has the weight
##
.
##
-void draw(SkCanvas* canvas) {
- const char* verbNames[] = { "move", "line", "quad", "conic", "cubic", "close", "done" };
- const int pointCount[] = { 1 , 2 , 3 , 3 , 4 , 1 , 0 };
- SkPath path;
- path.arcTo(20, 0, 20, 20, 20);
- SkPath::Iter iter(path, false);
- SkPath::Verb verb;
- do {
- SkPoint points[4];
- verb = iter.next(points);
- SkDebugf("%s ", verbNames[(int) verb]);
- for (int i = 0; i < pointCount[(int) verb]; ++i) {
- SkDebugf("{%g, %g}, ", points[i].fX, points[i].fY);
- }
- if (SkPath::kConic_Verb == verb) {
- SkDebugf("weight = %g", iter.conicWeight());
- }
- SkDebugf("\n");
- } while (SkPath::kDone_Verb != verb);
+void draw(SkCanvas* canvas) {
+ const char* verbNames[] = { "move", "line", "quad", "conic", "cubic", "close", "done" };
+ const int pointCount[] = { 1 , 2 , 3 , 3 , 4 , 1 , 0 };
+ SkPath path;
+ path.arcTo(20, 0, 20, 20, 20);
+ SkPath::Iter iter(path, false);
+ SkPath::Verb verb;
+ do {
+ SkPoint points[4];
+ verb = iter.next(points);
+ SkDebugf("%s ", verbNames[(int) verb]);
+ for (int i = 0; i < pointCount[(int) verb]; ++i) {
+ SkDebugf("{%g, %g}, ", points[i].fX, points[i].fY);
+ }
+ if (SkPath::kConic_Verb == verb) {
+ SkDebugf("weight = %g", iter.conicWeight());
+ }
+ SkDebugf("\n");
+ } while (SkPath::kDone_Verb != verb);
}
#StdOut
-move {0, 0},
-conic {0, 0}, {20, 0}, {20, 20}, weight = 0.707107
+move {0, 0},
+conic {0, 0}, {20, 0}, {20, 20}, weight = 0.707107
done
##
##
@@ -2623,199 +2655,200 @@ a hyperbolic segment can be approximated by straight lines connecting the
control Point with the end Points.
#Example
-void draw(SkCanvas* canvas) {
- const char* verbNames[] = { "move", "line", "quad", "conic", "cubic", "close", "done" };
- const int pointCount[] = { 1 , 2 , 3 , 3 , 4 , 1 , 0 };
- SkPath path;
- path.conicTo(20, 0, 20, 20, SK_ScalarInfinity);
- SkPath::Iter iter(path, false);
- SkPath::Verb verb;
- do {
- SkPoint points[4];
- verb = iter.next(points);
- SkDebugf("%s ", verbNames[(int) verb]);
- for (int i = 0; i < pointCount[(int) verb]; ++i) {
- SkDebugf("{%g, %g}, ", points[i].fX, points[i].fY);
- }
- if (SkPath::kConic_Verb == verb) {
- SkDebugf("weight = %g", iter.conicWeight());
- }
- SkDebugf("\n");
- } while (SkPath::kDone_Verb != verb);
+void draw(SkCanvas* canvas) {
+ const char* verbNames[] = { "move", "line", "quad", "conic", "cubic", "close", "done" };
+ const int pointCount[] = { 1 , 2 , 3 , 3 , 4 , 1 , 0 };
+ SkPath path;
+ path.conicTo(20, 0, 20, 20, SK_ScalarInfinity);
+ SkPath::Iter iter(path, false);
+ SkPath::Verb verb;
+ do {
+ SkPoint points[4];
+ verb = iter.next(points);
+ SkDebugf("%s ", verbNames[(int) verb]);
+ for (int i = 0; i < pointCount[(int) verb]; ++i) {
+ SkDebugf("{%g, %g}, ", points[i].fX, points[i].fY);
+ }
+ if (SkPath::kConic_Verb == verb) {
+ SkDebugf("weight = %g", iter.conicWeight());
+ }
+ SkDebugf("\n");
+ } while (SkPath::kDone_Verb != verb);
}
#StdOut
-move {0, 0},
-line {0, 0}, {20, 0},
-line {20, 0}, {20, 20},
+move {0, 0},
+line {0, 0}, {20, 0},
+line {20, 0}, {20, 20},
done
##
##
#Subtopic Weight ##
-
-#Method void conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
- SkScalar w)
-
- Adds Conic from Last_Point towards (x1, y1), to (x2, y2), weighted by w.
- If Path is empty, or last Verb is kClose_Verb, Last_Point is set to (0, 0)
- before adding Conic.
-
- conicTo appends kMove_Verb to Verb_Array and (0, 0) to Point_Array, if needed.
-
- If w is finite and not one, conicTo then appends kConic_Verb to Verb_Array;
- and (x1, y1), (x2, y2) to Point_Array; and w to Weights.
-
- If w is one, conicTo appends kQuad_Verb to Verb_Array, and
- (x1, y1), (x2, y2) to Point_Array.
-
- If w is not finite, conicTo appends kLine_Verb twice to Verb_Array, and
- (x1, y1), (x2, y2) to Point_Array.
-
- #Param x1 control Point of Conic in x. ##
- #Param y1 control Point of Conic in y. ##
- #Param x2 end Point of Conic in x. ##
- #Param y2 end Point of Conic in y. ##
- #Param w weight of added Conic. ##
-
- #Example
+
+#Method void conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
+ SkScalar w)
+
+ Adds Conic from Last_Point towards (x1, y1), to (x2, y2), weighted by w.
+ If Path is empty, or last Verb is kClose_Verb, Last_Point is set to (0, 0)
+ before adding Conic.
+
+ Appends kMove_Verb to Verb_Array and (0, 0) to Point_Array, if needed.
+
+ If w is finite and not one, appends kConic_Verb to Verb_Array;
+ and (x1, y1), (x2, y2) to Point_Array; and w to Conic_Weights.
+
+ If w is one, appends kQuad_Verb to Verb_Array, and
+ (x1, y1), (x2, y2) to Point_Array.
+
+ If w is not finite, appends kLine_Verb twice to Verb_Array, and
+ (x1, y1), (x2, y2) to Point_Array.
+
+ #Param x1 control Point of Conic in x ##
+ #Param y1 control Point of Conic in y ##
+ #Param x2 end Point of Conic in x ##
+ #Param y2 end Point of Conic in y ##
+ #Param w weight of added Conic ##
+
+ #Example
#Height 160
- #Description
- As weight increases, curve is pulled towards control point.
- The bottom two curves are elliptical; the next is parabolic; the
- top curve is hyperbolic.
- ##
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
- SkPoint conicPts[] = {{20, 150}, {120, 10}, {220, 150}};
- canvas->drawLine(conicPts[0], conicPts[1], paint);
- canvas->drawLine(conicPts[1], conicPts[2], paint);
- SkColor colors[] = { 0xff88ff00, 0xff0088bb, 0xff6600cc, 0xffbb3377 };
- paint.setStrokeWidth(3);
- SkScalar weight = 0.5f;
- for (unsigned i = 0; i < SK_ARRAY_COUNT(colors); ++i) {
- SkPath path;
- path.moveTo(conicPts[0]);
- path.conicTo(conicPts[1], conicPts[2], weight);
- paint.setColor(colors[i]);
- canvas->drawPath(path, paint);
- weight += 0.25f;
- }
-}
- ##
-
- #SeeAlso rConicTo arcTo addArc quadTo
-
-##
-
-#Method void conicTo(const SkPoint& p1, const SkPoint& p2, SkScalar w)
-
- Adds Conic from Last_Point towards Point p1, to Point p2, weighted by w.
- If Path is empty, or last Verb is kClose_Verb, Last_Point is set to (0, 0)
- before adding Conic.
-
- conicTo appends kMove_Verb to Verb_Array and (0, 0) to Point_Array, if needed.
-
- If w is finite and not one, conicTo then appends kConic_Verb to Verb_Array;
- and Points p1, p2 to Point_Array; and w to Weights.
-
- If w is one, conicTo appends kQuad_Verb to Verb_Array, and Points p1, p2
- to Point_Array.
-
- If w is not finite, conicTo appends kLine_Verb twice to Verb_Array, and
- Points p1, p2 to Point_Array.
-
- #Param p1 control Point of added Conic. ##
- #Param p2 end Point of added Conic. ##
- #Param w weight of added Conic. ##
-
- #Example
+ #Description
+ As weight increases, curve is pulled towards control point.
+ The bottom two curves are elliptical; the next is parabolic; the
+ top curve is hyperbolic.
+ ##
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ SkPoint conicPts[] = {{20, 150}, {120, 10}, {220, 150}};
+ canvas->drawLine(conicPts[0], conicPts[1], paint);
+ canvas->drawLine(conicPts[1], conicPts[2], paint);
+ SkColor colors[] = { 0xff88ff00, 0xff0088bb, 0xff6600cc, 0xffbb3377 };
+ paint.setStrokeWidth(3);
+ SkScalar weight = 0.5f;
+ for (unsigned i = 0; i < SK_ARRAY_COUNT(colors); ++i) {
+ SkPath path;
+ path.moveTo(conicPts[0]);
+ path.conicTo(conicPts[1], conicPts[2], weight);
+ paint.setColor(colors[i]);
+ canvas->drawPath(path, paint);
+ weight += 0.25f;
+ }
+}
+ ##
+
+ #SeeAlso rConicTo arcTo addArc quadTo
+
+##
+
+#Method void conicTo(const SkPoint& p1, const SkPoint& p2, SkScalar w)
+
+ Adds Conic from Last_Point towards Point p1, to Point p2, weighted by w.
+ If Path is empty, or last Verb is kClose_Verb, Last_Point is set to (0, 0)
+ before adding Conic.
+
+ Appends kMove_Verb to Verb_Array and (0, 0) to Point_Array, if needed.
+
+ If w is finite and not one, appends kConic_Verb to Verb_Array;
+ and Points p1, p2 to Point_Array; and w to Conic_Weights.
+
+ If w is one, appends kQuad_Verb to Verb_Array, and Points p1, p2
+ to Point_Array.
+
+ If w is not finite, appends kLine_Verb twice to Verb_Array, and
+ Points p1, p2 to Point_Array.
+
+ #Param p1 control Point of added Conic ##
+ #Param p2 end Point of added Conic ##
+ #Param w weight of added Conic ##
+
+ #Example
#Height 128
- #Description
- Conics and arcs use identical representations. As the arc sweep increases
- the conic weight also increases, but remains smaller than one.
- ##
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
- SkRect oval = {0, 20, 120, 140};
- SkPath path;
- for (int i = 0; i < 4; ++i) {
- path.moveTo(oval.centerX(), oval.fTop);
- path.arcTo(oval, -90, 90 - 20 * i, false);
- oval.inset(15, 15);
- }
- path.offset(100, 0);
- SkScalar conicWeights[] = { 0.707107f, 0.819152f, 0.906308f, 0.965926f };
- SkPoint conicPts[][3] = { { {40, 20}, {100, 20}, {100, 80} },
- { {40, 35}, {71.509f, 35}, {82.286f, 64.6091f} },
- { {40, 50}, {53.9892f, 50}, {62.981f, 60.7164f} },
- { {40, 65}, {44.0192f, 65}, {47.5f, 67.0096f} } };
- for (int i = 0; i < 4; ++i) {
- path.moveTo(conicPts[i][0]);
- path.conicTo(conicPts[i][1], conicPts[i][2], conicWeights[i]);
- }
- canvas->drawPath(path, paint);
-}
- ##
-
- #SeeAlso rConicTo arcTo addArc quadTo
-
-##
-
-#Method void rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
- SkScalar w)
-
- Adds Conic from Last_Point towards Vector (dx1, dy1), to Vector (dx2, dy2),
- weighted by w. If Path is empty, or last Verb
- is kClose_Verb, Last_Point is set to (0, 0) before adding Conic.
-
- rConicTo first appends kMove_Verb to Verb_Array and (0, 0) to Point_Array,
- if needed.
-
- If w is finite and not one, rConicTo then appends kConic_Verb to Verb_Array,
- and w is recorded as Conic_Weight; otherwise, if w is one, rConicTo appends
- kQuad_Verb to Verb_Array; or if w is not finite, rConicTo appends kLine_Verb
- twice to Verb_Array.
-
- In all cases rConicTo then appends Points control and end to Point_Array.
- control is Last_Point plus Vector (dx1, dy1).
- end is Last_Point plus Vector (dx2, dy2).
-
- rConicTo 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. ##
-
- #Example
- #Height 140
- void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
- SkPath path;
- path.moveTo(20, 80);
- path.rConicTo( 60, 0, 60, 60, 0.707107f);
- path.rConicTo( 0, -60, 60, -60, 0.707107f);
- path.rConicTo(-60, 0, -60, -60, 0.707107f);
- path.rConicTo( 0, 60, -60, 60, 0.707107f);
- canvas->drawPath(path, paint);
- }
- ##
-
- #SeeAlso conicTo arcTo addArc quadTo
-
-##
-
-#Topic Conic ##
-
-# ------------------------------------------------------------------------------
+ #Description
+ Conics and arcs use identical representations. As the arc sweep increases
+ the conic weight also increases, but remains smaller than one.
+ ##
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ SkRect oval = {0, 20, 120, 140};
+ SkPath path;
+ for (int i = 0; i < 4; ++i) {
+ path.moveTo(oval.centerX(), oval.fTop);
+ path.arcTo(oval, -90, 90 - 20 * i, false);
+ oval.inset(15, 15);
+ }
+ path.offset(100, 0);
+ SkScalar conicWeights[] = { 0.707107f, 0.819152f, 0.906308f, 0.965926f };
+ SkPoint conicPts[][3] = { { {40, 20}, {100, 20}, {100, 80} },
+ { {40, 35}, {71.509f, 35}, {82.286f, 64.6091f} },
+ { {40, 50}, {53.9892f, 50}, {62.981f, 60.7164f} },
+ { {40, 65}, {44.0192f, 65}, {47.5f, 67.0096f} } };
+ for (int i = 0; i < 4; ++i) {
+ path.moveTo(conicPts[i][0]);
+ path.conicTo(conicPts[i][1], conicPts[i][2], conicWeights[i]);
+ }
+ canvas->drawPath(path, paint);
+}
+ ##
+
+ #SeeAlso rConicTo arcTo addArc quadTo
+
+##
+
+#Method void rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
+ SkScalar w)
+
+ Adds Conic from Last_Point towards Vector (dx1, dy1), to Vector (dx2, dy2),
+ weighted by w. If Path is empty, or last Verb
+ is kClose_Verb, Last_Point is set to (0, 0) before adding Conic.
+
+ Appends kMove_Verb to Verb_Array and (0, 0) to Point_Array,
+ 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 Points control and end to Point_Array.
+ control is Last_Point plus Vector (dx1, dy1).
+ end is Last_Point plus Vector (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 ##
+
+ #Example
+ #Height 140
+ void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ SkPath path;
+ path.moveTo(20, 80);
+ path.rConicTo( 60, 0, 60, 60, 0.707107f);
+ path.rConicTo( 0, -60, 60, -60, 0.707107f);
+ path.rConicTo(-60, 0, -60, -60, 0.707107f);
+ path.rConicTo( 0, 60, -60, 60, 0.707107f);
+ canvas->drawPath(path, paint);
+ }
+ ##
+
+ #SeeAlso conicTo arcTo addArc quadTo
+
+##
+
+#Topic Conic ##
+
+# ------------------------------------------------------------------------------
#Topic Cubic
+#Substitute cubics
#Alias Cubics
Cubic describes a cubic Bezier, a third-order curve.
@@ -2824,1672 +2857,1681 @@ and curves from the end Point towards the second control Point.
#Example
#Height 160
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
- SkPoint cubicPts[] = {{20, 150}, {90, 10}, {160, 150}, {230, 10}};
- SkColor colors[] = { 0xff88ff00, 0xff0088bb, 0xff6600cc, 0xffbb3377 };
- for (unsigned i = 0; i < SK_ARRAY_COUNT(colors); ++i) {
- paint.setColor(0x7fffffff & colors[i]);
- paint.setStrokeWidth(1);
- for (unsigned j = 0; j < 3; ++j) {
- canvas->drawLine(cubicPts[j], cubicPts[j + 1], paint);
- }
- SkPath path;
- path.moveTo(cubicPts[0]);
- path.cubicTo(cubicPts[1], cubicPts[2], cubicPts[3]);
- paint.setStrokeWidth(3);
- paint.setColor(colors[i]);
- canvas->drawPath(path, paint);
- cubicPts[1].fY += 30;
- cubicPts[2].fX += 30;
- }
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ SkPoint cubicPts[] = {{20, 150}, {90, 10}, {160, 150}, {230, 10}};
+ SkColor colors[] = { 0xff88ff00, 0xff0088bb, 0xff6600cc, 0xffbb3377 };
+ for (unsigned i = 0; i < SK_ARRAY_COUNT(colors); ++i) {
+ paint.setColor(0x7fffffff & colors[i]);
+ paint.setStrokeWidth(1);
+ for (unsigned j = 0; j < 3; ++j) {
+ canvas->drawLine(cubicPts[j], cubicPts[j + 1], paint);
+ }
+ SkPath path;
+ path.moveTo(cubicPts[0]);
+ path.cubicTo(cubicPts[1], cubicPts[2], cubicPts[3]);
+ paint.setStrokeWidth(3);
+ paint.setColor(colors[i]);
+ canvas->drawPath(path, paint);
+ cubicPts[1].fY += 30;
+ cubicPts[2].fX += 30;
+ }
+}
+##
+
+#Method void cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
+ SkScalar x3, SkScalar y3)
+
+Adds Cubic from Last_Point towards (x1, y1), then towards (x2, y2), ending at
+(x3, y3). If Path is empty, or last Verb is kClose_Verb, Last_Point is set to
+(0, 0) before adding Cubic.
+
+Appends kMove_Verb to Verb_Array and (0, 0) to Point_Array, if needed;
+then appends kCubic_Verb to Verb_Array; and (x1, y1), (x2, y2), (x3, y3)
+to Point_Array.
+
+#Param x1 first control Point of Cubic in x ##
+#Param y1 first control Point of Cubic in y ##
+#Param x2 second control Point of Cubic in x ##
+#Param y2 second control Point of Cubic in y ##
+#Param x3 end Point of Cubic in x ##
+#Param y3 end Point of Cubic in y ##
+
+#Example
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ SkPath path;
+ path.moveTo(0, -10);
+ for (int i = 0; i < 128; i += 16) {
+ SkScalar c = i * 0.5f;
+ path.cubicTo( 10 + c, -10 - i, 10 + i, -10 - c, 10 + i, 0);
+ path.cubicTo( 14 + i, 14 + c, 14 + c, 14 + i, 0, 14 + i);
+ path.cubicTo(-18 - c, 18 + i, -18 - i, 18 + c, -18 - i, 0);
+ path.cubicTo(-22 - i, -22 - c, -22 - c, -22 - i, 0, -22 - i);
+ }
+ path.offset(128, 128);
+ canvas->drawPath(path, paint);
+}
+##
+
+#SeeAlso Contour moveTo rCubicTo quadTo
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void cubicTo(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3)
+
+Adds Cubic from Last_Point towards Point p1, then towards Point p2, ending at
+Point p3. If Path is empty, or last Verb is kClose_Verb, Last_Point is set to
+(0, 0) before adding Cubic.
+
+Appends kMove_Verb to Verb_Array and (0, 0) to Point_Array, if needed;
+then appends kCubic_Verb to Verb_Array; and Points p1, p2, p3
+to Point_Array.
+
+#Param p1 first control Point of Cubic ##
+#Param p2 second control Point of Cubic ##
+#Param p3 end Point of Cubic ##
+
+#Example
+#Height 84
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ SkPoint pts[] = { {20, 20}, {300, 80}, {-140, 90}, {220, 10} };
+ SkPath path;
+ path.moveTo(pts[0]);
+ path.cubicTo(pts[1], pts[2], pts[3]);
+ canvas->drawPath(path, paint);
+##
+
+#SeeAlso Contour moveTo rCubicTo quadTo
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
+ SkScalar x3, SkScalar y3)
+
+ Adds Cubic from Last_Point towards Vector (dx1, dy1), then towards
+ Vector (dx2, dy2), to Vector (dx3, dy3).
+ If Path is empty, or last Verb
+ is kClose_Verb, Last_Point is set to (0, 0) before adding Cubic.
+
+ Appends kMove_Verb to Verb_Array and (0, 0) to Point_Array,
+ if needed; then appends kCubic_Verb to Verb_Array; and appends Cubic
+ control and Cubic end to Point_Array.
+ Cubic control is Last_Point plus Vector (dx1, dy1).
+ Cubic end is Last_Point plus Vector (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 ##
+
+#Example
+ void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ SkPath path;
+ path.moveTo(24, 108);
+ for (int i = 0; i < 16; i++) {
+ SkScalar sx, sy;
+ sx = SkScalarSinCos(i * SK_ScalarPI / 8, &sy);
+ path.rCubicTo(40 * sx, 4 * sy, 4 * sx, 40 * sy, 40 * sx, 40 * sy);
+ }
+ canvas->drawPath(path, paint);
+ }
+##
+
+#SeeAlso Contour moveTo cubicTo quadTo
+
+##
+
+#Topic Cubic ##
+
+# ------------------------------------------------------------------------------
+
+#Topic Arc
+
+Arc can be constructed in a number of ways. Arc may be described by part of Oval and angles,
+by start point and end point, and by radius and tangent lines. Each construction has advantages,
+and some constructions correspond to Arc drawing in graphics standards.
+
+All Arc draws are implemented by one or more Conic draws. When Conic_Weight is less than one,
+Conic describes an Arc of some Oval or Circle.
+
+arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo)
+describes Arc as a piece of Oval, beginning at start angle, sweeping clockwise or counterclockwise,
+which may continue Contour or start a new one. This construction is similar to PostScript and
+HTML_Canvas arcs. Variation addArc always starts new Contour. Canvas::drawArc draws without
+requiring Path.
+
+arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar radius)
+describes Arc as tangent to the line (x0, y0), (x1, y1) and tangent to the line (x1, y1), (x2, y2)
+where (x0, y0) is the last Point added to Path. This construction is similar to PostScript and
+HTML_Canvas arcs.
+
+arcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc, Direction sweep,
+ SkScalar x, SkScalar y)
+describes Arc as part of Oval with radii (rx, ry), beginning at
+last Point added to Path and ending at (x, y). More than one Arc satisfies this criteria,
+so additional values choose a single solution. This construction is similar to SVG arcs.
+
+conicTo describes Arc of less than 180 degrees as a pair of tangent lines and Conic_Weight.
+conicTo can represent any Arc with a sweep less than 180 degrees at any rotation. All arcTo
+constructions are converted to Conic data when added to Path.
+
+#ToDo allow example to hide source and not be exposed as fiddle since markdown / html can't
+ do the kind of table shown in the illustration.
+ example is spaced correctly on fiddle but spacing is too wide on pc
+##
+
+#Example
+#Height 300
+#Width 600
+#Description
+#List
+# <sup>1</sup> arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo) ##
+# <sup>2</sup> parameter sets force MoveTo ##
+# <sup>3</sup> start angle must be multiple of 90 degrees. ##
+# <sup>4</sup> arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar radius) ##
+# <sup>5</sup> arcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,
+ Direction sweep, SkScalar x, SkScalar y) ##
+#List ##
+#Description ##
+#Function
+struct data {
+ const char* name;
+ char super;
+ int yn[10];
+};
+
+const data dataSet[] = {
+{ "arcTo sweep", '1', {1, 3, 1, 0, 0, 0, 0, 1, 0, 0 }},
+{ "drawArc", 0, {1, -1, 1, 1, 1, 1, 1, 0, 0, 0 }},
+{ "addArc", 0, {1, 1, 1, 4, 0, 1, 1, 1, 0, 0 }},
+{ "arcTo tangents", '4', {0, 0, 0, 0, 0, 0, 0, 1, 1, 0 }},
+{ "arcTo radii", '5', {1, 0, 1, 0, 0, 0, 0, 1, 1, 0 }},
+{ "conicTo", 0, {1, 1, 0, 0, 0, 0, 0, 1, 1, 1 }}
+};
+
+#define __degree_symbol__ "\xC2" "\xB0"
+
+const char* headers[] = {
+ "Oval part",
+ "force moveTo",
+ "can draw 180" __degree_symbol__,
+ "can draw 360" __degree_symbol__,
+ "can draw greater than 360" __degree_symbol__,
+ "ignored if radius is zero",
+ "ignored if sweep is zero",
+ "requires Path",
+ "describes rotation",
+ "describes perspective",
+};
+
+const char* yna[] = {
+ "n/a",
+ "no",
+ "yes"
+};
+
+##
+void draw(SkCanvas* canvas) {
+ SkPaint lp;
+ lp.setAntiAlias(true);
+ SkPaint tp(lp);
+ SkPaint sp(tp);
+ SkPaint bp(tp);
+ bp.setFakeBoldText(true);
+ sp.setTextSize(10);
+ lp.setColor(SK_ColorGRAY);
+ canvas->translate(0, 32);
+ const int tl = 115;
+ for (unsigned col = 0; col <= SK_ARRAY_COUNT(headers); ++col) {
+ canvas->drawLine(tl + col * 35, 100, tl + col * 35, 250, lp);
+ if (0 == col) {
+ continue;
+ }
+ canvas->drawLine(tl + col * 35, 100, tl + 100 + col * 35, 0, lp);
+ SkPath path;
+ path.moveTo(tl - 3 + col * 35, 103);
+ path.lineTo(tl + 124 + col * 35, -24);
+ canvas->drawTextOnPathHV(headers[col -1], strlen(headers[col -1]), path, 0, -9, bp);
+ }
+ for (unsigned row = 0; row <= SK_ARRAY_COUNT(dataSet); ++row) {
+ if (0 == row) {
+ canvas->drawLine(tl, 100, tl + 350, 100, lp);
+ } else {
+ canvas->drawLine(5, 100 + row * 25, tl + 350, 100 + row * 25, lp);
+ }
+ if (row == SK_ARRAY_COUNT(dataSet)) {
+ break;
+ }
+ canvas->drawString(dataSet[row].name, 5, 117 + row * 25, bp);
+ if (dataSet[row].super) {
+ SkScalar width = bp.measureText(dataSet[row].name, strlen(dataSet[row].name));
+ canvas->drawText(&dataSet[row].super, 1, 8 + width, 112 + row * 25, sp);
+ }
+ for (unsigned col = 0; col < SK_ARRAY_COUNT(headers); ++col) {
+ int val = dataSet[row].yn[col];
+ canvas->drawString(yna[SkTMin(2, val + 1)], tl + 5 + col * 35, 117 + row * 25, tp);
+ if (val > 1) {
+ char supe = '0' + val - 1;
+ canvas->drawText(&supe, 1, tl + 25 + col * 35, 112 + row * 25, sp);
+ }
+ }
+ }
+}
+#Example ##
+
+#Example
+#Height 128
+#Description
+#ToDo make this a list or table ##
+1 describes an arc from an oval, a starting angle, and a sweep angle.
+2 is similar to 1, but does not require building a path to draw.
+3 is similar to 1, but always begins new Contour.
+4 describes an arc from a pair of tangent lines and a radius.
+5 describes an arc from Oval center, arc start Point and arc end Point.
+6 describes an arc from a pair of tangent lines and a Conic_Weight.
+##
+void draw(SkCanvas* canvas) {
+ SkRect oval = {8, 8, 56, 56};
+ SkPaint ovalPaint;
+ ovalPaint.setAntiAlias(true);
+ SkPaint textPaint(ovalPaint);
+ ovalPaint.setStyle(SkPaint::kStroke_Style);
+ SkPaint arcPaint(ovalPaint);
+ arcPaint.setStrokeWidth(5);
+ arcPaint.setColor(SK_ColorBLUE);
+ canvas->translate(-64, 0);
+ for (char arcStyle = '1'; arcStyle <= '6'; ++arcStyle) {
+ '4' == arcStyle ? canvas->translate(-96, 55) : canvas->translate(64, 0);
+ canvas->drawText(&arcStyle, 1, 30, 36, textPaint);
+ canvas->drawOval(oval, ovalPaint);
+ SkPath path;
+ path.moveTo({56, 32});
+ switch (arcStyle) {
+ case '1':
+ path.arcTo(oval, 0, 90, false);
+ break;
+ case '2':
+ canvas->drawArc(oval, 0, 90, false, arcPaint);
+ continue;
+ case '3':
+ path.addArc(oval, 0, 90);
+ break;
+ case '4':
+ path.arcTo({56, 56}, {32, 56}, 24);
+ break;
+ case '5':
+ path.arcTo({24, 24}, 0, SkPath::kSmall_ArcSize, SkPath::kCW_Direction, {32, 56});
+ break;
+ case '6':
+ path.conicTo({56, 56}, {32, 56}, SK_ScalarRoot2Over2);
+ break;
+ }
+ canvas->drawPath(path, arcPaint);
+ }
+}
+#Example ##
+
+
+#Method void arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo)
+
+Append Arc to Path. 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 Path last Point to initial Arc Point if forceMoveTo
+is false and Path 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 ##
+
+#Example
+#Height 200
+#Description
+arcTo continues a previous contour when forceMoveTo is false and when Path
+is not empty.
+##
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ SkPath path;
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(4);
+ path.moveTo(0, 0);
+ path.arcTo({20, 20, 120, 120}, -90, 90, false);
+ canvas->drawPath(path, paint);
+ path.rewind();
+ path.arcTo({120, 20, 220, 120}, -90, 90, false);
+ canvas->drawPath(path, paint);
+ path.rewind();
+ path.moveTo(0, 0);
+ path.arcTo({20, 120, 120, 220}, -90, 90, true);
+ canvas->drawPath(path, paint);
+}
+##
+
+#SeeAlso addArc SkCanvas::drawArc conicTo
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar radius)
+
+Append Arc to Path, after appending Line if needed. Arc is implemented by Conic
+weighted to describe part of Circle. Arc is contained by tangent from
+last Path 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.
+
+#ToDo allow example to hide source and not be exposed as fiddle ##
+
+#Example
+#Height 226
+void draw(SkCanvas* canvas) {
+ SkPaint tangentPaint;
+ tangentPaint.setAntiAlias(true);
+ SkPaint textPaint(tangentPaint);
+ tangentPaint.setStyle(SkPaint::kStroke_Style);
+ tangentPaint.setColor(SK_ColorGRAY);
+ SkPaint arcPaint(tangentPaint);
+ arcPaint.setStrokeWidth(5);
+ arcPaint.setColor(SK_ColorBLUE);
+ SkPath path;
+ SkPoint pts[] = { {56, 20}, {200, 20}, {90, 190} };
+ SkScalar radius = 50;
+ path.moveTo(pts[0]);
+ path.arcTo(pts[1], pts[2], radius);
+ canvas->drawLine(pts[0], pts[1], tangentPaint);
+ canvas->drawLine(pts[1], pts[2], tangentPaint);
+ SkPoint lastPt;
+ (void) path.getLastPt(&lastPt);
+ SkVector radial = pts[2] - pts[1];
+ radial.setLength(radius);
+ SkPoint center = { lastPt.fX - radial.fY, lastPt.fY + radial.fX };
+ canvas->drawCircle(center, radius, tangentPaint);
+ canvas->drawLine(lastPt, center, tangentPaint);
+ radial = pts[1] - pts[0];
+ radial.setLength(radius);
+ SkPoint arcStart = { center.fX + radial.fY, center.fY - radial.fX };
+ canvas->drawLine(center, arcStart, tangentPaint);
+ canvas->drawPath(path, arcPaint);
+ textPaint.setTextAlign(SkPaint::kRight_Align);
+ canvas->drawString("(x0, y0)", pts[0].fX - 5, pts[0].fY, textPaint);
+ textPaint.setTextAlign(SkPaint::kLeft_Align);
+ canvas->drawString("(x1, y1)", pts[1].fX + 5, pts[1].fY, textPaint);
+ textPaint.setTextAlign(SkPaint::kCenter_Align);
+ canvas->drawString("(x2, y2)", pts[2].fX, pts[2].fY + 15, textPaint);
+ textPaint.setTextAlign(SkPaint::kRight_Align);
+ canvas->drawString("radius", center.fX + 15, center.fY + 25, textPaint);
+ canvas->drawString("radius", center.fX - 3, center.fY - 16, textPaint);
+}
+##
+
+If last Path Point does not start Arc, arcTo appends connecting Line to Path.
+The length of Vector from (x1, y1) to (x2, y2) does not affect Arc.
+
+#Example
+#Height 128
+void draw(SkCanvas* canvas) {
+ SkPaint tangentPaint;
+ tangentPaint.setAntiAlias(true);
+ SkPaint textPaint(tangentPaint);
+ tangentPaint.setStyle(SkPaint::kStroke_Style);
+ tangentPaint.setColor(SK_ColorGRAY);
+ SkPaint arcPaint(tangentPaint);
+ arcPaint.setStrokeWidth(5);
+ arcPaint.setColor(SK_ColorBLUE);
+ SkPath path;
+ SkPoint pts[] = { {156, 20}, {200, 20}, {170, 50} };
+ SkScalar radius = 50;
+ path.moveTo(pts[0]);
+ path.arcTo(pts[1], pts[2], radius);
+ canvas->drawLine(pts[0], pts[1], tangentPaint);
+ canvas->drawLine(pts[1], pts[2], tangentPaint);
+ SkPoint lastPt;
+ (void) path.getLastPt(&lastPt);
+ SkVector radial = pts[2] - pts[1];
+ radial.setLength(radius);
+ SkPoint center = { lastPt.fX - radial.fY, lastPt.fY + radial.fX };
+ canvas->drawLine(lastPt, center, tangentPaint);
+ radial = pts[1] - pts[0];
+ radial.setLength(radius);
+ SkPoint arcStart = { center.fX + radial.fY, center.fY - radial.fX };
+ canvas->drawLine(center, arcStart, tangentPaint);
+ canvas->drawPath(path, arcPaint);
+ textPaint.setTextAlign(SkPaint::kCenter_Align);
+ canvas->drawString("(x0, y0)", pts[0].fX, pts[0].fY - 7, textPaint);
+ textPaint.setTextAlign(SkPaint::kLeft_Align);
+ canvas->drawString("(x1, y1)", pts[1].fX + 5, pts[1].fY, textPaint);
+ textPaint.setTextAlign(SkPaint::kCenter_Align);
+ canvas->drawString("(x2, y2)", pts[2].fX, pts[2].fY + 15, textPaint);
+ textPaint.setTextAlign(SkPaint::kRight_Align);
+ canvas->drawString("radius", center.fX + 15, center.fY + 25, textPaint);
+ canvas->drawString("radius", center.fX - 5, center.fY - 20, textPaint);
+}
+##
+
+Arc sweep is always less than 180 degrees. If radius is zero, or if
+tangents are nearly parallel, arcTo appends Line from last Path Point to (x1, y1).
+
+arcTo appends at most one Line and one Conic.
+arcTo implements the functionality of PostScript_arct and HTML_Canvas_arcTo.
+
+#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 ##
+
+#Example
+#Description
+arcTo is represented by Line and circular Conic in Path.
+##
+void draw(SkCanvas* canvas) {
+ SkPath path;
+ path.moveTo({156, 20});
+ path.arcTo(200, 20, 170, 50, 50);
+ SkPath::Iter iter(path, false);
+ SkPoint p[4];
+ SkPath::Verb verb;
+ while (SkPath::kDone_Verb != (verb = iter.next(p))) {
+ switch (verb) {
+ case SkPath::kMove_Verb:
+ SkDebugf("move to (%g,%g)\n", p[0].fX, p[0].fY);
+ break;
+ case SkPath::kLine_Verb:
+ SkDebugf("line (%g,%g),(%g,%g)\n", p[0].fX, p[0].fY, p[1].fX, p[1].fY);
+ break;
+ case SkPath::kConic_Verb:
+ SkDebugf("conic (%g,%g),(%g,%g),(%g,%g) weight %g\n",
+ p[0].fX, p[0].fY, p[1].fX, p[1].fY, p[2].fX, p[2].fY, iter.conicWeight());
+ break;
+ default:
+ SkDebugf("unexpected verb\n");
+ }
+ }
+}
+#StdOut
+move to (156,20)
+line (156,20),(79.2893,20)
+conic (79.2893,20),(200,20),(114.645,105.355) weight 0.382683
+##
+##
+
+#SeeAlso conicTo
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius)
+
+Append Arc to Path, after appending Line if needed. Arc is implemented by Conic
+weighted to describe part of Circle. Arc is contained by tangent from
+last Path 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 Path Point does not start Arc, arcTo appends connecting Line to Path.
+The length of Vector 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 Path Point to p1.
+
+arcTo appends at most one Line and one Conic.
+arcTo implements the functionality of PostScript_arct and HTML_Canvas_arcTo.
+
+#Param p1 Point common to pair of tangents ##
+#Param p2 end of second tangent ##
+#Param radius distance from Arc to Circle center ##
+
+#Example
+#Description
+Because tangent lines are parallel, arcTo appends line from last Path Point to
+p1, but does not append a circular Conic.
+##
+void draw(SkCanvas* canvas) {
+ SkPath path;
+ path.moveTo({156, 20});
+ path.arcTo({200, 20}, {170, 20}, 50);
+ SkPath::Iter iter(path, false);
+ SkPoint p[4];
+ SkPath::Verb verb;
+ while (SkPath::kDone_Verb != (verb = iter.next(p))) {
+ switch (verb) {
+ case SkPath::kMove_Verb:
+ SkDebugf("move to (%g,%g)\n", p[0].fX, p[0].fY);
+ break;
+ case SkPath::kLine_Verb:
+ SkDebugf("line (%g,%g),(%g,%g)\n", p[0].fX, p[0].fY, p[1].fX, p[1].fY);
+ break;
+ case SkPath::kConic_Verb:
+ SkDebugf("conic (%g,%g),(%g,%g),(%g,%g) weight %g\n",
+ p[0].fX, p[0].fY, p[1].fX, p[1].fY, p[2].fX, p[2].fY, iter.conicWeight());
+ break;
+ default:
+ SkDebugf("unexpected verb\n");
+ }
+ }
+}
+#StdOut
+move to (156,20)
+line (156,20),(200,20)
+##
+##
+
+#SeeAlso conicTo
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Enum ArcSize
+
+#Code
+ enum ArcSize {
+ kSmall_ArcSize,
+ kLarge_ArcSize,
+ };
+##
+
+Four Oval parts with radii (rx, ry) start at last Path Point and ends at (x, y).
+ArcSize and Direction select one of the four Oval parts.
+
+#Const kSmall_ArcSize 0
+Smaller of Arc pair.
+##
+#Const kLarge_ArcSize 1
+Larger of Arc pair.
+##
+
+#Example
+#Height 160
+#Description
+Arc begins at top of Oval pair and ends at bottom. Arc can take four routes to get there.
+Two routes are large, and two routes are counterclockwise. The one route both large
+and counterclockwise is blue.
+##
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ for (auto sweep: { SkPath::kCW_Direction, SkPath::kCCW_Direction } ) {
+ for (auto arcSize : { SkPath::kSmall_ArcSize, SkPath::kLarge_ArcSize } ) {
+ SkPath path;
+ path.moveTo({120, 50});
+ path.arcTo(70, 40, 30, arcSize, sweep, 156, 100);
+ if (SkPath::kCCW_Direction == sweep && SkPath::kLarge_ArcSize == arcSize) {
+ paint.setColor(SK_ColorBLUE);
+ paint.setStrokeWidth(3);
+ }
+ canvas->drawPath(path, paint);
+ }
+ }
}
##
-
-#Method void cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
- SkScalar x3, SkScalar y3)
-
-Adds Cubic from Last_Point towards (x1, y1), then towards (x2, y2), ending at
-(x3, y3). If Path is empty, or last Verb is kClose_Verb, Last_Point is set to
-(0, 0) before adding Cubic.
-
-cubicTo appends kMove_Verb to Verb_Array and (0, 0) to Point_Array, if needed.
-cubicTo then appends kCubic_Verb to Verb_Array; and (x1, y1), (x2, y2), (x3, y3)
-to Point_Array.
-
-#Param x1 first control Point of Cubic in x. ##
-#Param y1 first control Point of Cubic in y. ##
-#Param x2 second control Point of Cubic in x. ##
-#Param y2 second control Point of Cubic in y. ##
-#Param x3 end Point of Cubic in x. ##
-#Param y3 end Point of Cubic in y. ##
-
-#Example
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
- SkPath path;
- path.moveTo(0, -10);
- for (int i = 0; i < 128; i += 16) {
- SkScalar c = i * 0.5f;
- path.cubicTo( 10 + c, -10 - i, 10 + i, -10 - c, 10 + i, 0);
- path.cubicTo( 14 + i, 14 + c, 14 + c, 14 + i, 0, 14 + i);
- path.cubicTo(-18 - c, 18 + i, -18 - i, 18 + c, -18 - i, 0);
- path.cubicTo(-22 - i, -22 - c, -22 - c, -22 - i, 0, -22 - i);
- }
- path.offset(128, 128);
- canvas->drawPath(path, paint);
-}
-##
-
-#SeeAlso Contour moveTo rCubicTo quadTo
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void cubicTo(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3)
-
-Adds Cubic from Last_Point towards Point p1, then towards Point p2, ending at
-Point p3. If Path is empty, or last Verb is kClose_Verb, Last_Point is set to
-(0, 0) before adding Cubic.
-
-cubicTo appends kMove_Verb to Verb_Array and (0, 0) to Point_Array, if needed.
-cubicTo then appends kCubic_Verb to Verb_Array; and Points p1, p2, p3
-to Point_Array.
-
-#Param p1 first control Point of Cubic. ##
-#Param p2 second control Point of Cubic. ##
-#Param p3 end Point of Cubic. ##
-
-#Example
-#Height 84
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
- SkPoint pts[] = { {20, 20}, {300, 80}, {-140, 90}, {220, 10} };
- SkPath path;
- path.moveTo(pts[0]);
- path.cubicTo(pts[1], pts[2], pts[3]);
- canvas->drawPath(path, paint);
-##
-
-#SeeAlso Contour moveTo rCubicTo quadTo
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
- SkScalar x3, SkScalar y3)
-
- Adds Cubic from Last_Point towards Vector (dx1, dy1), then towards
- Vector (dx2, dy2), to Vector (dx3, dy3).
- If Path is empty, or last Verb
- is kClose_Verb, Last_Point is set to (0, 0) before adding Cubic.
-
- rCubicTo first appends kMove_Verb to Verb_Array and (0, 0) to Point_Array,
- if needed. rCubicTo then appends kCubic_Verb to Verb_Array; and appends Cubic
- control and Cubic end to Point_Array.
- Cubic control is Last_Point plus Vector (dx1, dy1).
- Cubic end is Last_Point plus Vector (dx2, dy2).
- rCubicTo 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. ##
-
-#Example
- void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
- SkPath path;
- path.moveTo(24, 108);
- for (int i = 0; i < 16; i++) {
- SkScalar sx, sy;
- sx = SkScalarSinCos(i * SK_ScalarPI / 8, &sy);
- path.rCubicTo(40 * sx, 4 * sy, 4 * sx, 40 * sy, 40 * sx, 40 * sy);
- }
- canvas->drawPath(path, paint);
- }
-##
-
-#SeeAlso Contour moveTo cubicTo quadTo
-
-##
-
-#Topic Cubic ##
-
-# ------------------------------------------------------------------------------
-
-#Topic Arc
-
-Arc can be constructed in a number of ways. Arc may be described by part of Oval and angles,
-by start point and end point, and by radius and tangent lines. Each construction has advantages,
-and some constructions correspond to Arc drawing in graphics standards.
-
-All Arc draws are implemented by one or more Conic draws. When Conic_Weight is less than one,
-Conic describes an Arc of some Oval or Circle.
-
-arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo)
-describes Arc as a piece of Oval, beginning at start angle, sweeping clockwise or counterclockwise,
-which may continue Contour or start a new one. This construction is similar to PostScript and
-HTML_Canvas arcs. Variation addArc always starts new Contour. Canvas::drawArc draws without
-requiring Path.
-
-arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar radius)
-describes Arc as tangent to the line (x0, y0), (x1, y1) and tangent to the line (x1, y1), (x2, y2)
-where (x0, y0) is the last Point added to Path. This construction is similar to PostScript and
-HTML_Canvas arcs.
-
-arcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc, Direction sweep,
- SkScalar x, SkScalar y)
-describes Arc as part of Oval with radii (rx, ry), beginning at
-last Point added to Path and ending at (x, y). More than one Arc satisfies this criteria,
-so additional values choose a single solution. This construction is similar to SVG arcs.
-
-conicTo describes Arc of less than 180 degrees as a pair of tangent lines and Conic_Weight.
-conicTo can represent any Arc with a sweep less than 180 degrees at any rotation. All arcTo
-constructions are converted to Conic data when added to Path.
-
-#ToDo allow example to hide source and not be exposed as fiddle since markdown / html can't
- do the kind of table shown in the illustration.
- example is spaced correctly on fiddle but spacing is too wide on pc
-##
-
-#Example
-#Height 300
-#Width 600
-#Description
-#List
-# <sup>1</sup> arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo) ##
-# <sup>2</sup> parameter sets force MoveTo ##
-# <sup>3</sup> start angle must be multiple of 90 degrees. ##
-# <sup>4</sup> arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar radius) ##
-# <sup>5</sup> arcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,
- Direction sweep, SkScalar x, SkScalar y) ##
-#List ##
-#Description ##
-#Function
-struct data {
- const char* name;
- char super;
- int yn[10];
-};
-
-const data dataSet[] = {
-{ "arcTo sweep", '1', {1, 3, 1, 0, 0, 0, 0, 1, 0, 0 }},
-{ "drawArc", 0, {1, -1, 1, 1, 1, 1, 1, 0, 0, 0 }},
-{ "addArc", 0, {1, 1, 1, 4, 0, 1, 1, 1, 0, 0 }},
-{ "arcTo tangents", '4', {0, 0, 0, 0, 0, 0, 0, 1, 1, 0 }},
-{ "arcTo radii", '5', {1, 0, 1, 0, 0, 0, 0, 1, 1, 0 }},
-{ "conicTo", 0, {1, 1, 0, 0, 0, 0, 0, 1, 1, 1 }}
-};
-
-#define __degree_symbol__ "\xC2" "\xB0"
-
-const char* headers[] = {
- "Oval part",
- "force moveTo",
- "can draw 180" __degree_symbol__,
- "can draw 360" __degree_symbol__,
- "can draw greater than 360" __degree_symbol__,
- "ignored if radius is zero",
- "ignored if sweep is zero",
- "requires Path",
- "describes rotation",
- "describes perspective",
-};
-
-const char* yna[] = {
- "n/a",
- "no",
- "yes"
-};
-
-##
-void draw(SkCanvas* canvas) {
- SkPaint lp;
- lp.setAntiAlias(true);
- SkPaint tp(lp);
- SkPaint sp(tp);
- SkPaint bp(tp);
- bp.setFakeBoldText(true);
- sp.setTextSize(10);
- lp.setColor(SK_ColorGRAY);
- canvas->translate(0, 32);
- const int tl = 115;
- for (unsigned col = 0; col <= SK_ARRAY_COUNT(headers); ++col) {
- canvas->drawLine(tl + col * 35, 100, tl + col * 35, 250, lp);
- if (0 == col) {
- continue;
- }
- canvas->drawLine(tl + col * 35, 100, tl + 100 + col * 35, 0, lp);
- SkPath path;
- path.moveTo(tl - 3 + col * 35, 103);
- path.lineTo(tl + 124 + col * 35, -24);
- canvas->drawTextOnPathHV(headers[col -1], strlen(headers[col -1]), path, 0, -9, bp);
- }
- for (unsigned row = 0; row <= SK_ARRAY_COUNT(dataSet); ++row) {
- if (0 == row) {
- canvas->drawLine(tl, 100, tl + 350, 100, lp);
- } else {
- canvas->drawLine(5, 100 + row * 25, tl + 350, 100 + row * 25, lp);
- }
- if (row == SK_ARRAY_COUNT(dataSet)) {
- break;
- }
- canvas->drawString(dataSet[row].name, 5, 117 + row * 25, bp);
- if (dataSet[row].super) {
- SkScalar width = bp.measureText(dataSet[row].name, strlen(dataSet[row].name));
- canvas->drawText(&dataSet[row].super, 1, 8 + width, 112 + row * 25, sp);
- }
- for (unsigned col = 0; col < SK_ARRAY_COUNT(headers); ++col) {
- int val = dataSet[row].yn[col];
- canvas->drawString(yna[SkTMin(2, val + 1)], tl + 5 + col * 35, 117 + row * 25, tp);
- if (val > 1) {
- char supe = '0' + val - 1;
- canvas->drawText(&supe, 1, tl + 25 + col * 35, 112 + row * 25, sp);
- }
- }
- }
-}
-#Example ##
-
-#Example
-#Height 128
-#Description
-#ToDo make this a list or table ##
-1 describes an arc from an oval, a starting angle, and a sweep angle.
-2 is similar to 1, but does not require building a path to draw.
-3 is similar to 1, but always begins new Contour.
-4 describes an arc from a pair of tangent lines and a radius.
-5 describes an arc from Oval center, arc start Point and arc end Point.
-6 describes an arc from a pair of tangent lines and a Conic_Weight.
-##
-void draw(SkCanvas* canvas) {
- SkRect oval = {8, 8, 56, 56};
- SkPaint ovalPaint;
- ovalPaint.setAntiAlias(true);
- SkPaint textPaint(ovalPaint);
- ovalPaint.setStyle(SkPaint::kStroke_Style);
- SkPaint arcPaint(ovalPaint);
- arcPaint.setStrokeWidth(5);
- arcPaint.setColor(SK_ColorBLUE);
- canvas->translate(-64, 0);
- for (char arcStyle = '1'; arcStyle <= '6'; ++arcStyle) {
- '4' == arcStyle ? canvas->translate(-96, 55) : canvas->translate(64, 0);
- canvas->drawText(&arcStyle, 1, 30, 36, textPaint);
- canvas->drawOval(oval, ovalPaint);
- SkPath path;
- path.moveTo({56, 32});
- switch (arcStyle) {
- case '1':
- path.arcTo(oval, 0, 90, false);
- break;
- case '2':
- canvas->drawArc(oval, 0, 90, false, arcPaint);
- continue;
- case '3':
- path.addArc(oval, 0, 90);
- break;
- case '4':
- path.arcTo({56, 56}, {32, 56}, 24);
- break;
- case '5':
- path.arcTo({24, 24}, 0, SkPath::kSmall_ArcSize, SkPath::kCW_Direction, {32, 56});
- break;
- case '6':
- path.conicTo({56, 56}, {32, 56}, SK_ScalarRoot2Over2);
- break;
- }
- canvas->drawPath(path, arcPaint);
- }
-}
-#Example ##
-
-
-#Method void arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo)
-
-Append Arc to Path. 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 Path last Point to initial Arc Point if forceMoveTo
-is false and Path 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. ##
-
-#Example
-#Height 200
-#Description
-arcTo continues a previous contour when forceMoveTo is false and when Path
-is not empty.
-##
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- SkPath path;
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setStrokeWidth(4);
- path.moveTo(0, 0);
- path.arcTo({20, 20, 120, 120}, -90, 90, false);
- canvas->drawPath(path, paint);
- path.rewind();
- path.arcTo({120, 20, 220, 120}, -90, 90, false);
- canvas->drawPath(path, paint);
- path.rewind();
- path.moveTo(0, 0);
- path.arcTo({20, 120, 120, 220}, -90, 90, true);
- canvas->drawPath(path, paint);
-}
-##
-
-#SeeAlso addArc SkCanvas::drawArc conicTo
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar radius)
-
-Append Arc to Path, after appending Line if needed. Arc is implemented by Conic
-weighted to describe part of Circle. Arc is contained by tangent from
-last Path 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.
-
-#ToDo allow example to hide source and not be exposed as fiddle ##
-
-#Example
-#Height 226
-void draw(SkCanvas* canvas) {
- SkPaint tangentPaint;
- tangentPaint.setAntiAlias(true);
- SkPaint textPaint(tangentPaint);
- tangentPaint.setStyle(SkPaint::kStroke_Style);
- tangentPaint.setColor(SK_ColorGRAY);
- SkPaint arcPaint(tangentPaint);
- arcPaint.setStrokeWidth(5);
- arcPaint.setColor(SK_ColorBLUE);
- SkPath path;
- SkPoint pts[] = { {56, 20}, {200, 20}, {90, 190} };
- SkScalar radius = 50;
- path.moveTo(pts[0]);
- path.arcTo(pts[1], pts[2], radius);
- canvas->drawLine(pts[0], pts[1], tangentPaint);
- canvas->drawLine(pts[1], pts[2], tangentPaint);
- SkPoint lastPt;
- (void) path.getLastPt(&lastPt);
- SkVector radial = pts[2] - pts[1];
- radial.setLength(radius);
- SkPoint center = { lastPt.fX - radial.fY, lastPt.fY + radial.fX };
- canvas->drawCircle(center, radius, tangentPaint);
- canvas->drawLine(lastPt, center, tangentPaint);
- radial = pts[1] - pts[0];
- radial.setLength(radius);
- SkPoint arcStart = { center.fX + radial.fY, center.fY - radial.fX };
- canvas->drawLine(center, arcStart, tangentPaint);
- canvas->drawPath(path, arcPaint);
- textPaint.setTextAlign(SkPaint::kRight_Align);
- canvas->drawString("(x0, y0)", pts[0].fX - 5, pts[0].fY, textPaint);
- textPaint.setTextAlign(SkPaint::kLeft_Align);
- canvas->drawString("(x1, y1)", pts[1].fX + 5, pts[1].fY, textPaint);
- textPaint.setTextAlign(SkPaint::kCenter_Align);
- canvas->drawString("(x2, y2)", pts[2].fX, pts[2].fY + 15, textPaint);
- textPaint.setTextAlign(SkPaint::kRight_Align);
- canvas->drawString("radius", center.fX + 15, center.fY + 25, textPaint);
- canvas->drawString("radius", center.fX - 3, center.fY - 16, textPaint);
-}
-##
-
-If last Path Point does not start Arc, arcTo appends connecting Line to Path.
-The length of Vector from (x1, y1) to (x2, y2) does not affect Arc.
-
-#Example
-#Height 128
-void draw(SkCanvas* canvas) {
- SkPaint tangentPaint;
- tangentPaint.setAntiAlias(true);
- SkPaint textPaint(tangentPaint);
- tangentPaint.setStyle(SkPaint::kStroke_Style);
- tangentPaint.setColor(SK_ColorGRAY);
- SkPaint arcPaint(tangentPaint);
- arcPaint.setStrokeWidth(5);
- arcPaint.setColor(SK_ColorBLUE);
- SkPath path;
- SkPoint pts[] = { {156, 20}, {200, 20}, {170, 50} };
- SkScalar radius = 50;
- path.moveTo(pts[0]);
- path.arcTo(pts[1], pts[2], radius);
- canvas->drawLine(pts[0], pts[1], tangentPaint);
- canvas->drawLine(pts[1], pts[2], tangentPaint);
- SkPoint lastPt;
- (void) path.getLastPt(&lastPt);
- SkVector radial = pts[2] - pts[1];
- radial.setLength(radius);
- SkPoint center = { lastPt.fX - radial.fY, lastPt.fY + radial.fX };
- canvas->drawLine(lastPt, center, tangentPaint);
- radial = pts[1] - pts[0];
- radial.setLength(radius);
- SkPoint arcStart = { center.fX + radial.fY, center.fY - radial.fX };
- canvas->drawLine(center, arcStart, tangentPaint);
- canvas->drawPath(path, arcPaint);
- textPaint.setTextAlign(SkPaint::kCenter_Align);
- canvas->drawString("(x0, y0)", pts[0].fX, pts[0].fY - 7, textPaint);
- textPaint.setTextAlign(SkPaint::kLeft_Align);
- canvas->drawString("(x1, y1)", pts[1].fX + 5, pts[1].fY, textPaint);
- textPaint.setTextAlign(SkPaint::kCenter_Align);
- canvas->drawString("(x2, y2)", pts[2].fX, pts[2].fY + 15, textPaint);
- textPaint.setTextAlign(SkPaint::kRight_Align);
- canvas->drawString("radius", center.fX + 15, center.fY + 25, textPaint);
- canvas->drawString("radius", center.fX - 5, center.fY - 20, textPaint);
-}
-##
-
-Arc sweep is always less than 180 degrees. If radius is zero, or if
-tangents are nearly parallel, arcTo appends Line from last Path Point to (x1, y1).
-
-arcTo appends at most one Line and one Conic.
-arcTo implements the functionality of PostScript_arct and HTML_Canvas_arcTo.
-
-#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. ##
-
-#Example
-#Description
-arcTo is represented by Line and circular Conic in Path.
-##
-void draw(SkCanvas* canvas) {
- SkPath path;
- path.moveTo({156, 20});
- path.arcTo(200, 20, 170, 50, 50);
- SkPath::Iter iter(path, false);
- SkPoint p[4];
- SkPath::Verb verb;
- while (SkPath::kDone_Verb != (verb = iter.next(p))) {
- switch (verb) {
- case SkPath::kMove_Verb:
- SkDebugf("move to (%g,%g)\n", p[0].fX, p[0].fY);
- break;
- case SkPath::kLine_Verb:
- SkDebugf("line (%g,%g),(%g,%g)\n", p[0].fX, p[0].fY, p[1].fX, p[1].fY);
- break;
- case SkPath::kConic_Verb:
- SkDebugf("conic (%g,%g),(%g,%g),(%g,%g) weight %g\n",
- p[0].fX, p[0].fY, p[1].fX, p[1].fY, p[2].fX, p[2].fY, iter.conicWeight());
- break;
- default:
- SkDebugf("unexpected verb\n");
- }
- }
-}
-#StdOut
-move to (156,20)
-line (156,20),(79.2893,20)
-conic (79.2893,20),(200,20),(114.645,105.355) weight 0.382683
-##
-##
-
-#SeeAlso conicTo
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius)
-
-Append Arc to Path, after appending Line if needed. Arc is implemented by Conic
-weighted to describe part of Circle. Arc is contained by tangent from
-last Path 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 Path Point does not start Arc, arcTo appends connecting Line to Path.
-The length of Vector 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 Path Point to p1.
-
-arcTo appends at most one Line and one Conic.
-arcTo implements the functionality of PostScript_arct and HTML_Canvas_arcTo.
-
-#Param p1 Point common to pair of tangents. ##
-#Param p2 end of second tangent. ##
-#Param radius distance from Arc to Circle center. ##
-
-#Example
-#Description
-Because tangent lines are parallel, arcTo appends line from last Path Point to
-p1, but does not append a circular Conic.
-##
-void draw(SkCanvas* canvas) {
- SkPath path;
- path.moveTo({156, 20});
- path.arcTo({200, 20}, {170, 20}, 50);
- SkPath::Iter iter(path, false);
- SkPoint p[4];
- SkPath::Verb verb;
- while (SkPath::kDone_Verb != (verb = iter.next(p))) {
- switch (verb) {
- case SkPath::kMove_Verb:
- SkDebugf("move to (%g,%g)\n", p[0].fX, p[0].fY);
- break;
- case SkPath::kLine_Verb:
- SkDebugf("line (%g,%g),(%g,%g)\n", p[0].fX, p[0].fY, p[1].fX, p[1].fY);
- break;
- case SkPath::kConic_Verb:
- SkDebugf("conic (%g,%g),(%g,%g),(%g,%g) weight %g\n",
- p[0].fX, p[0].fY, p[1].fX, p[1].fY, p[2].fX, p[2].fY, iter.conicWeight());
- break;
- default:
- SkDebugf("unexpected verb\n");
- }
- }
-}
-#StdOut
-move to (156,20)
-line (156,20),(200,20)
-##
-##
-
-#SeeAlso conicTo
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Enum ArcSize
-
-#Code
- enum ArcSize {
- kSmall_ArcSize
- kLarge_ArcSize
- };
-##
-
-Four Oval parts with radii (rx, ry) start at last Path Point and ends at (x, y).
-ArcSize and Direction select one of the four Oval parts.
-
-#Const kSmall_ArcSize 0
-Smaller of Arc pair.
-##
-#Const kLarge_ArcSize 1
-Larger of Arc pair.
-##
-
-#Example
-#Height 160
-#Description
-Arc begins at top of Oval pair and ends at bottom. Arc can take four routes to get there.
-Two routes are large, and two routes are counterclockwise. The one route both large
-and counterclockwise is blue.
-##
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
- for (auto sweep: { SkPath::kCW_Direction, SkPath::kCCW_Direction } ) {
- for (auto arcSize : { SkPath::kSmall_ArcSize, SkPath::kLarge_ArcSize } ) {
- SkPath path;
- path.moveTo({120, 50});
- path.arcTo(70, 40, 30, arcSize, sweep, 156, 100);
- if (SkPath::kCCW_Direction == sweep && SkPath::kLarge_ArcSize == arcSize) {
- paint.setColor(SK_ColorBLUE);
- paint.setStrokeWidth(3);
- }
- canvas->drawPath(path, paint);
- }
- }
-}
-##
-
-#SeeAlso arcTo Direction
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void arcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,
- Direction sweep, SkScalar x, SkScalar y)
-
-Append Arc to Path. 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 Path Point 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 Path Point equals (x, y). arcTo scales radii (rx, ry) to fit last Path Point and
-(x, y) if both are greater than zero but too small.
-
-arcTo appends up to four Conic curves.
-arcTo implements the functionatlity 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; positve 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. ##
-
-#Example
-#Height 160
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
- for (auto sweep: { SkPath::kCW_Direction, SkPath::kCCW_Direction } ) {
- for (auto arcSize : { SkPath::kSmall_ArcSize, SkPath::kLarge_ArcSize } ) {
- SkPath path;
- path.moveTo({120, 50});
- path.arcTo(70, 40, 30, arcSize, sweep, 120.1, 50);
- if (SkPath::kCCW_Direction == sweep && SkPath::kLarge_ArcSize == arcSize) {
- paint.setColor(SK_ColorBLUE);
- paint.setStrokeWidth(3);
- }
- canvas->drawPath(path, paint);
- }
- }
-}
-##
-
-#SeeAlso rArcTo ArcSize Direction
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void arcTo(const SkPoint r, SkScalar xAxisRotate, ArcSize largeArc, Direction sweep,
- const SkPoint xy)
-
-Append Arc to Path. 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 Path Point 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 Path Point equals (x, y). arcTo scales radii r to fit last Path Point and
-xy if both are greater than zero but too small.
-
-arcTo appends up to four Conic curves.
-arcTo implements the functionatlity 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; positve values are clockwise. ##
-#Param largeArc chooses smaller or larger Arc. ##
-#Param sweep chooses clockwise or counterclockwise Arc. ##
-#Param xy end of Arc. ##
-
-#Example
-#Height 108
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- SkPath path;
- const SkPoint starts[] = {{20, 20}, {120, 20}, {70, 60}};
- for (auto start : starts) {
- path.moveTo(start.fX, start.fY);
- path.rArcTo(20, 20, 0, SkPath::kSmall_ArcSize, SkPath::kCCW_Direction, 60, 0);
- }
- canvas->drawPath(path, paint);
-}
-##
-
-#SeeAlso rArcTo ArcSize Direction
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void rArcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,
- Direction sweep, SkScalar dx, SkScalar dy)
-
-Append Arc to Path, relative to last Path Point. 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 Path Point (x0, y0) to
-(x0 + dx, y0 + dy), choosing one of four possible routes: clockwise or
-counterclockwise, and smaller or larger. If Path is empty, the start Arc Point
-is (0, 0).
-
-Arc sweep is always less than 360 degrees. arcTo appends Line to xy if either
-radii are zero, or if last Path Point equals (x, y). arcTo scales radii r to fit
-last Path Point and xy if both are greater than zero but too small.
-
-arcTo appends up to four Conic curves.
-arcTo implements the functionatlity 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; positve 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 Path Point. ##
-#Param dy y offset end of Arc from last Path Point. ##
-
-#Example
-#Height 108
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- SkPath path;
- const SkPoint starts[] = {{20, 20}, {120, 20}, {70, 60}};
- for (auto start : starts) {
- path.moveTo(start.fX, start.fY);
- path.rArcTo(20, 20, 0, SkPath::kSmall_ArcSize, SkPath::kCCW_Direction, 60, 0);
- }
- canvas->drawPath(path, paint);
-}
-##
-
-#SeeAlso arcTo ArcSize Direction
-
-##
-
-#Topic Arc ##
-
-# ------------------------------------------------------------------------------
-
-#Method void close()
-
-Append kClose_Verb to Path. A closed Contour connects the first and last Point
-with Line, forming a continous loop. Open and closed Contour draw the same
-with SkPaint::kFill_Style. With SkPaint::kStroke_Style, open Contour draws
-Paint_Stroke_Cap at Contour start and end; closed Contour draws
-Paint_Stroke_Join at Contour start and end.
-
-close() has no effect if Path is empty or last Path Verb is kClose_Verb.
-
-#Example
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setStrokeWidth(15);
- paint.setStrokeCap(SkPaint::kRound_Cap);
- SkPath path;
- const SkPoint points[] = {{20, 20}, {70, 20}, {40, 90}};
- path.addPoly(points, SK_ARRAY_COUNT(points), false);
- for (int loop = 0; loop < 2; ++loop) {
- for (auto style : {SkPaint::kStroke_Style, SkPaint::kFill_Style,
- SkPaint::kStrokeAndFill_Style} ) {
- paint.setStyle(style);
- canvas->drawPath(path, paint);
- canvas->translate(85, 0);
- }
- path.close();
- canvas->translate(-255, 128);
- }
-}
-##
-
-#SeeAlso
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method static bool IsInverseFillType(FillType fill)
-
-Returns true if fill is inverted and Path with fill represents area outside
-of its geometric bounds.
-
-#Table
-#Legend
-# FillType # is inverse ##
-##
-# kWinding_FillType # false ##
-# kEvenOdd_FillType # false ##
-# kInverseWinding_FillType # true ##
-# kInverseEvenOdd_FillType # true ##
-##
-
-#Param fill one of: kWinding_FillType, kEvenOdd_FillType,
- kInverseWinding_FillType, kInverseEvenOdd_FillType.
-##
-
-#Return true if Path fills outside its bounds. ##
-
-#Example
-#Function
-#define nameValue(fill) { SkPath::fill, #fill }
-
-##
-void draw(SkCanvas* canvas) {
- struct {
- SkPath::FillType fill;
- const char* name;
- } fills[] = {
- nameValue(kWinding_FillType),
- nameValue(kEvenOdd_FillType),
- nameValue(kInverseWinding_FillType),
- nameValue(kInverseEvenOdd_FillType),
- };
- for (auto fill: fills ) {
- SkDebugf("IsInverseFillType(%s) == %s\n", fill.name, SkPath::IsInverseFillType(fill.fill) ?
- "true" : "false");
- }
-}
-#StdOut
-IsInverseFillType(kWinding_FillType) == false
-IsInverseFillType(kEvenOdd_FillType) == false
-IsInverseFillType(kInverseWinding_FillType) == true
-IsInverseFillType(kInverseEvenOdd_FillType) == true
-##
-##
-
-#SeeAlso FillType getFillType setFillType ConvertToNonInverseFillType
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method static FillType ConvertToNonInverseFillType(FillType fill)
-
-Returns equivalent Fill_Type representing Path fill inside its bounds.
-.
-
-#Table
-#Legend
-# FillType # inside FillType ##
-##
-# kWinding_FillType # kWinding_FillType ##
-# kEvenOdd_FillType # kEvenOdd_FillType ##
-# kInverseWinding_FillType # kWinding_FillType ##
-# kInverseEvenOdd_FillType # kEvenOdd_FillType ##
-##
-
-#Param fill one of: kWinding_FillType, kEvenOdd_FillType,
- kInverseWinding_FillType, kInverseEvenOdd_FillType.
-##
-
-#Return fill, or kWinding_FillType or kEvenOdd_FillType if fill is inverted. ##
-
-#Example
-#Function
-#define nameValue(fill) { SkPath::fill, #fill }
-
-##
-void draw(SkCanvas* canvas) {
- struct {
- SkPath::FillType fill;
- const char* name;
- } fills[] = {
- nameValue(kWinding_FillType),
- nameValue(kEvenOdd_FillType),
- nameValue(kInverseWinding_FillType),
- nameValue(kInverseEvenOdd_FillType),
- };
- for (unsigned i = 0; i < SK_ARRAY_COUNT(fills); ++i) {
- if (fills[i].fill != (SkPath::FillType) i) {
- SkDebugf("fills array order does not match FillType enum order");
- break;
- }
- SkDebugf("ConvertToNonInverseFillType(%s) == %s\n", fills[i].name,
- fills[(int) SkPath::ConvertToNonInverseFillType(fills[i].fill)].name);
- }
-}
-#StdOut
-ConvertToNonInverseFillType(kWinding_FillType) == kWinding_FillType
-ConvertToNonInverseFillType(kEvenOdd_FillType) == kEvenOdd_FillType
-ConvertToNonInverseFillType(kInverseWinding_FillType) == kWinding_FillType
-ConvertToNonInverseFillType(kInverseEvenOdd_FillType) == kEvenOdd_FillType
-##
-##
-
-#SeeAlso FillType getFillType setFillType IsInverseFillType
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method static int ConvertConicToQuads(const SkPoint& p0, const SkPoint& p1, const SkPoint& p2,
- SkScalar w, SkPoint pts[], int pow2)
-
-Approximates Conic with Quad array. Conic is constructed from start Point p0,
-control Point p1, end Point 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 Point of previous Quad and first Point of
-next Quad. Maximum pts storage size is given by:
-#Formula
-(1 + 2 * (1 << pow2)) * sizeof(SkPoint)
-##
-ConvertConicToQuads returns Quad count used the approximation, which may be smaller
-than the number requested.
-
-Conic_Weight determines the amount of influence Conic control point has on the curve.
-w less than one represents an elliptical section. w greater than one represents
-a hyperbolic section. w equal to one represents a parabolic section.
-
-Two Quad curves are sufficient to approximate an elliptical Conic with a sweep
-of up to 90 degrees; in this case, set pow2 to one.
-
-#Param p0 Conic start Point. ##
-#Param p1 Conic control Point. ##
-#Param p2 Conic end Point. ##
-#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. ##
-
-#Example
-#Description
-A pair of Quad curves are drawn in red on top of the elliptical Conic curve in black.
-The middle curve is nearly circular. The top-right curve is parabolic, which can
-be drawn exactly with a single Quad.
-##
-void draw(SkCanvas* canvas) {
- SkPaint conicPaint;
- conicPaint.setAntiAlias(true);
- conicPaint.setStyle(SkPaint::kStroke_Style);
- SkPaint quadPaint(conicPaint);
- quadPaint.setColor(SK_ColorRED);
- SkPoint conic[] = { {20, 170}, {80, 170}, {80, 230} };
- for (auto weight : { .25f, .5f, .707f, .85f, 1.f } ) {
- SkPoint quads[5];
- SkPath::ConvertConicToQuads(conic[0], conic[1], conic[2], weight, quads, 1);
- SkPath path;
- path.moveTo(conic[0]);
- path.conicTo(conic[1], conic[2], weight);
- canvas->drawPath(path, conicPaint);
- path.rewind();
- path.moveTo(quads[0]);
- path.quadTo(quads[1], quads[2]);
- path.quadTo(quads[3], quads[4]);
- canvas->drawPath(path, quadPaint);
- canvas->translate(50, -50);
- }
-}
-##
-
-#SeeAlso Conic Quad
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method bool isRect(SkRect* rect, bool* isClosed = NULL, Direction* direction = NULL) const
-
-Returns true if Path is eqivalent to Rect when filled.
-If isRect returns false: rect, isClosed, and direction are unchanged.
-If isRect returns true: rect, isClosed, and direction are written to if not nullptr.
-
-rect may be smaller than the Path bounds. Path bounds may include kMove_Verb points
-that do not alter the area drawn by the returned rect.
-
-#Param rect storage for bounds of Rect; may be nullptr. ##
-#Param isClosed storage set to true if Path is closed; may be nullptr ##
-#Param direction storage set to Rect direction; may be nullptr. ##
-
-#Return true if Path contains Rect. ##
-
-#Example
-#Description
-After addRect, isRect returns true. Following moveTo permits isRect to return true, but
-following lineTo does not. addPoly returns true even though rect is not closed, and one
-side of rect is made up of consecutive line segments.
-##
-void draw(SkCanvas* canvas) {
- auto debugster = [](const char* prefix, const SkPath& path) -> void {
- SkRect rect;
- SkPath::Direction direction;
- bool isClosed;
- path.isRect(&rect, &isClosed, &direction) ?
- SkDebugf("%s is rect (%g, %g, %g, %g); is %s" "closed; direction %s\n", prefix,
- rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, isClosed ? "" : "not ",
- SkPath::kCW_Direction == direction ? "CW" : "CCW") :
- SkDebugf("%s is not rect\n", prefix);
- };
- SkPath path;
- debugster("empty", path);
- path.addRect({10, 20, 30, 40});
- debugster("addRect", path);
- path.moveTo(60, 70);
- debugster("moveTo", path);
- path.lineTo(60, 70);
- debugster("lineTo", path);
- path.reset();
- const SkPoint pts[] = { {0, 0}, {0, 80}, {80, 80}, {80, 0}, {40, 0}, {20, 0} };
- path.addPoly(pts, SK_ARRAY_COUNT(pts), false);
- debugster("addPoly", path);
-}
-#StdOut
-empty is not rect
-addRect is rect (10, 20, 30, 40); is closed; direction CW
-moveTo is rect (10, 20, 30, 40); is closed; direction CW
-lineTo is not rect
-addPoly is rect (0, 0, 80, 80); is not closed; direction CCW
-##
-##
-
-#SeeAlso computeTightBounds conservativelyContainsRect getBounds isConvex isLastContourClosed isNestedFillRects
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method bool isNestedFillRects(SkRect rect[2], Direction dirs[2] = NULL) const
-
-Returns true if Path is equivalent to nested Rect pair when filled.
-If isNestedFillRects returns false, rect and dirs are unchanged.
-If isNestedFillRects returns true, rect and dirs are written to if not nullptr:
-setting rect[0] to outer Rect, and rect[1] to inner Rect;
-setting dirs[0] to Direction of outer Rect, and dirs[1] to Direction of inner
-Rect.
-
-#Param rect storage for Rect pair; may be nullptr. ##
-#Param dirs storage for Direction pair; may be nullptr. ##
-
-#Return true if Path contains nested Rect pair. ##
-
-#Example
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setStrokeWidth(5);
- SkPath path;
- path.addRect({10, 20, 30, 40});
- paint.getFillPath(path, &path);
- SkRect rects[2];
- SkPath::Direction directions[2];
- if (path.isNestedFillRects(rects, directions)) {
- for (int i = 0; i < 2; ++i) {
- SkDebugf("%s (%g, %g, %g, %g); direction %s\n", i ? "inner" : "outer",
- rects[i].fLeft, rects[i].fTop, rects[i].fRight, rects[i].fBottom,
- SkPath::kCW_Direction == directions[i] ? "CW" : "CCW");
- }
- } else {
- SkDebugf("is not nested rectangles\n");
- }
-}
-#StdOut
-outer (7.5, 17.5, 32.5, 42.5); direction CW
-inner (12.5, 22.5, 27.5, 37.5); direction CCW
-##
-##
-
-#SeeAlso computeTightBounds conservativelyContainsRect getBounds isConvex isLastContourClosed isRect
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void addRect(const SkRect& rect, Direction dir = kCW_Direction)
-
-Add Rect to Path, appending kMove_Verb, three kLine_Verb, and kClose_Verb,
-starting with top-left corner of Rect; 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 Rect to add as a closed contour. ##
-#Param dir Direction to wind added contour. ##
-
-#Example
-#Description
-The left Rect dashes starting at the top-left corner, to the right.
-The right Rect dashes starting at the top-left corner, towards the bottom.
-##
-#Height 128
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setStrokeWidth(15);
- paint.setStrokeCap(SkPaint::kSquare_Cap);
- float intervals[] = { 5, 21.75f };
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 0));
- SkPath path;
- path.addRect({20, 20, 100, 100}, SkPath::kCW_Direction);
- canvas->drawPath(path, paint);
- path.rewind();
- path.addRect({140, 20, 220, 100}, SkPath::kCCW_Direction);
- canvas->drawPath(path, paint);
-}
-##
-
-#SeeAlso SkCanvas::drawRect Direction
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void addRect(const SkRect& rect, Direction dir, unsigned start)
-
-Add Rect to Path, appending kMove_Verb, three kLine_Verb, and kClose_Verb.
-If dir is kCW_Direction, Rect corners are added clockwise; if dir is
-kCCW_Direction, Rect corners are added counterclockwise.
-start determines the first corner added.
-
-#Table
-#Legend
-# start # first corner ##
-#Legend ##
-# 0 # top-left ##
-# 1 # top-right ##
-# 2 # bottom-right ##
-# 3 # bottom-left ##
-#Table ##
-
-#Param rect Rect to add as a closed contour. ##
-#Param dir Direction to wind added contour. ##
-#Param start Initial corner of Rect to add. ##
-
-#Example
-#Height 128
-#Description
-The arrow is just after the initial corner and points towards the next
-corner appended to Path.
-##
-void draw(SkCanvas* canvas) {
- const SkPoint arrow[] = { {5, -5}, {15, -5}, {20, 0}, {15, 5}, {5, 5}, {10, 0} };
- const SkRect rect = {10, 10, 54, 54};
- SkPaint rectPaint;
- rectPaint.setAntiAlias(true);
- rectPaint.setStyle(SkPaint::kStroke_Style);
- SkPaint arrowPaint(rectPaint);
- SkPath arrowPath;
- arrowPath.addPoly(arrow, SK_ARRAY_COUNT(arrow), true);
- arrowPaint.setPathEffect(SkPath1DPathEffect::Make(arrowPath, 176, 0,
- SkPath1DPathEffect::kRotate_Style));
- for (auto direction : { SkPath::kCW_Direction, SkPath::kCCW_Direction } ) {
- for (unsigned start : { 0, 1, 2, 3 } ) {
- SkPath path;
- path.addRect(rect, direction, start);
- canvas->drawPath(path, rectPaint);
- canvas->drawPath(path, arrowPaint);
- canvas->translate(64, 0);
- }
- canvas->translate(-256, 64);
- }
-}
-##
-
-#SeeAlso SkCanvas::drawRect Direction
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void addRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom,
- Direction dir = kCW_Direction)
-
-Add Rect (left, top, right, bottom) to Path,
-appending kMove_Verb, three kLine_Verb, and kClose_Verb,
-starting with top-left corner of Rect; 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 Rect. ##
-#Param top smaller y of Rect. ##
-#Param right larger x of Rect. ##
-#Param bottom larger y of Rect. ##
-#Param dir Direction to wind added contour. ##
-
-#Example
-#Description
-The left Rect dashes start at the top-left corner, and continue to the right.
-The right Rect dashes start at the top-left corner, and continue down.
-##
-#Height 128
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setStrokeWidth(15);
- paint.setStrokeCap(SkPaint::kSquare_Cap);
- float intervals[] = { 5, 21.75f };
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 0));
- for (auto direction : { SkPath::kCW_Direction, SkPath::kCCW_Direction } ) {
- SkPath path;
- path.addRect(20, 20, 100, 100, direction);
- canvas->drawPath(path, paint);
- canvas->translate(128, 0);
- }
-}
-##
-
-#SeeAlso SkCanvas::drawRect Direction
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void addOval(const SkRect& oval, Direction dir = kCW_Direction)
-
-Add Oval to path, appending kMove_Verb, four kConic_Verb, and kClose_Verb.
-Oval is upright ellipse bounded by Rect 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 Direction to wind ellipse. ##
-
-#Example
-#Height 120
- SkPaint paint;
- SkPath oval;
- oval.addOval({20, 20, 160, 80});
- canvas->drawPath(oval, paint);
-##
-
-#SeeAlso SkCanvas::drawOval Direction Oval
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void addOval(const SkRect& oval, Direction dir, unsigned start)
-
-Add Oval to Path, appending kMove_Verb, four kConic_Verb, and kClose_Verb.
-Oval is upright ellipse bounded by Rect 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.
-
-#Table
-#Legend
-# start # Point ##
-#Legend ##
-# 0 # oval.centerX(), oval.fTop ##
-# 1 # oval.fRight, oval.centerY() ##
-# 2 # oval.centerX(), oval.fBottom ##
-# 3 # oval.fLeft, oval.centerY() ##
-#Table ##
-
-#Param oval bounds of ellipse added. ##
-#Param dir Direction to wind ellipse. ##
-#Param start index of initial point of ellipse. ##
-
-#Example
-#Height 160
-void draw(SkCanvas* canvas) {
- const SkPoint arrow[] = { {0, -5}, {10, 0}, {0, 5} };
- const SkRect rect = {10, 10, 54, 54};
- SkPaint ovalPaint;
- ovalPaint.setAntiAlias(true);
- SkPaint textPaint(ovalPaint);
- textPaint.setTextAlign(SkPaint::kCenter_Align);
- ovalPaint.setStyle(SkPaint::kStroke_Style);
- SkPaint arrowPaint(ovalPaint);
- SkPath arrowPath;
- arrowPath.addPoly(arrow, SK_ARRAY_COUNT(arrow), true);
- arrowPaint.setPathEffect(SkPath1DPathEffect::Make(arrowPath, 176, 0,
- SkPath1DPathEffect::kRotate_Style));
- for (auto direction : { SkPath::kCW_Direction, SkPath::kCCW_Direction } ) {
- for (unsigned start : { 0, 1, 2, 3 } ) {
- SkPath path;
- path.addOval(rect, direction, start);
- canvas->drawPath(path, ovalPaint);
- canvas->drawPath(path, arrowPaint);
- canvas->drawText(&"0123"[start], 1, rect.centerX(), rect.centerY() + 5, textPaint);
- canvas->translate(64, 0);
- }
- canvas->translate(-256, 72);
- canvas->drawString(SkPath::kCW_Direction == direction ? "clockwise" : "counterclockwise",
- 128, 0, textPaint);
- }
-}
-##
-
-#SeeAlso SkCanvas::drawOval Direction Oval
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void addCircle(SkScalar x, SkScalar y, SkScalar radius,
- Direction dir = kCW_Direction)
-
-Add Circle centered at (x, y) of size radius to Path, appending kMove_Verb,
-four kConic_Verb, and kClose_Verb. Circle begins at (x + radius, y) and
-continues clockwise if dir is kCW_Direction, counterclockwise if dir is
-kCCW_Direction.
-
-addCircle has no effect if radius is zero or negative.
-
-#Param x center of Circle. ##
-#Param y center of Circle. ##
-#Param radius distance from center to edge. ##
-#Param dir Direction to wind Circle. ##
-
-#Example
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setStrokeWidth(10);
- for (int size = 10; size < 300; size += 20) {
- SkPath path;
- path.addCircle(128, 128, size, SkPath::kCW_Direction);
- canvas->drawPath(path, paint);
- }
-}
-##
-
-#SeeAlso SkCanvas::drawCircle Direction Circle
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle)
-
-Append Arc to Path, 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 bounds of ellipse containing Arc. ##
-#Param startAngle starting angle of Arc in degrees. ##
-#Param sweepAngle sweep, in degrees. Positive is clockwise; treated modulo 360. ##
-
-#Example
-#Description
-The middle row of the left and right columns draw differently from the entries
-above and below because sweepAngle is outside of the range of +/-360,
-and startAngle modulo 90 is not zero.
-##
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- for (auto start : { 0, 90, 135, 180, 270 } ) {
- for (auto sweep : { -450.f, -180.f, -90.f, 90.f, 180.f, 360.1f } ) {
- SkPath path;
- path.addArc({10, 10, 35, 45}, start, sweep);
- canvas->drawPath(path, paint);
- canvas->translate(252 / 6, 0);
- }
- canvas->translate(-252, 255 / 5);
- }
-}
-##
-
-#SeeAlso Arc arcTo SkCanvas::drawArc
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
- Direction dir = kCW_Direction)
-
-Append Round_Rect to Path, creating a new closed Contour. Round_Rect has bounds
-equal to rect; each corner is 90 degrees of an ellipse with radii (rx, ry). If
-dir is kCW_Direction, Round_Rect starts at top-left of the lower-left corner and
-winds clockwise. If dir is kCCW_Direction, Round_Rect 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
-Rect rect to Path.
-
-After appending, Path may be empty, or may contain: Rect, Oval, or RoundRect.
-
-#Param rect bounds of Round_Rect. ##
-#Param rx x-radius of rounded corners on the Round_Rect ##
-#Param ry y-radius of rounded corners on the Round_Rect ##
-#Param dir Direction to wind Round_Rect. ##
-
-#Example
-#Description
-If either radius is zero, path contains Rect and is drawn red.
-If sides are only radii, path contains Oval and is drawn blue.
-All remaining path draws are convex, and are drawn in gray; no
-paths constructed from addRoundRect are concave, so none are
-drawn in green.
-##
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setAntiAlias(true);
- for (auto xradius : { 0, 7, 13, 20 } ) {
- for (auto yradius : { 0, 9, 18, 40 } ) {
- SkPath path;
- path.addRoundRect({10, 10, 36, 46}, xradius, yradius);
- paint.setColor(path.isRect(nullptr) ? SK_ColorRED : path.isOval(nullptr) ?
- SK_ColorBLUE : path.isConvex() ? SK_ColorGRAY : SK_ColorGREEN);
- canvas->drawPath(path, paint);
- canvas->translate(64, 0);
- }
- canvas->translate(-256, 64);
- }
-}
-##
-
-#SeeAlso addRRect SkCanvas::drawRoundRect
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void addRoundRect(const SkRect& rect, const SkScalar radii[],
- Direction dir = kCW_Direction)
-
-Append Round_Rect to Path, creating a new closed Contour. Round_Rect has bounds
-equal to rect; each corner is 90 degrees of an ellipse with radii from the
-array.
-
-#Table
-#Legend
-# radii index # location ##
-#Legend ##
-# 0 # x-radius of top-left corner ##
-# 1 # y-radius of top-left corner ##
-# 2 # x-radius of top-right corner ##
-# 3 # y-radius of top-right corner ##
-# 4 # x-radius of bottom-right corner ##
-# 5 # y-radius of bottom-right corner ##
-# 6 # x-radius of bottom-left corner ##
-# 7 # y-radius of bottom-left corner ##
-#Table ##
-
-If dir is kCW_Direction, Round_Rect starts at top-left of the lower-left corner
-and winds clockwise. If dir is kCCW_Direction, Round_Rect starts at the
-bottom-left of the upper-left corner and winds counterclockwise.
-
-If both radii on any side of rect exceed its length, all radii are scaled
-uniformly until the corners fit. If either radius of a corner is less than or
-equal to zero, both are treated as zero.
-
-After appending, Path may be empty, or may contain: Rect, Oval, or RoundRect.
-
-#Param rect bounds of Round_Rect. ##
-#Param radii array of 8 SkScalar values, a radius pair for each corner. ##
-#Param dir Direction to wind Round_Rect. ##
-
-#Example
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setAntiAlias(true);
- SkScalar radii[] = { 80, 100, 0, 0, 40, 60, 0, 0 };
- SkPath path;
- SkMatrix rotate90;
- rotate90.setRotate(90, 128, 128);
- for (int i = 0; i < 4; ++i) {
- path.addRoundRect({10, 10, 110, 110}, radii);
- path.transform(rotate90);
- }
- canvas->drawPath(path, paint);
-}
-##
-
-#SeeAlso addRRect SkCanvas::drawRoundRect
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void addRRect(const SkRRect& rrect, Direction dir = kCW_Direction)
-
-Add rrect to Path, 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, Path may be empty, or may contain: Rect, Oval, or RRect.
-
-#Param rrect bounds and radii of rounded rectangle. ##
-#Param dir Direction to wind Round_Rect. ##
-
-#Example
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setAntiAlias(true);
- SkRRect rrect;
- SkVector radii[] = {{50, 50}, {0, 0}, {0, 0}, {50, 50}};
- rrect.setRectRadii({10, 10, 110, 110}, radii);
- SkPath path;
- SkMatrix rotate90;
- rotate90.setRotate(90, 128, 128);
- for (int i = 0; i < 4; ++i) {
- path.addRRect(rrect);
- path.transform(rotate90);
- }
- canvas->drawPath(path, paint);
-}
-##
-
-#SeeAlso addRoundRect SkCanvas::drawRRect
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void addRRect(const SkRRect& rrect, Direction dir, unsigned start)
-
-Add rrect to Path, 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.
-
-#Table
-#Legend
-# start # location ##
-#Legend ##
-# 0 # right of top-left corner ##
-# 1 # left of top-right corner ##
-# 2 # bottom of top-right corner ##
-# 3 # top of bottom-right corner ##
-# 4 # left of bottom-right corner ##
-# 5 # right of bottom-left corner ##
-# 6 # top of bottom-left corner ##
-# 7 # bottom of top-left corner ##
-#Table ##
-
-After appending, Path may be empty, or may contain: Rect, Oval, or RRect.
-
-#Param rrect bounds and radii of rounded rectangle. ##
-#Param dir Direction to wind RRect. ##
-#Param start Index of initial point of RRect. ##
-
-#Example
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setAntiAlias(true);
- SkRRect rrect;
- rrect.setRectXY({40, 40, 215, 215}, 50, 50);
- SkPath path;
- path.addRRect(rrect);
- canvas->drawPath(path, paint);
- for (int start = 0; start < 8; ++start) {
- SkPath textPath;
- textPath.addRRect(rrect, SkPath::kCW_Direction, start);
- canvas->drawTextOnPathHV(&"01234567"[start], 1, textPath, 0, -5, paint);
- }
-}
-##
-
-#SeeAlso addRoundRect SkCanvas::drawRRect
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void addPoly(const SkPoint pts[], int count, bool close)
-
-Add Contour created from Line Array. Given count pts, addPoly adds
-count - 1 Line segments. Contour added starts at pt[0], then adds a line
-for every additional Point in pts array. If close is true, addPoly
-appends kClose_Verb to Path, connecting pts[count - 1] and pts[0].
-
-If count is zero, append kMove_Verb to path.
-addPoly has no effect if count is less than one.
-
-#Param pts Array of Line sharing end and start Point. ##
-#Param count Length of Point array. ##
-#Param close true to add Line connecting Contour end and start. ##
-
-#Example
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setStrokeWidth(15);
- paint.setStrokeCap(SkPaint::kRound_Cap);
- const SkPoint points[] = {{20, 20}, {70, 20}, {40, 90}};
- for (bool close : { false, true } ) {
- SkPath path;
- path.addPoly(points, SK_ARRAY_COUNT(points), close);
- for (auto style : {SkPaint::kStroke_Style, SkPaint::kFill_Style,
- SkPaint::kStrokeAndFill_Style} ) {
- paint.setStyle(style);
- canvas->drawPath(path, paint);
- canvas->translate(85, 0);
- }
- canvas->translate(-255, 128);
- }
-}
-##
-
-#SeeAlso SkCanvas::drawPoints
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Enum AddPathMode
-
-#Code
- enum AddPathMode {
- kAppend_AddPathMode
- kExtend_AddPathMode
- };
-##
-
-AddPathMode chooses how addPath appends. Adding one Path to another can extend
-the last Contour or start a new Contour.
-
-#Const kAppend_AddPathMode
- Path Verbs, Points, and Weights are appended to destination unaltered.
- Since Path Verb_Array begins with kMove_Verb if src is not empty, this
- starts a new Contour.
-##
-#Const kExtend_AddPathMode
- If destination is closed or empty, start a new Contour. If destination
- is not empty, add Line from Last_Point to added Path first Point. Skip added
- Path initial kMove_Verb, then append remining Verbs, Points, and Weights.
-##
-
-#Example
-#Description
-test is built from path, open on the top row, and closed on the bottom row.
-The left column uses kAppend_AddPathMode; the right uses kExtend_AddPathMode.
-The top right composition is made up of one contour; the other three have two.
-##
-#Height 180
+
+#SeeAlso arcTo Direction
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void arcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,
+ Direction sweep, SkScalar x, SkScalar y)
+
+Append Arc to Path. 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 Path Point 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 Path Point equals (x, y). arcTo scales radii (rx, ry) to fit last Path Point and
+(x, y) if both are greater than zero but too small.
+
+arcTo appends up to four Conic curves.
+arcTo implements the functionatlity 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; positve 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 ##
+
+#Example
+#Height 160
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ for (auto sweep: { SkPath::kCW_Direction, SkPath::kCCW_Direction } ) {
+ for (auto arcSize : { SkPath::kSmall_ArcSize, SkPath::kLarge_ArcSize } ) {
+ SkPath path;
+ path.moveTo({120, 50});
+ path.arcTo(70, 40, 30, arcSize, sweep, 120.1, 50);
+ if (SkPath::kCCW_Direction == sweep && SkPath::kLarge_ArcSize == arcSize) {
+ paint.setColor(SK_ColorBLUE);
+ paint.setStrokeWidth(3);
+ }
+ canvas->drawPath(path, paint);
+ }
+ }
+}
+##
+
+#SeeAlso rArcTo ArcSize Direction
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void arcTo(const SkPoint r, SkScalar xAxisRotate, ArcSize largeArc, Direction sweep,
+ const SkPoint xy)
+
+Append Arc to Path. 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 Path Point 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 Path Point equals (x, y). arcTo scales radii r to fit last Path Point and
+xy if both are greater than zero but too small.
+
+arcTo appends up to four Conic curves.
+arcTo implements the functionatlity 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; positve values are clockwise ##
+#Param largeArc chooses smaller or larger Arc ##
+#Param sweep chooses clockwise or counterclockwise Arc ##
+#Param xy end of Arc ##
+
+#Example
+#Height 108
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ SkPath path;
+ const SkPoint starts[] = {{20, 20}, {120, 20}, {70, 60}};
+ for (auto start : starts) {
+ path.moveTo(start.fX, start.fY);
+ path.rArcTo(20, 20, 0, SkPath::kSmall_ArcSize, SkPath::kCCW_Direction, 60, 0);
+ }
+ canvas->drawPath(path, paint);
+}
+##
+
+#SeeAlso rArcTo ArcSize Direction
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void rArcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,
+ Direction sweep, SkScalar dx, SkScalar dy)
+
+Append Arc to Path, relative to last Path Point. 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 Path Point (x0, y0) to
+#Formula
+(x0 + dx, y0 + dy)
+##
+, choosing one of four possible routes: clockwise or
+counterclockwise, and smaller or larger. If Path is empty, the start Arc Point
+is (0, 0).
+
+Arc sweep is always less than 360 degrees. arcTo appends Line to xy if either
+radii are zero, or if last Path Point equals (x, y). arcTo scales radii r to fit
+last Path Point and xy if both are greater than zero but too small.
+
+arcTo appends up to four Conic curves.
+arcTo implements the functionatlity 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; positve 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 Path Point ##
+#Param dy y offset end of Arc from last Path Point ##
+
+#Example
+#Height 108
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ SkPath path;
+ const SkPoint starts[] = {{20, 20}, {120, 20}, {70, 60}};
+ for (auto start : starts) {
+ path.moveTo(start.fX, start.fY);
+ path.rArcTo(20, 20, 0, SkPath::kSmall_ArcSize, SkPath::kCCW_Direction, 60, 0);
+ }
+ canvas->drawPath(path, paint);
+}
+##
+
+#SeeAlso arcTo ArcSize Direction
+
+##
+
+#Topic Arc ##
+
+# ------------------------------------------------------------------------------
+
+#Method void close()
+
+Append kClose_Verb to Path. A closed Contour connects the first and last Point
+with Line, forming a continous loop. Open and closed Contour draw the same
+with SkPaint::kFill_Style. With SkPaint::kStroke_Style, open Contour draws
+Paint_Stroke_Cap at Contour start and end; closed Contour draws
+Paint_Stroke_Join at Contour start and end.
+
+close() has no effect if Path is empty or last Path Verb is kClose_Verb.
+
+#Example
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setStrokeWidth(15);
+ paint.setStrokeCap(SkPaint::kRound_Cap);
+ SkPath path;
+ const SkPoint points[] = {{20, 20}, {70, 20}, {40, 90}};
+ path.addPoly(points, SK_ARRAY_COUNT(points), false);
+ for (int loop = 0; loop < 2; ++loop) {
+ for (auto style : {SkPaint::kStroke_Style, SkPaint::kFill_Style,
+ SkPaint::kStrokeAndFill_Style} ) {
+ paint.setStyle(style);
+ canvas->drawPath(path, paint);
+ canvas->translate(85, 0);
+ }
+ path.close();
+ canvas->translate(-255, 128);
+ }
+}
+##
+
+#SeeAlso
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method static bool IsInverseFillType(FillType fill)
+
+Returns true if fill is inverted and Path with fill represents area outside
+of its geometric bounds.
+
+#Table
+#Legend
+# FillType # is inverse ##
+##
+# kWinding_FillType # false ##
+# kEvenOdd_FillType # false ##
+# kInverseWinding_FillType # true ##
+# kInverseEvenOdd_FillType # true ##
+##
+
+#Param fill one of: kWinding_FillType, kEvenOdd_FillType,
+ kInverseWinding_FillType, kInverseEvenOdd_FillType
+##
+
+#Return true if Path fills outside its bounds ##
+
+#Example
+#Function
+#define nameValue(fill) { SkPath::fill, #fill }
+
+##
+void draw(SkCanvas* canvas) {
+ struct {
+ SkPath::FillType fill;
+ const char* name;
+ } fills[] = {
+ nameValue(kWinding_FillType),
+ nameValue(kEvenOdd_FillType),
+ nameValue(kInverseWinding_FillType),
+ nameValue(kInverseEvenOdd_FillType),
+ };
+ for (auto fill: fills ) {
+ SkDebugf("IsInverseFillType(%s) == %s\n", fill.name, SkPath::IsInverseFillType(fill.fill) ?
+ "true" : "false");
+ }
+}
+#StdOut
+IsInverseFillType(kWinding_FillType) == false
+IsInverseFillType(kEvenOdd_FillType) == false
+IsInverseFillType(kInverseWinding_FillType) == true
+IsInverseFillType(kInverseEvenOdd_FillType) == true
+##
+##
+
+#SeeAlso FillType getFillType setFillType ConvertToNonInverseFillType
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method static FillType ConvertToNonInverseFillType(FillType fill)
+
+Returns equivalent Fill_Type representing Path fill inside its bounds.
+.
+
+#Table
+#Legend
+# FillType # inside FillType ##
+##
+# kWinding_FillType # kWinding_FillType ##
+# kEvenOdd_FillType # kEvenOdd_FillType ##
+# kInverseWinding_FillType # kWinding_FillType ##
+# kInverseEvenOdd_FillType # kEvenOdd_FillType ##
+##
+
+#Param fill one of: kWinding_FillType, kEvenOdd_FillType,
+ kInverseWinding_FillType, kInverseEvenOdd_FillType
+##
+
+#Return fill, or kWinding_FillType or kEvenOdd_FillType if fill is inverted ##
+
+#Example
+#Function
+#define nameValue(fill) { SkPath::fill, #fill }
+
+##
+void draw(SkCanvas* canvas) {
+ struct {
+ SkPath::FillType fill;
+ const char* name;
+ } fills[] = {
+ nameValue(kWinding_FillType),
+ nameValue(kEvenOdd_FillType),
+ nameValue(kInverseWinding_FillType),
+ nameValue(kInverseEvenOdd_FillType),
+ };
+ for (unsigned i = 0; i < SK_ARRAY_COUNT(fills); ++i) {
+ if (fills[i].fill != (SkPath::FillType) i) {
+ SkDebugf("fills array order does not match FillType enum order");
+ break;
+ }
+ SkDebugf("ConvertToNonInverseFillType(%s) == %s\n", fills[i].name,
+ fills[(int) SkPath::ConvertToNonInverseFillType(fills[i].fill)].name);
+ }
+}
+#StdOut
+ConvertToNonInverseFillType(kWinding_FillType) == kWinding_FillType
+ConvertToNonInverseFillType(kEvenOdd_FillType) == kEvenOdd_FillType
+ConvertToNonInverseFillType(kInverseWinding_FillType) == kWinding_FillType
+ConvertToNonInverseFillType(kInverseEvenOdd_FillType) == kEvenOdd_FillType
+##
+##
+
+#SeeAlso FillType getFillType setFillType IsInverseFillType
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method static int ConvertConicToQuads(const SkPoint& p0, const SkPoint& p1, const SkPoint& p2,
+ SkScalar w, SkPoint pts[], int pow2)
+
+Approximates Conic with Quad array. Conic is constructed from start Point p0,
+control Point p1, end Point 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 Point of previous Quad and first Point of
+next Quad. Maximum pts storage size is given by:
+#Formula
+(1 + 2 * (1 << pow2)) * sizeof(SkPoint)
+##
+ConvertConicToQuads returns Quad count used the approximation, which may be smaller
+than the number requested.
+
+Conic_Weight determines the amount of influence Conic control point has on the curve.
+w less than one represents an elliptical section. w greater than one represents
+a hyperbolic section. w equal to one represents a parabolic section.
+
+Two Quad curves are sufficient to approximate an elliptical Conic with a sweep
+of up to 90 degrees; in this case, set pow2 to one.
+
+#Param p0 Conic start Point ##
+#Param p1 Conic control Point ##
+#Param p2 Conic end Point ##
+#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 ##
+
+#Example
+#Description
+A pair of Quad curves are drawn in red on top of the elliptical Conic curve in black.
+The middle curve is nearly circular. The top-right curve is parabolic, which can
+be drawn exactly with a single Quad.
+##
+void draw(SkCanvas* canvas) {
+ SkPaint conicPaint;
+ conicPaint.setAntiAlias(true);
+ conicPaint.setStyle(SkPaint::kStroke_Style);
+ SkPaint quadPaint(conicPaint);
+ quadPaint.setColor(SK_ColorRED);
+ SkPoint conic[] = { {20, 170}, {80, 170}, {80, 230} };
+ for (auto weight : { .25f, .5f, .707f, .85f, 1.f } ) {
+ SkPoint quads[5];
+ SkPath::ConvertConicToQuads(conic[0], conic[1], conic[2], weight, quads, 1);
+ SkPath path;
+ path.moveTo(conic[0]);
+ path.conicTo(conic[1], conic[2], weight);
+ canvas->drawPath(path, conicPaint);
+ path.rewind();
+ path.moveTo(quads[0]);
+ path.quadTo(quads[1], quads[2]);
+ path.quadTo(quads[3], quads[4]);
+ canvas->drawPath(path, quadPaint);
+ canvas->translate(50, -50);
+ }
+}
+##
+
+#SeeAlso Conic Quad
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method bool isRect(SkRect* rect, bool* isClosed = nullptr, Direction* direction = nullptr) const
+
+Returns true if Path is eqivalent to Rect 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 Path bounds. Path bounds may include kMove_Verb points
+that do not alter the area drawn by the returned rect.
+
+#Param rect storage for bounds of Rect; may be nullptr ##
+#Param isClosed storage set to true if Path is closed; may be nullptr ##
+#Param direction storage set to Rect direction; may be nullptr ##
+
+#Return true if Path contains Rect ##
+
+#Example
+#Description
+After addRect, isRect returns true. Following moveTo permits isRect to return true, but
+following lineTo does not. addPoly returns true even though rect is not closed, and one
+side of rect is made up of consecutive line segments.
+##
+void draw(SkCanvas* canvas) {
+ auto debugster = [](const char* prefix, const SkPath& path) -> void {
+ SkRect rect;
+ SkPath::Direction direction;
+ bool isClosed;
+ path.isRect(&rect, &isClosed, &direction) ?
+ SkDebugf("%s is rect (%g, %g, %g, %g); is %s" "closed; direction %s\n", prefix,
+ rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, isClosed ? "" : "not ",
+ SkPath::kCW_Direction == direction ? "CW" : "CCW") :
+ SkDebugf("%s is not rect\n", prefix);
+ };
+ SkPath path;
+ debugster("empty", path);
+ path.addRect({10, 20, 30, 40});
+ debugster("addRect", path);
+ path.moveTo(60, 70);
+ debugster("moveTo", path);
+ path.lineTo(60, 70);
+ debugster("lineTo", path);
+ path.reset();
+ const SkPoint pts[] = { {0, 0}, {0, 80}, {80, 80}, {80, 0}, {40, 0}, {20, 0} };
+ path.addPoly(pts, SK_ARRAY_COUNT(pts), false);
+ debugster("addPoly", path);
+}
+#StdOut
+empty is not rect
+addRect is rect (10, 20, 30, 40); is closed; direction CW
+moveTo is rect (10, 20, 30, 40); is closed; direction CW
+lineTo is not rect
+addPoly is rect (0, 0, 80, 80); is not closed; direction CCW
+##
+##
+
+#SeeAlso computeTightBounds conservativelyContainsRect getBounds isConvex isLastContourClosed isNestedFillRects
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method bool isNestedFillRects(SkRect rect[2], Direction dirs[2] = nullptr) const
+
+Returns true if Path is equivalent to nested Rect 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 Rect, and rect[1] to inner Rect;
+setting dirs[0] to Direction of outer Rect, and dirs[1] to Direction of inner
+Rect.
+
+#Param rect storage for Rect pair; may be nullptr ##
+#Param dirs storage for Direction pair; may be nullptr ##
+
+#Return true if Path contains nested Rect pair ##
+
+#Example
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(5);
+ SkPath path;
+ path.addRect({10, 20, 30, 40});
+ paint.getFillPath(path, &path);
+ SkRect rects[2];
+ SkPath::Direction directions[2];
+ if (path.isNestedFillRects(rects, directions)) {
+ for (int i = 0; i < 2; ++i) {
+ SkDebugf("%s (%g, %g, %g, %g); direction %s\n", i ? "inner" : "outer",
+ rects[i].fLeft, rects[i].fTop, rects[i].fRight, rects[i].fBottom,
+ SkPath::kCW_Direction == directions[i] ? "CW" : "CCW");
+ }
+ } else {
+ SkDebugf("is not nested rectangles\n");
+ }
+}
+#StdOut
+outer (7.5, 17.5, 32.5, 42.5); direction CW
+inner (12.5, 22.5, 27.5, 37.5); direction CCW
+##
+##
+
+#SeeAlso computeTightBounds conservativelyContainsRect getBounds isConvex isLastContourClosed isRect
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void addRect(const SkRect& rect, Direction dir = kCW_Direction)
+
+Add Rect to Path, appending kMove_Verb, three kLine_Verb, and kClose_Verb,
+starting with top-left corner of Rect; 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 Rect to add as a closed contour ##
+#Param dir Direction to wind added contour ##
+
+#Example
+#Description
+The left Rect dashes starting at the top-left corner, to the right.
+The right Rect dashes starting at the top-left corner, towards the bottom.
+##
+#Height 128
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setStrokeWidth(15);
+ paint.setStrokeCap(SkPaint::kSquare_Cap);
+ float intervals[] = { 5, 21.75f };
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 0));
+ SkPath path;
+ path.addRect({20, 20, 100, 100}, SkPath::kCW_Direction);
+ canvas->drawPath(path, paint);
+ path.rewind();
+ path.addRect({140, 20, 220, 100}, SkPath::kCCW_Direction);
+ canvas->drawPath(path, paint);
+}
+##
+
+#SeeAlso SkCanvas::drawRect Direction
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void addRect(const SkRect& rect, Direction dir, unsigned start)
+
+Add Rect to Path, appending kMove_Verb, three kLine_Verb, and kClose_Verb.
+If dir is kCW_Direction, Rect corners are added clockwise; if dir is
+kCCW_Direction, Rect corners are added counterclockwise.
+start determines the first corner added.
+
+#Table
+#Legend
+# start # first corner ##
+#Legend ##
+# 0 # top-left ##
+# 1 # top-right ##
+# 2 # bottom-right ##
+# 3 # bottom-left ##
+#Table ##
+
+#Param rect Rect to add as a closed contour ##
+#Param dir Direction to wind added contour ##
+#Param start Initial corner of Rect to add ##
+
+#Example
+#Height 128
+#Description
+The arrow is just after the initial corner and points towards the next
+corner appended to Path.
+##
+void draw(SkCanvas* canvas) {
+ const SkPoint arrow[] = { {5, -5}, {15, -5}, {20, 0}, {15, 5}, {5, 5}, {10, 0} };
+ const SkRect rect = {10, 10, 54, 54};
+ SkPaint rectPaint;
+ rectPaint.setAntiAlias(true);
+ rectPaint.setStyle(SkPaint::kStroke_Style);
+ SkPaint arrowPaint(rectPaint);
+ SkPath arrowPath;
+ arrowPath.addPoly(arrow, SK_ARRAY_COUNT(arrow), true);
+ arrowPaint.setPathEffect(SkPath1DPathEffect::Make(arrowPath, 176, 0,
+ SkPath1DPathEffect::kRotate_Style));
+ for (auto direction : { SkPath::kCW_Direction, SkPath::kCCW_Direction } ) {
+ for (unsigned start : { 0, 1, 2, 3 } ) {
+ SkPath path;
+ path.addRect(rect, direction, start);
+ canvas->drawPath(path, rectPaint);
+ canvas->drawPath(path, arrowPaint);
+ canvas->translate(64, 0);
+ }
+ canvas->translate(-256, 64);
+ }
+}
+##
+
+#SeeAlso SkCanvas::drawRect Direction
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void addRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom,
+ Direction dir = kCW_Direction)
+
+Add Rect (left, top, right, bottom) to Path,
+appending kMove_Verb, three kLine_Verb, and kClose_Verb,
+starting with top-left corner of Rect; 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 Rect ##
+#Param top smaller y of Rect ##
+#Param right larger x of Rect ##
+#Param bottom larger y of Rect ##
+#Param dir Direction to wind added contour ##
+
+#Example
+#Description
+The left Rect dashes start at the top-left corner, and continue to the right.
+The right Rect dashes start at the top-left corner, and continue down.
+##
+#Height 128
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setStrokeWidth(15);
+ paint.setStrokeCap(SkPaint::kSquare_Cap);
+ float intervals[] = { 5, 21.75f };
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 0));
+ for (auto direction : { SkPath::kCW_Direction, SkPath::kCCW_Direction } ) {
+ SkPath path;
+ path.addRect(20, 20, 100, 100, direction);
+ canvas->drawPath(path, paint);
+ canvas->translate(128, 0);
+ }
+}
+##
+
+#SeeAlso SkCanvas::drawRect Direction
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void addOval(const SkRect& oval, Direction dir = kCW_Direction)
+
+Add Oval to path, appending kMove_Verb, four kConic_Verb, and kClose_Verb.
+Oval is upright ellipse bounded by Rect 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 Direction to wind ellipse ##
+
+#Example
+#Height 120
+ SkPaint paint;
+ SkPath oval;
+ oval.addOval({20, 20, 160, 80});
+ canvas->drawPath(oval, paint);
+##
+
+#SeeAlso SkCanvas::drawOval Direction Oval
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void addOval(const SkRect& oval, Direction dir, unsigned start)
+
+Add Oval to Path, appending kMove_Verb, four kConic_Verb, and kClose_Verb.
+Oval is upright ellipse bounded by Rect 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.
+
+#Table
+#Legend
+# start # Point ##
+#Legend ##
+# 0 # oval.centerX(), oval.fTop ##
+# 1 # oval.fRight, oval.centerY() ##
+# 2 # oval.centerX(), oval.fBottom ##
+# 3 # oval.fLeft, oval.centerY() ##
+#Table ##
+
+#Param oval bounds of ellipse added ##
+#Param dir Direction to wind ellipse ##
+#Param start index of initial point of ellipse ##
+
+#Example
+#Height 160
+void draw(SkCanvas* canvas) {
+ const SkPoint arrow[] = { {0, -5}, {10, 0}, {0, 5} };
+ const SkRect rect = {10, 10, 54, 54};
+ SkPaint ovalPaint;
+ ovalPaint.setAntiAlias(true);
+ SkPaint textPaint(ovalPaint);
+ textPaint.setTextAlign(SkPaint::kCenter_Align);
+ ovalPaint.setStyle(SkPaint::kStroke_Style);
+ SkPaint arrowPaint(ovalPaint);
+ SkPath arrowPath;
+ arrowPath.addPoly(arrow, SK_ARRAY_COUNT(arrow), true);
+ arrowPaint.setPathEffect(SkPath1DPathEffect::Make(arrowPath, 176, 0,
+ SkPath1DPathEffect::kRotate_Style));
+ for (auto direction : { SkPath::kCW_Direction, SkPath::kCCW_Direction } ) {
+ for (unsigned start : { 0, 1, 2, 3 } ) {
+ SkPath path;
+ path.addOval(rect, direction, start);
+ canvas->drawPath(path, ovalPaint);
+ canvas->drawPath(path, arrowPaint);
+ canvas->drawText(&"0123"[start], 1, rect.centerX(), rect.centerY() + 5, textPaint);
+ canvas->translate(64, 0);
+ }
+ canvas->translate(-256, 72);
+ canvas->drawString(SkPath::kCW_Direction == direction ? "clockwise" : "counterclockwise",
+ 128, 0, textPaint);
+ }
+}
+##
+
+#SeeAlso SkCanvas::drawOval Direction Oval
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void addCircle(SkScalar x, SkScalar y, SkScalar radius,
+ Direction dir = kCW_Direction)
+
+Add Circle centered at (x, y) of size radius to Path, appending kMove_Verb,
+four kConic_Verb, and kClose_Verb. Circle begins at
+#Formula
+(x + radius, y)
+##
+and continues clockwise if dir is kCW_Direction, counterclockwise if dir is
+kCCW_Direction.
+
+addCircle has no effect if radius is zero or negative.
+
+#Param x center of Circle ##
+#Param y center of Circle ##
+#Param radius distance from center to edge ##
+#Param dir Direction to wind Circle ##
+
+#Example
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(10);
+ for (int size = 10; size < 300; size += 20) {
+ SkPath path;
+ path.addCircle(128, 128, size, SkPath::kCW_Direction);
+ canvas->drawPath(path, paint);
+ }
+}
+##
+
+#SeeAlso SkCanvas::drawCircle Direction Circle
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle)
+
+Append Arc to Path, 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 bounds of ellipse containing Arc ##
+#Param startAngle starting angle of Arc in degrees ##
+#Param sweepAngle sweep, in degrees. Positive is clockwise; treated modulo 360 ##
+
+#Example
+#Description
+The middle row of the left and right columns draw differently from the entries
+above and below because sweepAngle is outside of the range of +/-360,
+and startAngle modulo 90 is not zero.
+##
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ for (auto start : { 0, 90, 135, 180, 270 } ) {
+ for (auto sweep : { -450.f, -180.f, -90.f, 90.f, 180.f, 360.1f } ) {
+ SkPath path;
+ path.addArc({10, 10, 35, 45}, start, sweep);
+ canvas->drawPath(path, paint);
+ canvas->translate(252 / 6, 0);
+ }
+ canvas->translate(-252, 255 / 5);
+ }
+}
+##
+
+#SeeAlso Arc arcTo SkCanvas::drawArc
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
+ Direction dir = kCW_Direction)
+
+Append Round_Rect to Path, creating a new closed Contour. Round_Rect has bounds
+equal to rect; each corner is 90 degrees of an ellipse with radii (rx, ry). If
+dir is kCW_Direction, Round_Rect starts at top-left of the lower-left corner and
+winds clockwise. If dir is kCCW_Direction, Round_Rect 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
+Rect rect to Path.
+
+After appending, Path may be empty, or may contain: Rect, Oval, or RoundRect.
+
+#Param rect bounds of Round_Rect ##
+#Param rx x-radius of rounded corners on the Round_Rect ##
+#Param ry y-radius of rounded corners on the Round_Rect ##
+#Param dir Direction to wind Round_Rect ##
+
+#Example
+#Description
+If either radius is zero, path contains Rect and is drawn red.
+If sides are only radii, path contains Oval and is drawn blue.
+All remaining path draws are convex, and are drawn in gray; no
+paths constructed from addRoundRect are concave, so none are
+drawn in green.
+##
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ for (auto xradius : { 0, 7, 13, 20 } ) {
+ for (auto yradius : { 0, 9, 18, 40 } ) {
+ SkPath path;
+ path.addRoundRect({10, 10, 36, 46}, xradius, yradius);
+ paint.setColor(path.isRect(nullptr) ? SK_ColorRED : path.isOval(nullptr) ?
+ SK_ColorBLUE : path.isConvex() ? SK_ColorGRAY : SK_ColorGREEN);
+ canvas->drawPath(path, paint);
+ canvas->translate(64, 0);
+ }
+ canvas->translate(-256, 64);
+ }
+}
+##
+
+#SeeAlso addRRect SkCanvas::drawRoundRect
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void addRoundRect(const SkRect& rect, const SkScalar radii[],
+ Direction dir = kCW_Direction)
+
+Append Round_Rect to Path, creating a new closed Contour. Round_Rect has bounds
+equal to rect; each corner is 90 degrees of an ellipse with radii from the
+array.
+
+#Table
+#Legend
+# radii index # location ##
+#Legend ##
+# 0 # x-radius of top-left corner ##
+# 1 # y-radius of top-left corner ##
+# 2 # x-radius of top-right corner ##
+# 3 # y-radius of top-right corner ##
+# 4 # x-radius of bottom-right corner ##
+# 5 # y-radius of bottom-right corner ##
+# 6 # x-radius of bottom-left corner ##
+# 7 # y-radius of bottom-left corner ##
+#Table ##
+
+If dir is kCW_Direction, Round_Rect starts at top-left of the lower-left corner
+and winds clockwise. If dir is kCCW_Direction, Round_Rect starts at the
+bottom-left of the upper-left corner and winds counterclockwise.
+
+If both radii on any side of rect exceed its length, all radii are scaled
+uniformly until the corners fit. If either radius of a corner is less than or
+equal to zero, both are treated as zero.
+
+After appending, Path may be empty, or may contain: Rect, Oval, or RoundRect.
+
+#Param rect bounds of Round_Rect ##
+#Param radii array of 8 SkScalar values, a radius pair for each corner ##
+#Param dir Direction to wind Round_Rect ##
+
+#Example
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ SkScalar radii[] = { 80, 100, 0, 0, 40, 60, 0, 0 };
+ SkPath path;
+ SkMatrix rotate90;
+ rotate90.setRotate(90, 128, 128);
+ for (int i = 0; i < 4; ++i) {
+ path.addRoundRect({10, 10, 110, 110}, radii);
+ path.transform(rotate90);
+ }
+ canvas->drawPath(path, paint);
+}
+##
+
+#SeeAlso addRRect SkCanvas::drawRoundRect
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void addRRect(const SkRRect& rrect, Direction dir = kCW_Direction)
+
+Add rrect to Path, 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, Path may be empty, or may contain: Rect, Oval, or Round_Rect.
+
+#Param rrect bounds and radii of rounded rectangle ##
+#Param dir Direction to wind Round_Rect ##
+
+#Example
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ SkRRect rrect;
+ SkVector radii[] = {{50, 50}, {0, 0}, {0, 0}, {50, 50}};
+ rrect.setRectRadii({10, 10, 110, 110}, radii);
+ SkPath path;
+ SkMatrix rotate90;
+ rotate90.setRotate(90, 128, 128);
+ for (int i = 0; i < 4; ++i) {
+ path.addRRect(rrect);
+ path.transform(rotate90);
+ }
+ canvas->drawPath(path, paint);
+}
+##
+
+#SeeAlso addRoundRect SkCanvas::drawRRect
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void addRRect(const SkRRect& rrect, Direction dir, unsigned start)
+
+Add rrect to Path, 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.
+
+#Table
+#Legend
+# start # location ##
+#Legend ##
+# 0 # right of top-left corner ##
+# 1 # left of top-right corner ##
+# 2 # bottom of top-right corner ##
+# 3 # top of bottom-right corner ##
+# 4 # left of bottom-right corner ##
+# 5 # right of bottom-left corner ##
+# 6 # top of bottom-left corner ##
+# 7 # bottom of top-left corner ##
+#Table ##
+
+After appending, Path may be empty, or may contain: Rect, Oval, or Round_Rect.
+
+#Param rrect bounds and radii of rounded rectangle ##
+#Param dir Direction to wind Round_Rect ##
+#Param start Index of initial point of Round_Rect ##
+
+#Example
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ SkRRect rrect;
+ rrect.setRectXY({40, 40, 215, 215}, 50, 50);
+ SkPath path;
+ path.addRRect(rrect);
+ canvas->drawPath(path, paint);
+ for (int start = 0; start < 8; ++start) {
+ SkPath textPath;
+ textPath.addRRect(rrect, SkPath::kCW_Direction, start);
+ canvas->drawTextOnPathHV(&"01234567"[start], 1, textPath, 0, -5, paint);
+ }
+}
+##
+
+#SeeAlso addRoundRect SkCanvas::drawRRect
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void addPoly(const SkPoint pts[], int count, bool close)
+
+Add Contour created from Line array, adding
+#Formula
+count - 1
+##
+Line segments. Contour added starts at pt[0], then adds a line
+for every additional Point in pts array. If close is true,
+appends kClose_Verb to Path, connecting pts[count - 1] and pts[0].
+
+If count is zero, append kMove_Verb to path.
+Has no effect if count is less than one.
+
+#Param pts Array of Line sharing end and start Point ##
+#Param count Length of Point array ##
+#Param close true to add Line connecting Contour end and start ##
+
+#Example
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setStrokeWidth(15);
+ paint.setStrokeCap(SkPaint::kRound_Cap);
+ const SkPoint points[] = {{20, 20}, {70, 20}, {40, 90}};
+ for (bool close : { false, true } ) {
+ SkPath path;
+ path.addPoly(points, SK_ARRAY_COUNT(points), close);
+ for (auto style : {SkPaint::kStroke_Style, SkPaint::kFill_Style,
+ SkPaint::kStrokeAndFill_Style} ) {
+ paint.setStyle(style);
+ canvas->drawPath(path, paint);
+ canvas->translate(85, 0);
+ }
+ canvas->translate(-255, 128);
+ }
+}
+##
+
+#SeeAlso SkCanvas::drawPoints
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Enum AddPathMode
+
+#Code
+ enum AddPathMode {
+ kAppend_AddPathMode,
+ kExtend_AddPathMode,
+ };
+##
+
+AddPathMode chooses how addPath appends. Adding one Path to another can extend
+the last Contour or start a new Contour.
+
+#Const kAppend_AddPathMode
+ Path Verbs, Points, and Conic_Weights are appended to destination unaltered.
+ Since Path Verb_Array begins with kMove_Verb if src is not empty, this
+ starts a new Contour.
+##
+#Const kExtend_AddPathMode
+ If destination is closed or empty, start a new Contour. If destination
+ is not empty, add Line from Last_Point to added Path first Point. Skip added
+ Path initial kMove_Verb, then append remining Verbs, Points, and Conic_Weights.
+##
+
+#Example
+#Description
+test is built from path, open on the top row, and closed on the bottom row.
+The left column uses kAppend_AddPathMode; the right uses kExtend_AddPathMode.
+The top right composition is made up of one contour; the other three have two.
+##
+#Height 180
SkPath path, path2;
path.moveTo(20, 20);
path.lineTo(20, 40);
@@ -4509,30 +4551,30 @@ The top right composition is made up of one contour; the other three have two.
canvas->translate(-200, 100);
path.close();
}
-##
-
-#SeeAlso addPath reverseAddPath
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void addPath(const SkPath& src, SkScalar dx, SkScalar dy,
- AddPathMode mode = kAppend_AddPathMode)
-
-Append src to Path, offset by (dx, dy).
-
-If mode is kAppend_AddPathMode, src Verb_Array, Point_Array, and Weights are
-added unaltered. If mode is kExtend_AddPathMode, add Line before appending
-Verbs, Points, and Weights.
-
-#Param src Path Verbs, Points, and Weights to add. ##
-#Param dx offset added to src Point_Array x coordinates. ##
-#Param dy offset added to src Point_Array y coordinates. ##
-#Param mode kAppend_AddPathMode or kExtend_AddPathMode. ##
-
-#Example
-#Height 180
+##
+
+#SeeAlso addPath reverseAddPath
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void addPath(const SkPath& src, SkScalar dx, SkScalar dy,
+ AddPathMode mode = kAppend_AddPathMode)
+
+Append src to Path, offset by (dx, dy).
+
+If mode is kAppend_AddPathMode, src Verb_Array, Point_Array, and Conic_Weights are
+added unaltered. If mode is kExtend_AddPathMode, add Line before appending
+Verbs, Points, and Conic_Weights.
+
+#Param src Path Verbs, Points, and Conic_Weights to add ##
+#Param dx offset added to src Point_Array x coordinates ##
+#Param dy offset added to src Point_Array y coordinates ##
+#Param mode kAppend_AddPathMode or kExtend_AddPathMode ##
+
+#Example
+#Height 180
SkPaint paint;
paint.setTextSize(128);
paint.setFakeBoldText(true);
@@ -4545,27 +4587,27 @@ Verbs, Points, and Weights.
paint.setStyle(SkPaint::kStroke_Style);
paint.setStrokeWidth(3);
canvas->drawPath(dest, paint);
-##
-
-#SeeAlso AddPathMode offset() reverseAddPath
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void addPath(const SkPath& src, AddPathMode mode = kAppend_AddPathMode)
-
-Append src to Path.
-
-If mode is kAppend_AddPathMode, src Verb_Array, Point_Array, and Weights are
-added unaltered. If mode is kExtend_AddPathMode, add Line before appending
-Verbs, Points, and Weights.
-
-#Param src Path Verbs, Points, and Weights to add. ##
-#Param mode kAppend_AddPathMode or kExtend_AddPathMode. ##
-
-#Example
-#Height 80
+##
+
+#SeeAlso AddPathMode offset() reverseAddPath
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void addPath(const SkPath& src, AddPathMode mode = kAppend_AddPathMode)
+
+Append src to Path.
+
+If mode is kAppend_AddPathMode, src Verb_Array, Point_Array, and Conic_Weights are
+added unaltered. If mode is kExtend_AddPathMode, add Line before appending
+Verbs, Points, and Conic_Weights.
+
+#Param src Path Verbs, Points, and Conic_Weights to add ##
+#Param mode kAppend_AddPathMode or kExtend_AddPathMode ##
+
+#Example
+#Height 80
SkPaint paint;
paint.setStyle(SkPaint::kStroke_Style);
SkPath dest, path;
@@ -4574,30 +4616,30 @@ Verbs, Points, and Weights.
dest.addPath(path, SkPath::kExtend_AddPathMode);
dest.offset(100, 0);
}
- canvas->drawPath(dest, paint);
-##
-
-#SeeAlso AddPathMode reverseAddPath
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void addPath(const SkPath& src, const SkMatrix& matrix, AddPathMode mode = kAppend_AddPathMode)
-
-Append src to Path, transformed by matrix. Transformed curves may have different
-Verbs, Points, and Weights.
-
-If mode is kAppend_AddPathMode, src Verb_Array, Point_Array, and Weights are
-added unaltered. If mode is kExtend_AddPathMode, add Line before appending
-Verbs, Points, and Weights.
-
-#Param src Path Verbs, Points, and Weights to add. ##
-#Param matrix Transform applied to src. ##
-#Param mode kAppend_AddPathMode or kExtend_AddPathMode. ##
-
-#Example
-#Height 160
+ canvas->drawPath(dest, paint);
+##
+
+#SeeAlso AddPathMode reverseAddPath
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void addPath(const SkPath& src, const SkMatrix& matrix, AddPathMode mode = kAppend_AddPathMode)
+
+Append src to Path, transformed by matrix. Transformed curves may have different
+Verbs, Points, and Conic_Weights.
+
+If mode is kAppend_AddPathMode, src Verb_Array, Point_Array, and Conic_Weights are
+added unaltered. If mode is kExtend_AddPathMode, add Line before appending
+Verbs, Points, and Conic_Weights.
+
+#Param src Path Verbs, Points, and Conic_Weights to add ##
+#Param matrix Transform applied to src ##
+#Param mode kAppend_AddPathMode or kExtend_AddPathMode ##
+
+#Example
+#Height 160
SkPaint paint;
paint.setStyle(SkPaint::kStroke_Style);
SkPath dest, path;
@@ -4609,23 +4651,23 @@ Verbs, Points, and Weights.
dest.addPath(path, matrix);
}
canvas->drawPath(dest, paint);
-##
-
-#SeeAlso AddPathMode transform() offset() reverseAddPath
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void reverseAddPath(const SkPath& src)
-
-Append src to Path, from back to front.
-Reversed src always appends a new Contour to Path.
-
-#Param src Path Verbs, Points, and Weights to add. ##
-
-#Example
-#Height 200
+##
+
+#SeeAlso AddPathMode transform() offset() reverseAddPath
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void reverseAddPath(const SkPath& src)
+
+Append src to Path, from back to front.
+Reversed src always appends a new Contour to Path.
+
+#Param src Path Verbs, Points, and Conic_Weights to add ##
+
+#Example
+#Height 200
SkPath path;
path.moveTo(20, 20);
path.lineTo(20, 40);
@@ -4647,25 +4689,25 @@ Reversed src always appends a new Contour to Path.
canvas->translate(-200, 100);
path.close();
}
-##
-
-#SeeAlso AddPathMode transform() offset() addPath
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void offset(SkScalar dx, SkScalar dy, SkPath* dst) const
-
-Offset Point_Array by (dx, dy). Offset Path replaces dst.
-If dst is nullptr, Path is replaced by offset data.
-
-#Param dx offset added to Point_Array x coordinates. ##
-#Param dy offset added to Point_Array y coordinates. ##
-#Param dst overwritten, translated copy of Path; may be nullptr. ##
-
-#Example
-#Height 60
+##
+
+#SeeAlso AddPathMode transform() offset() addPath
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void offset(SkScalar dx, SkScalar dy, SkPath* dst) const
+
+Offset Point_Array by (dx, dy). Offset Path replaces dst.
+If dst is nullptr, Path is replaced by offset data.
+
+#Param dx offset added to Point_Array x coordinates ##
+#Param dy offset added to Point_Array y coordinates ##
+#Param dst overwritten, translated copy of Path; may be nullptr ##
+
+#Example
+#Height 60
SkPath pattern;
pattern.moveTo(20, 20);
pattern.lineTo(20, 40);
@@ -4677,23 +4719,23 @@ If dst is nullptr, Path is replaced by offset data.
pattern.offset(20 * i, 0, &path);
canvas->drawPath(path, paint);
}
-##
-
-#SeeAlso addPath transform
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void offset(SkScalar dx, SkScalar dy)
-
-Offset Point_Array by (dx, dy). Path is replaced by offset data.
-
-#Param dx offset added to Point_Array x coordinates. ##
-#Param dy offset added to Point_Array y coordinates. ##
-
-#Example
-#Height 60
+##
+
+#SeeAlso addPath transform
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void offset(SkScalar dx, SkScalar dy)
+
+Offset Point_Array by (dx, dy). Path is replaced by offset data.
+
+#Param dx offset added to Point_Array x coordinates ##
+#Param dy offset added to Point_Array y coordinates ##
+
+#Example
+#Height 60
SkPath path;
path.moveTo(20, 20);
path.lineTo(20, 40);
@@ -4704,25 +4746,25 @@ Offset Point_Array by (dx, dy). Path is replaced by offset data.
canvas->drawPath(path, paint);
path.offset(20, 0);
}
-##
-
-#SeeAlso addPath transform SkCanvas::translate()
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void transform(const SkMatrix& matrix, SkPath* dst) const
-
-Transform Verb_Array, Point_Array, and weight by matrix.
-transform may change Verbs and increase their number.
-Transformed Path replaces dst; if dst is nullptr, original data
-is replaced.
-
-#Param matrix Matrix to apply to Path. ##
-#Param dst overwritten, transformed copy of Path; may be nullptr. ##
-
-#Example
+##
+
+#SeeAlso addPath transform SkCanvas::translate()
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void transform(const SkMatrix& matrix, SkPath* dst) const
+
+Transform Verb_Array, Point_Array, and weight by matrix.
+transform may change Verbs and increase their number.
+Transformed Path replaces dst; if dst is nullptr, original data
+is replaced.
+
+#Param matrix Matrix to apply to Path ##
+#Param dst overwritten, transformed copy of Path; may be nullptr ##
+
+#Example
#Height 200
SkPath pattern;
pattern.moveTo(100, 100);
@@ -4736,24 +4778,24 @@ is replaced.
matrix.setRotate(36 * i, 100, 100);
pattern.transform(matrix, &path);
canvas->drawPath(path, paint);
- }
-##
-
-#SeeAlso addPath offset SkCanvas::concat() SkMatrix
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void transform(const SkMatrix& matrix)
-
-Transform Verb_Array, Point_Array, and weight by matrix.
-transform may change Verbs and increase their number.
-Path is replaced by transformed data.
-
-#Param matrix Matrix to apply to Path. ##
-
-#Example
+ }
+##
+
+#SeeAlso addPath offset SkCanvas::concat() SkMatrix
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void transform(const SkMatrix& matrix)
+
+Transform Verb_Array, Point_Array, and weight by matrix.
+transform may change Verbs and increase their number.
+Path is replaced by transformed data.
+
+#Param matrix Matrix to apply to Path ##
+
+#Example
#Height 200
SkPath path;
path.moveTo(100, 100);
@@ -4765,31 +4807,31 @@ Path is replaced by transformed data.
matrix.setRotate(36, 100, 100);
path.transform(matrix);
canvas->drawPath(path, paint);
- }
-##
-
-#SeeAlso addPath offset SkCanvas::concat() SkMatrix
-
-##
-
-# ------------------------------------------------------------------------------
-
+ }
+##
+
+#SeeAlso addPath offset SkCanvas::concat() SkMatrix
+
+##
+
+# ------------------------------------------------------------------------------
+
#Subtopic Last_Point
Path is defined cumulatively, often by adding a segment to the end of last
Contour. Last_Point of Contour is shared as first Point of added Line or Curve.
Last_Point can be read and written directly with getLastPt and setLastPt.
-#Method bool getLastPt(SkPoint* lastPt) const
-
- Returns Last_Point on Path in lastPt. Returns false if Point_Array is empty,
- storing (0, 0) if lastPt is not nullptr.
-
- #Param lastPt storage for final Point in Point_Array; may be nullptr. ##
-
- #Return true if Point_Array contains one or more Points. ##
-
- #Example
+#Method bool getLastPt(SkPoint* lastPt) const
+
+ Returns Last_Point on Path in lastPt. Returns false if Point_Array is empty,
+ storing (0, 0) if lastPt is not nullptr.
+
+ #Param lastPt storage for final Point in Point_Array; may be nullptr ##
+
+ #Return true if Point_Array contains one or more Points ##
+
+ #Example
SkPath path;
path.moveTo(100, 100);
path.quadTo(100, 20, 20, 100);
@@ -4798,47 +4840,47 @@ Last_Point can be read and written directly with getLastPt and setLastPt.
path.transform(matrix);
SkPoint last;
path.getLastPt(&last);
- SkDebugf("last point: %g, %g\n", last.fX, last.fY);
- #StdOut
- last point: 35.2786, 52.9772
- ##
- ##
-
- #SeeAlso setLastPt
-
-##
-
-#Method void setLastPt(SkScalar x, SkScalar y)
-
- Set Last_Point to (x, y). If Point_Array is empty, append kMove_Verb to
- Verb_Array and (x, y) to Point_Array.
-
- #Param x set x-coordinate of Last_Point. ##
- #Param y set y-coordinate of Last_Point. ##
-
- #Example
- #Height 128
+ SkDebugf("last point: %g, %g\n", last.fX, last.fY);
+ #StdOut
+ last point: 35.2786, 52.9772
+ ##
+ ##
+
+ #SeeAlso setLastPt
+
+##
+
+#Method void setLastPt(SkScalar x, SkScalar y)
+
+ Set Last_Point to (x, y). If Point_Array is empty, append kMove_Verb to
+ Verb_Array and (x, y) to Point_Array.
+
+ #Param x set x-coordinate of Last_Point ##
+ #Param y set y-coordinate of Last_Point ##
+
+ #Example
+ #Height 128
SkPaint paint;
paint.setTextSize(128);
SkPath path;
paint.getTextPath("@", 1, 60, 100, &path);
path.setLastPt(20, 120);
- canvas->drawPath(path, paint);
- ##
-
- #SeeAlso getLastPt
-
-##
-
-#Method void setLastPt(const SkPoint& p)
-
- Set the last point on the path. If no points have been added, moveTo(p)
- is automatically called.
-
- #Param p set value of Last_Point. ##
-
- #Example
- #Height 128
+ canvas->drawPath(path, paint);
+ ##
+
+ #SeeAlso getLastPt
+
+##
+
+#Method void setLastPt(const SkPoint& p)
+
+ Set the last point on the path. If no points have been added, moveTo(p)
+ is automatically called.
+
+ #Param p set value of Last_Point ##
+
+ #Example
+ #Height 128
SkPaint paint;
paint.setTextSize(128);
SkPath path, path2;
@@ -4851,431 +4893,481 @@ Last_Point can be read and written directly with getLastPt and setLastPt.
path2.setLastPt(pt);
canvas->drawPath(path, paint);
canvas->drawPath(path2, paint);
- ##
-
- #SeeAlso getLastPt
-
-##
-
-#Subtopic Last_Point ##
-
-# ------------------------------------------------------------------------------
-
-#Enum SegmentMask
-
-#Code
- enum SegmentMask {
- kLine_SegmentMask = 1 << 0
- kQuad_SegmentMask = 1 << 1
- kConic_SegmentMask = 1 << 2
- kCubic_SegmentMask = 1 << 3
- };
-##
-
-SegmentMask constants correspond to each drawing Verb type in Path; for
-instance, if Path only contains Lines, only the kLine_SegmentMask bit is set.
-
-#Bug 6785 ##
-#Const kLine_SegmentMask 1
-Set if Verb_Array contains kLine_Verb.
-##
-#Const kQuad_SegmentMask 2
-Set if Verb_Array contains kQuad_Verb. Note that conicTo may add a Quad.
-##
-#Const kConic_SegmentMask 4
-Set if Verb_Array contains kConic_Verb.
-##
-#Const kCubic_SegmentMask 8
-Set if Verb_Array contains kCubic_Verb.
-##
-
-#Example
-#Description
-When conicTo has a weight of one, Quad is added to Path.
-##
- SkPath path;
- path.conicTo(10, 10, 20, 30, 1);
- SkDebugf("Path kConic_SegmentMask is %s\n", path.getSegmentMasks() &
- SkPath::kConic_SegmentMask ? "set" : "clear");
- SkDebugf("Path kQuad_SegmentMask is %s\n", path.getSegmentMasks() &
- SkPath::kQuad_SegmentMask ? "set" : "clear");
-#StdOut
-Path kConic_SegmentMask is clear
-Path kQuad_SegmentMask is set
-##
-##
-
-#SeeAlso getSegmentMasks Verb
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method uint32_t getSegmentMasks() const
-
-Returns a mask, where each set bit corresponds to a SegmentMask constant
-if Path contains one or more Verbs of that type.
-Returns zero if Path contains no Lines, Quads, Conics, or Cubics.
-
-getSegmentMasks() returns a cached result; it is very fast.
-
-#Return SegmentMask bits or zero. ##
-
-#Example
-SkPath path;
-path.quadTo(20, 30, 40, 50);
-path.close();
-const char* masks[] = { "line", "quad", "conic", "cubic" };
-int index = 0;
-for (auto mask : { SkPath::kLine_SegmentMask, SkPath::kQuad_SegmentMask,
- SkPath::kConic_SegmentMask, SkPath::kCubic_SegmentMask } ) {
- if (mask & path.getSegmentMasks()) {
- SkDebugf("mask %s set\n", masks[index]);
- }
- ++index;
-}
-#StdOut
-mask quad set
-##
-##
-
-#SeeAlso getSegmentMasks Verb
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method bool contains(SkScalar x, SkScalar y) const
-
-Returns true if the point (x, y) is contained by Path, taking into
-account FillType.
-
-#Table
-#Legend
-# FillType # contains() returns true if Point is enclosed by ##
-##
-# kWinding_FillType # a non-zero sum of Contour Directions. ##
-# kEvenOdd_FillType # an odd number of Contours. ##
-# kInverseWinding_FillType # a zero sum of Contour Directions. ##
-# kInverseEvenOdd_FillType # and even number of Contours. ##
-##
-
-#Param x x-coordinate of containment test. ##
-#Param y y-coordinate of containment test. ##
-
-#Return true if Point is in Path. ##
-
-#Example
-SkPath path;
-SkPaint paint;
-paint.setTextSize(256);
-paint.getTextPath("&", 1, 30, 220, &path);
-for (int y = 2; y < 256; y += 9) {
- for (int x = 2; x < 256; x += 9) {
- int coverage = 0;
- for (int iy = -4; iy <= 4; iy += 2) {
- for (int ix = -4; ix <= 4; ix += 2) {
- coverage += path.contains(x + ix, y + iy);
- }
- }
- paint.setColor(SkColorSetARGB(0x5f, 0xff * coverage / 25, 0, 0xff * (25 - coverage) / 25));
- canvas->drawCircle(x, y, 8, paint);
- }
-}
-##
-
-#SeeAlso conservativelyContainsRect Fill_Type Op
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void dump(SkWStream* stream, bool forceClose, bool dumpAsHex) const
-
-Writes text representation of Path to stream. If stream is nullptr, dump() writes to
-stdout. Set forceClose to true to get
-edges used to fill Path. Set dumpAsHex true to get exact binary representations
-of floating point numbers used in Point_Array and Weights.
-
-#Param stream writable Stream receiving Path text representation; may be nullptr. ##
-#Param forceClose true if missing kClose_Verb is output. ##
-#Param dumpAsHex true if SkScalar values are written as hexidecimal. ##
-
-#Example
- SkPath path;
- path.quadTo(20, 30, 40, 50);
- for (bool forceClose : { false, true } ) {
- for (bool dumpAsHex : { false, true } ) {
- path.dump(nullptr, forceClose, dumpAsHex);
- SkDebugf("\n");
- }
- }
-#StdOut
-path.setFillType(SkPath::kWinding_FillType);
-path.moveTo(0, 0);
-path.quadTo(20, 30, 40, 50);
-
-path.setFillType(SkPath::kWinding_FillType);
-path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0
-path.quadTo(SkBits2Float(0x41a00000), SkBits2Float(0x41f00000), SkBits2Float(0x42200000), SkBits2Float(0x42480000)); // 20, 30, 40, 50
-
-path.setFillType(SkPath::kWinding_FillType);
-path.moveTo(0, 0);
-path.quadTo(20, 30, 40, 50);
-path.lineTo(0, 0);
-path.close();
-
-path.setFillType(SkPath::kWinding_FillType);
-path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0
-path.quadTo(SkBits2Float(0x41a00000), SkBits2Float(0x41f00000), SkBits2Float(0x42200000), SkBits2Float(0x42480000)); // 20, 30, 40, 50
-path.lineTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0
-path.close();
-##
-##
-
-#SeeAlso SkRect::dump() SkRRect::dump() SkPathMeasure::dump()
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void dump() const
-
-Writes text representation of Path to stdout. The representation may be
-directly compiled as C++ code. Floating point values are written
-with limited precision; it may not be possible to reconstruct original Path
-from output.
-
-#Example
-SkPath path, copy;
-path.lineTo(6.f / 7, 2.f / 3);
-path.dump();
-copy.setFillType(SkPath::kWinding_FillType);
-copy.moveTo(0, 0);
-copy.lineTo(0.857143f, 0.666667f);
-SkDebugf("path is " "%s" "equal to copy\n", path == copy ? "" : "not ");
-#StdOut
-path.setFillType(SkPath::kWinding_FillType);
-path.moveTo(0, 0);
-path.lineTo(0.857143f, 0.666667f);
-path is not equal to copy
-##
-##
-
-#SeeAlso dumpHex SkRect::dump() SkRRect::dump() SkPathMeasure::dump() writeToMemory
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void dumpHex() const
-
-Writes text representation of Path to stdout. 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 Path.
-
-Use dumpHex when submitting #A bug reports against Skia # http://bug.skia.org ##.
-Slight value changes in Point_Array may cause the bug to disappear.
-
-#Example
-SkPath path, copy;
-path.lineTo(6.f / 7, 2.f / 3);
-path.dumpHex();
-copy.setFillType(SkPath::kWinding_FillType);
-copy.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0
-copy.lineTo(SkBits2Float(0x3f5b6db7), SkBits2Float(0x3f2aaaab)); // 0.857143f, 0.666667f
-SkDebugf("path is " "%s" "equal to copy\n", path == copy ? "" : "not ");
-#StdOut
-path.setFillType(SkPath::kWinding_FillType);
-path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0
-path.lineTo(SkBits2Float(0x3f5b6db7), SkBits2Float(0x3f2aaaab)); // 0.857143f, 0.666667f
-path is equal to copy
-##
-##
-
-#SeeAlso dump SkRect::dumpHex() SkRRect::dumpHex() writeToMemory
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method size_t writeToMemory(void* buffer) const
-
-Write Path to buffer, returning the number of bytes written.
-Pass nullptr to obtain the storage size.
-
-writeToMemory writes Fill_Type, Verb_Array, Point_Array, Conic_Weight, and
-additionally writes computed information like Convexity and bounds.
-
-writeToMemory should only be used in concert with readFromMemory.
-The format used for Path in memory is not guaranteed.
-
-#Param buffer storage for Path; may be nullptr. ##
-
-#Return size of storage required for Path; always a multiple of 4. ##
-
-#Example
-void draw(SkCanvas* canvas) {
- SkPath path, copy;
- path.lineTo(6.f / 7, 2.f / 3);
- size_t size = path.writeToMemory(nullptr);
- SkTDArray<char> storage;
- storage.setCount(size);
- path.writeToMemory(storage.begin());
- copy.readFromMemory(storage.begin(), size);
- SkDebugf("path is " "%s" "equal to copy\n", path == copy ? "" : "not ");
-}
-##
-
-#SeeAlso readFromMemory dump dumpHex
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method size_t readFromMemory(const void* buffer, size_t length)
-
-Initializes Path from buffer of size length. Returns zero if the buffer is
-data is inconsistent, or the length is too small.
-
-readFromMemory reads Fill_Type, Verb_Array, Point_Array, Conic_Weight, and
-additionally reads computed information like Convexity and bounds.
-
-readFromMemory should only be used in concert with writeToMemory.
-The format used for Path in memory is not guaranteed.
-
-#Param buffer storage for Path. ##
-#Param length buffer size in bytes; must be multiple of 4. ##
-
-#Return number of bytes read, or zero on failure. ##
-
-#Example
-void draw(SkCanvas* canvas) {
- SkPath path, copy;
- path.lineTo(6.f / 7, 2.f / 3);
- size_t size = path.writeToMemory(nullptr);
- SkTDArray<char> storage;
- storage.setCount(size);
- path.writeToMemory(storage.begin());
- size_t wrongSize = size - 4;
- size_t bytesRead = copy.readFromMemory(storage.begin(), wrongSize);
- SkDebugf("length = %u; returned by readFromMemory = %u\n", wrongSize, bytesRead);
- size_t largerSize = size + 4;
- bytesRead = copy.readFromMemory(storage.begin(), largerSize);
- SkDebugf("length = %u; returned by readFromMemory = %u\n", largerSize, bytesRead);
-}
-#StdOut
-length = 60; returned by readFromMemory = 0
-length = 68; returned by readFromMemory = 64
-##
-##
-
-#SeeAlso writeToMemory
-
-##
-
-# ------------------------------------------------------------------------------
-#Topic Generation_ID
-#Alias Generation_IDs
-
-Generation_ID provides a quick way to check if Verb_Array, Point_Array, or
-Conic_Weight has changed. Generation_ID is not a hash; identical Paths will
-not necessarily have matching Generation_IDs.
-
-Empty Paths have a Generation_ID of one.
-
-#Method uint32_t getGenerationID() const
-
-Returns a non-zero, globally unique value. A different value is returned
-if Verb_Array, Point_Array, or Conic_Weight changes.
-
-Setting Fill_Type does not change Generation_ID.
-
-Each time the path is modified, a different Generation_ID will be returned.
-
-#Bug 1762
-Fill_Type does affect Generation_ID on Android framework.
-##
-
-#Return non-zero, globally unique value. ##
-
-#Example
-SkPath path;
-SkDebugf("empty genID = %u\n", path.getGenerationID());
-path.lineTo(1, 2);
-SkDebugf("1st lineTo genID = %u\n", path.getGenerationID());
-path.rewind();
-SkDebugf("empty genID = %u\n", path.getGenerationID());
-path.lineTo(1, 2);
-SkDebugf("2nd lineTo genID = %u\n", path.getGenerationID());
-#StdOut
-empty genID = 1
-1st lineTo genID = 2
-empty genID = 1
-2nd lineTo genID = 3
-##
-##
-
-#SeeAlso operator==(const SkPath& a, const SkPath& b)
-
-##
-
-#Topic ##
-
-# ------------------------------------------------------------------------------
-
-#Method void validate() const
-
-Debugging check to see if Path data is consistent.
-Not currently maintained.
-
-#NoExample
-##
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method void experimentalValidateRef() const
-
-#Private
-Debugging check to see if Path data is consistent.
-Not ready for public use.
-##
-
-##
-
-# ------------------------------------------------------------------------------
-
+ ##
+
+ #SeeAlso getLastPt
+
+##
+
+#Subtopic Last_Point ##
+
+# ------------------------------------------------------------------------------
+
+#Enum SegmentMask
+
+#Code
+ enum SegmentMask {
+ kLine_SegmentMask = 1 << 0,
+ kQuad_SegmentMask = 1 << 1,
+ kConic_SegmentMask = 1 << 2,
+ kCubic_SegmentMask = 1 << 3,
+ };
+##
+
+SegmentMask constants correspond to each drawing Verb type in Path; for
+instance, if Path only contains Lines, only the kLine_SegmentMask bit is set.
+
+#Bug 6785 ##
+#Const kLine_SegmentMask 1
+Set if Verb_Array contains kLine_Verb.
+##
+#Const kQuad_SegmentMask 2
+Set if Verb_Array contains kQuad_Verb. Note that conicTo may add a Quad.
+##
+#Const kConic_SegmentMask 4
+Set if Verb_Array contains kConic_Verb.
+##
+#Const kCubic_SegmentMask 8
+Set if Verb_Array contains kCubic_Verb.
+##
+
+#Example
+#Description
+When conicTo has a weight of one, Quad is added to Path.
+##
+ SkPath path;
+ path.conicTo(10, 10, 20, 30, 1);
+ SkDebugf("Path kConic_SegmentMask is %s\n", path.getSegmentMasks() &
+ SkPath::kConic_SegmentMask ? "set" : "clear");
+ SkDebugf("Path kQuad_SegmentMask is %s\n", path.getSegmentMasks() &
+ SkPath::kQuad_SegmentMask ? "set" : "clear");
+#StdOut
+Path kConic_SegmentMask is clear
+Path kQuad_SegmentMask is set
+##
+##
+
+#SeeAlso getSegmentMasks Verb
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method uint32_t getSegmentMasks() const
+
+Returns a mask, where each set bit corresponds to a SegmentMask constant
+if Path contains one or more Verbs of that type.
+Returns zero if Path contains no Lines, or Curves: Quads, Conics, or Cubics.
+
+getSegmentMasks() returns a cached result; it is very fast.
+
+#Return SegmentMask bits or zero ##
+
+#Example
+SkPath path;
+path.quadTo(20, 30, 40, 50);
+path.close();
+const char* masks[] = { "line", "quad", "conic", "cubic" };
+int index = 0;
+for (auto mask : { SkPath::kLine_SegmentMask, SkPath::kQuad_SegmentMask,
+ SkPath::kConic_SegmentMask, SkPath::kCubic_SegmentMask } ) {
+ if (mask & path.getSegmentMasks()) {
+ SkDebugf("mask %s set\n", masks[index]);
+ }
+ ++index;
+}
+#StdOut
+mask quad set
+##
+##
+
+#SeeAlso getSegmentMasks Verb
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method bool contains(SkScalar x, SkScalar y) const
+
+Returns true if the point (x, y) is contained by Path, taking into
+account FillType.
+
+#Table
+#Legend
+# FillType # contains() returns true if Point is enclosed by ##
+##
+# kWinding_FillType # a non-zero sum of Contour Directions. ##
+# kEvenOdd_FillType # an odd number of Contours. ##
+# kInverseWinding_FillType # a zero sum of Contour Directions. ##
+# kInverseEvenOdd_FillType # and even number of Contours. ##
+##
+
+#Param x x-coordinate of containment test ##
+#Param y y-coordinate of containment test ##
+
+#Return true if Point is in Path ##
+
+#Example
+SkPath path;
+SkPaint paint;
+paint.setTextSize(256);
+paint.getTextPath("&", 1, 30, 220, &path);
+for (int y = 2; y < 256; y += 9) {
+ for (int x = 2; x < 256; x += 9) {
+ int coverage = 0;
+ for (int iy = -4; iy <= 4; iy += 2) {
+ for (int ix = -4; ix <= 4; ix += 2) {
+ coverage += path.contains(x + ix, y + iy);
+ }
+ }
+ paint.setColor(SkColorSetARGB(0x5f, 0xff * coverage / 25, 0, 0xff * (25 - coverage) / 25));
+ canvas->drawCircle(x, y, 8, paint);
+ }
+}
+##
+
+#SeeAlso conservativelyContainsRect Fill_Type Op
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void dump(SkWStream* stream, bool forceClose, bool dumpAsHex) const
+
+Writes text representation of Path to stream. If stream is nullptr, dump() writes to
+stdout. Set forceClose to true to get
+edges used to fill Path. Set dumpAsHex true to get exact binary representations
+of floating point numbers used in Point_Array and Conic_Weights.
+
+#Param stream writable Stream receiving Path text representation; may be nullptr ##
+#Param forceClose true if missing kClose_Verb is output ##
+#Param dumpAsHex true if SkScalar values are written as hexidecimal ##
+
+#Example
+ SkPath path;
+ path.quadTo(20, 30, 40, 50);
+ for (bool forceClose : { false, true } ) {
+ for (bool dumpAsHex : { false, true } ) {
+ path.dump(nullptr, forceClose, dumpAsHex);
+ SkDebugf("\n");
+ }
+ }
+#StdOut
+path.setFillType(SkPath::kWinding_FillType);
+path.moveTo(0, 0);
+path.quadTo(20, 30, 40, 50);
+
+path.setFillType(SkPath::kWinding_FillType);
+path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0
+path.quadTo(SkBits2Float(0x41a00000), SkBits2Float(0x41f00000), SkBits2Float(0x42200000), SkBits2Float(0x42480000)); // 20, 30, 40, 50
+
+path.setFillType(SkPath::kWinding_FillType);
+path.moveTo(0, 0);
+path.quadTo(20, 30, 40, 50);
+path.lineTo(0, 0);
+path.close();
+
+path.setFillType(SkPath::kWinding_FillType);
+path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0
+path.quadTo(SkBits2Float(0x41a00000), SkBits2Float(0x41f00000), SkBits2Float(0x42200000), SkBits2Float(0x42480000)); // 20, 30, 40, 50
+path.lineTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0
+path.close();
+##
+##
+
+#SeeAlso SkRect::dump() SkRRect::dump() SkPathMeasure::dump()
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void dump() const
+
+Writes text representation of Path to stdout. The representation may be
+directly compiled as C++ code. Floating point values are written
+with limited precision; it may not be possible to reconstruct original Path
+from output.
+
+#Example
+SkPath path, copy;
+path.lineTo(6.f / 7, 2.f / 3);
+path.dump();
+copy.setFillType(SkPath::kWinding_FillType);
+copy.moveTo(0, 0);
+copy.lineTo(0.857143f, 0.666667f);
+SkDebugf("path is " "%s" "equal to copy\n", path == copy ? "" : "not ");
+#StdOut
+path.setFillType(SkPath::kWinding_FillType);
+path.moveTo(0, 0);
+path.lineTo(0.857143f, 0.666667f);
+path is not equal to copy
+##
+##
+
+#SeeAlso dumpHex SkRect::dump() SkRRect::dump() SkPathMeasure::dump() writeToMemory
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method void dumpHex() const
+
+Writes text representation of Path to stdout. 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 Path.
+
+Use instead of dump() when submitting #A bug reports against Skia # http://bug.skia.org ##.
+Slight value changes in Point_Array may cause the bug to disappear.
+
+#Example
+SkPath path, copy;
+path.lineTo(6.f / 7, 2.f / 3);
+path.dumpHex();
+copy.setFillType(SkPath::kWinding_FillType);
+copy.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0
+copy.lineTo(SkBits2Float(0x3f5b6db7), SkBits2Float(0x3f2aaaab)); // 0.857143f, 0.666667f
+SkDebugf("path is " "%s" "equal to copy\n", path == copy ? "" : "not ");
+#StdOut
+path.setFillType(SkPath::kWinding_FillType);
+path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0
+path.lineTo(SkBits2Float(0x3f5b6db7), SkBits2Float(0x3f2aaaab)); // 0.857143f, 0.666667f
+path is equal to copy
+##
+##
+
+#SeeAlso dump SkRect::dumpHex() SkRRect::dumpHex() writeToMemory
+
+##
+
+# ------------------------------------------------------------------------------
+
+#Method size_t writeToMemory(void* buffer) const
+
+Writes Path to buffer, returning the number of bytes written.
+Pass nullptr to obtain the storage size.
+
+Writes Fill_Type, Verb_Array, Point_Array, Conic_Weight, and
+additionally writes computed information like Convexity and bounds.
+
+Use only be used in concert with readFromMemory;
+the format used for Path in memory is not guaranteed.
+
+#Param buffer storage for Path; may be nullptr ##
+
+#Return size of storage required for Path; always a multiple of 4 ##
+
+#Example
+void draw(SkCanvas* canvas) {
+ SkPath path, copy;
+ path.lineTo(6.f / 7, 2.f / 3);
+ size_t size = path.writeToMemory(nullptr);
+ SkTDArray<char> storage;
+ storage.setCount(size);
+ path.writeToMemory(storage.begin());
+ copy.readFromMemory(storage.begin(), size);
+ SkDebugf("path is " "%s" "equal to copy\n", path == copy ? "" : "not ");
+}
+#StdOut
+path is equal to copy
+##
+##
+
+#SeeAlso serialize readFromMemory dump dumpHex
+
+##
+
+#Method sk_sp<SkData> serialize() const
+
+Write Path to buffer, returning the buffer written to, wrapped in Data.
+
+serialize() writes Fill_Type, Verb_Array, Point_Array, Conic_Weight, and
+additionally writes computed information like Convexity and bounds.
+
+serialize() should only be used in concert with readFromMemory.
+The format used for Path in memory is not guaranteed.
+
+#Return Path data wrapped in Data buffer ##
+
+#Example
+void draw(SkCanvas* canvas) {
+ SkPath path, copy;
+ path.lineTo(6.f / 7, 2.f / 3);
+ sk_sp<SkData> data = path.serialize();
+ copy.readFromMemory(data->data(), data->size());
+ SkDebugf("path is " "%s" "equal to copy\n", path == copy ? "" : "not ");
+}
+#StdOut
+path is equal to copy
+##
+##
+
+#SeeAlso writeToMemory readFromMemory dump dumpHex
+##
+
+# ------------------------------------------------------------------------------
+
+#Method size_t readFromMemory(const void* buffer, size_t length)
+
+Initializes Path from buffer of size length. Returns zero if the buffer is
+data is inconsistent, or the length is too small.
+
+Reads Fill_Type, Verb_Array, Point_Array, Conic_Weight, and
+additionally reads computed information like Convexity and bounds.
+
+Used only in concert with writeToMemory;
+the format used for Path in memory is not guaranteed.
+
+#Param buffer storage for Path ##
+#Param length buffer size in bytes; must be multiple of 4 ##
+
+#Return number of bytes read, or zero on failure ##
+
+#Example
+void draw(SkCanvas* canvas) {
+ SkPath path, copy;
+ path.lineTo(6.f / 7, 2.f / 3);
+ size_t size = path.writeToMemory(nullptr);
+ SkTDArray<char> storage;
+ storage.setCount(size);
+ path.writeToMemory(storage.begin());
+ size_t wrongSize = size - 4;
+ size_t bytesRead = copy.readFromMemory(storage.begin(), wrongSize);
+ SkDebugf("length = %u; returned by readFromMemory = %u\n", wrongSize, bytesRead);
+ size_t largerSize = size + 4;
+ bytesRead = copy.readFromMemory(storage.begin(), largerSize);
+ SkDebugf("length = %u; returned by readFromMemory = %u\n", largerSize, bytesRead);
+}
+#StdOut
+length = 60; returned by readFromMemory = 0
+length = 68; returned by readFromMemory = 64
+##
+##
+
+#SeeAlso writeToMemory
+
+##
+
+# ------------------------------------------------------------------------------
+#Topic Generation_ID
+#Alias Generation_IDs
+
+Generation_ID provides a quick way to check if Verb_Array, Point_Array, or
+Conic_Weight has changed. Generation_ID is not a hash; identical Paths will
+not necessarily have matching Generation_IDs.
+
+Empty Paths have a Generation_ID of one.
+
+#Method uint32_t getGenerationID() const
+
+Returns a non-zero, globally unique value. A different value is returned
+if Verb_Array, Point_Array, or Conic_Weight changes.
+
+Setting Fill_Type does not change Generation_ID.
+
+Each time the path is modified, a different Generation_ID will be returned.
+
+#Bug 1762
+Fill_Type does affect Generation_ID on Android framework.
+##
+
+#Return non-zero, globally unique value ##
+
+#Example
+SkPath path;
+SkDebugf("empty genID = %u\n", path.getGenerationID());
+path.lineTo(1, 2);
+SkDebugf("1st lineTo genID = %u\n", path.getGenerationID());
+path.rewind();
+SkDebugf("empty genID = %u\n", path.getGenerationID());
+path.lineTo(1, 2);
+SkDebugf("2nd lineTo genID = %u\n", path.getGenerationID());
+#StdOut
+empty genID = 1
+1st lineTo genID = 2
+empty genID = 1
+2nd lineTo genID = 3
+##
+##
+
+#SeeAlso operator==(const SkPath& a, const SkPath& b)
+
+##
+
+#Topic ##
+
+# ------------------------------------------------------------------------------
+
+#Method bool isValid() const
+
+ Returns if Path data is consistent. Corrupt Path data is detected if
+ internal values are out of range or internal storage does not match
+ array dimensions.
+
+ #Return true if Path data is consistent ##
+
+ #NoExample
+ ##
+
+##
+
+#Method bool pathRefIsValid() const
+
+ Returns if Path data is consistent.
+
+ #Deprecated
+ To be deprecated soon.
+ ##
+
+ #Return true if Path data is consistent ##
+
+ #NoExample
+ ##
+##
+
+# ------------------------------------------------------------------------------
+
#Class Iter
Iterates through Verb_Array, and associated Point_Array and Conic_Weight.
Provides options to treat open Contours as closed, and to ignore
degenerate data.
+#Code
+class Iter {
+public:
+ Iter();
+ Iter(const SkPath& path, bool forceClose);
+ void setPath(const SkPath& path, bool forceClose);
+ Verb next(SkPoint pts[4], bool doConsumeDegenerates = true, bool exact = false);
+ SkScalar conicWeight() const;
+ bool isCloseLine() const;
+ bool isClosedContour() const;
+};
+##
+
#Example
#Height 128
#Description
-Ignoring the actual Verbs and replacing them with quads rounds the
+Ignoring the actual Verbs and replacing them with Quads rounds the
path of the glyph.
##
-void draw(SkCanvas* canvas) {
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setTextSize(256);
- SkPath asterisk, path;
- paint.getTextPath("*", 1, 50, 192, &asterisk);
- SkPath::Iter iter(asterisk, true);
- SkPoint start[4], pts[4];
- iter.next(start); // skip moveTo
- iter.next(start); // first quadTo
- path.moveTo((start[0] + start[1]) * 0.5f);
- while (SkPath::kClose_Verb != iter.next(pts)) {
- path.quadTo(pts[0], (pts[0] + pts[1]) * 0.5f);
- }
- path.quadTo(start[0], (start[0] + start[1]) * 0.5f);
- canvas->drawPath(path, paint);
+void draw(SkCanvas* canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setTextSize(256);
+ SkPath asterisk, path;
+ paint.getTextPath("*", 1, 50, 192, &asterisk);
+ SkPath::Iter iter(asterisk, true);
+ SkPoint start[4], pts[4];
+ iter.next(start); // skip moveTo
+ iter.next(start); // first quadTo
+ path.moveTo((start[0] + start[1]) * 0.5f);
+ while (SkPath::kClose_Verb != iter.next(pts)) {
+ path.quadTo(pts[0], (pts[0] + pts[1]) * 0.5f);
+ }
+ path.quadTo(start[0], (start[0] + start[1]) * 0.5f);
+ canvas->drawPath(path, paint);
}
##
@@ -5286,21 +5378,21 @@ void draw(SkCanvas* canvas) {
Initializes Iter with an empty Path. next() on Iter returns kDone_Verb.
Call setPath to initialize Iter at a later time.
-#Return Iter of empty Path. ##
+#Return Iter of empty Path ##
#Example
-void draw(SkCanvas* canvas) {
- SkPath::Iter iter;
- SkPoint points[4];
- SkDebugf("iter is " "%s" "done\n", SkPath::kDone_Verb == iter.next(points) ? "" : "not ");
- SkPath path;
- iter.setPath(path, false);
- SkDebugf("iter is " "%s" "done\n", SkPath::kDone_Verb == iter.next(points) ? "" : "not ");
+void draw(SkCanvas* canvas) {
+ SkPath::Iter iter;
+ SkPoint points[4];
+ SkDebugf("iter is " "%s" "done\n", SkPath::kDone_Verb == iter.next(points) ? "" : "not ");
+ SkPath path;
+ iter.setPath(path, false);
+ SkDebugf("iter is " "%s" "done\n", SkPath::kDone_Verb == iter.next(points) ? "" : "not ");
}
-#StdOut
-iter is done
-iter is done
-##
+#StdOut
+iter is done
+iter is done
+##
##
#SeeAlso setPath
@@ -5313,51 +5405,51 @@ Sets Iter to return elements of Verb_Array, Point_Array, and Conic_Weight in pat
If forceClose is true, Iter will add kLine_Verb and kClose_Verb after each
open Contour. path is not altered.
-#Param path Path to iterate. ##
-#Param forceClose true if open Contours generate kClose_Verb. ##
+#Param path Path to iterate ##
+#Param forceClose true if open Contours generate kClose_Verb ##
-#Return Iter of path. ##
+#Return Iter of path ##
#Example
-void draw(SkCanvas* canvas) {
- auto debugster = [](const char* prefix, SkPath::Iter& iter) -> void {
- SkDebugf("%s:\n", prefix);
- const char* verbStr[] = { "Move", "Line", "Quad", "Conic", "Cubic", "Close", "Done" };
- const int pointCount[] = { 1 , 2 , 3 , 3 , 4 , 1 , 0 };
- SkPath::Verb verb;
- do {
- SkPoint points[4];
- verb = iter.next(points);
- SkDebugf("k%s_Verb ", verbStr[(int) verb]);
- for (int i = 0; i < pointCount[(int) verb]; ++i) {
- SkDebugf("{%g, %g}, ", points[i].fX, points[i].fY);
- }
- if (SkPath::kConic_Verb == verb) {
- SkDebugf("weight = %g", iter.conicWeight());
- }
- SkDebugf("\n");
- } while (SkPath::kDone_Verb != verb);
- SkDebugf("\n");
- };
-
- SkPath path;
- path.quadTo(10, 20, 30, 40);
- SkPath::Iter openIter(path, false);
- debugster("open", openIter);
- SkPath::Iter closedIter(path, true);
- debugster("closed", closedIter);
+void draw(SkCanvas* canvas) {
+ auto debugster = [](const char* prefix, SkPath::Iter& iter) -> void {
+ SkDebugf("%s:\n", prefix);
+ const char* verbStr[] = { "Move", "Line", "Quad", "Conic", "Cubic", "Close", "Done" };
+ const int pointCount[] = { 1 , 2 , 3 , 3 , 4 , 1 , 0 };
+ SkPath::Verb verb;
+ do {
+ SkPoint points[4];
+ verb = iter.next(points);
+ SkDebugf("k%s_Verb ", verbStr[(int) verb]);
+ for (int i = 0; i < pointCount[(int) verb]; ++i) {
+ SkDebugf("{%g, %g}, ", points[i].fX, points[i].fY);
+ }
+ if (SkPath::kConic_Verb == verb) {
+ SkDebugf("weight = %g", iter.conicWeight());
+ }
+ SkDebugf("\n");
+ } while (SkPath::kDone_Verb != verb);
+ SkDebugf("\n");
+ };
+
+ SkPath path;
+ path.quadTo(10, 20, 30, 40);
+ SkPath::Iter openIter(path, false);
+ debugster("open", openIter);
+ SkPath::Iter closedIter(path, true);
+ debugster("closed", closedIter);
}
#StdOut
open:
-kMove_Verb {0, 0},
-kQuad_Verb {0, 0}, {10, 20}, {30, 40},
-kDone_Verb
-
-closed:
-kMove_Verb {0, 0},
-kQuad_Verb {0, 0}, {10, 20}, {30, 40},
-kLine_Verb {30, 40}, {0, 0},
-kClose_Verb {0, 0},
+kMove_Verb {0, 0},
+kQuad_Verb {0, 0}, {10, 20}, {30, 40},
+kDone_Verb
+
+closed:
+kMove_Verb {0, 0},
+kQuad_Verb {0, 0}, {10, 20}, {30, 40},
+kLine_Verb {30, 40}, {0, 0},
+kClose_Verb {0, 0},
kDone_Verb
##
##
@@ -5372,51 +5464,51 @@ Sets Iter to return elements of Verb_Array, Point_Array, and Conic_Weight in pat
If forceClose is true, Iter will add kLine_Verb and kClose_Verb after each
open Contour. path is not altered.
-#Param path Path to iterate. ##
-#Param forceClose true if open Contours generate kClose_Verb. ##
+#Param path Path to iterate ##
+#Param forceClose true if open Contours generate kClose_Verb ##
#Example
-void draw(SkCanvas* canvas) {
- auto debugster = [](const char* prefix, SkPath::Iter& iter) -> void {
- SkDebugf("%s:\n", prefix);
- const char* verbStr[] = { "Move", "Line", "Quad", "Conic", "Cubic", "Close", "Done" };
- const int pointCount[] = { 1 , 2 , 3 , 3 , 4 , 1 , 0 };
- SkPath::Verb verb;
- do {
- SkPoint points[4];
- verb = iter.next(points);
- SkDebugf("k%s_Verb ", verbStr[(int) verb]);
- for (int i = 0; i < pointCount[(int) verb]; ++i) {
- SkDebugf("{%g, %g}, ", points[i].fX, points[i].fY);
- }
- if (SkPath::kConic_Verb == verb) {
- SkDebugf("weight = %g", iter.conicWeight());
- }
- SkDebugf("\n");
- } while (SkPath::kDone_Verb != verb);
- SkDebugf("\n");
- };
-
- SkPath path;
- path.quadTo(10, 20, 30, 40);
- SkPath::Iter iter(path, false);
- debugster("quad open", iter);
- SkPath path2;
- path2.conicTo(1, 2, 3, 4, .5f);
- iter.setPath(path2, true);
- debugster("conic closed", iter);
+void draw(SkCanvas* canvas) {
+ auto debugster = [](const char* prefix, SkPath::Iter& iter) -> void {
+ SkDebugf("%s:\n", prefix);
+ const char* verbStr[] = { "Move", "Line", "Quad", "Conic", "Cubic", "Close", "Done" };
+ const int pointCount[] = { 1 , 2 , 3 , 3 , 4 , 1 , 0 };
+ SkPath::Verb verb;
+ do {
+ SkPoint points[4];
+ verb = iter.next(points);
+ SkDebugf("k%s_Verb ", verbStr[(int) verb]);
+ for (int i = 0; i < pointCount[(int) verb]; ++i) {
+ SkDebugf("{%g, %g}, ", points[i].fX, points[i].fY);
+ }
+ if (SkPath::kConic_Verb == verb) {
+ SkDebugf("weight = %g", iter.conicWeight());
+ }
+ SkDebugf("\n");
+ } while (SkPath::kDone_Verb != verb);
+ SkDebugf("\n");
+ };
+
+ SkPath path;
+ path.quadTo(10, 20, 30, 40);
+ SkPath::Iter iter(path, false);
+ debugster("quad open", iter);
+ SkPath path2;
+ path2.conicTo(1, 2, 3, 4, .5f);
+ iter.setPath(path2, true);
+ debugster("conic closed", iter);
}
#StdOut
-quad open:
-kMove_Verb {0, 0},
-kQuad_Verb {0, 0}, {10, 20}, {30, 40},
-kDone_Verb
-
-conic closed:
-kMove_Verb {0, 0},
-kConic_Verb {0, 0}, {1, 2}, {3, 4}, weight = 0.5
-kLine_Verb {3, 4}, {0, 0},
-kClose_Verb {0, 0},
+quad open:
+kMove_Verb {0, 0},
+kQuad_Verb {0, 0}, {10, 20}, {30, 40},
+kDone_Verb
+
+conic closed:
+kMove_Verb {0, 0},
+kConic_Verb {0, 0}, {1, 2}, {3, 4}, weight = 0.5
+kLine_Verb {3, 4}, {0, 0},
+kClose_Verb {0, 0},
kDone_Verb
##
##
@@ -5436,13 +5528,13 @@ 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 Point data describing returned Verb. ##
- #Param doConsumeDegenerates If true, skip degenerate Verbs. ##
+ #Param pts Storage for Point data describing returned Verb ##
+ #Param doConsumeDegenerates If true, skip degenerate Verbs ##
#Param exact If true, skip zero length curves. Has no effect if doConsumeDegenerates
- is false.
+ is false
##
- #Return next Verb from Verb_Array. ##
+ #Return next Verb from Verb_Array ##
#Example
#Description
@@ -5454,63 +5546,63 @@ the very small Line.
skip none shows all of the Verbs and Points in Path.
##
-void draw(SkCanvas* canvas) {
- auto debugster = [](const char* prefix, const SkPath& path, bool degen, bool exact) -> void {
- SkPath::Iter iter(path, false);
- SkDebugf("%s:\n", prefix);
- const char* verbStr[] = { "Move", "Line", "Quad", "Conic", "Cubic", "Close", "Done" };
- const int pointCount[] = { 1 , 2 , 3 , 3 , 4 , 1 , 0 };
- SkPath::Verb verb;
- do {
- SkPoint points[4];
- verb = iter.next(points, degen, exact);
- SkDebugf("k%s_Verb ", verbStr[(int) verb]);
- for (int i = 0; i < pointCount[(int) verb]; ++i) {
- SkDebugf("{%1.8g, %1.8g}, ", points[i].fX, points[i].fY);
- }
- SkDebugf("\n");
- } while (SkPath::kDone_Verb != verb);
- SkDebugf("\n");
- };
-
- SkPath path;
- path.moveTo(10, 10);
- path.moveTo(20, 20);
- path.quadTo(10, 20, 30, 40);
- path.moveTo(1, 1);
- path.close();
- path.moveTo(30, 30);
- path.lineTo(30, 30);
- path.moveTo(30, 30);
- path.lineTo(30.00001f, 30);
- debugster("skip degenerate", path, true, false);
- debugster("skip degenerate if exact", path, true, true);
- debugster("skip none", path, false, false);
+void draw(SkCanvas* canvas) {
+ auto debugster = [](const char* prefix, const SkPath& path, bool degen, bool exact) -> void {
+ SkPath::Iter iter(path, false);
+ SkDebugf("%s:\n", prefix);
+ const char* verbStr[] = { "Move", "Line", "Quad", "Conic", "Cubic", "Close", "Done" };
+ const int pointCount[] = { 1 , 2 , 3 , 3 , 4 , 1 , 0 };
+ SkPath::Verb verb;
+ do {
+ SkPoint points[4];
+ verb = iter.next(points, degen, exact);
+ SkDebugf("k%s_Verb ", verbStr[(int) verb]);
+ for (int i = 0; i < pointCount[(int) verb]; ++i) {
+ SkDebugf("{%1.8g, %1.8g}, ", points[i].fX, points[i].fY);
+ }
+ SkDebugf("\n");
+ } while (SkPath::kDone_Verb != verb);
+ SkDebugf("\n");
+ };
+
+ SkPath path;
+ path.moveTo(10, 10);
+ path.moveTo(20, 20);
+ path.quadTo(10, 20, 30, 40);
+ path.moveTo(1, 1);
+ path.close();
+ path.moveTo(30, 30);
+ path.lineTo(30, 30);
+ path.moveTo(30, 30);
+ path.lineTo(30.00001f, 30);
+ debugster("skip degenerate", path, true, false);
+ debugster("skip degenerate if exact", path, true, true);
+ debugster("skip none", path, false, false);
}
#StdOut
-skip degenerate:
-kMove_Verb {20, 20},
-kQuad_Verb {20, 20}, {10, 20}, {30, 40},
-kDone_Verb
-
-skip degenerate if exact:
-kMove_Verb {20, 20},
-kQuad_Verb {20, 20}, {10, 20}, {30, 40},
-kMove_Verb {30, 30},
-kLine_Verb {30, 30}, {30.00001, 30},
-kDone_Verb
-
-skip none:
-kMove_Verb {10, 10},
-kMove_Verb {20, 20},
-kQuad_Verb {20, 20}, {10, 20}, {30, 40},
-kMove_Verb {1, 1},
-kClose_Verb {1, 1},
-kMove_Verb {30, 30},
-kLine_Verb {30, 30}, {30, 30},
-kMove_Verb {30, 30},
-kLine_Verb {30, 30}, {30.00001, 30},
-kDone_Verb
+skip degenerate:
+kMove_Verb {20, 20},
+kQuad_Verb {20, 20}, {10, 20}, {30, 40},
+kDone_Verb
+
+skip degenerate if exact:
+kMove_Verb {20, 20},
+kQuad_Verb {20, 20}, {10, 20}, {30, 40},
+kMove_Verb {30, 30},
+kLine_Verb {30, 30}, {30.00001, 30},
+kDone_Verb
+
+skip none:
+kMove_Verb {10, 10},
+kMove_Verb {20, 20},
+kQuad_Verb {20, 20}, {10, 20}, {30, 40},
+kMove_Verb {1, 1},
+kClose_Verb {1, 1},
+kMove_Verb {30, 30},
+kLine_Verb {30, 30}, {30, 30},
+kMove_Verb {30, 30},
+kLine_Verb {30, 30}, {30.00001, 30},
+kDone_Verb
##
##
@@ -5525,24 +5617,24 @@ kDone_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(). ##
+ #Return Conic_Weight for Conic Points returned by next() ##
#Example
- void draw(SkCanvas* canvas) {
- SkPath path;
- path.conicTo(1, 2, 3, 4, .5f);
- SkPath::Iter iter(path, false);
- SkPoint p[4];
- SkDebugf("first verb is " "%s" "move\n", SkPath::kMove_Verb == iter.next(p) ? "" : "not ");
- SkDebugf("next verb is " "%s" "conic\n", SkPath::kConic_Verb == iter.next(p) ? "" : "not ");
- SkDebugf("conic points: {%g,%g}, {%g,%g}, {%g,%g}\n", p[0].fX, p[0].fY, p[1].fX, p[1].fY,
- p[2].fX, p[2].fY);
- SkDebugf("conic weight: %g\n", iter.conicWeight());
+ void draw(SkCanvas* canvas) {
+ SkPath path;
+ path.conicTo(1, 2, 3, 4, .5f);
+ SkPath::Iter iter(path, false);
+ SkPoint p[4];
+ SkDebugf("first verb is " "%s" "move\n", SkPath::kMove_Verb == iter.next(p) ? "" : "not ");
+ SkDebugf("next verb is " "%s" "conic\n", SkPath::kConic_Verb == iter.next(p) ? "" : "not ");
+ SkDebugf("conic points: {%g,%g}, {%g,%g}, {%g,%g}\n", p[0].fX, p[0].fY, p[1].fX, p[1].fY,
+ p[2].fX, p[2].fY);
+ SkDebugf("conic weight: %g\n", iter.conicWeight());
}
#StdOut
-first verb is move
-next verb is conic
-conic points: {0,0}, {1,2}, {3,4}
+first verb is move
+next verb is conic
+conic points: {0,0}, {1,2}, {3,4}
conic weight: 0.5
##
##
@@ -5560,31 +5652,31 @@ conic weight: 0.5
If next() has not been called, or next() did not return kLine_Verb,
result is undefined.
- #Return true if last kLine_Verb was generated by kClose_Verb. ##
+ #Return true if last kLine_Verb was generated by kClose_Verb ##
#Example
-void draw(SkCanvas* canvas) {
- SkPath path;
- path.moveTo(6, 7);
- path.conicTo(1, 2, 3, 4, .5f);
- path.close();
- SkPath::Iter iter(path, false);
- SkPoint p[4];
- SkDebugf("1st verb is " "%s" "move\n", SkPath::kMove_Verb == iter.next(p) ? "" : "not ");
- SkDebugf("moveTo point: {%g,%g}\n", p[0].fX, p[0].fY);
- SkDebugf("2nd verb is " "%s" "conic\n", SkPath::kConic_Verb == iter.next(p) ? "" : "not ");
- SkDebugf("3rd verb is " "%s" "line\n", SkPath::kLine_Verb == iter.next(p) ? "" : "not ");
- SkDebugf("line points: {%g,%g}, {%g,%g}\n", p[0].fX, p[0].fY, p[1].fX, p[1].fY);
- SkDebugf("line " "%s" "generated by close\n", iter.isCloseLine() ? "" : "not ");
- SkDebugf("4th verb is " "%s" "close\n", SkPath::kClose_Verb == iter.next(p) ? "" : "not ");
+void draw(SkCanvas* canvas) {
+ SkPath path;
+ path.moveTo(6, 7);
+ path.conicTo(1, 2, 3, 4, .5f);
+ path.close();
+ SkPath::Iter iter(path, false);
+ SkPoint p[4];
+ SkDebugf("1st verb is " "%s" "move\n", SkPath::kMove_Verb == iter.next(p) ? "" : "not ");
+ SkDebugf("moveTo point: {%g,%g}\n", p[0].fX, p[0].fY);
+ SkDebugf("2nd verb is " "%s" "conic\n", SkPath::kConic_Verb == iter.next(p) ? "" : "not ");
+ SkDebugf("3rd verb is " "%s" "line\n", SkPath::kLine_Verb == iter.next(p) ? "" : "not ");
+ SkDebugf("line points: {%g,%g}, {%g,%g}\n", p[0].fX, p[0].fY, p[1].fX, p[1].fY);
+ SkDebugf("line " "%s" "generated by close\n", iter.isCloseLine() ? "" : "not ");
+ SkDebugf("4th verb is " "%s" "close\n", SkPath::kClose_Verb == iter.next(p) ? "" : "not ");
}
#StdOut
-1st verb is move
-moveTo point: {6,7}
-2nd verb is conic
-3rd verb is line
-line points: {3,4}, {6,7}
-line generated by close
+1st verb is move
+moveTo point: {6,7}
+2nd verb is conic
+3rd verb is line
+line points: {3,4}, {6,7}
+line generated by close
4th verb is close
##
##
@@ -5598,26 +5690,26 @@ 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. ##
+#Return true if Contour is closed ##
#Example
-void draw(SkCanvas* canvas) {
- for (bool forceClose : { false, true } ) {
- SkPath path;
- path.conicTo(1, 2, 3, 4, .5f);
- SkPath::Iter iter(path, forceClose);
- SkDebugf("without close(), forceClose is %s: isClosedContour returns %s\n",
- forceClose ? "true " : "false", iter.isClosedContour() ? "true" : "false");
- path.close();
- iter.setPath(path, forceClose);
- SkDebugf("with close(), forceClose is %s: isClosedContour returns %s\n",
- forceClose ? "true " : "false", iter.isClosedContour() ? "true" : "false");
- }
+void draw(SkCanvas* canvas) {
+ for (bool forceClose : { false, true } ) {
+ SkPath path;
+ path.conicTo(1, 2, 3, 4, .5f);
+ SkPath::Iter iter(path, forceClose);
+ SkDebugf("without close(), forceClose is %s: isClosedContour returns %s\n",
+ forceClose ? "true " : "false", iter.isClosedContour() ? "true" : "false");
+ path.close();
+ iter.setPath(path, forceClose);
+ SkDebugf("with close(), forceClose is %s: isClosedContour returns %s\n",
+ forceClose ? "true " : "false", iter.isClosedContour() ? "true" : "false");
+ }
}
#StdOut
-without close(), forceClose is false: isClosedContour returns false
-with close(), forceClose is false: isClosedContour returns true
-without close(), forceClose is true : isClosedContour returns true
+without close(), forceClose is false: isClosedContour returns false
+with close(), forceClose is false: isClosedContour returns true
+without close(), forceClose is true : isClosedContour returns true
with close(), forceClose is true : isClosedContour returns true
##
##
@@ -5625,47 +5717,59 @@ with close(), forceClose is true : isClosedContour returns true
#SeeAlso Iter(const SkPath& path, bool forceClose)
##
-
-#Class Iter ##
-
+
+#Class Iter ##
+
#Class RawIter
Iterates through Verb_Array, and associated Point_Array and Conic_Weight.
Verb_Array, Point_Array, and Conic_Weight are returned unaltered.
+#Code
+ class RawIter {
+ public:
+ RawIter();
+ RawIter(const SkPath& path);
+ void setPath(const SkPath& path);
+ Verb next(SkPoint pts[4]);
+ Verb peek() const;
+ SkScalar conicWeight() const;
+ }
+##
+
#Method RawIter()
Initializes RawIter with an empty Path. next() on RawIter returns kDone_Verb.
Call setPath to initialize Iter at a later time.
- #Return RawIter of empty Path. ##
-
- #NoExample
- ##
- ##
+ #Return RawIter of empty Path ##
+
+ #NoExample
+ ##
+ ##
#Method RawIter(const SkPath& path)
Sets RawIter to return elements of Verb_Array, Point_Array, and Conic_Weight in path.
- #Param path Path to iterate. ##
+ #Param path Path to iterate ##
- #Return RawIter of path. ##
-
- #NoExample
- ##
- ##
+ #Return RawIter of path ##
+
+ #NoExample
+ ##
+ ##
#Method void setPath(const SkPath& path)
Sets Iter to return elements of Verb_Array, Point_Array, and Conic_Weight in path.
- #Param path Path to iterate. ##
-
- #NoExample
- ##
- ##
+ #Param path Path to iterate ##
+
+ #NoExample
+ ##
+ ##
#Method Verb next(SkPoint pts[4])
@@ -5673,82 +5777,82 @@ Verb_Array, Point_Array, and Conic_Weight are returned unaltered.
When Verb_Array is exhausted, returns kDone_Verb.
Zero to four Points are stored in pts, depending on the returned Verb.
- #Param pts Storage for Point data describing returned Verb. ##
+ #Param pts Storage for Point data describing returned Verb ##
- #Return next Verb from Verb_Array. ##
+ #Return next Verb from Verb_Array ##
#Example
- void draw(SkCanvas* canvas) {
- SkPath path;
- path.moveTo(50, 60);
- path.quadTo(10, 20, 30, 40);
- path.close();
- path.lineTo(30, 30);
- path.conicTo(1, 2, 3, 4, .5f);
- path.cubicTo(-1, -2, -3, -4, -5, -6);
- SkPath::RawIter iter(path);
- const char* verbStr[] = { "Move", "Line", "Quad", "Conic", "Cubic", "Close", "Done" };
- const int pointCount[] = { 1 , 2 , 3 , 3 , 4 , 1 , 0 };
- SkPath::Verb verb;
- do {
- SkPoint points[4];
- verb = iter.next(points);
- SkDebugf("k%s_Verb ", verbStr[(int) verb]);
- for (int i = 0; i < pointCount[(int) verb]; ++i) {
- SkDebugf("{%1.8g, %1.8g}, ", points[i].fX, points[i].fY);
- }
- if (SkPath::kConic_Verb == verb) {
- SkDebugf("weight = %g", iter.conicWeight());
- }
- SkDebugf("\n");
- } while (SkPath::kDone_Verb != verb);
+ void draw(SkCanvas* canvas) {
+ SkPath path;
+ path.moveTo(50, 60);
+ path.quadTo(10, 20, 30, 40);
+ path.close();
+ path.lineTo(30, 30);
+ path.conicTo(1, 2, 3, 4, .5f);
+ path.cubicTo(-1, -2, -3, -4, -5, -6);
+ SkPath::RawIter iter(path);
+ const char* verbStr[] = { "Move", "Line", "Quad", "Conic", "Cubic", "Close", "Done" };
+ const int pointCount[] = { 1 , 2 , 3 , 3 , 4 , 1 , 0 };
+ SkPath::Verb verb;
+ do {
+ SkPoint points[4];
+ verb = iter.next(points);
+ SkDebugf("k%s_Verb ", verbStr[(int) verb]);
+ for (int i = 0; i < pointCount[(int) verb]; ++i) {
+ SkDebugf("{%1.8g, %1.8g}, ", points[i].fX, points[i].fY);
+ }
+ if (SkPath::kConic_Verb == verb) {
+ SkDebugf("weight = %g", iter.conicWeight());
+ }
+ SkDebugf("\n");
+ } while (SkPath::kDone_Verb != verb);
}
#StdOut
- kMove_Verb {50, 60},
- kQuad_Verb {50, 60}, {10, 20}, {30, 40},
- kClose_Verb {50, 60},
- kMove_Verb {50, 60},
- kLine_Verb {50, 60}, {30, 30},
- kConic_Verb {30, 30}, {1, 2}, {3, 4}, weight = 0.5
- kCubic_Verb {3, 4}, {-1, -2}, {-3, -4}, {-5, -6},
+ kMove_Verb {50, 60},
+ kQuad_Verb {50, 60}, {10, 20}, {30, 40},
+ kClose_Verb {50, 60},
+ kMove_Verb {50, 60},
+ kLine_Verb {50, 60}, {30, 30},
+ kConic_Verb {30, 30}, {1, 2}, {3, 4}, weight = 0.5
+ kCubic_Verb {3, 4}, {-1, -2}, {-3, -4}, {-5, -6},
kDone_Verb
##
##
#SeeAlso peek()
- ##
+ ##
#Method Verb peek() const
Returns next Verb, but does not advance RawIter.
- #Return next Verb from Verb_Array. ##
+ #Return next Verb from Verb_Array ##
#Example
- SkPath path;
- path.quadTo(10, 20, 30, 40);
- path.conicTo(1, 2, 3, 4, .5f);
- path.cubicTo(1, 2, 3, 4, .5, 6);
- SkPath::RawIter iter(path);
- SkPath::Verb verb, peek = iter.peek();
- const char* verbStr[] = { "Move", "Line", "Quad", "Conic", "Cubic", "Close", "Done" };
- do {
- SkPoint points[4];
- verb = iter.next(points);
- SkDebugf("peek %s %c= verb %s\n", verbStr[peek], peek == verb ? '=' : '!', verbStr[verb]);
- peek = iter.peek();
+ SkPath path;
+ path.quadTo(10, 20, 30, 40);
+ path.conicTo(1, 2, 3, 4, .5f);
+ path.cubicTo(1, 2, 3, 4, .5, 6);
+ SkPath::RawIter iter(path);
+ SkPath::Verb verb, peek = iter.peek();
+ const char* verbStr[] = { "Move", "Line", "Quad", "Conic", "Cubic", "Close", "Done" };
+ do {
+ SkPoint points[4];
+ verb = iter.next(points);
+ SkDebugf("peek %s %c= verb %s\n", verbStr[peek], peek == verb ? '=' : '!', verbStr[verb]);
+ peek = iter.peek();
} while (SkPath::kDone_Verb != verb);
- SkDebugf("peek %s %c= verb %s\n", verbStr[peek], peek == verb ? '=' : '!', verbStr[verb]);
- #StdOut
- #Volatile
- peek Move == verb Move
- peek Quad == verb Quad
- peek Conic == verb Conic
- peek Cubic == verb Cubic
- peek Done == verb Done
- peek Done == verb Done
- ##
+ SkDebugf("peek %s %c= verb %s\n", verbStr[peek], peek == verb ? '=' : '!', verbStr[verb]);
+ #StdOut
+ #Volatile
+ peek Move == verb Move
+ peek Quad == verb Quad
+ peek Conic == verb Conic
+ peek Cubic == verb Cubic
+ peek Done == verb Done
+ peek Done == verb Done
+ ##
##
#Bug 6832
@@ -5760,43 +5864,43 @@ Verb_Array, Point_Array, and Conic_Weight are returned unaltered.
#SeeAlso next()
- ##
+ ##
+
+ #Method SkScalar conicWeight() const
- #Method SkScalar conicWeight() const
-
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(). ##
+
+ #Return Conic_Weight for Conic Points returned by next() ##
#Example
- void draw(SkCanvas* canvas) {
- SkPath path;
- path.conicTo(1, 2, 3, 4, .5f);
- SkPath::RawIter iter(path);
- SkPoint p[4];
- SkDebugf("first verb is " "%s" "move\n", SkPath::kMove_Verb == iter.next(p) ? "" : "not ");
- SkDebugf("next verb is " "%s" "conic\n", SkPath::kConic_Verb == iter.next(p) ? "" : "not ");
- SkDebugf("conic points: {%g,%g}, {%g,%g}, {%g,%g}\n", p[0].fX, p[0].fY, p[1].fX, p[1].fY,
- p[2].fX, p[2].fY);
- SkDebugf("conic weight: %g\n", iter.conicWeight());
+ void draw(SkCanvas* canvas) {
+ SkPath path;
+ path.conicTo(1, 2, 3, 4, .5f);
+ SkPath::RawIter iter(path);
+ SkPoint p[4];
+ SkDebugf("first verb is " "%s" "move\n", SkPath::kMove_Verb == iter.next(p) ? "" : "not ");
+ SkDebugf("next verb is " "%s" "conic\n", SkPath::kConic_Verb == iter.next(p) ? "" : "not ");
+ SkDebugf("conic points: {%g,%g}, {%g,%g}, {%g,%g}\n", p[0].fX, p[0].fY, p[1].fX, p[1].fY,
+ p[2].fX, p[2].fY);
+ SkDebugf("conic weight: %g\n", iter.conicWeight());
}
#StdOut
- first verb is move
- next verb is conic
- conic points: {0,0}, {1,2}, {3,4}
+ first verb is move
+ next verb is conic
+ conic points: {0,0}, {1,2}, {3,4}
conic weight: 0.5
##
##
#SeeAlso Conic_Weight
-
- ##
-
-#Class RawIter ##
-
-#Class SkPath ##
-
-#Topic Path ##
+
+ ##
+
+#Class RawIter ##
+
+#Class SkPath ##
+
+#Topic Path ##
diff --git a/docs/undocumented.bmh b/docs/undocumented.bmh
index 9e3ff056fd..e3c0bedb1b 100644
--- a/docs/undocumented.bmh
+++ b/docs/undocumented.bmh
@@ -13,7 +13,8 @@
GPU GPU-backed OpenGL Vulkan
NULL
RFC
- Bezier Coons
+ Bezier Coons Cartesian
+ C C++
SaveLayerFlags # not external; need to add typedef support
SkUserConfig.h # not external, but still thinking about how markup refers to this
SkXXX.h # ditto
diff --git a/include/core/SkPath.h b/include/core/SkPath.h
index c3031660a6..fb25b03426 100644
--- a/include/core/SkPath.h
+++ b/include/core/SkPath.h
@@ -83,7 +83,7 @@ public:
kInverseWinding_FillType,
/** Same as EvenOdd, but draws outside of the path, rather than inside
*/
- kInverseEvenOdd_FillType
+ kInverseEvenOdd_FillType,
};
/** Return the path's fill type. This is used to define how "inside" is
@@ -116,7 +116,7 @@ public:
enum Convexity {
kUnknown_Convexity,
kConvex_Convexity,
- kConcave_Convexity
+ kConcave_Convexity,
};
/**
@@ -848,7 +848,7 @@ public:
Instead, the start of source path will be extended by a straight
line to the end point of the destination path.
*/
- kExtend_AddPathMode
+ kExtend_AddPathMode,
};
/** Add a copy of src to the path, offset by (dx,dy)
@@ -973,9 +973,9 @@ public:
class SK_API Iter {
public:
Iter();
- Iter(const SkPath&, bool forceClose);
+ Iter(const SkPath& path, bool forceClose);
- void setPath(const SkPath&, bool forceClose);
+ 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.
@@ -989,8 +989,8 @@ public:
doConsumeDegenerates is false, exact has no effect.
@return The verb for the current segment
*/
- Verb next(SkPoint pts[4], bool doConsumeDegerates = true, bool exact = false) {
- if (doConsumeDegerates) {
+ Verb next(SkPoint pts[4], bool doConsumeDegenerates = true, bool exact = false) {
+ if (doConsumeDegenerates) {
this->consumeDegenerateSegments(exact);
}
return this->doNext(pts);
diff --git a/site/user/api/SkCanvas_Reference.md b/site/user/api/SkCanvas_Reference.md
index 062b74a34c..44942eee6a 100644
--- a/site/user/api/SkCanvas_Reference.md
+++ b/site/user/api/SkCanvas_Reference.md
@@ -56,9 +56,9 @@ when no <a href="undocumented#Surface">Surface</a> is required, and some helpers
| | description |
| --- | --- |
| <a href="#SkCanvas_empty_constructor">SkCanvas()</a> | No <a href="undocumented#Surface">Surface</a>, no dimensions. |
-| <a href="#SkCanvas_int_int_const_SkSurfaceProps_star">SkCanvas(int width, int height, const SkSurfaceProps* props = NULL)</a> | No <a href="undocumented#Surface">Surface</a>, set dimensions, <a href="#Properties">Surface Properties</a>. |
-| <a href="#SkCanvas_copy_constructor">SkCanvas(SkBaseDevice* device)</a> | Existing <a href="undocumented#Device">Device</a>. (<a href="undocumented#SkBaseDevice">SkBaseDevice</a> is private.) |
-| <a href="#SkCanvas_copy_constructor">SkCanvas(const SkBitmap& bitmap)</a> | Uses existing <a href="undocumented#Bitmap">Bitmap</a>. |
+| <a href="#SkCanvas_int_int_const_SkSurfaceProps_star">SkCanvas(int width, int height, const SkSurfaceProps* props = nullptr)</a> | No <a href="undocumented#Surface">Surface</a>, set dimensions, <a href="#Properties">Surface Properties</a>. |
+| <a href="#SkCanvas_copy_SkBaseDevice_star">SkCanvas(SkBaseDevice* device)</a> | Existing <a href="undocumented#Device">Device</a>. (<a href="undocumented#SkBaseDevice">SkBaseDevice</a> is private.) |
+| <a href="#SkCanvas_copy_const_SkBitmap">SkCanvas(const SkBitmap& bitmap)</a> | Uses existing <a href="undocumented#Bitmap">Bitmap</a>. |
| <a href="#SkCanvas_const_SkBitmap_const_SkSurfaceProps">SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)</a> | Uses existing <a href="undocumented#Bitmap">Bitmap</a> and <a href="#Properties">Surface Properties</a>. |
| <a href="#SkCanvas_MakeRasterDirect">MakeRasterDirect</a> | Creates from <a href="undocumented#SkImageInfo">SkImageInfo</a> and <a href="#Storage">Pixel Storage</a>. |
| <a href="#SkCanvas_MakeRasterDirectN32">MakeRasterDirectN32</a> | Creates from image data and <a href="#Storage">Pixel Storage</a>. |
@@ -133,7 +133,7 @@ when no <a href="undocumented#Surface">Surface</a> is required, and some helpers
| <a href="#SkCanvas_quickReject">quickReject</a> | Returns if <a href="undocumented#Rect">Rect</a> is outside <a href="#Clip">Clip</a>. |
| <a href="#SkCanvas_readPixels">readPixels</a> | Copies and converts rectangle of pixels from <a href="#Canvas">Canvas</a>. |
| <a href="#SkCanvas_resetMatrix">resetMatrix</a> | Resets <a href="#Matrix">Matrix</a> to identity. |
-| <a href="#SkCanvas_restore">restore</a> | Restores changes to <a href="#Clip">Clip</a> and <a href="#Matrix">Matrix</a>, pops save stack. |
+| <a href="#SkCanvas_restore">restore</a> | Restores changes to <a href="#Clip">Clip</a> and <a href="#Matrix">Matrix</a>, pops <a href="#SkCanvas_save">save</a> stack. |
| <a href="#SkCanvas_restoreToCount">restoreToCount</a> | Restores changes to <a href="#Clip">Clip</a> and <a href="#Matrix">Matrix</a> to given depth. |
| <a href="#SkCanvas_rotate">rotate</a> | Rotates <a href="#Matrix">Matrix</a>. |
| <a href="#SkCanvas_save">save</a> | Saves <a href="#Clip">Clip</a> and <a href="#Matrix">Matrix</a> on stack. |
@@ -305,7 +305,7 @@ paint draws text top to bottom
## SkCanvas
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
-SkCanvas(int width, int height, const SkSurfaceProps* props = NULL)
+SkCanvas(int width, int height, const SkSurfaceProps* props = nullptr)
</pre>
Creates <a href="#Canvas">Canvas</a> of the specified dimensions without a <a href="undocumented#Surface">Surface</a>.
@@ -351,51 +351,51 @@ canvas is empty
---
-<a name="SkCanvas_copy_constructor"></a>
+<a name="SkCanvas_copy_SkBaseDevice_star"></a>
## SkCanvas
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
explicit SkCanvas(SkBaseDevice* device)
</pre>
-Construct a canvas that draws into <a href="#SkCanvas_copy_constructor_device">device</a>.
+Construct a canvas that draws into <a href="#SkCanvas_copy_SkBaseDevice_star_device">device</a>.
Used by child classes of <a href="#SkCanvas">SkCanvas</a>.
### Parameters
-<table> <tr> <td><a name="SkCanvas_copy_constructor_device"> <code><strong>device </strong></code> </a></td> <td>
-specifies a <a href="#SkCanvas_copy_constructor_device">device</a> for the canvas to draw into</td>
+<table> <tr> <td><a name="SkCanvas_copy_SkBaseDevice_star_device"> <code><strong>device </strong></code> </a></td> <td>
+specifies a <a href="#SkCanvas_copy_SkBaseDevice_star_device">device</a> for the canvas to draw into</td>
</tr>
</table>
### Return Value
-<a href="#Canvas">Canvas</a> that can be used to draw into <a href="#SkCanvas_copy_constructor_device">device</a>
+<a href="#Canvas">Canvas</a> that can be used to draw into <a href="#SkCanvas_copy_SkBaseDevice_star_device">device</a>
### Example
-<div><fiddle-embed name="cc6d6fd6d9aa98b12984e11ef52172ec"></fiddle-embed></div>
+<div><fiddle-embed name=""></fiddle-embed></div>
---
-<a name="SkCanvas_copy_constructor"></a>
+<a name="SkCanvas_copy_const_SkBitmap"></a>
## SkCanvas
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
explicit SkCanvas(const SkBitmap& bitmap)
</pre>
-Construct a canvas that draws into <a href="#SkCanvas_copy_constructor_bitmap">bitmap</a>.
+Construct a canvas that draws into <a href="#SkCanvas_copy_const_SkBitmap_bitmap">bitmap</a>.
Sets <a href="#SkSurfaceProps_kLegacyFontHost_InitType">SkSurfaceProps::kLegacyFontHost InitType</a> in constructed <a href="undocumented#Surface">Surface</a>.
-<a href="undocumented#Bitmap">Bitmap</a> is copied so that subsequently editing <a href="#SkCanvas_copy_constructor_bitmap">bitmap</a> will not affect
+<a href="undocumented#Bitmap">Bitmap</a> is copied so that subsequently editing <a href="#SkCanvas_copy_const_SkBitmap_bitmap">bitmap</a> will not affect
constructed <a href="#Canvas">Canvas</a>.
May be deprecated in the future.
### Parameters
-<table> <tr> <td><a name="SkCanvas_copy_constructor_bitmap"> <code><strong>bitmap </strong></code> </a></td> <td>
+<table> <tr> <td><a name="SkCanvas_copy_const_SkBitmap_bitmap"> <code><strong>bitmap </strong></code> </a></td> <td>
width, height, <a href="#Color_Type">Image Color Type</a>, <a href="#Alpha_Type">Image Alpha Type</a>, and pixel
storage of <a href="undocumented#Raster_Surface">Raster Surface</a></td>
</tr>
@@ -403,25 +403,25 @@ storage of <a href="undocumented#Raster_Surface">Raster Surface</a></td>
### Return Value
-<a href="#Canvas">Canvas</a> that can be used to draw into <a href="#SkCanvas_copy_constructor_bitmap">bitmap</a>
+<a href="#Canvas">Canvas</a> that can be used to draw into <a href="#SkCanvas_copy_const_SkBitmap_bitmap">bitmap</a>
### Example
-<div><fiddle-embed name=""><div>The actual output depends on the installed fonts.</div>
+<div><fiddle-embed name="cc6d6fd6d9aa98b12984e11ef52172ec"><div>The actual output depends on the installed fonts.</div>
#### Example Output
~~~~
-----
---x--
---x--
---x--
---x--
---x--
---x--
+---x-
+---x-
+---x-
+---x-
+---x-
+---x-
-----
---x--
---x--
+---x-
+---x-
-----
~~~~
@@ -749,7 +749,7 @@ Returns <a href="undocumented#GPU_Context">GPU Context</a> of the <a href="undoc
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes,
- SkIPoint* origin = NULL)
+ SkIPoint* origin = nullptr)
</pre>
Returns the pixel base address, <a href="#Info">Image Info</a>, <a href="#SkCanvas_accessTopLayerPixels_rowBytes">rowBytes</a>, and <a href="#SkCanvas_accessTopLayerPixels_origin">origin</a> if the pixels
@@ -1227,13 +1227,13 @@ bounds of the <a href="#Canvas">Canvas</a> <a href="undocumented#Surface">Surfac
<a href="undocumented#Draw_Filter">Draw Filter</a> (deprecated on most platforms) modifies the paint before drawing.
<a href="#SkCanvas_save">save</a>, <a href="#SkCanvas_saveLayer">saveLayer</a>, <a href="#SkCanvas_saveLayerPreserveLCDTextRequests">saveLayerPreserveLCDTextRequests</a>, and <a href="#SkCanvas_saveLayerAlpha">saveLayerAlpha</a>
-save state and return the depth of the stack.
+<a href="#SkCanvas_save">save</a> state and return the depth of the stack.
<a href="#SkCanvas_restore">restore</a>, <a href="#SkCanvas_restoreToCount">restoreToCount</a>, and
### Example
-<div><fiddle-embed name="a4548baa133302e933b4d3442c06f5b3"><div>Draw to ever smaller clips; then restore drawing to full canvas.
+<div><fiddle-embed name="a4548baa133302e933b4d3442c06f5b3"><div>Draw to ever smaller clips; then <a href="#SkCanvas_restore">restore</a> drawing to full canvas.
Note that the second <a href="#SkCanvas_clipRect">clipRect</a> is not permitted to enlarge <a href="#Clip">Clip</a>.</div></fiddle-embed></div>
Each <a href="#Clip">Clip</a> uses the current <a href="#Matrix">Matrix</a> for its coordinates.
@@ -1264,7 +1264,7 @@ and <a href="#SkCanvas_resetMatrix">resetMatrix</a>. <a href="#Clip">Clip</a> ma
Saved <a href="#Canvas">Canvas</a> state is put on a stack; multiple calls to <a href="#SkCanvas_save">save</a> should be balance
by an equal number of calls to <a href="#SkCanvas_restore">restore</a>.
-Call <a href="#SkCanvas_restoreToCount">restoreToCount</a> with result to restore this and subsequent saves.
+Call <a href="#SkCanvas_restoreToCount">restoreToCount</a> with result to <a href="#SkCanvas_restore">restore</a> this and subsequent saves.
### Return Value
@@ -1312,7 +1312,7 @@ a specific rectangle, use <a href="#SkCanvas_clipRect">clipRect</a>.
Optional <a href="SkPaint_Reference#Paint">Paint</a> <a href="#SkCanvas_saveLayer_paint">paint</a> applies <a href="#Alpha">Color Alpha</a>, <a href="undocumented#Color_Filter">Color Filter</a>, <a href="undocumented#Image_Filter">Image Filter</a>, and
<a href="undocumented#Blend_Mode">Blend Mode</a> when <a href="#SkCanvas_restore">restore</a> is called.
-Call <a href="#SkCanvas_restoreToCount">restoreToCount</a> with returned value to restore this and subsequent saves.
+Call <a href="#SkCanvas_restoreToCount">restoreToCount</a> with returned value to <a href="#SkCanvas_restore">restore</a> this and subsequent saves.
### Parameters
@@ -1353,7 +1353,7 @@ a specific rectangle, use <a href="#SkCanvas_clipRect">clipRect</a>.
Optional <a href="SkPaint_Reference#Paint">Paint</a> <a href="#SkCanvas_saveLayer_2_paint">paint</a> applies <a href="#Alpha">Color Alpha</a>, <a href="undocumented#Color_Filter">Color Filter</a>, <a href="undocumented#Image_Filter">Image Filter</a>, and
<a href="undocumented#Blend_Mode">Blend Mode</a> when <a href="#SkCanvas_restore">restore</a> is called.
-Call <a href="#SkCanvas_restoreToCount">restoreToCount</a> with returned value to restore this and subsequent saves.
+Call <a href="#SkCanvas_restoreToCount">restoreToCount</a> with returned value to <a href="#SkCanvas_restore">restore</a> this and subsequent saves.
### Parameters
@@ -1399,7 +1399,7 @@ a specific rectangle, use <a href="#SkCanvas_clipRect">clipRect</a>.
Optional <a href="SkPaint_Reference#Paint">Paint</a> <a href="#SkCanvas_saveLayerPreserveLCDTextRequests_paint">paint</a> applies <a href="#Alpha">Color Alpha</a>, <a href="undocumented#Color_Filter">Color Filter</a>, <a href="undocumented#Image_Filter">Image Filter</a>, and
<a href="undocumented#Blend_Mode">Blend Mode</a> when <a href="#SkCanvas_restore">restore</a> is called.
-Call <a href="#SkCanvas_restoreToCount">restoreToCount</a> with returned value to restore this and subsequent saves.
+Call <a href="#SkCanvas_restoreToCount">restoreToCount</a> with returned value to <a href="#SkCanvas_restore">restore</a> this and subsequent saves.
Draw text on an opaque background so that <a href="SkPaint_Reference#LCD_Text">LCD Text</a> blends correctly with the
prior layer. <a href="SkPaint_Reference#LCD_Text">LCD Text</a> drawn on a background with transparency may result in
@@ -1446,7 +1446,7 @@ a specific rectangle, use <a href="#SkCanvas_clipRect">clipRect</a>.
<a href="#SkCanvas_saveLayerAlpha_alpha">alpha</a> of zero is fully transparent, 255 is fully opaque.
-Call <a href="#SkCanvas_restoreToCount">restoreToCount</a> with returned value to restore this and subsequent saves.
+Call <a href="#SkCanvas_restoreToCount">restoreToCount</a> with returned value to <a href="#SkCanvas_restore">restore</a> this and subsequent saves.
### Parameters
@@ -1721,7 +1721,7 @@ and blends the offscreen bitmap with alpha opacity onto the prior layer.
<a href="#SkCanvas_SaveLayerRec">SaveLayerRec</a> contains the state used to create the layer offscreen.
-Call <a href="#SkCanvas_restoreToCount">restoreToCount</a> with returned value to restore this and subsequent saves.
+Call <a href="#SkCanvas_restoreToCount">restoreToCount</a> with returned value to <a href="#SkCanvas_restore">restore</a> this and subsequent saves.
### Parameters
@@ -1732,12 +1732,12 @@ offscreen state</td>
### Return Value
-depth of save state stack
+depth of <a href="#SkCanvas_save">save</a> state stack
### Example
<div><fiddle-embed name="0da8c199f1d9ec4d1b9c5d1114d6cbd6"><div>The example draws an image, and saves it into a layer with <a href="#SkCanvas_kInitWithPrevious_SaveLayerFlag">kInitWithPrevious SaveLayerFlag</a>.
-Next it punches a hole in the layer and restore with <a href="#SkBlendMode_kPlus">SkBlendMode::kPlus</a>.
+Next it punches a hole in the layer and <a href="#SkCanvas_restore">restore</a> with <a href="#SkBlendMode_kPlus">SkBlendMode::kPlus</a>.
Where the layer was cleared, the original image will draw unchanged.
Outside of the circle the mandrill is brightened.</div></fiddle-embed></div>
@@ -1770,11 +1770,11 @@ int getSaveCount() const
Returns the number of saved states, each containing: <a href="#Matrix">Matrix</a>, <a href="#Clip">Clip</a>, and <a href="undocumented#Draw_Filter">Draw Filter</a>.
Equals the number of <a href="#SkCanvas_save">save</a> calls less the number of <a href="#SkCanvas_restore">restore</a> calls plus one.
-The save count of a new canvas is one.
+The <a href="#SkCanvas_save">save</a> count of a new canvas is one.
### Return Value
-depth of save state stack
+depth of <a href="#SkCanvas_save">save</a> state stack
### Example
@@ -1808,7 +1808,7 @@ Restores state to initial values if <a href="#SkCanvas_restoreToCount_saveCount"
### Parameters
<table> <tr> <td><a name="SkCanvas_restoreToCount_saveCount"> <code><strong>saveCount </strong></code> </a></td> <td>
-depth of state stack to restore</td>
+depth of state stack to <a href="#SkCanvas_restore">restore</a></td>
</tr>
</table>
@@ -1848,9 +1848,9 @@ the result with <a href="#Matrix">Matrix</a>.
### Parameters
<table> <tr> <td><a name="SkCanvas_translate_dx"> <code><strong>dx </strong></code> </a></td> <td>
-distance to translate in x</td>
+distance to <a href="#SkCanvas_translate">translate</a> in x</td>
</tr> <tr> <td><a name="SkCanvas_translate_dy"> <code><strong>dy </strong></code> </a></td> <td>
-distance to translate in y</td>
+distance to <a href="#SkCanvas_translate">translate</a> in y</td>
</tr>
</table>
@@ -1859,10 +1859,10 @@ distance to translate in y</td>
<div><fiddle-embed name="eb93d5fa66a5f7a10f4f9210494d7222"><div><a href="#SkCanvas_scale">scale</a> followed by <a href="#SkCanvas_translate">translate</a> produces different results from <a href="#SkCanvas_translate">translate</a> followed
by <a href="#SkCanvas_scale">scale</a>.
-The blue stroke follows translate of (50, 50); a black
-fill follows scale of (2, 1/2.f). After restoring the clip, which resets
-<a href="#Matrix">Matrix</a>, a red frame follows the same scale of (2, 1/2.f); a gray fill
-follows translate of (50, 50).</div></fiddle-embed></div>
+The blue stroke follows <a href="#SkCanvas_translate">translate</a> of (50, 50); a black
+fill follows <a href="#SkCanvas_scale">scale</a> of (2, 1/2.f). After restoring the clip, which resets
+<a href="#Matrix">Matrix</a>, a red frame follows the same <a href="#SkCanvas_scale">scale</a> of (2, 1/2.f); a gray fill
+follows <a href="#SkCanvas_translate">translate</a> of (50, 50).</div></fiddle-embed></div>
---
@@ -1875,7 +1875,7 @@ void scale(SkScalar sx, SkScalar sy)
Scale <a href="#Matrix">Matrix</a> by <a href="#SkCanvas_scale_sx">sx</a> on the x-axis and <a href="#SkCanvas_scale_sy">sy</a> on the y-axis.
-Mathematically, replace <a href="#Matrix">Matrix</a> with a scale matrix
+Mathematically, replace <a href="#Matrix">Matrix</a> with a <a href="#SkCanvas_scale">scale</a> matrix
pre-multiplied with <a href="#Matrix">Matrix</a>.
This has the effect of scaling the drawing by (<a href="#SkCanvas_scale_sx">sx</a>, <a href="#SkCanvas_scale_sy">sy</a>) before transforming
@@ -1884,9 +1884,9 @@ the result with <a href="#Matrix">Matrix</a>.
### Parameters
<table> <tr> <td><a name="SkCanvas_scale_sx"> <code><strong>sx </strong></code> </a></td> <td>
-amount to scale in x</td>
+amount to <a href="#SkCanvas_scale">scale</a> in x</td>
</tr> <tr> <td><a name="SkCanvas_scale_sy"> <code><strong>sy </strong></code> </a></td> <td>
-amount to scale in y</td>
+amount to <a href="#SkCanvas_scale">scale</a> in y</td>
</tr>
</table>
@@ -1914,7 +1914,7 @@ the result with <a href="#Matrix">Matrix</a>.
### Parameters
<table> <tr> <td><a name="SkCanvas_rotate_degrees"> <code><strong>degrees </strong></code> </a></td> <td>
-amount to rotate, in <a href="#SkCanvas_rotate_degrees">degrees</a></td>
+amount to <a href="#SkCanvas_rotate">rotate</a>, in <a href="#SkCanvas_rotate_degrees">degrees</a></td>
</tr>
</table>
@@ -1942,11 +1942,11 @@ transforming the result with <a href="#Matrix">Matrix</a>.
### Parameters
<table> <tr> <td><a name="SkCanvas_rotate_2_degrees"> <code><strong>degrees </strong></code> </a></td> <td>
-amount to rotate, in <a href="#SkCanvas_rotate_2_degrees">degrees</a></td>
+amount to <a href="#SkCanvas_rotate">rotate</a>, in <a href="#SkCanvas_rotate_2_degrees">degrees</a></td>
</tr> <tr> <td><a name="SkCanvas_rotate_2_px"> <code><strong>px </strong></code> </a></td> <td>
-x-coordinate of the point to rotate about</td>
+x-coordinate of the point to <a href="#SkCanvas_rotate">rotate</a> about</td>
</tr> <tr> <td><a name="SkCanvas_rotate_2_py"> <code><strong>py </strong></code> </a></td> <td>
-y-coordinate of the point to rotate about</td>
+y-coordinate of the point to <a href="#SkCanvas_rotate">rotate</a> about</td>
</tr>
</table>
@@ -1967,7 +1967,7 @@ Skew <a href="#Matrix">Matrix</a> by <a href="#SkCanvas_skew_sx">sx</a> on the x
skews the drawing right as y increases; a positive value of <a href="#SkCanvas_skew_sy">sy</a> skews the drawing
down as x increases.
-Mathematically, replace <a href="#Matrix">Matrix</a> with a skew matrix pre-multiplied with <a href="#Matrix">Matrix</a>.
+Mathematically, replace <a href="#Matrix">Matrix</a> with a <a href="#SkCanvas_skew">skew</a> matrix pre-multiplied with <a href="#Matrix">Matrix</a>.
This has the effect of skewing the drawing by (<a href="#SkCanvas_skew_sx">sx</a>, <a href="#SkCanvas_skew_sy">sy</a>) before transforming
the result with <a href="#Matrix">Matrix</a>.
@@ -1975,19 +1975,19 @@ the result with <a href="#Matrix">Matrix</a>.
### Parameters
<table> <tr> <td><a name="SkCanvas_skew_sx"> <code><strong>sx </strong></code> </a></td> <td>
-amount to skew in x</td>
+amount to <a href="#SkCanvas_skew">skew</a> in x</td>
</tr> <tr> <td><a name="SkCanvas_skew_sy"> <code><strong>sy </strong></code> </a></td> <td>
-amount to skew in y</td>
+amount to <a href="#SkCanvas_skew">skew</a> in y</td>
</tr>
</table>
### Example
-<div><fiddle-embed name="2e2acc21d7774df7e0940a30ad2ca99e"><div>Black text mimics an oblique text style by using a negative skew in x that
+<div><fiddle-embed name="2e2acc21d7774df7e0940a30ad2ca99e"><div>Black text mimics an oblique text style by using a negative <a href="#SkCanvas_skew">skew</a> in x that
shifts the geometry to the right as the y values decrease.
-Red text uses a positive skew in y to shift the geometry down as the x values
+Red text uses a positive <a href="#SkCanvas_skew">skew</a> in y to shift the geometry down as the x values
increase.
-Blue text combines x and y skew to rotate and scale.</div></fiddle-embed></div>
+Blue text combines x and y <a href="#SkCanvas_skew">skew</a> to <a href="#SkCanvas_rotate">rotate</a> and <a href="#SkCanvas_scale">scale</a>.</div></fiddle-embed></div>
---
@@ -3320,7 +3320,7 @@ a smart pointer as a convenience. The pairs of calls are otherwise identical.
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
void drawImage(const SkImage* image, SkScalar left, SkScalar top,
- const SkPaint* paint = NULL)
+ const SkPaint* paint = nullptr)
</pre>
Draw <a href="undocumented#Image">Image</a> <a href="#SkCanvas_drawImage_image">image</a>, with its top-left corner at (<a href="#SkCanvas_drawImage_left">left</a>, <a href="#SkCanvas_drawImage_top">top</a>),
@@ -3355,7 +3355,7 @@ and so on; or nullptr</td>
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top,
- const SkPaint* paint = NULL)
+ const SkPaint* paint = nullptr)
</pre>
Draw <a href="undocumented#Image">Image</a> <a href="#SkCanvas_drawImage_2_image">image</a>, with its top-left corner at (<a href="#SkCanvas_drawImage_2_left">left</a>, <a href="#SkCanvas_drawImage_2_top">top</a>),
@@ -3787,7 +3787,7 @@ and below <a href="#SkCanvas_drawImageNine_2_center">center</a> to fill the rema
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
- const SkPaint* paint = NULL)
+ const SkPaint* paint = nullptr)
</pre>
Draw <a href="undocumented#Bitmap">Bitmap</a> <a href="#SkCanvas_drawBitmap_bitmap">bitmap</a>, with its top-left corner at (<a href="#SkCanvas_drawBitmap_left">left</a>, <a href="#SkCanvas_drawBitmap_top">top</a>),
@@ -3962,7 +3962,7 @@ filter strictly within src or draw faster</td>
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
- const SkRect& dst, const SkPaint* paint = NULL)
+ const SkRect& dst, const SkPaint* paint = nullptr)
</pre>
Draw <a href="undocumented#Bitmap">Bitmap</a> <a href="#SkCanvas_drawBitmapNine_bitmap">bitmap</a> stretched differentially to fit into <a href="undocumented#Rect">Rect</a> <a href="#SkCanvas_drawBitmapNine_dst">dst</a>.
@@ -4096,9 +4096,9 @@ Draw <a href="undocumented#Bitmap">Bitmap</a> <a href="#SkCanvas_drawBitmapLatti
<a href="#SkCanvas_Lattice">Lattice</a> <a href="#SkCanvas_drawBitmapLattice_lattice">lattice</a> divides <a href="#SkCanvas_drawBitmapLattice_bitmap">bitmap</a> into a rectangular grid.
Each intersection of an even-numbered row and column is fixed; like the corners
-of <a href="#SkCanvas_drawBitmapNine">drawBitmapNine</a>, fixed <a href="#SkCanvas_drawBitmapLattice_lattice">lattice</a> elements never scale larger than their initial
+of <a href="#SkCanvas_drawBitmapNine">drawBitmapNine</a>, fixed <a href="#SkCanvas_drawBitmapLattice_lattice">lattice</a> elements never <a href="#SkCanvas_scale">scale</a> larger than their initial
size and shrink proportionately when all fixed elements exceed the <a href="#SkCanvas_drawBitmapLattice_bitmap">bitmap</a>'s
-dimension. All other grid elements scale to fill the available space, if any.
+dimension. All other grid elements <a href="#SkCanvas_scale">scale</a> to fill the available space, if any.
Additionally transform draw using <a href="#Clip">Clip</a>, <a href="#Matrix">Matrix</a>, and optional <a href="SkPaint_Reference#Paint">Paint</a> <a href="#SkCanvas_drawBitmapLattice_paint">paint</a>.
@@ -4148,9 +4148,9 @@ Draw <a href="undocumented#Image">Image</a> <a href="#SkCanvas_drawImageLattice_
<a href="#SkCanvas_Lattice">Lattice</a> <a href="#SkCanvas_drawImageLattice_lattice">lattice</a> divides <a href="#SkCanvas_drawImageLattice_image">image</a> into a rectangular grid.
Each intersection of an even-numbered row and column is fixed; like the corners
-of <a href="#SkCanvas_drawBitmapNine">drawBitmapNine</a>, fixed <a href="#SkCanvas_drawImageLattice_lattice">lattice</a> elements never scale larger than their initial
+of <a href="#SkCanvas_drawBitmapNine">drawBitmapNine</a>, fixed <a href="#SkCanvas_drawImageLattice_lattice">lattice</a> elements never <a href="#SkCanvas_scale">scale</a> larger than their initial
size and shrink proportionately when all fixed elements exceed the bitmap's
-dimension. All other grid elements scale to fill the available space, if any.
+dimension. All other grid elements <a href="#SkCanvas_scale">scale</a> to fill the available space, if any.
Additionally transform draw using <a href="#Clip">Clip</a>, <a href="#Matrix">Matrix</a>, and optional <a href="SkPaint_Reference#Paint">Paint</a> <a href="#SkCanvas_drawImageLattice_paint">paint</a>.
@@ -4517,7 +4517,7 @@ void drawTextRSXform(const void* text, size_t byteLength,
Draw <a href="#SkCanvas_drawTextRSXform_text">text</a>, transforming each glyph by the corresponding <a href="undocumented#SkRSXform">SkRSXform</a>,
using <a href="#Clip">Clip</a>, <a href="#Matrix">Matrix</a>, and <a href="SkPaint_Reference#Paint">Paint</a> <a href="#SkCanvas_drawTextRSXform_paint">paint</a>.
-<a href="undocumented#RSXform">RSXform</a> array specifies a separate square scale, rotation, and translation for
+<a href="undocumented#RSXform">RSXform</a> array specifies a separate square <a href="#SkCanvas_scale">scale</a>, rotation, and translation for
each glyph.
Optional <a href="undocumented#Rect">Rect</a> <a href="#SkCanvas_drawTextRSXform_cullRect">cullRect</a> is a conservative bounds of <a href="#SkCanvas_drawTextRSXform_text">text</a>, taking into account
@@ -4688,7 +4688,7 @@ Draw <a href="undocumented#Picture">Picture</a> <a href="#SkCanvas_drawPicture_3
<table> <tr> <td><a name="SkCanvas_drawPicture_3_picture"> <code><strong>picture </strong></code> </a></td> <td>
recorded drawing commands to play</td>
</tr> <tr> <td><a name="SkCanvas_drawPicture_3_matrix"> <code><strong>matrix </strong></code> </a></td> <td>
-<a href="#Matrix">Matrix</a> to rotate, scale, translate, and so on; may be nullptr</td>
+<a href="#Matrix">Matrix</a> to <a href="#SkCanvas_rotate">rotate</a>, <a href="#SkCanvas_scale">scale</a>, <a href="#SkCanvas_translate">translate</a>, and so on; may be nullptr</td>
</tr> <tr> <td><a name="SkCanvas_drawPicture_3_paint"> <code><strong>paint </strong></code> </a></td> <td>
<a href="SkPaint_Reference#Paint">Paint</a> to apply transparency, filtering, and so on; may be nullptr</td>
</tr>
@@ -4717,7 +4717,7 @@ Draw <a href="undocumented#Picture">Picture</a> <a href="#SkCanvas_drawPicture_4
<table> <tr> <td><a name="SkCanvas_drawPicture_4_picture"> <code><strong>picture </strong></code> </a></td> <td>
recorded drawing commands to play</td>
</tr> <tr> <td><a name="SkCanvas_drawPicture_4_matrix"> <code><strong>matrix </strong></code> </a></td> <td>
-<a href="#Matrix">Matrix</a> to rotate, scale, translate, and so on; may be nullptr</td>
+<a href="#Matrix">Matrix</a> to <a href="#SkCanvas_rotate">rotate</a>, <a href="#SkCanvas_scale">scale</a>, <a href="#SkCanvas_translate">translate</a>, and so on; may be nullptr</td>
</tr> <tr> <td><a name="SkCanvas_drawPicture_4_paint"> <code><strong>paint </strong></code> </a></td> <td>
<a href="SkPaint_Reference#Paint">Paint</a> to apply transparency, filtering, and so on; may be nullptr</td>
</tr>
@@ -5050,7 +5050,7 @@ number of sprites to draw</td>
## drawDrawable
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
-void drawDrawable(SkDrawable* drawable, const SkMatrix* matrix = NULL)
+void drawDrawable(SkDrawable* drawable, const SkMatrix* matrix = nullptr)
</pre>
Draw <a href="undocumented#Drawable">Drawable</a> <a href="#SkCanvas_drawDrawable_drawable">drawable</a> using <a href="#Clip">Clip</a> and <a href="#Matrix">Matrix</a>, concatenated with
diff --git a/site/user/api/SkPaint_Reference.md b/site/user/api/SkPaint_Reference.md
index de06852bc9..236acdf5f5 100644
--- a/site/user/api/SkPaint_Reference.md
+++ b/site/user/api/SkPaint_Reference.md
@@ -101,8 +101,8 @@ Multiple colors are drawn either by using multiple paints or with objects like
| | description |
| --- | --- |
| <a href="#SkPaint_empty_constructor">SkPaint()</a> | Constructs with default values. |
-| <a href="#SkPaint_copy_constructor">SkPaint(const SkPaint& paint)</a> | Makes a shallow copy. |
-| <a href="#SkPaint_move_constructor">SkPaint(SkPaint&& paint)</a> | Moves paint without copying it. |
+| <a href="#SkPaint_copy_const_SkPaint">SkPaint(const SkPaint& paint)</a> | Makes a shallow copy. |
+| <a href="#SkPaint_move_SkPaint">SkPaint(SkPaint&& paint)</a> | Moves paint without copying it. |
| | Decreases <a href="undocumented#Reference_Count">Reference Count</a> of owned objects. |
## <a name="Operators"></a> Operators
@@ -283,7 +283,7 @@ default initialized <a href="#Paint">Paint</a>
---
-<a name="SkPaint_copy_constructor"></a>
+<a name="SkPaint_copy_const_SkPaint"></a>
## SkPaint
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
@@ -292,7 +292,7 @@ SkPaint(const SkPaint& paint)
Makes a shallow copy of <a href="#Paint">Paint</a>. <a href="undocumented#Typeface">Typeface</a>, <a href="undocumented#Path_Effect">Path Effect</a>, <a href="undocumented#Shader">Shader</a>,
<a href="undocumented#Mask_Filter">Mask Filter</a>, <a href="undocumented#Color_Filter">Color Filter</a>, <a href="undocumented#Rasterizer">Rasterizer</a>, <a href="undocumented#Draw_Looper">Draw Looper</a>, and <a href="undocumented#Image_Filter">Image Filter</a> are shared
-between the original <a href="#SkPaint_copy_constructor_paint">paint</a> and the copy. Objects containing <a href="undocumented#Reference_Count">Reference Count</a> increment
+between the original <a href="#SkPaint_copy_const_SkPaint_paint">paint</a> and the copy. Objects containing <a href="undocumented#Reference_Count">Reference Count</a> increment
their references by one.
The referenced objects <a href="undocumented#Path_Effect">Path Effect</a>, <a href="undocumented#Shader">Shader</a>, <a href="undocumented#Mask_Filter">Mask Filter</a>, <a href="undocumented#Color_Filter">Color Filter</a>, <a href="undocumented#Rasterizer">Rasterizer</a>,
@@ -301,14 +301,14 @@ This prevents objects with <a href="undocumented#Reference_Count">Reference Coun
### Parameters
-<table> <tr> <td><a name="SkPaint_copy_constructor_paint"> <code><strong>paint </strong></code> </a></td> <td>
+<table> <tr> <td><a name="SkPaint_copy_const_SkPaint_paint"> <code><strong>paint </strong></code> </a></td> <td>
original to copy</td>
</tr>
</table>
### Return Value
-shallow copy of <a href="#SkPaint_copy_constructor_paint">paint</a>
+shallow copy of <a href="#SkPaint_copy_const_SkPaint_paint">paint</a>
### Example
@@ -325,7 +325,7 @@ SK_ColorBLUE == paint2.getColor()
---
-<a name="SkPaint_move_constructor"></a>
+<a name="SkPaint_move_SkPaint"></a>
## SkPaint
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
@@ -333,20 +333,20 @@ SkPaint(SkPaint&& paint)
</pre>
Implements a move constructor to avoid incrementing the reference counts
-of objects referenced by the <a href="#SkPaint_move_constructor_paint">paint</a>.
+of objects referenced by the <a href="#SkPaint_move_SkPaint_paint">paint</a>.
-After the call, <a href="#SkPaint_move_constructor_paint">paint</a> is undefined, and can be safely destructed.
+After the call, <a href="#SkPaint_move_SkPaint_paint">paint</a> is undefined, and can be safely destructed.
### Parameters
-<table> <tr> <td><a name="SkPaint_move_constructor_paint"> <code><strong>paint </strong></code> </a></td> <td>
+<table> <tr> <td><a name="SkPaint_move_SkPaint_paint"> <code><strong>paint </strong></code> </a></td> <td>
original to move</td>
</tr>
</table>
### Return Value
-content of <a href="#SkPaint_move_constructor_paint">paint</a>
+content of <a href="#SkPaint_move_SkPaint_paint">paint</a>
### Example
@@ -643,7 +643,7 @@ by the client.
### Parameters
<table> <tr> <td><a name="SkPaint_unflatten_buffer"> <code><strong>buffer </strong></code> </a></td> <td>
-serialized data to unflatten</td>
+serialized data to <a href="#SkPaint_unflatten">unflatten</a></td>
</tr>
</table>
@@ -4692,7 +4692,7 @@ double width = 10
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
size_t breakText(const void* text, size_t length, SkScalar maxWidth,
- SkScalar* measuredWidth = NULL) const
+ SkScalar* measuredWidth = nullptr) const
</pre>
Returns the bytes of <a href="#SkPaint_breakText_text">text</a> that fit within <a href="#SkPaint_breakText_maxWidth">maxWidth</a>.
@@ -4735,7 +4735,7 @@ bytes of <a href="#SkPaint_breakText_text">text</a> that fit, always less than o
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
int getTextWidths(const void* text, size_t byteLength, SkScalar widths[],
- SkRect bounds[] = NULL) const
+ SkRect bounds[] = nullptr) const
</pre>
Retrieves the advance and <a href="#SkPaint_getTextWidths_bounds">bounds</a> for each glyph in <a href="#SkPaint_getTextWidths_text">text</a>, and returns
diff --git a/site/user/api/SkPath_Reference.md b/site/user/api/SkPath_Reference.md
index 5ae7337780..13196dfbce 100644
--- a/site/user/api/SkPath_Reference.md
+++ b/site/user/api/SkPath_Reference.md
@@ -5,7 +5,7 @@ SkPath Reference
<a href="#Path">Path</a> contains <a href="#Line">Lines</a> and <a href="#Curve">Curves</a> which can be stroked or filled. <a href="#Contour">Contour</a> is
composed of a series of connected <a href="#Line">Lines</a> and <a href="#Curve">Curves</a>. <a href="#Path">Path</a> may contain zero,
one, or more <a href="#Contour">Contours</a>.
-Each <a href="undocumented#Line">Line</a> and <a href="undocumented#Curve">Curve</a> are described by <a href="#Verb">Verb</a>, <a href="#Point">Points</a>, and optional Weight.
+Each <a href="undocumented#Line">Line</a> and <a href="undocumented#Curve">Curve</a> are described by <a href="#Verb">Verb</a>, <a href="#Point">Points</a>, and optional <a href="#Conic_Weight">Conic Weight</a>.
Each pair of connected <a href="#Line">Lines</a> and <a href="#Curve">Curves</a> share common <a href="undocumented#Point">Point</a>; for instance, <a href="#Path">Path</a>
containing two connected <a href="#Line">Lines</a> are described the <a href="#Verb">Verb</a> sequence:
@@ -78,6 +78,22 @@ makes them visible.
<div><fiddle-embed name="62848df605af6258653d9e16b27d8f7f"></fiddle-embed></div>
# <a name="SkPath"></a> Class SkPath
+<a href="#Path">Paths</a> contain geometry. <a href="#Path">Paths</a> may be empty, or contain one or more <a href="#Verb">Verbs</a> that
+outline a figure. <a href="#Path">Path</a> always starts with a move verb to a <a href="undocumented#Cartesian">Cartesian</a>
+coordinate, and may be followed by additional verbs that add lines or curves.
+Adding a <a href="#SkPath_close">close</a> verb makes the geometry into a continuous loop, a closed contour.
+<a href="#Path">Paths</a> may contain any number of contours, each beginnning with a move verb.
+
+<a href="#Path">Path</a> contours may contain only a move verb, or may also contain lines,
+quadratic Beziers, conics, and cubic Beziers. <a href="#Path">Path</a> contours may be open or
+closed.
+
+When used to draw a filled area, <a href="#Path">Path</a> describes whether the fill is inside or
+outside the geometry. <a href="#Path">Path</a> also describes the winding rule used to fill
+overlapping contours.
+
+Internally, <a href="#Path">Path</a> lazily computes metrics likes bounds and convexity. Call
+<a href="#SkPath_updateBoundsCache">SkPath::updateBoundsCache</a> to make <a href="#Path">Path</a> thread safe.
# <a name="Overview"></a> Overview
@@ -97,15 +113,15 @@ makes them visible.
| class or struct | description |
| --- | --- |
-| <a href="SkPath_Reference#Iter">Iter</a> | Iterates through lines and curves, skipping degenerates. |
-| <a href="SkPath_Reference#RawIter">RawIter</a> | Iterates through lines and curves, including degenerates. |
+| <a href="#SkPath_Iter">Iter</a> | Iterates through lines and curves, skipping degenerates. |
+| <a href="#SkPath_RawIter">RawIter</a> | Iterates through lines and curves, including degenerates. |
## <a name="Constructors"></a> Constructors
| | description |
| --- | --- |
| <a href="#SkPath_empty_constructor">SkPath()</a> | Constructs with default values. |
-| <a href="#SkPath_copy_constructor">SkPath(const SkPath& path)</a> | Makes a shallow copy. |
+| <a href="#SkPath_copy_const_SkPath">SkPath(const SkPath& path)</a> | Makes a shallow copy. |
| | Decreases <a href="undocumented#Reference_Count">Reference Count</a> of owned objects. |
## <a name="Operators"></a> Operators
@@ -143,14 +159,14 @@ makes them visible.
| <a href="#SkPath_countPoints">countPoints</a> | Returns <a href="#Point_Array">Point Array</a> length. |
| <a href="#SkPath_countVerbs">countVerbs</a> | Returns <a href="#Verb_Array">Verb Array</a> length. |
| <a href="#SkPath_cubicTo">cubicTo</a> | Appends <a href="#Cubic">Cubic</a>. |
-| <a href="#SkPath_dump">dump</a> | Sends text representation using floats to stdout. |
+| <a href="#SkPath_dump_2">dump</a> | Sends text representation using floats to stdout. |
| <a href="#SkPath_dumpHex">dumpHex</a> | Sends text representation using hexadecimal to stdout. |
| <a href="#SkPath_experimentalValidateRef">experimentalValidateRef</a> | Experimental; debugging only. |
| <a href="#SkPath_getBounds">getBounds</a> | Returns maximum and minimum of <a href="#Point_Array">Point Array</a>. |
| <a href="#SkPath_getConvexity">getConvexity</a> | Returns geometry convexity, computing if necessary. |
| <a href="#SkPath_getConvexityOrUnknown">getConvexityOrUnknown</a> | Returns geometry convexity if known. |
| <a href="#SkPath_getFillType">getFillType</a> | Returns <a href="#Fill_Type">Fill Type</a>: winding, even-odd, inverse. |
-| <a href="#SkPath_getGenerationID">getGenerationID</a> | Returns unique ID. |
+| <a href="#SkPath_getGenerationID">getGenerationID</a> | Returns <a href="#SkPath_unique">unique</a> ID. |
| <a href="#SkPath_getLastPt">getLastPt</a> | Returns <a href="#Last_Point">Last Point</a>. |
| <a href="#SkPath_getPoint">getPoint</a> | Returns entry from <a href="#Point_Array">Point Array</a>. |
| <a href="#SkPath_getPoints">getPoints</a> | Returns <a href="#Point_Array">Point Array</a>. |
@@ -161,7 +177,7 @@ makes them visible.
| <a href="#SkPath_isConvex">isConvex</a> | Returns if geometry is convex. |
| <a href="#SkPath_isEmpty">isEmpty</a> | Returns if verb count is zero. |
| <a href="#SkPath_isFinite">isFinite</a> | Returns if all <a href="undocumented#Point">Point</a> values are finite. |
-| <a href="#SkPath_isInterpolatable">isInterpolatable</a> | Returns if pair contains equal counts of <a href="#Verb_Array">Verb Array</a> and <a href="#Weight">Weights</a>. |
+| <a href="#SkPath_isInterpolatable">isInterpolatable</a> | Returns if pair <a href="#SkPath_contains">contains</a> equal counts of <a href="#Verb_Array">Verb Array</a> and <a href="#Weight">Weights</a>. |
| <a href="#SkPath_isInverseFillType">isInverseFillType</a> | Returns if <a href="#Fill_Type">Fill Type</a> fills outside geometry. |
| <a href="#SkPath_isLastContourClosed">isLastContourClosed</a> | Returns if final <a href="#Contour">Contour</a> forms a loop. |
| <a href="#SkPath_isLine">isLine</a> | Returns if describes <a href="undocumented#Line">Line</a>. |
@@ -169,6 +185,7 @@ makes them visible.
| <a href="#SkPath_isOval">isOval</a> | Returns if describes <a href="undocumented#Oval">Oval</a>. |
| <a href="#SkPath_isRRect">isRRect</a> | Returns if describes <a href="undocumented#Round_Rect">Round Rect</a>. |
| <a href="#SkPath_isRect">isRect</a> | Returns if describes <a href="undocumented#Rect">Rect</a>. |
+| <a href="#SkPath_isValid">isValid</a> | Returns if data is internally consistent. |
| <a href="#SkPath_isVolatile">isVolatile</a> | Returns if <a href="undocumented#Device">Device</a> should not cache. |
| <a href="#SkPath_lineTo">lineTo</a> | Appends <a href="undocumented#Line">Line</a>. |
| <a href="#SkPath_moveTo">moveTo</a> | Starts <a href="#Contour">Contour</a>. |
@@ -180,10 +197,11 @@ makes them visible.
| <a href="#SkPath_rLineTo">rLineTo</a> | Appends <a href="undocumented#Line">Line</a> relative to <a href="#Last_Point">Last Point</a>. |
| <a href="#SkPath_rMoveTo">rMoveTo</a> | Starts <a href="#Contour">Contour</a> relative to <a href="#Last_Point">Last Point</a>. |
| <a href="#SkPath_rQuadTo">rQuadTo</a> | Appends <a href="#Quad">Quad</a> relative to <a href="#Last_Point">Last Point</a>. |
-| <a href="#SkPath_readFromMemory">readFromMemory</a> | Initialize from buffer. |
+| <a href="#SkPath_readFromMemory">readFromMemory</a> | Initializes from buffer. |
| <a href="#SkPath_reset">reset</a> | Removes <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, and <a href="#Weight">Weights</a>; frees memory. |
| <a href="#SkPath_reverseAddPath">reverseAddPath</a> | Adds contents of <a href="#Path">Path</a> back to front. |
| <a href="#SkPath_rewind">rewind</a> | Removes <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, and <a href="#Weight">Weights</a>; leaves memory allocated. |
+| <a href="#SkPath_serialize">serialize</a> | Copies data to buffer. |
| <a href="#SkPath_setConvexity">setConvexity</a> | Sets if geometry is convex to avoid future computation. |
| <a href="#SkPath_setFillType">setFillType</a> | Sets <a href="#Fill_Type">Fill Type</a>: winding, even-odd, inverse. |
| <a href="#SkPath_setIsConvex">setIsConvex</a> | Deprecated. |
@@ -193,8 +211,8 @@ makes them visible.
| <a href="#SkPath_toggleInverseFillType">toggleInverseFillType</a> | Toggles <a href="#Fill_Type">Fill Type</a> between inside and outside geometry. |
| <a href="#SkPath_transform">transform</a> | Applies <a href="undocumented#Matrix">Matrix</a> to <a href="#Point_Array">Point Array</a> and <a href="#Weight">Weights</a>. |
| <a href="#SkPath_unique">unique</a> | Returns if data has single owner. |
-| <a href="#SkPath_updateBoundsCache">updateBoundsCache</a> | Refresh result of <a href="#SkPath_getBounds">getBounds</a>. |
-| <a href="#SkPath_writeToMemory">writeToMemory</a> | Copy data to buffer. |
+| <a href="#SkPath_updateBoundsCache">updateBoundsCache</a> | Refreshes result of <a href="#SkPath_getBounds">getBounds</a>. |
+| <a href="#SkPath_writeToMemory">writeToMemory</a> | Copies data to buffer. |
## <a name="Verb"></a> Verb
@@ -202,16 +220,16 @@ makes them visible.
<pre style="padding: 1em 1em 1em 1em;width: 44em; background-color: #f0f0f0">
enum <a href="#Verb">Verb</a> {
-<a href="#SkPath_kMove_Verb">kMove Verb</a>
-<a href="#SkPath_kLine_Verb">kLine Verb</a>
-<a href="#SkPath_kQuad_Verb">kQuad Verb</a>
-<a href="#SkPath_kConic_Verb">kConic Verb</a>
-<a href="#SkPath_kCubic_Verb">kCubic Verb</a>
-<a href="#SkPath_kClose_Verb">kClose Verb</a>
-<a href="#SkPath_kDone_Verb">kDone Verb</a>
+<a href="#SkPath_kMove_Verb">kMove Verb</a>,
+<a href="#SkPath_kLine_Verb">kLine Verb</a>,
+<a href="#SkPath_kQuad_Verb">kQuad Verb</a>,
+<a href="#SkPath_kConic_Verb">kConic Verb</a>,
+<a href="#SkPath_kCubic_Verb">kCubic Verb</a>,
+<a href="#SkPath_kClose_Verb">kClose Verb</a>,
+<a href="#SkPath_kDone_Verb">kDone Verb</a>,
};</pre>
-<a href="#Verb">Verb</a> instructs <a href="#Path">Path</a> how to interpret one or more <a href="undocumented#Point">Point</a> and optional Weight;
+<a href="#Verb">Verb</a> instructs <a href="#Path">Path</a> how to interpret one or more <a href="undocumented#Point">Point</a> and optional <a href="#Conic_Weight">Conic Weight</a>;
manage <a href="#Contour">Contour</a>, and terminate <a href="#Path">Path</a>.
### Constants
@@ -230,11 +248,11 @@ manage <a href="#Contour">Contour</a>, and terminate <a href="#Path">Path</a>.
and control <a href="undocumented#Point">Point</a> to end <a href="undocumented#Point">Point</a>.</td>
</tr>
<tr>
- <td><a name="SkPath_kConic_Verb"> <code><strong>SkPath::kConic_Verb </strong></code> </a></td><td>3</td><td>Adds <a href="#Conic">Conic</a> from <a href="#Last_Point">Last Point</a>, using control <a href="undocumented#Point">Point</a>, end <a href="undocumented#Point">Point</a>, and Weight.
+ <td><a name="SkPath_kConic_Verb"> <code><strong>SkPath::kConic_Verb </strong></code> </a></td><td>3</td><td>Adds <a href="#Conic">Conic</a> from <a href="#Last_Point">Last Point</a>, using control <a href="undocumented#Point">Point</a>, end <a href="undocumented#Point">Point</a>, and <a href="#Conic_Weight">Conic Weight</a>.
<a href="#Conic">Conic</a> is a elliptical, parabolic, or hyperbolic section within tangents
from <a href="#Last_Point">Last Point</a> to control <a href="undocumented#Point">Point</a>, and control <a href="undocumented#Point">Point</a> to end <a href="undocumented#Point">Point</a>, constrained
-by Weight. Weight less than one is elliptical; equal to one is parabolic
-(and identical to <a href="#Quad">Quad</a>); greater than one hyperbolic.</td>
+by <a href="#Conic_Weight">Conic Weight</a>. <a href="#Conic_Weight">Conic Weight</a> less than one is elliptical; equal to one is
+parabolic (and identical to <a href="#Quad">Quad</a>); greater than one hyperbolic.</td>
</tr>
<tr>
<td><a name="SkPath_kCubic_Verb"> <code><strong>SkPath::kCubic_Verb </strong></code> </a></td><td>4</td><td>Adds <a href="#Cubic">Cubic</a> from <a href="#Last_Point">Last Point</a>, using two control <a href="#Point">Points</a>, and end <a href="undocumented#Point">Point</a>.
@@ -284,12 +302,12 @@ verbs: kMove_Verb kLine_Verb kQuad_Verb kClose_Verb kMove_Verb kCubic_Verb kConi
<pre style="padding: 1em 1em 1em 1em;width: 44em; background-color: #f0f0f0">
enum <a href="#Direction">Direction</a> {
-<a href="#SkPath_kCW_Direction">kCW Direction</a>
-<a href="#SkPath_kCCW_Direction">kCCW Direction</a>
+<a href="#SkPath_kCW_Direction">kCW Direction</a>,
+<a href="#SkPath_kCCW_Direction">kCCW Direction</a>,
};</pre>
<a href="#Direction">Direction</a> describes whether <a href="#Contour">Contour</a> is clockwise or counterclockwise.
-When <a href="#Path">Path</a> contains multiple overlapping <a href="#Contour">Contours</a>, <a href="#Direction">Direction</a> together with
+When <a href="#Path">Path</a> <a href="#SkPath_contains">contains</a> multiple overlapping <a href="#Contour">Contours</a>, <a href="#Direction">Direction</a> together with
<a href="#Fill_Type">Fill Type</a> determines whether overlaps are filled or form holes.
<a href="#Direction">Direction</a> also determines how <a href="#Contour">Contour</a> is measured. For instance, dashing
@@ -304,10 +322,10 @@ travel counterclockwise.
<table>
<tr>
- <td><a name="SkPath_kCW_Direction"> <code><strong>SkPath::kCW_Direction </strong></code> </a></td><td>Contour travels in a clockwise direction. </td><td></td>
+ <td><a name="SkPath_kCW_Direction"> <code><strong>SkPath::kCW_Direction </strong></code> </a></td><td>0</td><td><a href="#Contour">Contour</a> travels in a clockwise direction.</td>
</tr>
<tr>
- <td><a name="SkPath_kCCW_Direction"> <code><strong>SkPath::kCCW_Direction </strong></code> </a></td><td>Contour travels in a counterclockwise direction. </td><td></td>
+ <td><a name="SkPath_kCCW_Direction"> <code><strong>SkPath::kCCW_Direction </strong></code> </a></td><td>1</td><td><a href="#Contour">Contour</a> travels in a counterclockwise direction.</td>
</tr>
</table>
@@ -333,7 +351,7 @@ By default, <a href="#Path">Path</a> has no <a href="#Verb">Verbs</a>, no <a hre
### Return Value
-empty <a href="#Path">Path</a>.
+empty <a href="#Path">Path</a>
### Example
@@ -349,18 +367,18 @@ path is empty
### See Also
-reset rewind
+<a href="#SkPath_reset">reset</a> <a href="#SkPath_rewind">rewind</a>
---
-<a name="SkPath_copy_constructor"></a>
+<a name="SkPath_copy_const_SkPath"></a>
## SkPath
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
SkPath(const SkPath& path)
</pre>
-Copy constructor makes two paths identical by value. Internally, <a href="#SkPath_copy_constructor_path">path</a> and
+Copy constructor makes two paths identical by value. Internally, <a href="#SkPath_copy_const_SkPath_path">path</a> and
the returned result share pointer values. The underlying <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>
and <a href="#Weight">Weights</a> are copied when modified.
@@ -370,18 +388,18 @@ pointers are not exposed.
### Parameters
-<table> <tr> <td><a name="SkPath_copy_constructor_path"> <code><strong>path </strong></code> </a></td> <td>
-<a href="#Path">Path</a> to copy by value.</td>
+<table> <tr> <td><a name="SkPath_copy_const_SkPath_path"> <code><strong>path </strong></code> </a></td> <td>
+<a href="#Path">Path</a> to copy by value</td>
</tr>
</table>
### Return Value
-Copy of <a href="#Path">Path</a>.
+Copy of <a href="#Path">Path</a>
### Example
-<div><fiddle-embed name="647312aacd946c8a6eabaca797140432"><div>Modifying one <a href="#SkPath_copy_constructor_path">path</a> does not effect another, even if they started as copies
+<div><fiddle-embed name="647312aacd946c8a6eabaca797140432"><div>Modifying one <a href="#SkPath_copy_const_SkPath_path">path</a> does not effect another, even if they started as copies
of each other.</div>
#### Example Output
@@ -417,7 +435,7 @@ Releases ownership of any shared data and deletes data if <a href="#Path">Path</
### See Also
-<a href="#SkPath_empty_constructor">SkPath()</a> <a href="#SkPath_copy_constructor">SkPath(const SkPath& path)</a> <a href="#SkPath_copy_assignment_operator">operator=(const SkPath& path)</a>
+<a href="#SkPath_empty_constructor">SkPath()</a> <a href="#SkPath_copy_const_SkPath">SkPath(const SkPath& path)</a> <a href="#SkPath_copy_assignment_operator">operator=(const SkPath& path)</a>
---
@@ -439,13 +457,13 @@ pointers are not exposed.
### Parameters
<table> <tr> <td><a name="SkPath_copy_assignment_operator_path"> <code><strong>path </strong></code> </a></td> <td>
-<a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, <a href="#Weight">Weights</a>, amd <a href="#Fill_Type">Fill Type</a> to copy.</td>
+<a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, <a href="#Weight">Weights</a>, amd <a href="#Fill_Type">Fill Type</a> to copy</td>
</tr>
</table>
### Return Value
-<a href="#Path">Path</a> copied by value.
+<a href="#Path">Path</a> copied by value
### Example
@@ -462,7 +480,7 @@ path2 bounds = 10, 20, 30, 40
### See Also
-<a href="#SkPath_swap">swap</a> <a href="#SkPath_copy_constructor">SkPath(const SkPath& path)</a>
+<a href="#SkPath_swap">swap</a> <a href="#SkPath_copy_const_SkPath">SkPath(const SkPath& path)</a>
---
@@ -470,7 +488,7 @@ path2 bounds = 10, 20, 30, 40
## operator==
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
-friend SK_API bool operator==(const SkPath& a, const SkPath& b)
+bool operator==(const SkPath& a, const SkPath& b)
</pre>
Compares <a href="#SkPath_equal_operator_a">a</a> and <a href="#SkPath_equal_operator_b">b</a>; returns true if <a href="#Fill_Type">Fill Type</a>, <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, and <a href="#Weight">Weights</a>
@@ -479,15 +497,15 @@ are equivalent.
### Parameters
<table> <tr> <td><a name="SkPath_equal_operator_a"> <code><strong>a </strong></code> </a></td> <td>
-<a href="#Path">Path</a> to compare.</td>
+<a href="#Path">Path</a> to compare</td>
</tr> <tr> <td><a name="SkPath_equal_operator_b"> <code><strong>b </strong></code> </a></td> <td>
-<a href="#Path">Path</a> to compare.</td>
+<a href="#Path">Path</a> to compare</td>
</tr>
</table>
### Return Value
-true if <a href="#Path">Path</a> pair are equivalent.
+true if <a href="#Path">Path</a> pair are equivalent
### Example
@@ -511,7 +529,7 @@ reset one == two
## operator!=
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
-friend bool operator!=(const SkPath& a, const SkPath& b)
+bool operator!=(const SkPath& a, const SkPath& b)
</pre>
Compares <a href="#SkPath_not_equal_operator_a">a</a> and <a href="#SkPath_not_equal_operator_b">b</a>; returns true if <a href="#Fill_Type">Fill Type</a>, <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, and <a href="#Weight">Weights</a>
@@ -520,15 +538,15 @@ are not equivalent.
### Parameters
<table> <tr> <td><a name="SkPath_not_equal_operator_a"> <code><strong>a </strong></code> </a></td> <td>
-<a href="#Path">Path</a> to compare.</td>
+<a href="#Path">Path</a> to compare</td>
</tr> <tr> <td><a name="SkPath_not_equal_operator_b"> <code><strong>b </strong></code> </a></td> <td>
-<a href="#Path">Path</a> to compare.</td>
+<a href="#Path">Path</a> to compare</td>
</tr>
</table>
### Return Value
-true if <a href="#Path">Path</a> pair are not equivalent.
+true if <a href="#Path">Path</a> pair are not equivalent
### Example
@@ -558,19 +576,19 @@ Return true if <a href="#Path">Paths</a> contain equal <a href="#Verb">Verbs</a>
If <a href="#Path">Paths</a> contain one or more <a href="#Conic">Conics</a>, the <a href="#Weight">Weights</a> must match.
<a href="#SkPath_conicTo">conicTo</a> may add different <a href="#Verb">Verbs</a> depending on <a href="#Conic_Weight">Conic Weight</a>, so it is not
-trival to interpolate a pair of <a href="#Path">Paths</a> containing <a href="#Conic">Conics</a> with different
+trival to <a href="#SkPath_interpolate">interpolate</a> a pair of <a href="#Path">Paths</a> containing <a href="#Conic">Conics</a> with different
<a href="#Conic_Weight">Conic Weight</a> values.
### Parameters
<table> <tr> <td><a name="SkPath_isInterpolatable_compare"> <code><strong>compare </strong></code> </a></td> <td>
-<a href="#Path">Path</a> to <a href="#SkPath_isInterpolatable_compare">compare</a>.</td>
+<a href="#Path">Path</a> to <a href="#SkPath_isInterpolatable_compare">compare</a></td>
</tr>
</table>
### Return Value
-true if <a href="#Path">Paths</a> <a href="#Verb_Array">Verb Array</a> and <a href="#Weight">Weights</a> are equivalent.
+true if <a href="#Path">Paths</a> <a href="#Verb_Array">Verb Array</a> and <a href="#Weight">Weights</a> are equivalent
### Example
@@ -601,26 +619,29 @@ Interpolate between <a href="#Path">Paths</a> with equal sized <a href="SkPath_R
Copy <a href="#Verb_Array">Verb Array</a> and <a href="#Weight">Weights</a> to <a href="#SkPath_interpolate_out">out</a>,
and set <a href="#SkPath_interpolate_out">out</a> <a href="#Point_Array">Point Array</a> to a weighted average of this <a href="#Point_Array">Point Array</a> and <a href="#SkPath_interpolate_ending">ending</a>
<a href="#Point_Array">Point Array</a>, using the formula:
-(this->points * <a href="#SkPath_interpolate_weight">weight</a>) + ending->points * (1 - <a href="#SkPath_interpolate_weight">weight</a>)<a href="#SkPath_interpolate">interpolate</a> returns false and leaves <a href="#SkPath_interpolate_out">out</a> unchanged if <a href="#Point_Array">Point Array</a> is not
+(this->points * <a href="#SkPath_interpolate_weight">weight</a>) + ending->points * (1 - <a href="#SkPath_interpolate_weight">weight</a>)<a href="#SkPath_interpolate_weight">weight</a> is most useful when between zero (<a href="#SkPath_interpolate_ending">ending</a> <a href="#Point_Array">Point Array</a>) and
+one (this <a href="#Point_Array">Point Array</a>); will work with values outside of this
+range.
+
+<a href="#SkPath_interpolate">interpolate</a> returns false and leaves <a href="#SkPath_interpolate_out">out</a> unchanged if <a href="#Point_Array">Point Array</a> is not
the same size as <a href="#SkPath_interpolate_ending">ending</a> <a href="#Point_Array">Point Array</a>. Call <a href="#SkPath_isInterpolatable">isInterpolatable</a> to check <a href="#Path">Path</a>
compatibility prior to calling <a href="#SkPath_interpolate">interpolate</a>.
### Parameters
<table> <tr> <td><a name="SkPath_interpolate_ending"> <code><strong>ending </strong></code> </a></td> <td>
-<a href="#Point_Array">Point Array</a> averaged with this <a href="#Point_Array">Point Array</a>.</td>
+<a href="#Point_Array">Point Array</a> averaged with this <a href="#Point_Array">Point Array</a></td>
</tr> <tr> <td><a name="SkPath_interpolate_weight"> <code><strong>weight </strong></code> </a></td> <td>
-Most useful when between zero (<a href="#SkPath_interpolate_ending">ending</a> <a href="#Point_Array">Point Array</a>) and
-one (this <a href="#Point_Array">Point Array</a>); will work with values outside of this
-range.</td>
+contribution of <a href="#SkPath_interpolate_ending">ending</a> <a href="#Point_Array">Point Array</a>, and
+one minus contribution of this <a href="#Point_Array">Point Array</a></td>
</tr> <tr> <td><a name="SkPath_interpolate_out"> <code><strong>out </strong></code> </a></td> <td>
-</td>
+<a href="#Path">Path</a> replaced by interpolated averages</td>
</tr>
</table>
### Return Value
-true if <a href="#Path">Paths</a> contain same number of <a href="#Point">Points</a>.
+true if <a href="#Path">Paths</a> contain same number of <a href="#Point">Points</a>
### Example
@@ -641,7 +662,7 @@ bool unique() const
### Return Value
-true if <a href="#Path">Path</a> has one owner.
+true if <a href="#Path">Path</a> has one owner
---
@@ -651,10 +672,10 @@ true if <a href="#Path">Path</a> has one owner.
<pre style="padding: 1em 1em 1em 1em;width: 44em; background-color: #f0f0f0">
enum <a href="#SkPath_FillType">FillType</a> {
-<a href="#SkPath_kWinding_FillType">kWinding FillType</a>
-<a href="#SkPath_kEvenOdd_FillType">kEvenOdd FillType</a>
-<a href="#SkPath_kInverseWinding_FillType">kInverseWinding FillType</a>
-<a href="#SkPath_kInverseEvenOdd_FillType">kInverseEvenOdd FillType</a>
+<a href="#SkPath_kWinding_FillType">kWinding FillType</a>,
+<a href="#SkPath_kEvenOdd_FillType">kEvenOdd FillType</a>,
+<a href="#SkPath_kInverseWinding_FillType">kInverseWinding FillType</a>,
+<a href="#SkPath_kInverseEvenOdd_FillType">kInverseEvenOdd FillType</a>,
};</pre>
<a href="#Fill_Type">Fill Type</a> selects the rule used to fill <a href="#Path">Path</a>. <a href="#Path">Path</a> set to <a href="#SkPath_kWinding_FillType">kWinding FillType</a>
@@ -676,16 +697,16 @@ same as the outer parts of the top rectangles, which have a winding of 1.</div><
<table>
<tr>
- <td><a name="SkPath_kWinding_FillType"> <code><strong>SkPath::kWinding_FillType </strong></code> </a></td><td>Specifies fill as area is enclosed by a non-zero sum of Contour Directions.</td><td></td>
+ <td><a name="SkPath_kWinding_FillType"> <code><strong>SkPath::kWinding_FillType </strong></code> </a></td><td>0</td><td>Specifies fill as area is enclosed by a non-zero sum of <a href="#Contour">Contour</a> <a href="#Direction">Directions</a>.</td>
</tr>
<tr>
- <td><a name="SkPath_kEvenOdd_FillType"> <code><strong>SkPath::kEvenOdd_FillType </strong></code> </a></td><td>Specifies fill as area enclosed by an odd number of Contours.</td><td></td>
+ <td><a name="SkPath_kEvenOdd_FillType"> <code><strong>SkPath::kEvenOdd_FillType </strong></code> </a></td><td>1</td><td>Specifies fill as area enclosed by an odd number of <a href="#Contour">Contours</a>.</td>
</tr>
<tr>
- <td><a name="SkPath_kInverseWinding_FillType"> <code><strong>SkPath::kInverseWinding_FillType </strong></code> </a></td><td>Specifies fill as area is enclosed by a zero sum of Contour Directions.</td><td></td>
+ <td><a name="SkPath_kInverseWinding_FillType"> <code><strong>SkPath::kInverseWinding_FillType </strong></code> </a></td><td>2</td><td>Specifies fill as area is enclosed by a zero sum of <a href="#Contour">Contour</a> <a href="#Direction">Directions</a>.</td>
</tr>
<tr>
- <td><a name="SkPath_kInverseEvenOdd_FillType"> <code><strong>SkPath::kInverseEvenOdd_FillType </strong></code> </a></td><td>Specifies fill as area enclosed by an even number of Contours.</td><td></td>
+ <td><a name="SkPath_kInverseEvenOdd_FillType"> <code><strong>SkPath::kInverseEvenOdd_FillType </strong></code> </a></td><td>3</td><td>Specifies fill as area enclosed by an even number of <a href="#Contour">Contours</a>.</td>
</tr>
</table>
@@ -712,7 +733,7 @@ Returns <a href="#SkPath_FillType">FillType</a>, the rule used to fill <a href="
### Return Value
one of: <a href="#SkPath_kWinding_FillType">kWinding FillType</a>, <a href="#SkPath_kEvenOdd_FillType">kEvenOdd FillType</a>, <a href="#SkPath_kInverseWinding_FillType">kInverseWinding FillType</a>,
-<a href="#SkPath_kInverseEvenOdd_FillType">kInverseEvenOdd FillType</a>.
+<a href="#SkPath_kInverseEvenOdd_FillType">kInverseEvenOdd FillType</a>
### Example
@@ -739,14 +760,14 @@ default path fill type is kWinding_FillType
void setFillType(FillType ft)
</pre>
-Sets <a href="#SkPath_FillType">FillType</a>, the rule used to fill <a href="#Path">Path</a>. While <a href="#SkPath_setFillType">setFillType</a> does not check
+Sets <a href="#SkPath_FillType">FillType</a>, the rule used to fill <a href="#Path">Path</a>. While there is no check
that <a href="#SkPath_setFillType_ft">ft</a> is legal, values outside of <a href="#SkPath_FillType">FillType</a> are not supported.
### Parameters
<table> <tr> <td><a name="SkPath_setFillType_ft"> <code><strong>ft </strong></code> </a></td> <td>
one of: <a href="#SkPath_kWinding_FillType">kWinding FillType</a>, <a href="#SkPath_kEvenOdd_FillType">kEvenOdd FillType</a>, <a href="#SkPath_kInverseWinding_FillType">kInverseWinding FillType</a>,
-<a href="#SkPath_kInverseEvenOdd_FillType">kInverseEvenOdd FillType</a>.</td>
+<a href="#SkPath_kInverseEvenOdd_FillType">kInverseEvenOdd FillType</a></td>
</tr>
</table>
@@ -772,7 +793,7 @@ extends indefinitely.
### Return Value
-true if <a href="#SkPath_FillType">FillType</a> is <a href="#SkPath_kInverseWinding_FillType">kInverseWinding FillType</a> or <a href="#SkPath_kInverseEvenOdd_FillType">kInverseEvenOdd FillType</a>.
+true if <a href="#SkPath_FillType">FillType</a> is <a href="#SkPath_kInverseWinding_FillType">kInverseWinding FillType</a> or <a href="#SkPath_kInverseEvenOdd_FillType">kInverseEvenOdd FillType</a>
### Example
@@ -827,10 +848,10 @@ unmodified by the original <a href="#SkPath_FillType">FillType</a>.
enum <a href="#Convexity">Convexity</a> {
<a href="#SkPath_kUnknown_Convexity">kUnknown Convexity</a>,
<a href="#SkPath_kConvex_Convexity">kConvex Convexity</a>,
-<a href="#SkPath_kConcave_Convexity">kConcave Convexity</a>
+<a href="#SkPath_kConcave_Convexity">kConcave Convexity</a>,
};</pre>
-<a href="#Path">Path</a> is convex if it contains one <a href="#Contour">Contour</a> and <a href="#Contour">Contour</a> loops no more than
+<a href="#Path">Path</a> is convex if it <a href="#SkPath_contains">contains</a> one <a href="#Contour">Contour</a> and <a href="#Contour">Contour</a> loops no more than
360 degrees, and <a href="#Contour">Contour</a> angles all have same <a href="#SkPath_Direction">Direction</a>. Convex <a href="#Path">Path</a>
may have better performance and require fewer resources on <a href="undocumented#GPU_Surface">GPU Surface</a>.
@@ -845,13 +866,13 @@ if needed by destination <a href="undocumented#Surface">Surface</a>.
<table>
<tr>
- <td><a name="SkPath_kUnknown_Convexity"> <code><strong>SkPath::kUnknown_Convexity </strong></code> </a></td><td>Indicates Convexity has not been determined.</td><td></td>
+ <td><a name="SkPath_kUnknown_Convexity"> <code><strong>SkPath::kUnknown_Convexity </strong></code> </a></td><td>0</td><td>Indicates <a href="#Convexity">Convexity</a> has not been determined.</td>
</tr>
<tr>
- <td><a name="SkPath_kConvex_Convexity"> <code><strong>SkPath::kConvex_Convexity </strong></code> </a></td><td>Path has one Contour made of a simple geometry without indentations.</td><td></td>
+ <td><a name="SkPath_kConvex_Convexity"> <code><strong>SkPath::kConvex_Convexity </strong></code> </a></td><td>1</td><td><a href="#Path">Path</a> has one <a href="#Contour">Contour</a> made of a simple geometry without indentations.</td>
</tr>
<tr>
- <td><a name="SkPath_kConcave_Convexity"> <code><strong>SkPath::kConcave_Convexity </strong></code> </a></td><td>Path has more than one Contour, or a geometry with indentations.</td><td></td>
+ <td><a name="SkPath_kConcave_Convexity"> <code><strong>SkPath::kConcave_Convexity </strong></code> </a></td><td>2</td><td><a href="#Path">Path</a> has more than one <a href="#Contour">Contour</a>, or a geometry with indentations.</td>
</tr>
</table>
@@ -878,7 +899,7 @@ or if <a href="#Path">Path</a> has been altered since <a href="#Convexity">Conve
### Return Value
-Computed or stored <a href="#Convexity">Convexity</a>.
+Computed or stored <a href="#Convexity">Convexity</a>
### Example
@@ -902,7 +923,7 @@ Returns last computed <a href="#Convexity">Convexity</a>, or <a href="#SkPath_kU
### Return Value
-Stored <a href="#Convexity">Convexity</a>.
+Stored <a href="#Convexity">Convexity</a>
### Example
@@ -936,7 +957,7 @@ altered.
### Parameters
<table> <tr> <td><a name="SkPath_setConvexity_convexity"> <code><strong>convexity </strong></code> </a></td> <td>
-One of <a href="#SkPath_kUnknown_Convexity">kUnknown Convexity</a>, <a href="#SkPath_kConvex_Convexity">kConvex Convexity</a>, or <a href="#SkPath_kConcave_Convexity">kConcave Convexity</a>.</td>
+one of: <a href="#SkPath_kUnknown_Convexity">kUnknown Convexity</a>, <a href="#SkPath_kConvex_Convexity">kConvex Convexity</a>, or <a href="#SkPath_kConcave_Convexity">kConcave Convexity</a></td>
</tr>
</table>
@@ -963,7 +984,7 @@ the path has not been altered, <a href="#Convexity">Convexity</a> is not recompu
### Return Value
-true if <a href="#Convexity">Convexity</a> stored or computed is <a href="#SkPath_kConvex_Convexity">kConvex Convexity</a>.
+true if <a href="#Convexity">Convexity</a> stored or computed is <a href="#SkPath_kConvex_Convexity">kConvex Convexity</a>
### Example
@@ -983,7 +1004,11 @@ true if <a href="#Convexity">Convexity</a> stored or computed is <a href="#SkPat
void setIsConvex(bool isConvex)
</pre>
-Use <a href="#SkPath_setConvexity">setConvexity</a>.
+Deprecated. Use <a href="#SkPath_setConvexity">setConvexity</a>.
+
+### See Also
+
+<a href="#Convexity">Convexity</a> <a href="#SkPath_setConvexity">setConvexity</a> <a href="#SkPath_getConvexity">getConvexity</a>
---
@@ -994,29 +1019,33 @@ Use <a href="#SkPath_setConvexity">setConvexity</a>.
bool isOval(SkRect* rect, Direction* dir = nullptr, unsigned* start = nullptr) const
</pre>
-<a href="#Path">Path</a> is <a href="undocumented#Oval">Oval</a> if constructed by <a href="#SkPath_addCircle">addCircle</a>, <a href="#SkPath_addOval">addOval</a>; and in some cases,
+Returns true if constructed by <a href="#SkPath_addCircle">addCircle</a>, <a href="#SkPath_addOval">addOval</a>; and in some cases,
<a href="#SkPath_addRoundRect">addRoundRect</a>, <a href="#SkPath_addRRect">addRRect</a>. <a href="#Path">Path</a> constructed with <a href="#SkPath_conicTo">conicTo</a> or <a href="#SkPath_rConicTo">rConicTo</a> will not
return true though <a href="#Path">Path</a> draws <a href="undocumented#Oval">Oval</a>.
-<a href="#SkPath_isOval">isOval</a> triggers performance optimizations on some <a href="undocumented#GPU_Surface">GPU Surface</a> implementations.
+<a href="#SkPath_isOval_rect">rect</a> receives bounds of <a href="undocumented#Oval">Oval</a>.
+<a href="#SkPath_isOval_dir">dir</a> receives <a href="#SkPath_Direction">Direction</a> of <a href="undocumented#Oval">Oval</a>: <a href="#SkPath_kCW_Direction">kCW Direction</a> if clockwise, <a href="#SkPath_kCCW_Direction">kCCW Direction</a> if
+counterclockwise.
+<a href="#SkPath_isOval_start">start</a> receives <a href="#SkPath_isOval_start">start</a> of <a href="undocumented#Oval">Oval</a>: 0 for top, 1 for right, 2 for bottom, 3 for left.
+
+<a href="#SkPath_isOval_rect">rect</a>, <a href="#SkPath_isOval_dir">dir</a>, and <a href="#SkPath_isOval_start">start</a> are unmodified if <a href="undocumented#Oval">Oval</a> is not found.
+
+Triggers performance optimizations on some <a href="undocumented#GPU_Surface">GPU Surface</a> implementations.
### Parameters
<table> <tr> <td><a name="SkPath_isOval_rect"> <code><strong>rect </strong></code> </a></td> <td>
-storage for bounding <a href="undocumented#Rect">Rect</a> of <a href="undocumented#Oval">Oval</a>. <a href="undocumented#Oval">Oval</a> is <a href="undocumented#Circle">Circle</a> if <a href="#SkPath_isOval_rect">rect</a> width
-equals <a href="#SkPath_isOval_rect">rect</a> height. Unwritten if <a href="#Path">Path</a> is not <a href="undocumented#Oval">Oval</a>. May be nullptr.</td>
+storage for bounding <a href="undocumented#Rect">Rect</a> of <a href="undocumented#Oval">Oval</a>; may be nullptr</td>
</tr> <tr> <td><a name="SkPath_isOval_dir"> <code><strong>dir </strong></code> </a></td> <td>
-storage for <a href="#SkPath_Direction">Direction</a>; <a href="#SkPath_kCW_Direction">kCW Direction</a> if clockwise, <a href="#SkPath_kCCW_Direction">kCCW Direction</a> if
-counterclockwise. Unwritten if <a href="#Path">Path</a> is not <a href="undocumented#Oval">Oval</a>. May be nullptr.</td>
+storage for <a href="#SkPath_Direction">Direction</a>; may be nullptr</td>
</tr> <tr> <td><a name="SkPath_isOval_start"> <code><strong>start </strong></code> </a></td> <td>
-storage for <a href="#SkPath_isOval_start">start</a> of <a href="undocumented#Oval">Oval</a>: 0 for top,
-1 for right, 2 for bottom, 3 for left. Unwritten if <a href="#Path">Path</a> is not <a href="undocumented#Oval">Oval</a>. May be nullptr.</td>
+storage for <a href="#SkPath_isOval_start">start</a> of <a href="undocumented#Oval">Oval</a>; may be nullptr</td>
</tr>
</table>
### Return Value
-true if <a href="#Path">Path</a> was constructed by method that reduces to <a href="undocumented#Oval">Oval</a>.
+true if <a href="#Path">Path</a> was constructed by method that reduces to <a href="undocumented#Oval">Oval</a>
### Example
@@ -1035,29 +1064,33 @@ true if <a href="#Path">Path</a> was constructed by method that reduces to <a hr
bool isRRect(SkRRect* rrect, Direction* dir = nullptr, unsigned* start = nullptr) const
</pre>
-<a href="#Path">Path</a> is <a href="undocumented#Round_Rect">Round Rect</a> if constructed by <a href="#SkPath_addRoundRect">addRoundRect</a>, <a href="#SkPath_addRRect">addRRect</a>; and if construction
+Returns true if constructed by <a href="#SkPath_addRoundRect">addRoundRect</a>, <a href="#SkPath_addRRect">addRRect</a>; and if construction
is not empty, not <a href="undocumented#Rect">Rect</a>, and not <a href="undocumented#Oval">Oval</a>. <a href="#Path">Path</a> constructed with other other calls
will not return true though <a href="#Path">Path</a> draws <a href="undocumented#Round_Rect">Round Rect</a>.
-<a href="#SkPath_isRRect">isRRect</a> triggers performance optimizations on some <a href="undocumented#GPU_Surface">GPU Surface</a> implementations.
+<a href="#SkPath_isRRect_rrect">rrect</a> receives bounds of <a href="undocumented#Round_Rect">Round Rect</a>.
+<a href="#SkPath_isRRect_dir">dir</a> receives <a href="#SkPath_Direction">Direction</a> of <a href="undocumented#Oval">Oval</a>: <a href="#SkPath_kCW_Direction">kCW Direction</a> if clockwise, <a href="#SkPath_kCCW_Direction">kCCW Direction</a> if
+counterclockwise.
+<a href="#SkPath_isRRect_start">start</a> receives <a href="#SkPath_isRRect_start">start</a> of <a href="undocumented#Round_Rect">Round Rect</a>: 0 for top, 1 for right, 2 for bottom, 3 for left.
+
+<a href="#SkPath_isRRect_rrect">rrect</a>, <a href="#SkPath_isRRect_dir">dir</a>, and <a href="#SkPath_isRRect_start">start</a> are unmodified if <a href="undocumented#Round_Rect">Round Rect</a> is not found.
+
+Triggers performance optimizations on some <a href="undocumented#GPU_Surface">GPU Surface</a> implementations.
### Parameters
<table> <tr> <td><a name="SkPath_isRRect_rrect"> <code><strong>rrect </strong></code> </a></td> <td>
-storage for bounding <a href="undocumented#Rect">Rect</a> of <a href="undocumented#Round_Rect">Round Rect</a>.
-Unwritten if <a href="#Path">Path</a> is not <a href="undocumented#Round_Rect">Round Rect</a>. May be nullptr.</td>
+storage for bounding <a href="undocumented#Rect">Rect</a> of <a href="undocumented#Round_Rect">Round Rect</a>; may be nullptr</td>
</tr> <tr> <td><a name="SkPath_isRRect_dir"> <code><strong>dir </strong></code> </a></td> <td>
-storage for <a href="#SkPath_Direction">Direction</a>; <a href="#SkPath_kCW_Direction">kCW Direction</a> if clockwise, <a href="#SkPath_kCCW_Direction">kCCW Direction</a> if
-counterclockwise. Unwritten if <a href="#Path">Path</a> is not <a href="undocumented#Round_Rect">Round Rect</a>. May be nullptr.</td>
+storage for <a href="#SkPath_Direction">Direction</a>; may be nullptr</td>
</tr> <tr> <td><a name="SkPath_isRRect_start"> <code><strong>start </strong></code> </a></td> <td>
-storage for <a href="#SkPath_isRRect_start">start</a> of <a href="undocumented#Round_Rect">Round Rect</a>: 0 for top,
-1 for right, 2 for bottom, 3 for left. Unwritten if <a href="#Path">Path</a> is not <a href="undocumented#Round_Rect">Round Rect</a>. May be nullptr.</td>
+storage for <a href="#SkPath_isRRect_start">start</a> of <a href="undocumented#Round_Rect">Round Rect</a>; may be nullptr</td>
</tr>
</table>
### Return Value
-true for <a href="undocumented#Round_Rect">Round Rect</a> <a href="#Path">Path</a> constructed by <a href="#SkPath_addRoundRect">addRoundRect</a> or <a href="#SkPath_addRRect">addRRect</a>.
+true for <a href="undocumented#Round_Rect">Round Rect</a> <a href="#Path">Path</a> constructed by <a href="#SkPath_addRoundRect">addRoundRect</a> or <a href="#SkPath_addRRect">addRRect</a>
### Example
@@ -1123,11 +1156,11 @@ bool isEmpty() const
</pre>
Empty <a href="#Path">Path</a> may have <a href="#SkPath_FillType">FillType</a> but has no <a href="undocumented#SkPoint">SkPoint</a>, <a href="#SkPath_Verb">Verb</a>, or <a href="#Conic_Weight">Conic Weight</a>.
-<a href="#SkPath_empty_constructor">SkPath()</a> constructs empty <a href="#Path">Path</a>; <a href="#SkPath_reset">reset</a> and (rewind) make <a href="#Path">Path</a> empty.
+<a href="#SkPath_empty_constructor">SkPath()</a> constructs empty <a href="#Path">Path</a>; <a href="#SkPath_reset">reset</a> and (<a href="#SkPath_rewind">rewind</a>) make <a href="#Path">Path</a> empty.
### Return Value
-true if the path contains no <a href="#SkPath_Verb">Verb</a> array.
+true if the path <a href="#SkPath_contains">contains</a> no <a href="#SkPath_Verb">Verb</a> array
### Example
@@ -1163,7 +1196,7 @@ closed <a href="#Contour">Contour</a> draws <a href="#Stroke_Join">Paint Stroke
### Return Value
-true if the last <a href="#Contour">Contour</a> ends with a <a href="#SkPath_kClose_Verb">kClose Verb</a>.
+true if the last <a href="#Contour">Contour</a> ends with a <a href="#SkPath_kClose_Verb">kClose Verb</a>
### Example
@@ -1194,14 +1227,13 @@ after close last contour is closed
bool isFinite() const
</pre>
-Finite <a href="undocumented#Point">Point</a> array values are between negative <a href="undocumented#SK_ScalarMax">SK ScalarMax</a> and
-positive <a href="undocumented#SK_ScalarMax">SK ScalarMax</a>. Any <a href="undocumented#Point">Point</a> array value of
-<a href="undocumented#SK_ScalarInfinity">SK ScalarInfinity</a>, <a href="undocumented#SK_ScalarNegativeInfinity">SK ScalarNegativeInfinity</a>, or <a href="undocumented#SK_ScalarNaN">SK ScalarNaN</a>
-cause <a href="#SkPath_isFinite">isFinite</a> to return false.
+Returns true for finite <a href="undocumented#Point">Point</a> array values between negative <a href="undocumented#SK_ScalarMax">SK ScalarMax</a> and
+positive <a href="undocumented#SK_ScalarMax">SK ScalarMax</a>. Returns false for any <a href="undocumented#Point">Point</a> array value of
+<a href="undocumented#SK_ScalarInfinity">SK ScalarInfinity</a>, <a href="undocumented#SK_ScalarNegativeInfinity">SK ScalarNegativeInfinity</a>, or <a href="undocumented#SK_ScalarNaN">SK ScalarNaN</a>.
### Return Value
-true if all <a href="undocumented#Point">Point</a> values are finite.
+true if all <a href="undocumented#Point">Point</a> values are finite
### Example
@@ -1237,7 +1269,7 @@ may not speed repeated drawing.
### Return Value
-true if caller will alter <a href="#Path">Path</a> after drawing.
+true if caller will alter <a href="#Path">Path</a> after drawing
### Example
@@ -1280,7 +1312,7 @@ Mark unchanging <a href="#Path">Path</a> non-volative to improve repeated render
### Parameters
<table> <tr> <td><a name="SkPath_setIsVolatile_isVolatile"> <code><strong>isVolatile </strong></code> </a></td> <td>
-true if caller will alter <a href="#Path">Path</a> after drawing.</td>
+true if caller will alter <a href="#Path">Path</a> after drawing</td>
</tr>
</table>
@@ -1308,18 +1340,18 @@ treated as a point.
### Parameters
<table> <tr> <td><a name="SkPath_IsLineDegenerate_p1"> <code><strong>p1 </strong></code> </a></td> <td>
-<a href="undocumented#Line">Line</a> start point.</td>
+line start point</td>
</tr> <tr> <td><a name="SkPath_IsLineDegenerate_p2"> <code><strong>p2 </strong></code> </a></td> <td>
-<a href="undocumented#Line">Line</a> end point.</td>
+line end point</td>
</tr> <tr> <td><a name="SkPath_IsLineDegenerate_exact"> <code><strong>exact </strong></code> </a></td> <td>
If true, returns true only if <a href="#SkPath_IsLineDegenerate_p1">p1</a> equals <a href="#SkPath_IsLineDegenerate_p2">p2</a>. If false, returns true
-if <a href="#SkPath_IsLineDegenerate_p1">p1</a> equals or nearly equals <a href="#SkPath_IsLineDegenerate_p2">p2</a>.</td>
+if <a href="#SkPath_IsLineDegenerate_p1">p1</a> equals or nearly equals <a href="#SkPath_IsLineDegenerate_p2">p2</a></td>
</tr>
</table>
### Return Value
-true if <a href="undocumented#Line">Line</a> is degenerate; its length is effectively zero.
+true if <a href="undocumented#Line">Line</a> is degenerate; its length is effectively zero
### Example
@@ -1359,20 +1391,20 @@ treated as a point.
### Parameters
<table> <tr> <td><a name="SkPath_IsQuadDegenerate_p1"> <code><strong>p1 </strong></code> </a></td> <td>
-<a href="#Quad">Quad</a> start point.</td>
+quad start point</td>
</tr> <tr> <td><a name="SkPath_IsQuadDegenerate_p2"> <code><strong>p2 </strong></code> </a></td> <td>
-<a href="#Quad">Quad</a> control point.</td>
+quad control point</td>
</tr> <tr> <td><a name="SkPath_IsQuadDegenerate_p3"> <code><strong>p3 </strong></code> </a></td> <td>
-<a href="#Quad">Quad</a> end point.</td>
+quad end point</td>
</tr> <tr> <td><a name="SkPath_IsQuadDegenerate_exact"> <code><strong>exact </strong></code> </a></td> <td>
-If true, returns true only if <a href="#SkPath_IsQuadDegenerate_p1">p1</a>, <a href="#SkPath_IsQuadDegenerate_p2">p2</a>, and <a href="#SkPath_IsQuadDegenerate_p3">p3</a> are equal.
-If false, returns true if <a href="#SkPath_IsQuadDegenerate_p1">p1</a>, <a href="#SkPath_IsQuadDegenerate_p2">p2</a>, and <a href="#SkPath_IsQuadDegenerate_p3">p3</a> are equal or nearly equal.</td>
+if true, returns true only if <a href="#SkPath_IsQuadDegenerate_p1">p1</a>, <a href="#SkPath_IsQuadDegenerate_p2">p2</a>, and <a href="#SkPath_IsQuadDegenerate_p3">p3</a> are equal;
+if false, returns true if <a href="#SkPath_IsQuadDegenerate_p1">p1</a>, <a href="#SkPath_IsQuadDegenerate_p2">p2</a>, and <a href="#SkPath_IsQuadDegenerate_p3">p3</a> are equal or nearly equal</td>
</tr>
</table>
### Return Value
-true if <a href="#Quad">Quad</a> is degenerate; its length is effectively zero.
+true if <a href="#Quad">Quad</a> is degenerate; its length is effectively zero
### Example
@@ -1412,22 +1444,22 @@ treated as a point.
### Parameters
<table> <tr> <td><a name="SkPath_IsCubicDegenerate_p1"> <code><strong>p1 </strong></code> </a></td> <td>
-<a href="#Cubic">Cubic</a> start point.</td>
+cubic start point</td>
</tr> <tr> <td><a name="SkPath_IsCubicDegenerate_p2"> <code><strong>p2 </strong></code> </a></td> <td>
-<a href="#Cubic">Cubic</a> control point 1.</td>
+cubic control point 1</td>
</tr> <tr> <td><a name="SkPath_IsCubicDegenerate_p3"> <code><strong>p3 </strong></code> </a></td> <td>
-<a href="#Cubic">Cubic</a> control point 2.</td>
+cubic control point 2</td>
</tr> <tr> <td><a name="SkPath_IsCubicDegenerate_p4"> <code><strong>p4 </strong></code> </a></td> <td>
-<a href="#Cubic">Cubic</a> end point.</td>
+cubic end point</td>
</tr> <tr> <td><a name="SkPath_IsCubicDegenerate_exact"> <code><strong>exact </strong></code> </a></td> <td>
-If true, returns true only if <a href="#SkPath_IsCubicDegenerate_p1">p1</a>, <a href="#SkPath_IsCubicDegenerate_p2">p2</a>, <a href="#SkPath_IsCubicDegenerate_p3">p3</a>, and <a href="#SkPath_IsCubicDegenerate_p4">p4</a> are equal.
-If false, returns true if <a href="#SkPath_IsCubicDegenerate_p1">p1</a>, <a href="#SkPath_IsCubicDegenerate_p2">p2</a>, <a href="#SkPath_IsCubicDegenerate_p3">p3</a>, and <a href="#SkPath_IsCubicDegenerate_p4">p4</a> are equal or nearly equal.</td>
+if true, returns true only if <a href="#SkPath_IsCubicDegenerate_p1">p1</a>, <a href="#SkPath_IsCubicDegenerate_p2">p2</a>, <a href="#SkPath_IsCubicDegenerate_p3">p3</a>, and <a href="#SkPath_IsCubicDegenerate_p4">p4</a> are equal;
+if false, returns true if <a href="#SkPath_IsCubicDegenerate_p1">p1</a>, <a href="#SkPath_IsCubicDegenerate_p2">p2</a>, <a href="#SkPath_IsCubicDegenerate_p3">p3</a>, and <a href="#SkPath_IsCubicDegenerate_p4">p4</a> are equal or nearly equal</td>
</tr>
</table>
### Return Value
-true if <a href="#Cubic">Cubic</a> is degenerate; its length is effectively zero.
+true if <a href="#Cubic">Cubic</a> is degenerate; its length is effectively zero
### Example
@@ -1451,22 +1483,22 @@ true if <a href="#Cubic">Cubic</a> is degenerate; its length is effectively zero
bool isLine(SkPoint line[2]) const
</pre>
-Returns true if <a href="#Path">Path</a> contains only one <a href="undocumented#Line">Line</a>;
+Returns true if <a href="#Path">Path</a> <a href="#SkPath_contains">contains</a> only one <a href="undocumented#Line">Line</a>;
<a href="#Verb">Path Verb</a> array has two entries: <a href="#SkPath_kMove_Verb">kMove Verb</a>, <a href="#SkPath_kLine_Verb">kLine Verb</a>.
-If <a href="#Path">Path</a> contains one <a href="undocumented#Line">Line</a> and <a href="#SkPath_isLine_line">line</a> is not nullptr, <a href="#SkPath_isLine_line">line</a> is set to
+If <a href="#Path">Path</a> <a href="#SkPath_contains">contains</a> one <a href="undocumented#Line">Line</a> and <a href="#SkPath_isLine_line">line</a> is not nullptr, <a href="#SkPath_isLine_line">line</a> is set to
<a href="undocumented#Line">Line</a> start point and <a href="undocumented#Line">Line</a> end point.
Returns false if <a href="#Path">Path</a> is not one <a href="undocumented#Line">Line</a>; <a href="#SkPath_isLine_line">line</a> is unaltered.
### Parameters
<table> <tr> <td><a name="SkPath_isLine_line"> <code><strong>line </strong></code> </a></td> <td>
-storage for <a href="undocumented#Line">Line</a>. May be nullptr.</td>
+storage for <a href="undocumented#Line">Line</a>. May be nullptr</td>
</tr>
</table>
### Return Value
-true if <a href="#Path">Path</a> contains exactly one <a href="undocumented#Line">Line</a>.
+true if <a href="#Path">Path</a> <a href="#SkPath_contains">contains</a> exactly one <a href="undocumented#Line">Line</a>
### Example
@@ -1487,13 +1519,13 @@ second move is not line
## <a name="Point_Array"></a> Point Array
-<a href="#Point_Array">Point Array</a> contains <a href="#Point">Points</a> satisfying the allocated <a href="#Point">Points</a> for
+<a href="#Point_Array">Point Array</a> <a href="#SkPath_contains">contains</a> <a href="#Point">Points</a> satisfying the allocated <a href="#Point">Points</a> for
each <a href="#SkPath_Verb">Verb</a> in <a href="#Verb_Array">Verb Array</a>. For instance, <a href="#Path">Path</a> containing one <a href="#Contour">Contour</a> with <a href="undocumented#Line">Line</a>
and <a href="#Quad">Quad</a> is described by <a href="#Verb_Array">Verb Array</a>: move to, line to, quad to; and
one <a href="undocumented#Point">Point</a> for move, one <a href="undocumented#Point">Point</a> for <a href="undocumented#Line">Line</a>, two <a href="#Point">Points</a> for <a href="#Quad">Quad</a>; totaling four <a href="#Point">Points</a>.
<a href="#Point_Array">Point Array</a> may be read directly from <a href="#Path">Path</a> with <a href="#SkPath_getPoints">getPoints</a>, or inspected with
-<a href="#SkPath_getPoint">getPoint</a>, with <a href="SkPath_Reference#Iter">Iter</a>, or with <a href="SkPath_Reference#RawIter">RawIter</a>.
+<a href="#SkPath_getPoint">getPoint</a>, with <a href="#SkPath_Iter">Iter</a>, or with <a href="#SkPath_RawIter">RawIter</a>.
<a name="SkPath_getPoints"></a>
## getPoints
@@ -1509,15 +1541,15 @@ If <a href="#SkPath_getPoints_max">max</a> is greater than number of <a href="#S
### Parameters
<table> <tr> <td><a name="SkPath_getPoints_points"> <code><strong>points </strong></code> </a></td> <td>
-storage for <a href="#Path">Path</a> <a href="undocumented#Point">Point</a> array. May be nullptr.</td>
+storage for <a href="#Path">Path</a> <a href="undocumented#Point">Point</a> array. May be nullptr</td>
</tr> <tr> <td><a name="SkPath_getPoints_max"> <code><strong>max </strong></code> </a></td> <td>
-Number of <a href="#SkPath_getPoints_points">points</a> alloted in <a href="#SkPath_getPoints_points">points</a> storage; must be greater than or equal to zero.</td>
+maximum to copy; must be greater than or equal to zero</td>
</tr>
</table>
### Return Value
-<a href="#Path">Path</a> <a href="undocumented#Point">Point</a> array length.
+<a href="#Path">Path</a> <a href="undocumented#Point">Point</a> array length
### Example
@@ -1552,7 +1584,7 @@ Returns the number of points in <a href="#Path">Path</a>.
### Return Value
-<a href="#Path">Path</a> <a href="undocumented#Point">Point</a> array length.
+<a href="#Path">Path</a> <a href="undocumented#Point">Point</a> array length
### Example
@@ -1584,18 +1616,18 @@ SkPoint getPoint(int index) const
Returns <a href="undocumented#Point">Point</a> at <a href="#SkPath_getPoint_index">index</a> in <a href="#Point_Array">Point Array</a>. Valid range for <a href="#SkPath_getPoint_index">index</a> is
0 to <a href="#SkPath_countPoints">countPoints</a> - 1.
-If the <a href="#SkPath_getPoint_index">index</a> is out of range, <a href="#SkPath_getPoint">getPoint</a> returns (0, 0).
+Returns (0, 0) if <a href="#SkPath_getPoint_index">index</a> is out of range.
### Parameters
<table> <tr> <td><a name="SkPath_getPoint_index"> <code><strong>index </strong></code> </a></td> <td>
-<a href="#Point_Array">Point Array</a> element selector.</td>
+<a href="undocumented#Point">Point</a> array element selector</td>
</tr>
</table>
### Return Value
-<a href="#Point_Array">Point Array</a> value or (0, 0).
+<a href="undocumented#Point">Point</a> array value or (0, 0)
### Example
@@ -1624,8 +1656,8 @@ the quantity of <a href="#SkPath_kMove_Verb">kMove Verb</a> equals the <a href="
<a href="#Verb_Array">Verb Array</a> does not include or count <a href="#SkPath_kDone_Verb">kDone Verb</a>; it is a convenience
returned when iterating through <a href="#Verb_Array">Verb Array</a>.
-<a href="#Verb_Array">Verb Array</a> may be read directly from <a href="#Path">Path</a> with <a href="#SkPath_getVerbs">getVerbs</a>, or inspected with <a href="SkPath_Reference#Iter">Iter</a>,
-or with <a href="SkPath_Reference#RawIter">RawIter</a>.
+<a href="#Verb_Array">Verb Array</a> may be read directly from <a href="#Path">Path</a> with <a href="#SkPath_getVerbs">getVerbs</a>, or inspected with <a href="#SkPath_Iter">Iter</a>,
+or with <a href="#SkPath_RawIter">RawIter</a>.
<a name="SkPath_countVerbs"></a>
## countVerbs
@@ -1639,7 +1671,7 @@ Returns the number of <a href="#Verb">Verbs</a>: <a href="#SkPath_kMove_Verb">kM
### Return Value
-Length of <a href="#Verb_Array">Verb Array</a>.
+length of <a href="#Verb_Array">Verb Array</a>
### Example
@@ -1656,7 +1688,7 @@ round rect verb count: 10
### See Also
-<a href="#SkPath_getVerbs">getVerbs</a> <a href="SkPath_Reference#Iter">Iter</a> <a href="SkPath_Reference#RawIter">RawIter</a>
+<a href="#SkPath_getVerbs">getVerbs</a> <a href="#SkPath_Iter">Iter</a> <a href="#SkPath_RawIter">RawIter</a>
---
@@ -1673,9 +1705,9 @@ Returns the number of <a href="#SkPath_getVerbs_verbs">verbs</a> in the path. Up
### Parameters
<table> <tr> <td><a name="SkPath_getVerbs_verbs"> <code><strong>verbs </strong></code> </a></td> <td>
-If not null, receives up to <a href="#SkPath_getVerbs_max">max</a> <a href="#SkPath_getVerbs_verbs">verbs</a></td>
+storage for <a href="#SkPath_getVerbs_verbs">verbs</a>, may be nullptr</td>
</tr> <tr> <td><a name="SkPath_getVerbs_max"> <code><strong>max </strong></code> </a></td> <td>
-The maximum number of <a href="#SkPath_getVerbs_verbs">verbs</a> to copy into <a href="#SkPath_getVerbs_verbs">verbs</a></td>
+maximum number to copy into <a href="#SkPath_getVerbs_verbs">verbs</a></td>
</tr>
</table>
@@ -1700,7 +1732,7 @@ just right verb count: 3 move line line
### See Also
-<a href="#SkPath_countVerbs">countVerbs</a> <a href="#SkPath_getPoints">getPoints</a> <a href="SkPath_Reference#Iter">Iter</a> <a href="SkPath_Reference#RawIter">RawIter</a>
+<a href="#SkPath_countVerbs">countVerbs</a> <a href="#SkPath_getPoints">getPoints</a> <a href="#SkPath_Iter">Iter</a> <a href="#SkPath_RawIter">RawIter</a>
---
@@ -1722,7 +1754,7 @@ making assignment as efficient as <a href="#SkPath_swap">swap</a>.
### Parameters
<table> <tr> <td><a name="SkPath_swap_other"> <code><strong>other </strong></code> </a></td> <td>
-<a href="#Path">Path</a> exchanged by value.</td>
+<a href="#Path">Path</a> exchanged by value</td>
</tr>
</table>
@@ -1752,16 +1784,16 @@ path2 bounds = 10, 20, 30, 40
const SkRect& getBounds() const
</pre>
-Returns minimum and maximum x and y values of <a href="#Point_Array">Point Array</a>. If <a href="#Path">Path</a> contains
-no points, <a href="#SkPath_getBounds">getBounds</a> returns (0, 0, 0, 0). Returned bounds width and height may
+Returns minimum and maximum x and y values of <a href="#Point_Array">Point Array</a>.
+Returns (0, 0, 0, 0) if <a href="#Path">Path</a> <a href="#SkPath_contains">contains</a> no points. Returned bounds width and height may
be larger or smaller than area affected when <a href="#Path">Path</a> is drawn.
-<a href="#SkPath_getBounds">getBounds</a> includes all <a href="#Point">Points</a> added to <a href="#Path">Path</a>, including <a href="#Point">Points</a> associated with
+<a href="undocumented#Rect">Rect</a> returned includes all <a href="#Point">Points</a> added to <a href="#Path">Path</a>, including <a href="#Point">Points</a> associated with
<a href="#SkPath_kMove_Verb">kMove Verb</a> that define empty <a href="#Contour">Contours</a>.
### Return Value
-bounds of all <a href="#Point">Points</a> in <a href="#Point_Array">Point Array</a>.
+bounds of all <a href="#Point">Points</a> in <a href="#Point_Array">Point Array</a>
### Example
@@ -1794,10 +1826,9 @@ void updateBoundsCache() const
Update internal bounds so that subsequent calls to <a href="#SkPath_getBounds">getBounds</a> are instantaneous.
Unaltered copies of <a href="#Path">Path</a> may also access cached bounds through <a href="#SkPath_getBounds">getBounds</a>.
-For now, <a href="#SkPath_updateBoundsCache">updateBoundsCache</a> is identical to <a href="#SkPath_getBounds">getBounds</a>, where the
-returned value is ignored.
+For now, identical to calling <a href="#SkPath_getBounds">getBounds</a> and ignoring the returned value.
-<a href="#SkPath_updateBoundsCache">updateBoundsCache</a> prepares a <a href="#Path">Path</a> subsequently drawn from multiple threads,
+Call to prepare <a href="#Path">Path</a> subsequently drawn from multiple threads,
to avoid a race condition where each draw separately computes the bounds.
### Example
@@ -1828,20 +1859,22 @@ SkRect computeTightBounds() const
</pre>
Returns minimum and maximum x and y values of the lines and curves in <a href="#Path">Path</a>.
-If <a href="#Path">Path</a> contains no points, <a href="#SkPath_computeTightBounds">computeTightBounds</a> returns (0, 0, 0, 0).
+Returns (0, 0, 0, 0) if <a href="#Path">Path</a> <a href="#SkPath_contains">contains</a> no points.
Returned bounds width and height may be larger or smaller than area affected
when <a href="#Path">Path</a> is drawn.
-<a href="#SkPath_computeTightBounds">computeTightBounds</a> behaves identically to <a href="#SkPath_getBounds">getBounds</a> when <a href="#Path">Path</a> contains
-only lines. If <a href="#Path">Path</a> contains curves, compute <a href="#SkPath_computeTightBounds">computeTightBounds</a> includes
-the maximum extent of the <a href="#Quad">Quad</a>, <a href="#Conic">Conic</a>, or <a href="#Cubic">Cubic</a>; is slower,
-and does not cache the result.
+Includes <a href="#Point">Points</a> associated with <a href="#SkPath_kMove_Verb">kMove Verb</a> that define empty
+<a href="#Contour">Contours</a>.
-Like <a href="#SkPath_getBounds">getBounds</a>, <a href="#SkPath_computeTightBounds">computeTightBounds</a> includes <a href="#Point">Points</a> associated with
-<a href="#SkPath_kMove_Verb">kMove Verb</a> that define empty <a href="#Contour">Contours</a>.
+Behaves identically to <a href="#SkPath_getBounds">getBounds</a> when <a href="#Path">Path</a> <a href="#SkPath_contains">contains</a>
+only lines. If <a href="#Path">Path</a> <a href="#SkPath_contains">contains</a> curves, computed bounds includes
+the maximum extent of the <a href="#Quad">Quad</a>, <a href="#Conic">Conic</a>, or <a href="#Cubic">Cubic</a>; is slower than <a href="#SkPath_getBounds">getBounds</a>;
+and unlike <a href="#SkPath_getBounds">getBounds</a>, does not cache the result.
### Return Value
+tight bounds of curves in <a href="#Path">Path</a>
+
### Example
<div><fiddle-embed name="da34f02e69ec98d5681300aea9a2d0bf">
@@ -1874,19 +1907,19 @@ May return false when <a href="#SkPath_conservativelyContainsRect_rect">rect</a>
For now, only returns true if <a href="#Path">Path</a> has one <a href="#Contour">Contour</a> and is convex.
<a href="#SkPath_conservativelyContainsRect_rect">rect</a> may share points and edges with <a href="#Path">Path</a> and be contained.
-If <a href="#SkPath_conservativelyContainsRect_rect">rect</a> is empty, that is, it has zero width or height; <a href="#SkPath_conservativelyContainsRect">conservativelyContainsRect</a>
-returns true if the <a href="undocumented#Point">Point</a> or <a href="undocumented#Line">Line</a> described by <a href="#SkPath_conservativelyContainsRect_rect">rect</a> is contained by <a href="#Path">Path</a>.
+Returns true if <a href="#SkPath_conservativelyContainsRect_rect">rect</a> is empty, that is, it has zero width or height; and
+the <a href="undocumented#Point">Point</a> or <a href="undocumented#Line">Line</a> described by <a href="#SkPath_conservativelyContainsRect_rect">rect</a> is contained by <a href="#Path">Path</a>.
### Parameters
<table> <tr> <td><a name="SkPath_conservativelyContainsRect_rect"> <code><strong>rect </strong></code> </a></td> <td>
-<a href="undocumented#Rect">Rect</a>, <a href="undocumented#Line">Line</a>, or <a href="undocumented#Point">Point</a> checked for containment.</td>
+<a href="undocumented#Rect">Rect</a>, <a href="undocumented#Line">Line</a>, or <a href="undocumented#Point">Point</a> checked for containment</td>
</tr>
</table>
### Return Value
-true if <a href="#SkPath_conservativelyContainsRect_rect">rect</a> is contained.
+true if <a href="#SkPath_conservativelyContainsRect_rect">rect</a> is contained
### Example
@@ -1894,7 +1927,7 @@ true if <a href="#SkPath_conservativelyContainsRect_rect">rect</a> is contained.
### See Also
-contains <a href="undocumented#Op">Op</a> <a href="undocumented#Rect">Rect</a> <a href="#SkPath_Convexity">Convexity</a>
+<a href="#SkPath_contains">contains</a> <a href="undocumented#Op">Op</a> <a href="undocumented#Rect">Rect</a> <a href="#SkPath_Convexity">Convexity</a>
---
@@ -1906,13 +1939,13 @@ void incReserve(unsigned extraPtCount)
</pre>
grows <a href="#Path">Path</a> <a href="#Verb_Array">Verb Array</a> and <a href="#Point_Array">Point Array</a> to contain <a href="#SkPath_incReserve_extraPtCount">extraPtCount</a> additional <a href="#Point">Points</a>.
-<a href="#SkPath_incReserve">incReserve</a> may improve performance and use less memory by
+May improve performance and use less memory by
reducing the number and size of allocations when creating <a href="#Path">Path</a>.
### Parameters
<table> <tr> <td><a name="SkPath_incReserve_extraPtCount"> <code><strong>extraPtCount </strong></code> </a></td> <td>
-number of additional <a href="#Point">Points</a> to preallocate.</td>
+number of additional <a href="#Point">Points</a> to preallocate</td>
</tr>
</table>
@@ -1938,9 +1971,9 @@ Adds beginning of <a href="#Contour">Contour</a> at <a href="undocumented#Point"
### Parameters
<table> <tr> <td><a name="SkPath_moveTo_x"> <code><strong>x </strong></code> </a></td> <td>
-x-coordinate of <a href="#Contour">Contour</a> start.</td>
+x-coordinate of <a href="#Contour">Contour</a> start</td>
</tr> <tr> <td><a name="SkPath_moveTo_y"> <code><strong>y </strong></code> </a></td> <td>
-y-coordinate of <a href="#Contour">Contour</a> start.</td>
+y-coordinate of <a href="#Contour">Contour</a> start</td>
</tr>
</table>
@@ -1963,7 +1996,7 @@ Adds beginning of <a href="#Contour">Contour</a> at <a href="undocumented#Point"
### Parameters
<table> <tr> <td><a name="SkPath_moveTo_2_p"> <code><strong>p </strong></code> </a></td> <td>
-<a href="#Contour">Contour</a> start.</td>
+contour start</td>
</tr>
</table>
@@ -1986,15 +2019,15 @@ void rMoveTo(SkScalar dx, SkScalar dy)
Adds beginning of <a href="#Contour">Contour</a> relative to <a href="#Last_Point">Last Point</a>.
If <a href="#Path">Path</a> is empty, starts <a href="#Contour">Contour</a> at (<a href="#SkPath_rMoveTo_dx">dx</a>, <a href="#SkPath_rMoveTo_dy">dy</a>).
-Otherwise, start <a href="#Contour">Contour</a> at <a href="#Last_Point">Last Point</a> offset by (<a href="#SkPath_rMoveTo_dx">dx</a>, <a href="#SkPath_rMoveTo_dy">dy</a>).
-<a href="#SkPath_rMoveTo">rMoveTo</a> stands for relative move to.
+Otherwise, start <a href="#Contour">Contour</a> at <a href="#Last_Point">Last Point</a> <a href="#SkPath_offset">offset</a> by (<a href="#SkPath_rMoveTo_dx">dx</a>, <a href="#SkPath_rMoveTo_dy">dy</a>).
+Function name stands for relative move to.
### Parameters
<table> <tr> <td><a name="SkPath_rMoveTo_dx"> <code><strong>dx </strong></code> </a></td> <td>
-offset from <a href="#Last_Point">Last Point</a> x to <a href="#Contour">Contour</a> start x.</td>
+<a href="#SkPath_offset">offset</a> from <a href="#Last_Point">Last Point</a> x to <a href="#Contour">Contour</a> start x</td>
</tr> <tr> <td><a name="SkPath_rMoveTo_dy"> <code><strong>dy </strong></code> </a></td> <td>
-offset from <a href="#Last_Point">Last Point</a> y to <a href="#Contour">Contour</a> start y.</td>
+<a href="#SkPath_offset">offset</a> from <a href="#Last_Point">Last Point</a> y to <a href="#Contour">Contour</a> start y</td>
</tr>
</table>
@@ -2024,9 +2057,9 @@ Adds <a href="undocumented#Line">Line</a> from <a href="#Last_Point">Last Point<
### Parameters
<table> <tr> <td><a name="SkPath_lineTo_x"> <code><strong>x </strong></code> </a></td> <td>
-end of added <a href="undocumented#Line">Line</a> in <a href="#SkPath_lineTo_x">x</a>.</td>
+end of added <a href="undocumented#Line">Line</a> in <a href="#SkPath_lineTo_x">x</a></td>
</tr> <tr> <td><a name="SkPath_lineTo_y"> <code><strong>y </strong></code> </a></td> <td>
-end of added <a href="undocumented#Line">Line</a> in <a href="#SkPath_lineTo_y">y</a>.</td>
+end of added <a href="undocumented#Line">Line</a> in <a href="#SkPath_lineTo_y">y</a></td>
</tr>
</table>
@@ -2053,7 +2086,7 @@ Adds <a href="undocumented#Line">Line</a> from <a href="#Last_Point">Last Point<
### Parameters
<table> <tr> <td><a name="SkPath_lineTo_2_p"> <code><strong>p </strong></code> </a></td> <td>
-end <a href="undocumented#Point">Point</a> of added <a href="undocumented#Line">Line</a>.</td>
+end <a href="undocumented#Point">Point</a> of added <a href="undocumented#Line">Line</a></td>
</tr>
</table>
@@ -2077,17 +2110,17 @@ void rLineTo(SkScalar dx, SkScalar dy)
Adds <a href="undocumented#Line">Line</a> from <a href="#Last_Point">Last Point</a> to <a href="undocumented#Vector">Vector</a> (<a href="#SkPath_rLineTo_dx">dx</a>, <a href="#SkPath_rLineTo_dy">dy</a>). If <a href="#Path">Path</a> is empty, or last <a href="#SkPath_Verb">Verb</a> is
<a href="#SkPath_kClose_Verb">kClose Verb</a>, <a href="#Last_Point">Last Point</a> is set to (0, 0) before adding <a href="undocumented#Line">Line</a>.
-<a href="#SkPath_rLineTo">rLineTo</a> first appends <a href="#SkPath_kMove_Verb">kMove Verb</a> to <a href="#Verb_Array">Verb Array</a> and (0, 0) to <a href="#Point_Array">Point Array</a>, if needed.
-<a href="#SkPath_rLineTo">rLineTo</a> then appends <a href="#SkPath_kLine_Verb">kLine Verb</a> to <a href="#Verb_Array">Verb Array</a> and <a href="undocumented#Line">Line</a> end to <a href="#Point_Array">Point Array</a>.
+Appends <a href="#SkPath_kMove_Verb">kMove Verb</a> to <a href="#Verb_Array">Verb Array</a> and (0, 0) to <a href="#Point_Array">Point Array</a>, if needed;
+then appends <a href="#SkPath_kLine_Verb">kLine Verb</a> to <a href="#Verb_Array">Verb Array</a> and <a href="undocumented#Line">Line</a> end to <a href="#Point_Array">Point Array</a>.
<a href="undocumented#Line">Line</a> end is <a href="#Last_Point">Last Point</a> plus <a href="undocumented#Vector">Vector</a> (<a href="#SkPath_rLineTo_dx">dx</a>, <a href="#SkPath_rLineTo_dy">dy</a>).
-<a href="#SkPath_rLineTo">rLineTo</a> stands for relative line to.
+Function name stands for relative line to.
### Parameters
<table> <tr> <td><a name="SkPath_rLineTo_dx"> <code><strong>dx </strong></code> </a></td> <td>
-offset from <a href="#Last_Point">Last Point</a> x to <a href="undocumented#Line">Line</a> end x.</td>
+<a href="#SkPath_offset">offset</a> from <a href="#Last_Point">Last Point</a> x to <a href="undocumented#Line">Line</a> end x</td>
</tr> <tr> <td><a name="SkPath_rLineTo_dy"> <code><strong>dy </strong></code> </a></td> <td>
-offset from <a href="#Last_Point">Last Point</a> y to <a href="undocumented#Line">Line</a> end y.</td>
+<a href="#SkPath_offset">offset</a> from <a href="#Last_Point">Last Point</a> y to <a href="undocumented#Line">Line</a> end y</td>
</tr>
</table>
@@ -2131,20 +2164,20 @@ Adds <a href="#Quad">Quad</a> from <a href="#Last_Point">Last Point</a> towards
If <a href="#Path">Path</a> is empty, or last <a href="#SkPath_Verb">Verb</a> is <a href="#SkPath_kClose_Verb">kClose Verb</a>, <a href="#Last_Point">Last Point</a> is set to (0, 0)
before adding <a href="#Quad">Quad</a>.
-<a href="#SkPath_quadTo">quadTo</a> appends <a href="#SkPath_kMove_Verb">kMove Verb</a> to <a href="#Verb_Array">Verb Array</a> and (0, 0) to <a href="#Point_Array">Point Array</a>, if needed.
-<a href="#SkPath_quadTo">quadTo</a> then appends <a href="#SkPath_kQuad_Verb">kQuad Verb</a> to <a href="#Verb_Array">Verb Array</a>; and (<a href="#SkPath_quadTo_x1">x1</a>, <a href="#SkPath_quadTo_y1">y1</a>), (<a href="#SkPath_quadTo_x2">x2</a>, <a href="#SkPath_quadTo_y2">y2</a>)
+Appends <a href="#SkPath_kMove_Verb">kMove Verb</a> to <a href="#Verb_Array">Verb Array</a> and (0, 0) to <a href="#Point_Array">Point Array</a>, if needed;
+then appends <a href="#SkPath_kQuad_Verb">kQuad Verb</a> to <a href="#Verb_Array">Verb Array</a>; and (<a href="#SkPath_quadTo_x1">x1</a>, <a href="#SkPath_quadTo_y1">y1</a>), (<a href="#SkPath_quadTo_x2">x2</a>, <a href="#SkPath_quadTo_y2">y2</a>)
to <a href="#Point_Array">Point Array</a>.
### Parameters
<table> <tr> <td><a name="SkPath_quadTo_x1"> <code><strong>x1 </strong></code> </a></td> <td>
-control <a href="undocumented#Point">Point</a> of <a href="#Quad">Quad</a> in x.</td>
+control <a href="undocumented#Point">Point</a> of <a href="#Quad">Quad</a> in x</td>
</tr> <tr> <td><a name="SkPath_quadTo_y1"> <code><strong>y1 </strong></code> </a></td> <td>
-control <a href="undocumented#Point">Point</a> of <a href="#Quad">Quad</a> in y.</td>
+control <a href="undocumented#Point">Point</a> of <a href="#Quad">Quad</a> in y</td>
</tr> <tr> <td><a name="SkPath_quadTo_x2"> <code><strong>x2 </strong></code> </a></td> <td>
-end <a href="undocumented#Point">Point</a> of <a href="#Quad">Quad</a> in x.</td>
+end <a href="undocumented#Point">Point</a> of <a href="#Quad">Quad</a> in x</td>
</tr> <tr> <td><a name="SkPath_quadTo_y2"> <code><strong>y2 </strong></code> </a></td> <td>
-end <a href="undocumented#Point">Point</a> of <a href="#Quad">Quad</a> in y.</td>
+end <a href="undocumented#Point">Point</a> of <a href="#Quad">Quad</a> in y</td>
</tr>
</table>
@@ -2166,16 +2199,16 @@ Adds <a href="#Quad">Quad</a> from <a href="#Last_Point">Last Point</a> towards
If <a href="#Path">Path</a> is empty, or last <a href="#SkPath_Verb">Verb</a> is <a href="#SkPath_kClose_Verb">kClose Verb</a>, <a href="#Last_Point">Last Point</a> is set to (0, 0)
before adding <a href="#Quad">Quad</a>.
-<a href="#SkPath_quadTo">quadTo</a> appends <a href="#SkPath_kMove_Verb">kMove Verb</a> to <a href="#Verb_Array">Verb Array</a> and (0, 0) to <a href="#Point_Array">Point Array</a>, if needed.
-<a href="#SkPath_quadTo">quadTo</a> then appends <a href="#SkPath_kQuad_Verb">kQuad Verb</a> to <a href="#Verb_Array">Verb Array</a>; and <a href="#Point">Points</a> <a href="#SkPath_quadTo_2_p1">p1</a>, <a href="#SkPath_quadTo_2_p2">p2</a>
+Appends <a href="#SkPath_kMove_Verb">kMove Verb</a> to <a href="#Verb_Array">Verb Array</a> and (0, 0) to <a href="#Point_Array">Point Array</a>, if needed;
+then appends <a href="#SkPath_kQuad_Verb">kQuad Verb</a> to <a href="#Verb_Array">Verb Array</a>; and <a href="#Point">Points</a> <a href="#SkPath_quadTo_2_p1">p1</a>, <a href="#SkPath_quadTo_2_p2">p2</a>
to <a href="#Point_Array">Point Array</a>.
### Parameters
<table> <tr> <td><a name="SkPath_quadTo_2_p1"> <code><strong>p1 </strong></code> </a></td> <td>
-control <a href="undocumented#Point">Point</a> of added <a href="#Quad">Quad</a>.</td>
+control <a href="undocumented#Point">Point</a> of added <a href="#Quad">Quad</a></td>
</tr> <tr> <td><a name="SkPath_quadTo_2_p2"> <code><strong>p2 </strong></code> </a></td> <td>
-end <a href="undocumented#Point">Point</a> of added <a href="#Quad">Quad</a>.</td>
+end <a href="undocumented#Point">Point</a> of added <a href="#Quad">Quad</a></td>
</tr>
</table>
@@ -2200,23 +2233,23 @@ Adds <a href="#Quad">Quad</a> from <a href="#Last_Point">Last Point</a> towards
If <a href="#Path">Path</a> is empty, or last <a href="#SkPath_Verb">Verb</a>
is <a href="#SkPath_kClose_Verb">kClose Verb</a>, <a href="#Last_Point">Last Point</a> is set to (0, 0) before adding <a href="#Quad">Quad</a>.
-<a href="#SkPath_rQuadTo">rQuadTo</a> first appends <a href="#SkPath_kMove_Verb">kMove Verb</a> to <a href="#Verb_Array">Verb Array</a> and (0, 0) to <a href="#Point_Array">Point Array</a>,
-if needed. <a href="#SkPath_rQuadTo">rQuadTo</a> then appends <a href="#SkPath_kQuad_Verb">kQuad Verb</a> to <a href="#Verb_Array">Verb Array</a>; and appends <a href="#Quad">Quad</a>
+Appends <a href="#SkPath_kMove_Verb">kMove Verb</a> to <a href="#Verb_Array">Verb Array</a> and (0, 0) to <a href="#Point_Array">Point Array</a>,
+if needed; then appends <a href="#SkPath_kQuad_Verb">kQuad Verb</a> to <a href="#Verb_Array">Verb Array</a>; and appends <a href="#Quad">Quad</a>
control and <a href="#Quad">Quad</a> end to <a href="#Point_Array">Point Array</a>.
<a href="#Quad">Quad</a> control is <a href="#Last_Point">Last Point</a> plus <a href="undocumented#Vector">Vector</a> (<a href="#SkPath_rQuadTo_dx1">dx1</a>, <a href="#SkPath_rQuadTo_dy1">dy1</a>).
<a href="#Quad">Quad</a> end is <a href="#Last_Point">Last Point</a> plus <a href="undocumented#Vector">Vector</a> (<a href="#SkPath_rQuadTo_dx2">dx2</a>, <a href="#SkPath_rQuadTo_dy2">dy2</a>).
-<a href="#SkPath_rQuadTo">rQuadTo</a> stands for relative quad to.
+Function name stands for relative quad to.
### Parameters
<table> <tr> <td><a name="SkPath_rQuadTo_dx1"> <code><strong>dx1 </strong></code> </a></td> <td>
-offset from <a href="#Last_Point">Last Point</a> x to <a href="#Quad">Quad</a> control x.</td>
+<a href="#SkPath_offset">offset</a> from <a href="#Last_Point">Last Point</a> x to <a href="#Quad">Quad</a> control x</td>
</tr> <tr> <td><a name="SkPath_rQuadTo_dy1"> <code><strong>dy1 </strong></code> </a></td> <td>
-offset from <a href="#Last_Point">Last Point</a> x to <a href="#Quad">Quad</a> control y.</td>
+<a href="#SkPath_offset">offset</a> from <a href="#Last_Point">Last Point</a> x to <a href="#Quad">Quad</a> control y</td>
</tr> <tr> <td><a name="SkPath_rQuadTo_dx2"> <code><strong>dx2 </strong></code> </a></td> <td>
-offset from <a href="#Last_Point">Last Point</a> x to <a href="#Quad">Quad</a> end x.</td>
+<a href="#SkPath_offset">offset</a> from <a href="#Last_Point">Last Point</a> x to <a href="#Quad">Quad</a> end x</td>
</tr> <tr> <td><a name="SkPath_rQuadTo_dy2"> <code><strong>dy2 </strong></code> </a></td> <td>
-offset from <a href="#Last_Point">Last Point</a> x to <a href="#Quad">Quad</a> end y.</td>
+<a href="#SkPath_offset">offset</a> from <a href="#Last_Point">Last Point</a> x to <a href="#Quad">Quad</a> end y</td>
</tr>
</table>
@@ -2236,8 +2269,8 @@ parabola, or a piece of a hyperbola. <a href="#Conic">Conic</a> begins at a star
curves towards a control <a href="undocumented#Point">Point</a>, and then curves to an end <a href="undocumented#Point">Point</a>. The influence
of the control <a href="undocumented#Point">Point</a> is determined by <a href="#Conic_Weight">Conic Weight</a>.
-Each <a href="#Conic">Conic</a> in <a href="#Path">Path</a> adds two <a href="#Point">Points</a> and one Weight. <a href="#Weight">Weights</a> in <a href="#Path">Path</a> may be
-inspected with <a href="SkPath_Reference#Iter">Iter</a>, or with <a href="SkPath_Reference#RawIter">RawIter</a>.
+Each <a href="#Conic">Conic</a> in <a href="#Path">Path</a> adds two <a href="#Point">Points</a> and one <a href="#Conic_Weight">Conic Weight</a>. <a href="#Weight">Conic Weights</a> in <a href="#Path">Path</a>
+may be inspected with <a href="#SkPath_Iter">Iter</a>, or with <a href="#SkPath_RawIter">RawIter</a>.
## <a name="Weight"></a> Weight
@@ -2247,7 +2280,7 @@ parabolic segment.
### Example
-<div><fiddle-embed name="2aadded3d20dfef34d1c8abe28c7bc8d"><div>When <a href="#Conic">Conic</a> weight is one, <a href="#Quad">Quad</a> is added to path; the two are identical.</div>
+<div><fiddle-embed name="2aadded3d20dfef34d1c8abe28c7bc8d"><div>When <a href="#Conic_Weight">Conic Weight</a> is one, <a href="#Quad">Quad</a> is added to path; the two are identical.</div>
#### Example Output
@@ -2305,29 +2338,29 @@ Adds <a href="#Conic">Conic</a> from <a href="#Last_Point">Last Point</a> toward
If <a href="#Path">Path</a> is empty, or last <a href="#SkPath_Verb">Verb</a> is <a href="#SkPath_kClose_Verb">kClose Verb</a>, <a href="#Last_Point">Last Point</a> is set to (0, 0)
before adding <a href="#Conic">Conic</a>.
-<a href="#SkPath_conicTo">conicTo</a> appends <a href="#SkPath_kMove_Verb">kMove Verb</a> to <a href="#Verb_Array">Verb Array</a> and (0, 0) to <a href="#Point_Array">Point Array</a>, if needed.
+Appends <a href="#SkPath_kMove_Verb">kMove Verb</a> to <a href="#Verb_Array">Verb Array</a> and (0, 0) to <a href="#Point_Array">Point Array</a>, if needed.
-If <a href="#SkPath_conicTo_w">w</a> is finite and not one, <a href="#SkPath_conicTo">conicTo</a> then appends <a href="#SkPath_kConic_Verb">kConic Verb</a> to <a href="#Verb_Array">Verb Array</a>;
-and (<a href="#SkPath_conicTo_x1">x1</a>, <a href="#SkPath_conicTo_y1">y1</a>), (<a href="#SkPath_conicTo_x2">x2</a>, <a href="#SkPath_conicTo_y2">y2</a>) to <a href="#Point_Array">Point Array</a>; and <a href="#SkPath_conicTo_w">w</a> to <a href="#Weight">Weights</a>.
+If <a href="#SkPath_conicTo_w">w</a> is finite and not one, appends <a href="#SkPath_kConic_Verb">kConic Verb</a> to <a href="#Verb_Array">Verb Array</a>;
+and (<a href="#SkPath_conicTo_x1">x1</a>, <a href="#SkPath_conicTo_y1">y1</a>), (<a href="#SkPath_conicTo_x2">x2</a>, <a href="#SkPath_conicTo_y2">y2</a>) to <a href="#Point_Array">Point Array</a>; and <a href="#SkPath_conicTo_w">w</a> to <a href="#Weight">Conic Weights</a>.
-If <a href="#SkPath_conicTo_w">w</a> is one, <a href="#SkPath_conicTo">conicTo</a> appends <a href="#SkPath_kQuad_Verb">kQuad Verb</a> to <a href="#Verb_Array">Verb Array</a>, and
+If <a href="#SkPath_conicTo_w">w</a> is one, appends <a href="#SkPath_kQuad_Verb">kQuad Verb</a> to <a href="#Verb_Array">Verb Array</a>, and
(<a href="#SkPath_conicTo_x1">x1</a>, <a href="#SkPath_conicTo_y1">y1</a>), (<a href="#SkPath_conicTo_x2">x2</a>, <a href="#SkPath_conicTo_y2">y2</a>) to <a href="#Point_Array">Point Array</a>.
-If <a href="#SkPath_conicTo_w">w</a> is not finite, <a href="#SkPath_conicTo">conicTo</a> appends <a href="#SkPath_kLine_Verb">kLine Verb</a> twice to <a href="#Verb_Array">Verb Array</a>, and
+If <a href="#SkPath_conicTo_w">w</a> is not finite, appends <a href="#SkPath_kLine_Verb">kLine Verb</a> twice to <a href="#Verb_Array">Verb Array</a>, and
(<a href="#SkPath_conicTo_x1">x1</a>, <a href="#SkPath_conicTo_y1">y1</a>), (<a href="#SkPath_conicTo_x2">x2</a>, <a href="#SkPath_conicTo_y2">y2</a>) to <a href="#Point_Array">Point Array</a>.
### Parameters
<table> <tr> <td><a name="SkPath_conicTo_x1"> <code><strong>x1 </strong></code> </a></td> <td>
-control <a href="undocumented#Point">Point</a> of <a href="#Conic">Conic</a> in x.</td>
+control <a href="undocumented#Point">Point</a> of <a href="#Conic">Conic</a> in x</td>
</tr> <tr> <td><a name="SkPath_conicTo_y1"> <code><strong>y1 </strong></code> </a></td> <td>
-control <a href="undocumented#Point">Point</a> of <a href="#Conic">Conic</a> in y.</td>
+control <a href="undocumented#Point">Point</a> of <a href="#Conic">Conic</a> in y</td>
</tr> <tr> <td><a name="SkPath_conicTo_x2"> <code><strong>x2 </strong></code> </a></td> <td>
-end <a href="undocumented#Point">Point</a> of <a href="#Conic">Conic</a> in x.</td>
+end <a href="undocumented#Point">Point</a> of <a href="#Conic">Conic</a> in x</td>
</tr> <tr> <td><a name="SkPath_conicTo_y2"> <code><strong>y2 </strong></code> </a></td> <td>
-end <a href="undocumented#Point">Point</a> of <a href="#Conic">Conic</a> in y.</td>
+end <a href="undocumented#Point">Point</a> of <a href="#Conic">Conic</a> in y</td>
</tr> <tr> <td><a name="SkPath_conicTo_w"> <code><strong>w </strong></code> </a></td> <td>
-weight of added <a href="#Conic">Conic</a>.</td>
+weight of added <a href="#Conic">Conic</a></td>
</tr>
</table>
@@ -2351,25 +2384,25 @@ Adds <a href="#Conic">Conic</a> from <a href="#Last_Point">Last Point</a> toward
If <a href="#Path">Path</a> is empty, or last <a href="#SkPath_Verb">Verb</a> is <a href="#SkPath_kClose_Verb">kClose Verb</a>, <a href="#Last_Point">Last Point</a> is set to (0, 0)
before adding <a href="#Conic">Conic</a>.
-<a href="#SkPath_conicTo">conicTo</a> appends <a href="#SkPath_kMove_Verb">kMove Verb</a> to <a href="#Verb_Array">Verb Array</a> and (0, 0) to <a href="#Point_Array">Point Array</a>, if needed.
+Appends <a href="#SkPath_kMove_Verb">kMove Verb</a> to <a href="#Verb_Array">Verb Array</a> and (0, 0) to <a href="#Point_Array">Point Array</a>, if needed.
-If <a href="#SkPath_conicTo_2_w">w</a> is finite and not one, <a href="#SkPath_conicTo">conicTo</a> then appends <a href="#SkPath_kConic_Verb">kConic Verb</a> to <a href="#Verb_Array">Verb Array</a>;
-and <a href="#Point">Points</a> <a href="#SkPath_conicTo_2_p1">p1</a>, <a href="#SkPath_conicTo_2_p2">p2</a> to <a href="#Point_Array">Point Array</a>; and <a href="#SkPath_conicTo_2_w">w</a> to <a href="#Weight">Weights</a>.
+If <a href="#SkPath_conicTo_2_w">w</a> is finite and not one, appends <a href="#SkPath_kConic_Verb">kConic Verb</a> to <a href="#Verb_Array">Verb Array</a>;
+and <a href="#Point">Points</a> <a href="#SkPath_conicTo_2_p1">p1</a>, <a href="#SkPath_conicTo_2_p2">p2</a> to <a href="#Point_Array">Point Array</a>; and <a href="#SkPath_conicTo_2_w">w</a> to <a href="#Weight">Conic Weights</a>.
-If <a href="#SkPath_conicTo_2_w">w</a> is one, <a href="#SkPath_conicTo">conicTo</a> appends <a href="#SkPath_kQuad_Verb">kQuad Verb</a> to <a href="#Verb_Array">Verb Array</a>, and <a href="#Point">Points</a> <a href="#SkPath_conicTo_2_p1">p1</a>, <a href="#SkPath_conicTo_2_p2">p2</a>
+If <a href="#SkPath_conicTo_2_w">w</a> is one, appends <a href="#SkPath_kQuad_Verb">kQuad Verb</a> to <a href="#Verb_Array">Verb Array</a>, and <a href="#Point">Points</a> <a href="#SkPath_conicTo_2_p1">p1</a>, <a href="#SkPath_conicTo_2_p2">p2</a>
to <a href="#Point_Array">Point Array</a>.
-If <a href="#SkPath_conicTo_2_w">w</a> is not finite, <a href="#SkPath_conicTo">conicTo</a> appends <a href="#SkPath_kLine_Verb">kLine Verb</a> twice to <a href="#Verb_Array">Verb Array</a>, and
+If <a href="#SkPath_conicTo_2_w">w</a> is not finite, appends <a href="#SkPath_kLine_Verb">kLine Verb</a> twice to <a href="#Verb_Array">Verb Array</a>, and
<a href="#Point">Points</a> <a href="#SkPath_conicTo_2_p1">p1</a>, <a href="#SkPath_conicTo_2_p2">p2</a> to <a href="#Point_Array">Point Array</a>.
### Parameters
<table> <tr> <td><a name="SkPath_conicTo_2_p1"> <code><strong>p1 </strong></code> </a></td> <td>
-control <a href="undocumented#Point">Point</a> of added <a href="#Conic">Conic</a>.</td>
+control <a href="undocumented#Point">Point</a> of added <a href="#Conic">Conic</a></td>
</tr> <tr> <td><a name="SkPath_conicTo_2_p2"> <code><strong>p2 </strong></code> </a></td> <td>
-end <a href="undocumented#Point">Point</a> of added <a href="#Conic">Conic</a>.</td>
+end <a href="undocumented#Point">Point</a> of added <a href="#Conic">Conic</a></td>
</tr> <tr> <td><a name="SkPath_conicTo_2_w"> <code><strong>w </strong></code> </a></td> <td>
-weight of added <a href="#Conic">Conic</a>.</td>
+weight of added <a href="#Conic">Conic</a></td>
</tr>
</table>
@@ -2395,31 +2428,31 @@ Adds <a href="#Conic">Conic</a> from <a href="#Last_Point">Last Point</a> toward
weighted by <a href="#SkPath_rConicTo_w">w</a>. If <a href="#Path">Path</a> is empty, or last <a href="#SkPath_Verb">Verb</a>
is <a href="#SkPath_kClose_Verb">kClose Verb</a>, <a href="#Last_Point">Last Point</a> is set to (0, 0) before adding <a href="#Conic">Conic</a>.
-<a href="#SkPath_rConicTo">rConicTo</a> first appends <a href="#SkPath_kMove_Verb">kMove Verb</a> to <a href="#Verb_Array">Verb Array</a> and (0, 0) to <a href="#Point_Array">Point Array</a>,
+Appends <a href="#SkPath_kMove_Verb">kMove Verb</a> to <a href="#Verb_Array">Verb Array</a> and (0, 0) to <a href="#Point_Array">Point Array</a>,
if needed.
-If <a href="#SkPath_rConicTo_w">w</a> is finite and not one, <a href="#SkPath_rConicTo">rConicTo</a> then appends <a href="#SkPath_kConic_Verb">kConic Verb</a> to <a href="#Verb_Array">Verb Array</a>,
-and <a href="#SkPath_rConicTo_w">w</a> is recorded as <a href="#Conic_Weight">Conic Weight</a>; otherwise, if <a href="#SkPath_rConicTo_w">w</a> is one, <a href="#SkPath_rConicTo">rConicTo</a> appends
-<a href="#SkPath_kQuad_Verb">kQuad Verb</a> to <a href="#Verb_Array">Verb Array</a>; or if <a href="#SkPath_rConicTo_w">w</a> is not finite, <a href="#SkPath_rConicTo">rConicTo</a> appends <a href="#SkPath_kLine_Verb">kLine Verb</a>
+If <a href="#SkPath_rConicTo_w">w</a> is finite and not one, next appends <a href="#SkPath_kConic_Verb">kConic Verb</a> to <a href="#Verb_Array">Verb Array</a>,
+and <a href="#SkPath_rConicTo_w">w</a> is recorded as <a href="#Conic_Weight">Conic Weight</a>; otherwise, if <a href="#SkPath_rConicTo_w">w</a> is one, appends
+<a href="#SkPath_kQuad_Verb">kQuad Verb</a> to <a href="#Verb_Array">Verb Array</a>; or if <a href="#SkPath_rConicTo_w">w</a> is not finite, appends <a href="#SkPath_kLine_Verb">kLine Verb</a>
twice to <a href="#Verb_Array">Verb Array</a>.
-In all cases <a href="#SkPath_rConicTo">rConicTo</a> then appends <a href="#Point">Points</a> control and end to <a href="#Point_Array">Point Array</a>.
+In all cases appends <a href="#Point">Points</a> control and end to <a href="#Point_Array">Point Array</a>.
control is <a href="#Last_Point">Last Point</a> plus <a href="undocumented#Vector">Vector</a> (<a href="#SkPath_rConicTo_dx1">dx1</a>, <a href="#SkPath_rConicTo_dy1">dy1</a>).
end is <a href="#Last_Point">Last Point</a> plus <a href="undocumented#Vector">Vector</a> (<a href="#SkPath_rConicTo_dx2">dx2</a>, <a href="#SkPath_rConicTo_dy2">dy2</a>).
-<a href="#SkPath_rConicTo">rConicTo</a> stands for relative conic to.
+Function name stands for relative conic to.
### Parameters
<table> <tr> <td><a name="SkPath_rConicTo_dx1"> <code><strong>dx1 </strong></code> </a></td> <td>
-offset from <a href="#Last_Point">Last Point</a> x to <a href="#Conic">Conic</a> control x.</td>
+<a href="#SkPath_offset">offset</a> from <a href="#Last_Point">Last Point</a> x to <a href="#Conic">Conic</a> control x</td>
</tr> <tr> <td><a name="SkPath_rConicTo_dy1"> <code><strong>dy1 </strong></code> </a></td> <td>
-offset from <a href="#Last_Point">Last Point</a> x to <a href="#Conic">Conic</a> control y.</td>
+<a href="#SkPath_offset">offset</a> from <a href="#Last_Point">Last Point</a> x to <a href="#Conic">Conic</a> control y</td>
</tr> <tr> <td><a name="SkPath_rConicTo_dx2"> <code><strong>dx2 </strong></code> </a></td> <td>
-offset from <a href="#Last_Point">Last Point</a> x to <a href="#Conic">Conic</a> end x.</td>
+<a href="#SkPath_offset">offset</a> from <a href="#Last_Point">Last Point</a> x to <a href="#Conic">Conic</a> end x</td>
</tr> <tr> <td><a name="SkPath_rConicTo_dy2"> <code><strong>dy2 </strong></code> </a></td> <td>
-offset from <a href="#Last_Point">Last Point</a> x to <a href="#Conic">Conic</a> end y.</td>
+<a href="#SkPath_offset">offset</a> from <a href="#Last_Point">Last Point</a> x to <a href="#Conic">Conic</a> end y</td>
</tr> <tr> <td><a name="SkPath_rConicTo_w"> <code><strong>w </strong></code> </a></td> <td>
-weight of added <a href="#Conic">Conic</a>.</td>
+weight of added <a href="#Conic">Conic</a></td>
</tr>
</table>
@@ -2454,24 +2487,24 @@ Adds <a href="#Cubic">Cubic</a> from <a href="#Last_Point">Last Point</a> toward
(<a href="#SkPath_cubicTo_x3">x3</a>, <a href="#SkPath_cubicTo_y3">y3</a>). If <a href="#Path">Path</a> is empty, or last <a href="#SkPath_Verb">Verb</a> is <a href="#SkPath_kClose_Verb">kClose Verb</a>, <a href="#Last_Point">Last Point</a> is set to
(0, 0) before adding <a href="#Cubic">Cubic</a>.
-<a href="#SkPath_cubicTo">cubicTo</a> appends <a href="#SkPath_kMove_Verb">kMove Verb</a> to <a href="#Verb_Array">Verb Array</a> and (0, 0) to <a href="#Point_Array">Point Array</a>, if needed.
-<a href="#SkPath_cubicTo">cubicTo</a> then appends <a href="#SkPath_kCubic_Verb">kCubic Verb</a> to <a href="#Verb_Array">Verb Array</a>; and (<a href="#SkPath_cubicTo_x1">x1</a>, <a href="#SkPath_cubicTo_y1">y1</a>), (<a href="#SkPath_cubicTo_x2">x2</a>, <a href="#SkPath_cubicTo_y2">y2</a>), (<a href="#SkPath_cubicTo_x3">x3</a>, <a href="#SkPath_cubicTo_y3">y3</a>)
+Appends <a href="#SkPath_kMove_Verb">kMove Verb</a> to <a href="#Verb_Array">Verb Array</a> and (0, 0) to <a href="#Point_Array">Point Array</a>, if needed;
+then appends <a href="#SkPath_kCubic_Verb">kCubic Verb</a> to <a href="#Verb_Array">Verb Array</a>; and (<a href="#SkPath_cubicTo_x1">x1</a>, <a href="#SkPath_cubicTo_y1">y1</a>), (<a href="#SkPath_cubicTo_x2">x2</a>, <a href="#SkPath_cubicTo_y2">y2</a>), (<a href="#SkPath_cubicTo_x3">x3</a>, <a href="#SkPath_cubicTo_y3">y3</a>)
to <a href="#Point_Array">Point Array</a>.
### Parameters
<table> <tr> <td><a name="SkPath_cubicTo_x1"> <code><strong>x1 </strong></code> </a></td> <td>
-first control <a href="undocumented#Point">Point</a> of <a href="#Cubic">Cubic</a> in x.</td>
+first control <a href="undocumented#Point">Point</a> of <a href="#Cubic">Cubic</a> in x</td>
</tr> <tr> <td><a name="SkPath_cubicTo_y1"> <code><strong>y1 </strong></code> </a></td> <td>
-first control <a href="undocumented#Point">Point</a> of <a href="#Cubic">Cubic</a> in y.</td>
+first control <a href="undocumented#Point">Point</a> of <a href="#Cubic">Cubic</a> in y</td>
</tr> <tr> <td><a name="SkPath_cubicTo_x2"> <code><strong>x2 </strong></code> </a></td> <td>
-second control <a href="undocumented#Point">Point</a> of <a href="#Cubic">Cubic</a> in x.</td>
+second control <a href="undocumented#Point">Point</a> of <a href="#Cubic">Cubic</a> in x</td>
</tr> <tr> <td><a name="SkPath_cubicTo_y2"> <code><strong>y2 </strong></code> </a></td> <td>
-second control <a href="undocumented#Point">Point</a> of <a href="#Cubic">Cubic</a> in y.</td>
+second control <a href="undocumented#Point">Point</a> of <a href="#Cubic">Cubic</a> in y</td>
</tr> <tr> <td><a name="SkPath_cubicTo_x3"> <code><strong>x3 </strong></code> </a></td> <td>
-end <a href="undocumented#Point">Point</a> of <a href="#Cubic">Cubic</a> in x.</td>
+end <a href="undocumented#Point">Point</a> of <a href="#Cubic">Cubic</a> in x</td>
</tr> <tr> <td><a name="SkPath_cubicTo_y3"> <code><strong>y3 </strong></code> </a></td> <td>
-end <a href="undocumented#Point">Point</a> of <a href="#Cubic">Cubic</a> in y.</td>
+end <a href="undocumented#Point">Point</a> of <a href="#Cubic">Cubic</a> in y</td>
</tr>
</table>
@@ -2493,18 +2526,18 @@ Adds <a href="#Cubic">Cubic</a> from <a href="#Last_Point">Last Point</a> toward
<a href="undocumented#Point">Point</a> <a href="#SkPath_cubicTo_2_p3">p3</a>. If <a href="#Path">Path</a> is empty, or last <a href="#SkPath_Verb">Verb</a> is <a href="#SkPath_kClose_Verb">kClose Verb</a>, <a href="#Last_Point">Last Point</a> is set to
(0, 0) before adding <a href="#Cubic">Cubic</a>.
-<a href="#SkPath_cubicTo">cubicTo</a> appends <a href="#SkPath_kMove_Verb">kMove Verb</a> to <a href="#Verb_Array">Verb Array</a> and (0, 0) to <a href="#Point_Array">Point Array</a>, if needed.
-<a href="#SkPath_cubicTo">cubicTo</a> then appends <a href="#SkPath_kCubic_Verb">kCubic Verb</a> to <a href="#Verb_Array">Verb Array</a>; and <a href="#Point">Points</a> <a href="#SkPath_cubicTo_2_p1">p1</a>, <a href="#SkPath_cubicTo_2_p2">p2</a>, <a href="#SkPath_cubicTo_2_p3">p3</a>
+Appends <a href="#SkPath_kMove_Verb">kMove Verb</a> to <a href="#Verb_Array">Verb Array</a> and (0, 0) to <a href="#Point_Array">Point Array</a>, if needed;
+then appends <a href="#SkPath_kCubic_Verb">kCubic Verb</a> to <a href="#Verb_Array">Verb Array</a>; and <a href="#Point">Points</a> <a href="#SkPath_cubicTo_2_p1">p1</a>, <a href="#SkPath_cubicTo_2_p2">p2</a>, <a href="#SkPath_cubicTo_2_p3">p3</a>
to <a href="#Point_Array">Point Array</a>.
### Parameters
<table> <tr> <td><a name="SkPath_cubicTo_2_p1"> <code><strong>p1 </strong></code> </a></td> <td>
-first control <a href="undocumented#Point">Point</a> of <a href="#Cubic">Cubic</a>.</td>
+first control <a href="undocumented#Point">Point</a> of <a href="#Cubic">Cubic</a></td>
</tr> <tr> <td><a name="SkPath_cubicTo_2_p2"> <code><strong>p2 </strong></code> </a></td> <td>
-second control <a href="undocumented#Point">Point</a> of <a href="#Cubic">Cubic</a>.</td>
+second control <a href="undocumented#Point">Point</a> of <a href="#Cubic">Cubic</a></td>
</tr> <tr> <td><a name="SkPath_cubicTo_2_p3"> <code><strong>p3 </strong></code> </a></td> <td>
-end <a href="undocumented#Point">Point</a> of <a href="#Cubic">Cubic</a>.</td>
+end <a href="undocumented#Point">Point</a> of <a href="#Cubic">Cubic</a></td>
</tr>
</table>
@@ -2531,27 +2564,27 @@ Adds <a href="#Cubic">Cubic</a> from <a href="#Last_Point">Last Point</a> toward
If <a href="#Path">Path</a> is empty, or last <a href="#SkPath_Verb">Verb</a>
is <a href="#SkPath_kClose_Verb">kClose Verb</a>, <a href="#Last_Point">Last Point</a> is set to (0, 0) before adding <a href="#Cubic">Cubic</a>.
-<a href="#SkPath_rCubicTo">rCubicTo</a> first appends <a href="#SkPath_kMove_Verb">kMove Verb</a> to <a href="#Verb_Array">Verb Array</a> and (0, 0) to <a href="#Point_Array">Point Array</a>,
-if needed. <a href="#SkPath_rCubicTo">rCubicTo</a> then appends <a href="#SkPath_kCubic_Verb">kCubic Verb</a> to <a href="#Verb_Array">Verb Array</a>; and appends <a href="#Cubic">Cubic</a>
+Appends <a href="#SkPath_kMove_Verb">kMove Verb</a> to <a href="#Verb_Array">Verb Array</a> and (0, 0) to <a href="#Point_Array">Point Array</a>,
+if needed; then appends <a href="#SkPath_kCubic_Verb">kCubic Verb</a> to <a href="#Verb_Array">Verb Array</a>; and appends <a href="#Cubic">Cubic</a>
control and <a href="#Cubic">Cubic</a> end to <a href="#Point_Array">Point Array</a>.
<a href="#Cubic">Cubic</a> control is <a href="#Last_Point">Last Point</a> plus <a href="undocumented#Vector">Vector</a> (dx1, dy1).
<a href="#Cubic">Cubic</a> end is <a href="#Last_Point">Last Point</a> plus <a href="undocumented#Vector">Vector</a> (dx2, dy2).
-<a href="#SkPath_rCubicTo">rCubicTo</a> stands for relative cubic to.
+Function name stands for relative cubic to.
### Parameters
<table> <tr> <td><a name="SkPath_rCubicTo_x1"> <code><strong>x1 </strong></code> </a></td> <td>
-offset from <a href="#Last_Point">Last Point</a> x to first <a href="#Cubic">Cubic</a> control x.</td>
+<a href="#SkPath_offset">offset</a> from <a href="#Last_Point">Last Point</a> x to first <a href="#Cubic">Cubic</a> control x</td>
</tr> <tr> <td><a name="SkPath_rCubicTo_y1"> <code><strong>y1 </strong></code> </a></td> <td>
-offset from <a href="#Last_Point">Last Point</a> x to first <a href="#Cubic">Cubic</a> control y.</td>
+<a href="#SkPath_offset">offset</a> from <a href="#Last_Point">Last Point</a> x to first <a href="#Cubic">Cubic</a> control y</td>
</tr> <tr> <td><a name="SkPath_rCubicTo_x2"> <code><strong>x2 </strong></code> </a></td> <td>
-offset from <a href="#Last_Point">Last Point</a> x to second <a href="#Cubic">Cubic</a> control x.</td>
+<a href="#SkPath_offset">offset</a> from <a href="#Last_Point">Last Point</a> x to second <a href="#Cubic">Cubic</a> control x</td>
</tr> <tr> <td><a name="SkPath_rCubicTo_y2"> <code><strong>y2 </strong></code> </a></td> <td>
-offset from <a href="#Last_Point">Last Point</a> x to second <a href="#Cubic">Cubic</a> control y.</td>
+<a href="#SkPath_offset">offset</a> from <a href="#Last_Point">Last Point</a> x to second <a href="#Cubic">Cubic</a> control y</td>
</tr> <tr> <td><a name="SkPath_rCubicTo_x3"> <code><strong>x3 </strong></code> </a></td> <td>
-offset from <a href="#Last_Point">Last Point</a> x to <a href="#Cubic">Cubic</a> end x.</td>
+<a href="#SkPath_offset">offset</a> from <a href="#Last_Point">Last Point</a> x to <a href="#Cubic">Cubic</a> end x</td>
</tr> <tr> <td><a name="SkPath_rCubicTo_y3"> <code><strong>y3 </strong></code> </a></td> <td>
-offset from <a href="#Last_Point">Last Point</a> x to <a href="#Cubic">Cubic</a> end y.</td>
+<a href="#SkPath_offset">offset</a> from <a href="#Last_Point">Last Point</a> x to <a href="#Cubic">Cubic</a> end y</td>
</tr>
</table>
@@ -2638,13 +2671,13 @@ of <a href="#Arc">Arc</a>. Angles greater than -360 and less than 360 are treate
### Parameters
<table> <tr> <td><a name="SkPath_arcTo_oval"> <code><strong>oval </strong></code> </a></td> <td>
-bounds of ellipse containing <a href="#Arc">Arc</a>.</td>
+bounds of ellipse containing <a href="#Arc">Arc</a></td>
</tr> <tr> <td><a name="SkPath_arcTo_startAngle"> <code><strong>startAngle </strong></code> </a></td> <td>
-starting angle of <a href="#Arc">Arc</a> in degrees.</td>
+starting angle of <a href="#Arc">Arc</a> in degrees</td>
</tr> <tr> <td><a name="SkPath_arcTo_sweepAngle"> <code><strong>sweepAngle </strong></code> </a></td> <td>
-sweep, in degrees. Positive is clockwise; treated modulo 360.</td>
+sweep, in degrees. Positive is clockwise; treated modulo 360</td>
</tr> <tr> <td><a name="SkPath_arcTo_forceMoveTo"> <code><strong>forceMoveTo </strong></code> </a></td> <td>
-true to start a new contour with <a href="#Arc">Arc</a>.</td>
+true to start a new contour with <a href="#Arc">Arc</a></td>
</tr>
</table>
@@ -2688,15 +2721,15 @@ tangents are nearly parallel, <a href="#SkPath_arcTo">arcTo</a> appends <a href=
### Parameters
<table> <tr> <td><a name="SkPath_arcTo_2_x1"> <code><strong>x1 </strong></code> </a></td> <td>
-x common to pair of tangents.</td>
+x common to pair of tangents</td>
</tr> <tr> <td><a name="SkPath_arcTo_2_y1"> <code><strong>y1 </strong></code> </a></td> <td>
-y common to pair of tangents.</td>
+y common to pair of tangents</td>
</tr> <tr> <td><a name="SkPath_arcTo_2_x2"> <code><strong>x2 </strong></code> </a></td> <td>
-x end of second tangent.</td>
+x end of second tangent</td>
</tr> <tr> <td><a name="SkPath_arcTo_2_y2"> <code><strong>y2 </strong></code> </a></td> <td>
-y end of second tangent.</td>
+y end of second tangent</td>
</tr> <tr> <td><a name="SkPath_arcTo_2_radius"> <code><strong>radius </strong></code> </a></td> <td>
-distance from <a href="#Arc">Arc</a> to <a href="undocumented#Circle">Circle</a> center.</td>
+distance from <a href="#Arc">Arc</a> to <a href="undocumented#Circle">Circle</a> center</td>
</tr>
</table>
@@ -2741,11 +2774,11 @@ tangents are nearly parallel, <a href="#SkPath_arcTo">arcTo</a> appends <a href=
### Parameters
<table> <tr> <td><a name="SkPath_arcTo_3_p1"> <code><strong>p1 </strong></code> </a></td> <td>
-<a href="undocumented#Point">Point</a> common to pair of tangents.</td>
+<a href="undocumented#Point">Point</a> common to pair of tangents</td>
</tr> <tr> <td><a name="SkPath_arcTo_3_p2"> <code><strong>p2 </strong></code> </a></td> <td>
-end of second tangent.</td>
+end of second tangent</td>
</tr> <tr> <td><a name="SkPath_arcTo_3_radius"> <code><strong>radius </strong></code> </a></td> <td>
-distance from <a href="#Arc">Arc</a> to <a href="undocumented#Circle">Circle</a> center.</td>
+distance from <a href="#Arc">Arc</a> to <a href="undocumented#Circle">Circle</a> center</td>
</tr>
</table>
@@ -2773,8 +2806,8 @@ line (156,20),(200,20)
<pre style="padding: 1em 1em 1em 1em;width: 44em; background-color: #f0f0f0">
enum <a href="#SkPath_ArcSize">ArcSize</a> {
-<a href="#SkPath_kSmall_ArcSize">kSmall ArcSize</a>
-<a href="#SkPath_kLarge_ArcSize">kLarge ArcSize</a>
+<a href="#SkPath_kSmall_ArcSize">kSmall ArcSize</a>,
+<a href="#SkPath_kLarge_ArcSize">kLarge ArcSize</a>,
};</pre>
Four <a href="undocumented#Oval">Oval</a> parts with radii (rx, ry) start at last <a href="#Path">Path</a> <a href="undocumented#Point">Point</a> and ends at (x, y).
@@ -2822,19 +2855,19 @@ cast to int is zero.
### Parameters
<table> <tr> <td><a name="SkPath_arcTo_4_rx"> <code><strong>rx </strong></code> </a></td> <td>
-radius in <a href="#SkPath_arcTo_4_x">x</a> before x-axis rotation.</td>
+radius in <a href="#SkPath_arcTo_4_x">x</a> before x-axis rotation</td>
</tr> <tr> <td><a name="SkPath_arcTo_4_ry"> <code><strong>ry </strong></code> </a></td> <td>
-radius in <a href="#SkPath_arcTo_4_y">y</a> before x-axis rotation.</td>
+radius in <a href="#SkPath_arcTo_4_y">y</a> before x-axis rotation</td>
</tr> <tr> <td><a name="SkPath_arcTo_4_xAxisRotate"> <code><strong>xAxisRotate </strong></code> </a></td> <td>
-x-axis rotation in degrees; positve values are clockwise.</td>
+x-axis rotation in degrees; positve values are clockwise</td>
</tr> <tr> <td><a name="SkPath_arcTo_4_largeArc"> <code><strong>largeArc </strong></code> </a></td> <td>
-chooses smaller or larger <a href="#Arc">Arc</a>.</td>
+chooses smaller or larger <a href="#Arc">Arc</a></td>
</tr> <tr> <td><a name="SkPath_arcTo_4_sweep"> <code><strong>sweep </strong></code> </a></td> <td>
-chooses clockwise or counterclockwise <a href="#Arc">Arc</a>.</td>
+chooses clockwise or counterclockwise <a href="#Arc">Arc</a></td>
</tr> <tr> <td><a name="SkPath_arcTo_4_x"> <code><strong>x </strong></code> </a></td> <td>
-end of <a href="#Arc">Arc</a>.</td>
+end of <a href="#Arc">Arc</a></td>
</tr> <tr> <td><a name="SkPath_arcTo_4_y"> <code><strong>y </strong></code> </a></td> <td>
-end of <a href="#Arc">Arc</a>.</td>
+end of <a href="#Arc">Arc</a></td>
</tr>
</table>
@@ -2870,15 +2903,15 @@ cast to int is zero.
### Parameters
<table> <tr> <td><a name="SkPath_arcTo_5_r"> <code><strong>r </strong></code> </a></td> <td>
-radii in x and y before x-axis rotation.</td>
+radii in x and y before x-axis rotation</td>
</tr> <tr> <td><a name="SkPath_arcTo_5_xAxisRotate"> <code><strong>xAxisRotate </strong></code> </a></td> <td>
-x-axis rotation in degrees; positve values are clockwise.</td>
+x-axis rotation in degrees; positve values are clockwise</td>
</tr> <tr> <td><a name="SkPath_arcTo_5_largeArc"> <code><strong>largeArc </strong></code> </a></td> <td>
-chooses smaller or larger <a href="#Arc">Arc</a>.</td>
+chooses smaller or larger <a href="#Arc">Arc</a></td>
</tr> <tr> <td><a name="SkPath_arcTo_5_sweep"> <code><strong>sweep </strong></code> </a></td> <td>
-chooses clockwise or counterclockwise <a href="#Arc">Arc</a>.</td>
+chooses clockwise or counterclockwise <a href="#Arc">Arc</a></td>
</tr> <tr> <td><a name="SkPath_arcTo_5_xy"> <code><strong>xy </strong></code> </a></td> <td>
-end of <a href="#Arc">Arc</a>.</td>
+end of <a href="#Arc">Arc</a></td>
</tr>
</table>
@@ -2902,8 +2935,8 @@ void rArcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,
Append <a href="#Arc">Arc</a> to <a href="#Path">Path</a>, relative to last <a href="#Path">Path</a> <a href="undocumented#Point">Point</a>. <a href="#Arc">Arc</a> is implemented by one or
more <a href="#Conic">Conic</a>, weighted to describe part of <a href="undocumented#Oval">Oval</a> with radii (r.fX, r.fY) rotated by
-<a href="#SkPath_rArcTo_xAxisRotate">xAxisRotate</a> degrees. <a href="#Arc">Arc</a> curves from last <a href="#Path">Path</a> <a href="undocumented#Point">Point</a> (x0, y0) to
-(x0 + <a href="#SkPath_rArcTo_dx">dx</a>, y0 + <a href="#SkPath_rArcTo_dy">dy</a>), choosing one of four possible routes: clockwise or
+<a href="#SkPath_rArcTo_xAxisRotate">xAxisRotate</a> degrees. <a href="#Arc">Arc</a> curves from last <a href="#Path">Path</a> <a href="undocumented#Point">Point</a> (x0, y0) to(x0 + <a href="#SkPath_rArcTo_dx">dx</a>, y0 + <a href="#SkPath_rArcTo_dy">dy</a>),
+choosing one of four possible routes: clockwise or
counterclockwise, and smaller or larger. If <a href="#Path">Path</a> is empty, the start <a href="#Arc">Arc</a> <a href="undocumented#Point">Point</a>
is (0, 0).
@@ -2919,19 +2952,19 @@ opposite the integer value of <a href="#SkPath_rArcTo_sweep">sweep</a>; <a href=
### Parameters
<table> <tr> <td><a name="SkPath_rArcTo_rx"> <code><strong>rx </strong></code> </a></td> <td>
-radius in x before x-axis rotation.</td>
+radius in x before x-axis rotation</td>
</tr> <tr> <td><a name="SkPath_rArcTo_ry"> <code><strong>ry </strong></code> </a></td> <td>
-radius in y before x-axis rotation.</td>
+radius in y before x-axis rotation</td>
</tr> <tr> <td><a name="SkPath_rArcTo_xAxisRotate"> <code><strong>xAxisRotate </strong></code> </a></td> <td>
-x-axis rotation in degrees; positve values are clockwise.</td>
+x-axis rotation in degrees; positve values are clockwise</td>
</tr> <tr> <td><a name="SkPath_rArcTo_largeArc"> <code><strong>largeArc </strong></code> </a></td> <td>
-chooses smaller or larger <a href="#Arc">Arc</a>.</td>
+chooses smaller or larger <a href="#Arc">Arc</a></td>
</tr> <tr> <td><a name="SkPath_rArcTo_sweep"> <code><strong>sweep </strong></code> </a></td> <td>
-chooses clockwise or counterclockwise <a href="#Arc">Arc</a>.</td>
+chooses clockwise or counterclockwise <a href="#Arc">Arc</a></td>
</tr> <tr> <td><a name="SkPath_rArcTo_dx"> <code><strong>dx </strong></code> </a></td> <td>
-x offset end of <a href="#Arc">Arc</a> from last <a href="#Path">Path</a> <a href="undocumented#Point">Point</a>.</td>
+x <a href="#SkPath_offset">offset</a> end of <a href="#Arc">Arc</a> from last <a href="#Path">Path</a> <a href="undocumented#Point">Point</a></td>
</tr> <tr> <td><a name="SkPath_rArcTo_dy"> <code><strong>dy </strong></code> </a></td> <td>
-y offset end of <a href="#Arc">Arc</a> from last <a href="#Path">Path</a> <a href="undocumented#Point">Point</a>.</td>
+y <a href="#SkPath_offset">offset</a> end of <a href="#Arc">Arc</a> from last <a href="#Path">Path</a> <a href="undocumented#Point">Point</a></td>
</tr>
</table>
@@ -2989,13 +3022,13 @@ of its geometric bounds.
<table> <tr> <td><a name="SkPath_IsInverseFillType_fill"> <code><strong>fill </strong></code> </a></td> <td>
one of: <a href="#SkPath_kWinding_FillType">kWinding FillType</a>, <a href="#SkPath_kEvenOdd_FillType">kEvenOdd FillType</a>,
-<a href="#SkPath_kInverseWinding_FillType">kInverseWinding FillType</a>, <a href="#SkPath_kInverseEvenOdd_FillType">kInverseEvenOdd FillType</a>.</td>
+<a href="#SkPath_kInverseWinding_FillType">kInverseWinding FillType</a>, <a href="#SkPath_kInverseEvenOdd_FillType">kInverseEvenOdd FillType</a></td>
</tr>
</table>
### Return Value
-true if <a href="#Path">Path</a> fills outside its bounds.
+true if <a href="#Path">Path</a> fills outside its bounds
### Example
@@ -3039,13 +3072,13 @@ Returns equivalent <a href="#Fill_Type">Fill Type</a> representing <a href="#Pat
<table> <tr> <td><a name="SkPath_ConvertToNonInverseFillType_fill"> <code><strong>fill </strong></code> </a></td> <td>
one of: <a href="#SkPath_kWinding_FillType">kWinding FillType</a>, <a href="#SkPath_kEvenOdd_FillType">kEvenOdd FillType</a>,
-<a href="#SkPath_kInverseWinding_FillType">kInverseWinding FillType</a>, <a href="#SkPath_kInverseEvenOdd_FillType">kInverseEvenOdd FillType</a>.</td>
+<a href="#SkPath_kInverseWinding_FillType">kInverseWinding FillType</a>, <a href="#SkPath_kInverseEvenOdd_FillType">kInverseEvenOdd FillType</a></td>
</tr>
</table>
### Return Value
-<a href="#SkPath_ConvertToNonInverseFillType_fill">fill</a>, or <a href="#SkPath_kWinding_FillType">kWinding FillType</a> or <a href="#SkPath_kEvenOdd_FillType">kEvenOdd FillType</a> if <a href="#SkPath_ConvertToNonInverseFillType_fill">fill</a> is inverted.
+<a href="#SkPath_ConvertToNonInverseFillType_fill">fill</a>, or <a href="#SkPath_kWinding_FillType">kWinding FillType</a> or <a href="#SkPath_kEvenOdd_FillType">kEvenOdd FillType</a> if <a href="#SkPath_ConvertToNonInverseFillType_fill">fill</a> is inverted
### Example
@@ -3095,23 +3128,23 @@ of up to 90 degrees; in this case, set <a href="#SkPath_ConvertConicToQuads_pow2
### Parameters
<table> <tr> <td><a name="SkPath_ConvertConicToQuads_p0"> <code><strong>p0 </strong></code> </a></td> <td>
-<a href="#Conic">Conic</a> start <a href="undocumented#Point">Point</a>.</td>
+<a href="#Conic">Conic</a> start <a href="undocumented#Point">Point</a></td>
</tr> <tr> <td><a name="SkPath_ConvertConicToQuads_p1"> <code><strong>p1 </strong></code> </a></td> <td>
-<a href="#Conic">Conic</a> control <a href="undocumented#Point">Point</a>.</td>
+<a href="#Conic">Conic</a> control <a href="undocumented#Point">Point</a></td>
</tr> <tr> <td><a name="SkPath_ConvertConicToQuads_p2"> <code><strong>p2 </strong></code> </a></td> <td>
-<a href="#Conic">Conic</a> end <a href="undocumented#Point">Point</a>.</td>
+<a href="#Conic">Conic</a> end <a href="undocumented#Point">Point</a></td>
</tr> <tr> <td><a name="SkPath_ConvertConicToQuads_w"> <code><strong>w </strong></code> </a></td> <td>
-<a href="#Conic">Conic</a> weight.</td>
+<a href="#Conic">Conic</a> weight</td>
</tr> <tr> <td><a name="SkPath_ConvertConicToQuads_pts"> <code><strong>pts </strong></code> </a></td> <td>
-storage for <a href="#Quad">Quad</a> array.</td>
+storage for <a href="#Quad">Quad</a> array</td>
</tr> <tr> <td><a name="SkPath_ConvertConicToQuads_pow2"> <code><strong>pow2 </strong></code> </a></td> <td>
-<a href="#Quad">Quad</a> count, as power of two, normally 0 to 5 (1 to 32 <a href="#Quad">Quad</a> curves).</td>
+<a href="#Quad">Quad</a> count, as power of two, normally 0 to 5 (1 to 32 <a href="#Quad">Quad</a> curves)</td>
</tr>
</table>
### Return Value
-Number of <a href="#Quad">Quad</a> curves written to <a href="#SkPath_ConvertConicToQuads_pts">pts</a>.
+Number of <a href="#Quad">Quad</a> curves written to <a href="#SkPath_ConvertConicToQuads_pts">pts</a>
### Example
@@ -3129,12 +3162,13 @@ be drawn exactly with a single <a href="#Quad">Quad</a>.</div></fiddle-embed></d
## isRect
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
-bool isRect(SkRect* rect, bool* isClosed = NULL, Direction* direction = NULL) const
+bool isRect(SkRect* rect, bool* isClosed = nullptr,
+ Direction* direction = nullptr) const
</pre>
Returns true if <a href="#Path">Path</a> is eqivalent to <a href="undocumented#Rect">Rect</a> when filled.
-If <a href="#SkPath_isRect">isRect</a> returns false: <a href="#SkPath_isRect_rect">rect</a>, <a href="#SkPath_isRect_isClosed">isClosed</a>, and <a href="#SkPath_isRect_direction">direction</a> are unchanged.
-If <a href="#SkPath_isRect">isRect</a> returns true: <a href="#SkPath_isRect_rect">rect</a>, <a href="#SkPath_isRect_isClosed">isClosed</a>, and <a href="#SkPath_isRect_direction">direction</a> are written to if not nullptr.
+If false: <a href="#SkPath_isRect_rect">rect</a>, <a href="#SkPath_isRect_isClosed">isClosed</a>, and <a href="#SkPath_isRect_direction">direction</a> are unchanged.
+If true: <a href="#SkPath_isRect_rect">rect</a>, <a href="#SkPath_isRect_isClosed">isClosed</a>, and <a href="#SkPath_isRect_direction">direction</a> are written to if not nullptr.
<a href="#SkPath_isRect_rect">rect</a> may be smaller than the <a href="#Path">Path</a> bounds. <a href="#Path">Path</a> bounds may include <a href="#SkPath_kMove_Verb">kMove Verb</a> points
that do not alter the area drawn by the returned <a href="#SkPath_isRect_rect">rect</a>.
@@ -3142,17 +3176,17 @@ that do not alter the area drawn by the returned <a href="#SkPath_isRect_rect">r
### Parameters
<table> <tr> <td><a name="SkPath_isRect_rect"> <code><strong>rect </strong></code> </a></td> <td>
-storage for bounds of <a href="undocumented#Rect">Rect</a>; may be nullptr.</td>
+storage for bounds of <a href="undocumented#Rect">Rect</a>; may be nullptr</td>
</tr> <tr> <td><a name="SkPath_isRect_isClosed"> <code><strong>isClosed </strong></code> </a></td> <td>
storage set to true if <a href="#Path">Path</a> is closed; may be nullptr</td>
</tr> <tr> <td><a name="SkPath_isRect_direction"> <code><strong>direction </strong></code> </a></td> <td>
-storage set to <a href="undocumented#Rect">Rect</a> <a href="#SkPath_isRect_direction">direction</a>; may be nullptr.</td>
+storage set to <a href="undocumented#Rect">Rect</a> <a href="#SkPath_isRect_direction">direction</a>; may be nullptr</td>
</tr>
</table>
### Return Value
-true if <a href="#Path">Path</a> contains <a href="undocumented#Rect">Rect</a>.
+true if <a href="#Path">Path</a> <a href="#SkPath_contains">contains</a> <a href="undocumented#Rect">Rect</a>
### Example
@@ -3182,12 +3216,12 @@ addPoly is rect (0, 0, 80, 80); is not closed; direction CCW
## isNestedFillRects
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
-bool isNestedFillRects(SkRect rect[2], Direction dirs[2] = NULL) const
+bool isNestedFillRects(SkRect rect[2], Direction dirs[2] = nullptr) const
</pre>
Returns true if <a href="#Path">Path</a> is equivalent to nested <a href="undocumented#Rect">Rect</a> pair when filled.
-If <a href="#SkPath_isNestedFillRects">isNestedFillRects</a> returns false, <a href="#SkPath_isNestedFillRects_rect">rect</a> and <a href="#SkPath_isNestedFillRects_dirs">dirs</a> are unchanged.
-If <a href="#SkPath_isNestedFillRects">isNestedFillRects</a> returns true, <a href="#SkPath_isNestedFillRects_rect">rect</a> and <a href="#SkPath_isNestedFillRects_dirs">dirs</a> are written to if not nullptr:
+If false, <a href="#SkPath_isNestedFillRects_rect">rect</a> and <a href="#SkPath_isNestedFillRects_dirs">dirs</a> are unchanged.
+If true, <a href="#SkPath_isNestedFillRects_rect">rect</a> and <a href="#SkPath_isNestedFillRects_dirs">dirs</a> are written to if not nullptr:
setting <a href="#SkPath_isNestedFillRects_rect">rect</a>[0] to outer <a href="undocumented#Rect">Rect</a>, and <a href="#SkPath_isNestedFillRects_rect">rect</a>[1] to inner <a href="undocumented#Rect">Rect</a>;
setting <a href="#SkPath_isNestedFillRects_dirs">dirs</a>[0] to <a href="#SkPath_Direction">Direction</a> of outer <a href="undocumented#Rect">Rect</a>, and <a href="#SkPath_isNestedFillRects_dirs">dirs</a>[1] to <a href="#SkPath_Direction">Direction</a> of inner
<a href="undocumented#Rect">Rect</a>.
@@ -3195,15 +3229,15 @@ setting <a href="#SkPath_isNestedFillRects_dirs">dirs</a>[0] to <a href="#SkPath
### Parameters
<table> <tr> <td><a name="SkPath_isNestedFillRects_rect"> <code><strong>rect </strong></code> </a></td> <td>
-storage for <a href="undocumented#Rect">Rect</a> pair; may be nullptr.</td>
+storage for <a href="undocumented#Rect">Rect</a> pair; may be nullptr</td>
</tr> <tr> <td><a name="SkPath_isNestedFillRects_dirs"> <code><strong>dirs </strong></code> </a></td> <td>
-storage for <a href="#SkPath_Direction">Direction</a> pair; may be nullptr.</td>
+storage for <a href="#SkPath_Direction">Direction</a> pair; may be nullptr</td>
</tr>
</table>
### Return Value
-true if <a href="#Path">Path</a> contains nested <a href="undocumented#Rect">Rect</a> pair.
+true if <a href="#Path">Path</a> <a href="#SkPath_contains">contains</a> nested <a href="undocumented#Rect">Rect</a> pair
### Example
@@ -3239,9 +3273,9 @@ bottom-right, and top-right if <a href="#SkPath_addRect_dir">dir</a> is <a href=
### Parameters
<table> <tr> <td><a name="SkPath_addRect_rect"> <code><strong>rect </strong></code> </a></td> <td>
-<a href="undocumented#Rect">Rect</a> to add as a closed contour.</td>
+<a href="undocumented#Rect">Rect</a> to add as a closed contour</td>
</tr> <tr> <td><a name="SkPath_addRect_dir"> <code><strong>dir </strong></code> </a></td> <td>
-<a href="#SkPath_Direction">Direction</a> to wind added contour.</td>
+<a href="#SkPath_Direction">Direction</a> to wind added contour</td>
</tr>
</table>
@@ -3275,11 +3309,11 @@ If <a href="#SkPath_addRect_2_dir">dir</a> is <a href="#SkPath_kCW_Direction">kC
### Parameters
<table> <tr> <td><a name="SkPath_addRect_2_rect"> <code><strong>rect </strong></code> </a></td> <td>
-<a href="undocumented#Rect">Rect</a> to add as a closed contour.</td>
+<a href="undocumented#Rect">Rect</a> to add as a closed contour</td>
</tr> <tr> <td><a name="SkPath_addRect_2_dir"> <code><strong>dir </strong></code> </a></td> <td>
-<a href="#SkPath_Direction">Direction</a> to wind added contour.</td>
+<a href="#SkPath_Direction">Direction</a> to wind added contour</td>
</tr> <tr> <td><a name="SkPath_addRect_2_start"> <code><strong>start </strong></code> </a></td> <td>
-Initial corner of <a href="undocumented#Rect">Rect</a> to add.</td>
+Initial corner of <a href="undocumented#Rect">Rect</a> to add</td>
</tr>
</table>
@@ -3308,15 +3342,15 @@ bottom-right, and top-right if <a href="#SkPath_addRect_3_dir">dir</a> is <a hre
### Parameters
<table> <tr> <td><a name="SkPath_addRect_3_left"> <code><strong>left </strong></code> </a></td> <td>
-smaller x of <a href="undocumented#Rect">Rect</a>.</td>
+smaller x of <a href="undocumented#Rect">Rect</a></td>
</tr> <tr> <td><a name="SkPath_addRect_3_top"> <code><strong>top </strong></code> </a></td> <td>
-smaller y of <a href="undocumented#Rect">Rect</a>.</td>
+smaller y of <a href="undocumented#Rect">Rect</a></td>
</tr> <tr> <td><a name="SkPath_addRect_3_right"> <code><strong>right </strong></code> </a></td> <td>
-larger x of <a href="undocumented#Rect">Rect</a>.</td>
+larger x of <a href="undocumented#Rect">Rect</a></td>
</tr> <tr> <td><a name="SkPath_addRect_3_bottom"> <code><strong>bottom </strong></code> </a></td> <td>
-larger y of <a href="undocumented#Rect">Rect</a>.</td>
+larger y of <a href="undocumented#Rect">Rect</a></td>
</tr> <tr> <td><a name="SkPath_addRect_3_dir"> <code><strong>dir </strong></code> </a></td> <td>
-<a href="#SkPath_Direction">Direction</a> to wind added contour.</td>
+<a href="#SkPath_Direction">Direction</a> to wind added contour</td>
</tr>
</table>
@@ -3348,9 +3382,9 @@ This form is identical to
### Parameters
<table> <tr> <td><a name="SkPath_addOval_oval"> <code><strong>oval </strong></code> </a></td> <td>
-bounds of ellipse added.</td>
+bounds of ellipse added</td>
</tr> <tr> <td><a name="SkPath_addOval_dir"> <code><strong>dir </strong></code> </a></td> <td>
-<a href="#SkPath_Direction">Direction</a> to wind ellipse.</td>
+<a href="#SkPath_Direction">Direction</a> to wind ellipse</td>
</tr>
</table>
@@ -3383,11 +3417,11 @@ clockwise if <a href="#SkPath_addOval_2_dir">dir</a> is <a href="#SkPath_kCW_Dir
### Parameters
<table> <tr> <td><a name="SkPath_addOval_2_oval"> <code><strong>oval </strong></code> </a></td> <td>
-bounds of ellipse added.</td>
+bounds of ellipse added</td>
</tr> <tr> <td><a name="SkPath_addOval_2_dir"> <code><strong>dir </strong></code> </a></td> <td>
-<a href="#SkPath_Direction">Direction</a> to wind ellipse.</td>
+<a href="#SkPath_Direction">Direction</a> to wind ellipse</td>
</tr> <tr> <td><a name="SkPath_addOval_2_start"> <code><strong>start </strong></code> </a></td> <td>
-index of initial point of ellipse.</td>
+index of initial point of ellipse</td>
</tr>
</table>
@@ -3410,8 +3444,7 @@ void addCircle(SkScalar x, SkScalar y, SkScalar radius,
</pre>
Add <a href="undocumented#Circle">Circle</a> centered at (<a href="#SkPath_addCircle_x">x</a>, <a href="#SkPath_addCircle_y">y</a>) of size <a href="#SkPath_addCircle_radius">radius</a> to <a href="#Path">Path</a>, appending <a href="#SkPath_kMove_Verb">kMove Verb</a>,
-four <a href="#SkPath_kConic_Verb">kConic Verb</a>, and <a href="#SkPath_kClose_Verb">kClose Verb</a>. <a href="undocumented#Circle">Circle</a> begins at (<a href="#SkPath_addCircle_x">x</a> + <a href="#SkPath_addCircle_radius">radius</a>, <a href="#SkPath_addCircle_y">y</a>) and
-continues clockwise if <a href="#SkPath_addCircle_dir">dir</a> is <a href="#SkPath_kCW_Direction">kCW Direction</a>, counterclockwise if <a href="#SkPath_addCircle_dir">dir</a> is
+four <a href="#SkPath_kConic_Verb">kConic Verb</a>, and <a href="#SkPath_kClose_Verb">kClose Verb</a>. <a href="undocumented#Circle">Circle</a> begins at(<a href="#SkPath_addCircle_x">x</a> + <a href="#SkPath_addCircle_radius">radius</a>, <a href="#SkPath_addCircle_y">y</a>)and continues clockwise if <a href="#SkPath_addCircle_dir">dir</a> is <a href="#SkPath_kCW_Direction">kCW Direction</a>, counterclockwise if <a href="#SkPath_addCircle_dir">dir</a> is
<a href="#SkPath_kCCW_Direction">kCCW Direction</a>.
<a href="#SkPath_addCircle">addCircle</a> has no effect if <a href="#SkPath_addCircle_radius">radius</a> is zero or negative.
@@ -3419,13 +3452,13 @@ continues clockwise if <a href="#SkPath_addCircle_dir">dir</a> is <a href="#SkPa
### Parameters
<table> <tr> <td><a name="SkPath_addCircle_x"> <code><strong>x </strong></code> </a></td> <td>
-center of <a href="undocumented#Circle">Circle</a>.</td>
+center of <a href="undocumented#Circle">Circle</a></td>
</tr> <tr> <td><a name="SkPath_addCircle_y"> <code><strong>y </strong></code> </a></td> <td>
-center of <a href="undocumented#Circle">Circle</a>.</td>
+center of <a href="undocumented#Circle">Circle</a></td>
</tr> <tr> <td><a name="SkPath_addCircle_radius"> <code><strong>radius </strong></code> </a></td> <td>
-distance from center to edge.</td>
+distance from center to edge</td>
</tr> <tr> <td><a name="SkPath_addCircle_dir"> <code><strong>dir </strong></code> </a></td> <td>
-<a href="#SkPath_Direction">Direction</a> to wind <a href="undocumented#Circle">Circle</a>.</td>
+<a href="#SkPath_Direction">Direction</a> to wind <a href="undocumented#Circle">Circle</a></td>
</tr>
</table>
@@ -3458,11 +3491,11 @@ modulo 360, and <a href="#Arc">Arc</a> may or may not draw depending on numeric
### Parameters
<table> <tr> <td><a name="SkPath_addArc_oval"> <code><strong>oval </strong></code> </a></td> <td>
-bounds of ellipse containing <a href="#Arc">Arc</a>.</td>
+bounds of ellipse containing <a href="#Arc">Arc</a></td>
</tr> <tr> <td><a name="SkPath_addArc_startAngle"> <code><strong>startAngle </strong></code> </a></td> <td>
-starting angle of <a href="#Arc">Arc</a> in degrees.</td>
+starting angle of <a href="#Arc">Arc</a> in degrees</td>
</tr> <tr> <td><a name="SkPath_addArc_sweepAngle"> <code><strong>sweepAngle </strong></code> </a></td> <td>
-sweep, in degrees. Positive is clockwise; treated modulo 360.</td>
+sweep, in degrees. Positive is clockwise; treated modulo 360</td>
</tr>
</table>
@@ -3501,20 +3534,20 @@ After appending, <a href="#Path">Path</a> may be empty, or may contain: <a href=
### Parameters
<table> <tr> <td><a name="SkPath_addRoundRect_rect"> <code><strong>rect </strong></code> </a></td> <td>
-bounds of <a href="undocumented#Round_Rect">Round Rect</a>.</td>
+bounds of <a href="undocumented#Round_Rect">Round Rect</a></td>
</tr> <tr> <td><a name="SkPath_addRoundRect_rx"> <code><strong>rx </strong></code> </a></td> <td>
x-radius of rounded corners on the <a href="undocumented#Round_Rect">Round Rect</a></td>
</tr> <tr> <td><a name="SkPath_addRoundRect_ry"> <code><strong>ry </strong></code> </a></td> <td>
y-radius of rounded corners on the <a href="undocumented#Round_Rect">Round Rect</a></td>
</tr> <tr> <td><a name="SkPath_addRoundRect_dir"> <code><strong>dir </strong></code> </a></td> <td>
-<a href="#SkPath_Direction">Direction</a> to wind <a href="undocumented#Round_Rect">Round Rect</a>.</td>
+<a href="#SkPath_Direction">Direction</a> to wind <a href="undocumented#Round_Rect">Round Rect</a></td>
</tr>
</table>
### Example
-<div><fiddle-embed name="24736f685f265cf533f1700c042db353"><div>If either radius is zero, path contains <a href="undocumented#Rect">Rect</a> and is drawn red.
-If sides are only radii, path contains <a href="undocumented#Oval">Oval</a> and is drawn blue.
+<div><fiddle-embed name="24736f685f265cf533f1700c042db353"><div>If either radius is zero, path <a href="#SkPath_contains">contains</a> <a href="undocumented#Rect">Rect</a> and is drawn red.
+If sides are only radii, path <a href="#SkPath_contains">contains</a> <a href="undocumented#Oval">Oval</a> and is drawn blue.
All remaining path draws are convex, and are drawn in gray; no
paths constructed from <a href="#SkPath_addRoundRect">addRoundRect</a> are concave, so none are
drawn in green.</div></fiddle-embed></div>
@@ -3558,11 +3591,11 @@ After appending, <a href="#Path">Path</a> may be empty, or may contain: <a href=
### Parameters
<table> <tr> <td><a name="SkPath_addRoundRect_2_rect"> <code><strong>rect </strong></code> </a></td> <td>
-bounds of <a href="undocumented#Round_Rect">Round Rect</a>.</td>
+bounds of <a href="undocumented#Round_Rect">Round Rect</a></td>
</tr> <tr> <td><a name="SkPath_addRoundRect_2_radii"> <code><strong>radii </strong></code> </a></td> <td>
-array of 8 <a href="undocumented#SkScalar">SkScalar</a> values, a radius pair for each corner.</td>
+array of 8 <a href="undocumented#SkScalar">SkScalar</a> values, a radius pair for each corner</td>
</tr> <tr> <td><a name="SkPath_addRoundRect_2_dir"> <code><strong>dir </strong></code> </a></td> <td>
-<a href="#SkPath_Direction">Direction</a> to wind <a href="undocumented#Round_Rect">Round Rect</a>.</td>
+<a href="#SkPath_Direction">Direction</a> to wind <a href="undocumented#Round_Rect">Round Rect</a></td>
</tr>
</table>
@@ -3588,14 +3621,14 @@ Add <a href="#SkPath_addRRect_rrect">rrect</a> to <a href="#Path">Path</a>, crea
winds clockwise. If <a href="#SkPath_addRRect_dir">dir</a> is <a href="#SkPath_kCCW_Direction">kCCW Direction</a>, <a href="#SkPath_addRRect_rrect">rrect</a> starts at the bottom-left
of the upper-left corner and winds counterclockwise.
-After appending, <a href="#Path">Path</a> may be empty, or may contain: <a href="undocumented#Rect">Rect</a>, <a href="undocumented#Oval">Oval</a>, or RRect.
+After appending, <a href="#Path">Path</a> may be empty, or may contain: <a href="undocumented#Rect">Rect</a>, <a href="undocumented#Oval">Oval</a>, or <a href="undocumented#Round_Rect">Round Rect</a>.
### Parameters
<table> <tr> <td><a name="SkPath_addRRect_rrect"> <code><strong>rrect </strong></code> </a></td> <td>
-bounds and radii of rounded rectangle.</td>
+bounds and radii of rounded rectangle</td>
</tr> <tr> <td><a name="SkPath_addRRect_dir"> <code><strong>dir </strong></code> </a></td> <td>
-<a href="#SkPath_Direction">Direction</a> to wind <a href="undocumented#Round_Rect">Round Rect</a>.</td>
+<a href="#SkPath_Direction">Direction</a> to wind <a href="undocumented#Round_Rect">Round Rect</a></td>
</tr>
</table>
@@ -3628,16 +3661,16 @@ winds clockwise; if <a href="#SkPath_addRRect_2_dir">dir</a> is <a href="#SkPath
| 6 | top of bottom-left corner |
| 7 | bottom of top-left corner |
-After appending, <a href="#Path">Path</a> may be empty, or may contain: <a href="undocumented#Rect">Rect</a>, <a href="undocumented#Oval">Oval</a>, or RRect.
+After appending, <a href="#Path">Path</a> may be empty, or may contain: <a href="undocumented#Rect">Rect</a>, <a href="undocumented#Oval">Oval</a>, or <a href="undocumented#Round_Rect">Round Rect</a>.
### Parameters
<table> <tr> <td><a name="SkPath_addRRect_2_rrect"> <code><strong>rrect </strong></code> </a></td> <td>
-bounds and radii of rounded rectangle.</td>
+bounds and radii of rounded rectangle</td>
</tr> <tr> <td><a name="SkPath_addRRect_2_dir"> <code><strong>dir </strong></code> </a></td> <td>
-<a href="#SkPath_Direction">Direction</a> to wind RRect.</td>
+<a href="#SkPath_Direction">Direction</a> to wind <a href="undocumented#Round_Rect">Round Rect</a></td>
</tr> <tr> <td><a name="SkPath_addRRect_2_start"> <code><strong>start </strong></code> </a></td> <td>
-Index of initial point of RRect.</td>
+Index of initial point of <a href="undocumented#Round_Rect">Round Rect</a></td>
</tr>
</table>
@@ -3658,22 +3691,21 @@ Index of initial point of RRect.</td>
void addPoly(const SkPoint pts[], int count, bool close)
</pre>
-Add <a href="#Contour">Contour</a> created from <a href="undocumented#Line">Line</a> Array. Given <a href="#SkPath_addPoly_count">count</a> <a href="#SkPath_addPoly_pts">pts</a>, <a href="#SkPath_addPoly">addPoly</a> adds
-<a href="#SkPath_addPoly_count">count</a> - 1 <a href="undocumented#Line">Line</a> segments. <a href="#Contour">Contour</a> added starts at pt[0], then adds a line
-for every additional <a href="undocumented#Point">Point</a> in <a href="#SkPath_addPoly_pts">pts</a> array. If <a href="#SkPath_addPoly_close">close</a> is true, <a href="#SkPath_addPoly">addPoly</a>
+Add <a href="#Contour">Contour</a> created from <a href="undocumented#Line">Line</a> array, adding<a href="#SkPath_addPoly_count">count</a> - 1<a href="undocumented#Line">Line</a> segments. <a href="#Contour">Contour</a> added starts at pt[0], then adds a line
+for every additional <a href="undocumented#Point">Point</a> in <a href="#SkPath_addPoly_pts">pts</a> array. If <a href="#SkPath_close">close</a> is true,
appends <a href="#SkPath_kClose_Verb">kClose Verb</a> to <a href="#Path">Path</a>, connecting <a href="#SkPath_addPoly_pts">pts</a>[<a href="#SkPath_addPoly_count">count</a> - 1] and <a href="#SkPath_addPoly_pts">pts</a>[0].
If <a href="#SkPath_addPoly_count">count</a> is zero, append <a href="#SkPath_kMove_Verb">kMove Verb</a> to path.
-<a href="#SkPath_addPoly">addPoly</a> has no effect if <a href="#SkPath_addPoly_count">count</a> is less than one.
+Has no effect if <a href="#SkPath_addPoly_count">count</a> is less than one.
### Parameters
<table> <tr> <td><a name="SkPath_addPoly_pts"> <code><strong>pts </strong></code> </a></td> <td>
-Array of <a href="undocumented#Line">Line</a> sharing end and start <a href="undocumented#Point">Point</a>.</td>
+Array of <a href="undocumented#Line">Line</a> sharing end and start <a href="undocumented#Point">Point</a></td>
</tr> <tr> <td><a name="SkPath_addPoly_count"> <code><strong>count </strong></code> </a></td> <td>
-Length of <a href="undocumented#Point">Point</a> array.</td>
+Length of <a href="undocumented#Point">Point</a> array</td>
</tr> <tr> <td><a name="SkPath_addPoly_close"> <code><strong>close </strong></code> </a></td> <td>
-true to add <a href="undocumented#Line">Line</a> connecting <a href="#Contour">Contour</a> end and start.</td>
+true to add <a href="undocumented#Line">Line</a> connecting <a href="#Contour">Contour</a> end and start</td>
</tr>
</table>
@@ -3691,8 +3723,8 @@ true to add <a href="undocumented#Line">Line</a> connecting <a href="#Contour">C
<pre style="padding: 1em 1em 1em 1em;width: 44em; background-color: #f0f0f0">
enum <a href="#SkPath_AddPathMode">AddPathMode</a> {
-<a href="#SkPath_kAppend_AddPathMode">kAppend AddPathMode</a>
-<a href="#SkPath_kExtend_AddPathMode">kExtend AddPathMode</a>
+<a href="#SkPath_kAppend_AddPathMode">kAppend AddPathMode</a>,
+<a href="#SkPath_kExtend_AddPathMode">kExtend AddPathMode</a>,
};</pre>
<a href="#SkPath_AddPathMode">AddPathMode</a> chooses how <a href="#SkPath_addPath">addPath</a> appends. Adding one <a href="#Path">Path</a> to another can extend
@@ -3702,12 +3734,12 @@ the last <a href="#Contour">Contour</a> or start a new <a href="#Contour">Contou
<table>
<tr>
- <td><a name="SkPath_kAppend_AddPathMode"> <code><strong>SkPath::kAppend_AddPathMode </strong></code> </a></td><td>Path Verbs, Points, and Weights are appended to destination unaltered.</td><td>Since <a href="#Path">Path</a> <a href="#Verb_Array">Verb Array</a> begins with <a href="#SkPath_kMove_Verb">kMove Verb</a> if src is not empty, this
+ <td><a name="SkPath_kAppend_AddPathMode"> <code><strong>SkPath::kAppend_AddPathMode </strong></code> </a></td><td>Path Verbs, Points, and Conic_Weights are appended to destination unaltered.</td><td>Since <a href="#Path">Path</a> <a href="#Verb_Array">Verb Array</a> begins with <a href="#SkPath_kMove_Verb">kMove Verb</a> if src is not empty, this
starts a new <a href="#Contour">Contour</a>.</td>
</tr>
<tr>
<td><a name="SkPath_kExtend_AddPathMode"> <code><strong>SkPath::kExtend_AddPathMode </strong></code> </a></td><td>If destination is closed or empty, start a new Contour. If destination</td><td>is not empty, add <a href="undocumented#Line">Line</a> from <a href="#Last_Point">Last Point</a> to added <a href="#Path">Path</a> first <a href="undocumented#Point">Point</a>. Skip added
-<a href="#Path">Path</a> initial <a href="#SkPath_kMove_Verb">kMove Verb</a>, then append remining <a href="#Verb">Verbs</a>, <a href="#Point">Points</a>, and <a href="#Weight">Weights</a>.</td>
+<a href="#Path">Path</a> initial <a href="#SkPath_kMove_Verb">kMove Verb</a>, then append remining <a href="#Verb">Verbs</a>, <a href="#Point">Points</a>, and <a href="#Weight">Conic Weights</a>.</td>
</tr>
</table>
@@ -3731,22 +3763,22 @@ void addPath(const SkPath& src, SkScalar dx, SkScalar dy,
AddPathMode mode = kAppend_AddPathMode)
</pre>
-Append <a href="#SkPath_addPath_src">src</a> to <a href="#Path">Path</a>, offset by (<a href="#SkPath_addPath_dx">dx</a>, <a href="#SkPath_addPath_dy">dy</a>).
+Append <a href="#SkPath_addPath_src">src</a> to <a href="#Path">Path</a>, <a href="#SkPath_offset">offset</a> by (<a href="#SkPath_addPath_dx">dx</a>, <a href="#SkPath_addPath_dy">dy</a>).
-If <a href="#SkPath_addPath_mode">mode</a> is <a href="#SkPath_kAppend_AddPathMode">kAppend AddPathMode</a>, <a href="#SkPath_addPath_src">src</a> <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, and <a href="#Weight">Weights</a> are
+If <a href="#SkPath_addPath_mode">mode</a> is <a href="#SkPath_kAppend_AddPathMode">kAppend AddPathMode</a>, <a href="#SkPath_addPath_src">src</a> <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, and <a href="#Weight">Conic Weights</a> are
added unaltered. If <a href="#SkPath_addPath_mode">mode</a> is <a href="#SkPath_kExtend_AddPathMode">kExtend AddPathMode</a>, add <a href="undocumented#Line">Line</a> before appending
-<a href="#Verb">Verbs</a>, <a href="#Point">Points</a>, and <a href="#Weight">Weights</a>.
+<a href="#Verb">Verbs</a>, <a href="#Point">Points</a>, and <a href="#Weight">Conic Weights</a>.
### Parameters
<table> <tr> <td><a name="SkPath_addPath_src"> <code><strong>src </strong></code> </a></td> <td>
-<a href="#Path">Path</a> <a href="#Verb">Verbs</a>, <a href="#Point">Points</a>, and <a href="#Weight">Weights</a> to add.</td>
+<a href="#Path">Path</a> <a href="#Verb">Verbs</a>, <a href="#Point">Points</a>, and <a href="#Weight">Conic Weights</a> to add</td>
</tr> <tr> <td><a name="SkPath_addPath_dx"> <code><strong>dx </strong></code> </a></td> <td>
-offset added to <a href="#SkPath_addPath_src">src</a> <a href="#Point_Array">Point Array</a> x coordinates.</td>
+<a href="#SkPath_offset">offset</a> added to <a href="#SkPath_addPath_src">src</a> <a href="#Point_Array">Point Array</a> x coordinates</td>
</tr> <tr> <td><a name="SkPath_addPath_dy"> <code><strong>dy </strong></code> </a></td> <td>
-offset added to <a href="#SkPath_addPath_src">src</a> <a href="#Point_Array">Point Array</a> y coordinates.</td>
+<a href="#SkPath_offset">offset</a> added to <a href="#SkPath_addPath_src">src</a> <a href="#Point_Array">Point Array</a> y coordinates</td>
</tr> <tr> <td><a name="SkPath_addPath_mode"> <code><strong>mode </strong></code> </a></td> <td>
-<a href="#SkPath_kAppend_AddPathMode">kAppend AddPathMode</a> or <a href="#SkPath_kExtend_AddPathMode">kExtend AddPathMode</a>.</td>
+<a href="#SkPath_kAppend_AddPathMode">kAppend AddPathMode</a> or <a href="#SkPath_kExtend_AddPathMode">kExtend AddPathMode</a></td>
</tr>
</table>
@@ -3766,16 +3798,16 @@ void addPath(const SkPath& src, AddPathMode mode = kAppend_AddPathMode)
Append <a href="#SkPath_addPath_2_src">src</a> to <a href="#Path">Path</a>.
-If <a href="#SkPath_addPath_2_mode">mode</a> is <a href="#SkPath_kAppend_AddPathMode">kAppend AddPathMode</a>, <a href="#SkPath_addPath_2_src">src</a> <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, and <a href="#Weight">Weights</a> are
+If <a href="#SkPath_addPath_2_mode">mode</a> is <a href="#SkPath_kAppend_AddPathMode">kAppend AddPathMode</a>, <a href="#SkPath_addPath_2_src">src</a> <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, and <a href="#Weight">Conic Weights</a> are
added unaltered. If <a href="#SkPath_addPath_2_mode">mode</a> is <a href="#SkPath_kExtend_AddPathMode">kExtend AddPathMode</a>, add <a href="undocumented#Line">Line</a> before appending
-<a href="#Verb">Verbs</a>, <a href="#Point">Points</a>, and <a href="#Weight">Weights</a>.
+<a href="#Verb">Verbs</a>, <a href="#Point">Points</a>, and <a href="#Weight">Conic Weights</a>.
### Parameters
<table> <tr> <td><a name="SkPath_addPath_2_src"> <code><strong>src </strong></code> </a></td> <td>
-<a href="#Path">Path</a> <a href="#Verb">Verbs</a>, <a href="#Point">Points</a>, and <a href="#Weight">Weights</a> to add.</td>
+<a href="#Path">Path</a> <a href="#Verb">Verbs</a>, <a href="#Point">Points</a>, and <a href="#Weight">Conic Weights</a> to add</td>
</tr> <tr> <td><a name="SkPath_addPath_2_mode"> <code><strong>mode </strong></code> </a></td> <td>
-<a href="#SkPath_kAppend_AddPathMode">kAppend AddPathMode</a> or <a href="#SkPath_kExtend_AddPathMode">kExtend AddPathMode</a>.</td>
+<a href="#SkPath_kAppend_AddPathMode">kAppend AddPathMode</a> or <a href="#SkPath_kExtend_AddPathMode">kExtend AddPathMode</a></td>
</tr>
</table>
@@ -3795,20 +3827,20 @@ void addPath(const SkPath& src, const SkMatrix& matrix,
</pre>
Append <a href="#SkPath_addPath_3_src">src</a> to <a href="#Path">Path</a>, transformed by <a href="#SkPath_addPath_3_matrix">matrix</a>. Transformed curves may have different
-<a href="#Verb">Verbs</a>, <a href="#Point">Points</a>, and <a href="#Weight">Weights</a>.
+<a href="#Verb">Verbs</a>, <a href="#Point">Points</a>, and <a href="#Weight">Conic Weights</a>.
-If <a href="#SkPath_addPath_3_mode">mode</a> is <a href="#SkPath_kAppend_AddPathMode">kAppend AddPathMode</a>, <a href="#SkPath_addPath_3_src">src</a> <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, and <a href="#Weight">Weights</a> are
+If <a href="#SkPath_addPath_3_mode">mode</a> is <a href="#SkPath_kAppend_AddPathMode">kAppend AddPathMode</a>, <a href="#SkPath_addPath_3_src">src</a> <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, and <a href="#Weight">Conic Weights</a> are
added unaltered. If <a href="#SkPath_addPath_3_mode">mode</a> is <a href="#SkPath_kExtend_AddPathMode">kExtend AddPathMode</a>, add <a href="undocumented#Line">Line</a> before appending
-<a href="#Verb">Verbs</a>, <a href="#Point">Points</a>, and <a href="#Weight">Weights</a>.
+<a href="#Verb">Verbs</a>, <a href="#Point">Points</a>, and <a href="#Weight">Conic Weights</a>.
### Parameters
<table> <tr> <td><a name="SkPath_addPath_3_src"> <code><strong>src </strong></code> </a></td> <td>
-<a href="#Path">Path</a> <a href="#Verb">Verbs</a>, <a href="#Point">Points</a>, and <a href="#Weight">Weights</a> to add.</td>
+<a href="#Path">Path</a> <a href="#Verb">Verbs</a>, <a href="#Point">Points</a>, and <a href="#Weight">Conic Weights</a> to add</td>
</tr> <tr> <td><a name="SkPath_addPath_3_matrix"> <code><strong>matrix </strong></code> </a></td> <td>
-Transform applied to <a href="#SkPath_addPath_3_src">src</a>.</td>
+Transform applied to <a href="#SkPath_addPath_3_src">src</a></td>
</tr> <tr> <td><a name="SkPath_addPath_3_mode"> <code><strong>mode </strong></code> </a></td> <td>
-<a href="#SkPath_kAppend_AddPathMode">kAppend AddPathMode</a> or <a href="#SkPath_kExtend_AddPathMode">kExtend AddPathMode</a>.</td>
+<a href="#SkPath_kAppend_AddPathMode">kAppend AddPathMode</a> or <a href="#SkPath_kExtend_AddPathMode">kExtend AddPathMode</a></td>
</tr>
</table>
@@ -3835,7 +3867,7 @@ Reversed <a href="#SkPath_reverseAddPath_src">src</a> always appends a new <a hr
### Parameters
<table> <tr> <td><a name="SkPath_reverseAddPath_src"> <code><strong>src </strong></code> </a></td> <td>
-<a href="#Path">Path</a> <a href="#Verb">Verbs</a>, <a href="#Point">Points</a>, and <a href="#Weight">Weights</a> to add.</td>
+<a href="#Path">Path</a> <a href="#Verb">Verbs</a>, <a href="#Point">Points</a>, and <a href="#Weight">Conic Weights</a> to add</td>
</tr>
</table>
@@ -3857,16 +3889,16 @@ void offset(SkScalar dx, SkScalar dy, SkPath* dst) const
</pre>
Offset <a href="#Point_Array">Point Array</a> by (<a href="#SkPath_offset_dx">dx</a>, <a href="#SkPath_offset_dy">dy</a>). Offset <a href="#Path">Path</a> replaces <a href="#SkPath_offset_dst">dst</a>.
-If <a href="#SkPath_offset_dst">dst</a> is nullptr, <a href="#Path">Path</a> is replaced by offset data.
+If <a href="#SkPath_offset_dst">dst</a> is nullptr, <a href="#Path">Path</a> is replaced by <a href="#SkPath_offset">offset</a> data.
### Parameters
<table> <tr> <td><a name="SkPath_offset_dx"> <code><strong>dx </strong></code> </a></td> <td>
-offset added to <a href="#Point_Array">Point Array</a> x coordinates.</td>
+<a href="#SkPath_offset">offset</a> added to <a href="#Point_Array">Point Array</a> x coordinates</td>
</tr> <tr> <td><a name="SkPath_offset_dy"> <code><strong>dy </strong></code> </a></td> <td>
-offset added to <a href="#Point_Array">Point Array</a> y coordinates.</td>
+<a href="#SkPath_offset">offset</a> added to <a href="#Point_Array">Point Array</a> y coordinates</td>
</tr> <tr> <td><a name="SkPath_offset_dst"> <code><strong>dst </strong></code> </a></td> <td>
-overwritten, translated copy of <a href="#Path">Path</a>; may be nullptr.</td>
+overwritten, translated copy of <a href="#Path">Path</a>; may be nullptr</td>
</tr>
</table>
@@ -3876,7 +3908,7 @@ overwritten, translated copy of <a href="#Path">Path</a>; may be nullptr.</td>
### See Also
-<a href="#SkPath_addPath">addPath</a> transform
+<a href="#SkPath_addPath">addPath</a> <a href="#SkPath_transform">transform</a>
---
@@ -3884,14 +3916,14 @@ overwritten, translated copy of <a href="#Path">Path</a>; may be nullptr.</td>
void offset(SkScalar dx, SkScalar dy)
</pre>
-Offset <a href="#Point_Array">Point Array</a> by (<a href="#SkPath_offset_2_dx">dx</a>, <a href="#SkPath_offset_2_dy">dy</a>). <a href="#Path">Path</a> is replaced by offset data.
+Offset <a href="#Point_Array">Point Array</a> by (<a href="#SkPath_offset_2_dx">dx</a>, <a href="#SkPath_offset_2_dy">dy</a>). <a href="#Path">Path</a> is replaced by <a href="#SkPath_offset">offset</a> data.
### Parameters
<table> <tr> <td><a name="SkPath_offset_2_dx"> <code><strong>dx </strong></code> </a></td> <td>
-offset added to <a href="#Point_Array">Point Array</a> x coordinates.</td>
+<a href="#SkPath_offset">offset</a> added to <a href="#Point_Array">Point Array</a> x coordinates</td>
</tr> <tr> <td><a name="SkPath_offset_2_dy"> <code><strong>dy </strong></code> </a></td> <td>
-offset added to <a href="#Point_Array">Point Array</a> y coordinates.</td>
+<a href="#SkPath_offset">offset</a> added to <a href="#Point_Array">Point Array</a> y coordinates</td>
</tr>
</table>
@@ -3901,7 +3933,7 @@ offset added to <a href="#Point_Array">Point Array</a> y coordinates.</td>
### See Also
-<a href="#SkPath_addPath">addPath</a> transform <a href="#SkCanvas_translate">SkCanvas::translate()</a>
+<a href="#SkPath_addPath">addPath</a> <a href="#SkPath_transform">transform</a> <a href="#SkCanvas_translate">SkCanvas::translate()</a>
---
@@ -3913,16 +3945,16 @@ void transform(const SkMatrix& matrix, SkPath* dst) const
</pre>
Transform <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, and weight by <a href="#SkPath_transform_matrix">matrix</a>.
-transform may change <a href="#Verb">Verbs</a> and increase their number.
+<a href="#SkPath_transform">transform</a> may change <a href="#Verb">Verbs</a> and increase their number.
Transformed <a href="#Path">Path</a> replaces <a href="#SkPath_transform_dst">dst</a>; if <a href="#SkPath_transform_dst">dst</a> is nullptr, original data
is replaced.
### Parameters
<table> <tr> <td><a name="SkPath_transform_matrix"> <code><strong>matrix </strong></code> </a></td> <td>
-<a href="undocumented#Matrix">Matrix</a> to apply to <a href="#Path">Path</a>.</td>
+<a href="undocumented#Matrix">Matrix</a> to apply to <a href="#Path">Path</a></td>
</tr> <tr> <td><a name="SkPath_transform_dst"> <code><strong>dst </strong></code> </a></td> <td>
-overwritten, transformed copy of <a href="#Path">Path</a>; may be nullptr.</td>
+overwritten, transformed copy of <a href="#Path">Path</a>; may be nullptr</td>
</tr>
</table>
@@ -3932,7 +3964,7 @@ overwritten, transformed copy of <a href="#Path">Path</a>; may be nullptr.</td>
### See Also
-<a href="#SkPath_addPath">addPath</a> offset <a href="#SkCanvas_concat">SkCanvas::concat()</a> <a href="undocumented#SkMatrix">SkMatrix</a>
+<a href="#SkPath_addPath">addPath</a> <a href="#SkPath_offset">offset</a> <a href="#SkCanvas_concat">SkCanvas::concat()</a> <a href="undocumented#SkMatrix">SkMatrix</a>
---
@@ -3941,13 +3973,13 @@ void transform(const SkMatrix& matrix)
</pre>
Transform <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, and weight by <a href="#SkPath_transform_2_matrix">matrix</a>.
-transform may change <a href="#Verb">Verbs</a> and increase their number.
+<a href="#SkPath_transform">transform</a> may change <a href="#Verb">Verbs</a> and increase their number.
<a href="#Path">Path</a> is replaced by transformed data.
### Parameters
<table> <tr> <td><a name="SkPath_transform_2_matrix"> <code><strong>matrix </strong></code> </a></td> <td>
-<a href="undocumented#Matrix">Matrix</a> to apply to <a href="#Path">Path</a>.</td>
+<a href="undocumented#Matrix">Matrix</a> to apply to <a href="#Path">Path</a></td>
</tr>
</table>
@@ -3957,7 +3989,7 @@ transform may change <a href="#Verb">Verbs</a> and increase their number.
### See Also
-<a href="#SkPath_addPath">addPath</a> offset <a href="#SkCanvas_concat">SkCanvas::concat()</a> <a href="undocumented#SkMatrix">SkMatrix</a>
+<a href="#SkPath_addPath">addPath</a> <a href="#SkPath_offset">offset</a> <a href="#SkCanvas_concat">SkCanvas::concat()</a> <a href="undocumented#SkMatrix">SkMatrix</a>
---
@@ -3980,13 +4012,13 @@ storing (0, 0) if <a href="#SkPath_getLastPt_lastPt">lastPt</a> is not nullptr.
### Parameters
<table> <tr> <td><a name="SkPath_getLastPt_lastPt"> <code><strong>lastPt </strong></code> </a></td> <td>
-storage for final <a href="undocumented#Point">Point</a> in <a href="#Point_Array">Point Array</a>; may be nullptr.</td>
+storage for final <a href="undocumented#Point">Point</a> in <a href="#Point_Array">Point Array</a>; may be nullptr</td>
</tr>
</table>
### Return Value
-true if <a href="#Point_Array">Point Array</a> contains one or more <a href="#Point">Points</a>.
+true if <a href="#Point_Array">Point Array</a> <a href="#SkPath_contains">contains</a> one or more <a href="#Point">Points</a>
### Example
@@ -4019,9 +4051,9 @@ Set <a href="#Last_Point">Last Point</a> to (<a href="#SkPath_setLastPt_x">x</a>
### Parameters
<table> <tr> <td><a name="SkPath_setLastPt_x"> <code><strong>x </strong></code> </a></td> <td>
-set x-coordinate of <a href="#Last_Point">Last Point</a>.</td>
+set x-coordinate of <a href="#Last_Point">Last Point</a></td>
</tr> <tr> <td><a name="SkPath_setLastPt_y"> <code><strong>y </strong></code> </a></td> <td>
-set y-coordinate of <a href="#Last_Point">Last Point</a>.</td>
+set y-coordinate of <a href="#Last_Point">Last Point</a></td>
</tr>
</table>
@@ -4044,7 +4076,7 @@ Set the last point on the path. If no points have been added,
### Parameters
<table> <tr> <td><a name="SkPath_setLastPt_2_p"> <code><strong>p </strong></code> </a></td> <td>
-set value of <a href="#Last_Point">Last Point</a>.</td>
+set value of <a href="#Last_Point">Last Point</a></td>
</tr>
</table>
@@ -4062,29 +4094,29 @@ set value of <a href="#Last_Point">Last Point</a>.</td>
<pre style="padding: 1em 1em 1em 1em;width: 44em; background-color: #f0f0f0">
enum <a href="#SkPath_SegmentMask">SegmentMask</a> {
-<a href="#SkPath_kLine_SegmentMask">kLine SegmentMask</a> = 1 << 0
-<a href="#SkPath_kQuad_SegmentMask">kQuad SegmentMask</a> = 1 << 1
-<a href="#SkPath_kConic_SegmentMask">kConic SegmentMask</a> = 1 << 2
-<a href="#SkPath_kCubic_SegmentMask">kCubic SegmentMask</a> = 1 << 3
+<a href="#SkPath_kLine_SegmentMask">kLine SegmentMask</a> = 1 << 0,
+<a href="#SkPath_kQuad_SegmentMask">kQuad SegmentMask</a> = 1 << 1,
+<a href="#SkPath_kConic_SegmentMask">kConic SegmentMask</a> = 1 << 2,
+<a href="#SkPath_kCubic_SegmentMask">kCubic SegmentMask</a> = 1 << 3,
};</pre>
<a href="#SkPath_SegmentMask">SegmentMask</a> constants correspond to each drawing <a href="#SkPath_Verb">Verb</a> type in <a href="#Path">Path</a>; for
-instance, if <a href="#Path">Path</a> only contains <a href="#Line">Lines</a>, only the <a href="#SkPath_kLine_SegmentMask">kLine SegmentMask</a> bit is set.
+instance, if <a href="#Path">Path</a> only <a href="#SkPath_contains">contains</a> <a href="#Line">Lines</a>, only the <a href="#SkPath_kLine_SegmentMask">kLine SegmentMask</a> bit is set.
### Constants
<table>
<tr>
- <td><a name="SkPath_kLine_SegmentMask"> <code><strong>SkPath::kLine_SegmentMask </strong></code> </a></td><td>1</td><td>Set if <a href="#Verb_Array">Verb Array</a> contains <a href="#SkPath_kLine_Verb">kLine Verb</a>.</td>
+ <td><a name="SkPath_kLine_SegmentMask"> <code><strong>SkPath::kLine_SegmentMask </strong></code> </a></td><td>1</td><td>Set if <a href="#Verb_Array">Verb Array</a> <a href="#SkPath_contains">contains</a> <a href="#SkPath_kLine_Verb">kLine Verb</a>.</td>
</tr>
<tr>
- <td><a name="SkPath_kQuad_SegmentMask"> <code><strong>SkPath::kQuad_SegmentMask </strong></code> </a></td><td>2</td><td>Set if <a href="#Verb_Array">Verb Array</a> contains <a href="#SkPath_kQuad_Verb">kQuad Verb</a>. Note that <a href="#SkPath_conicTo">conicTo</a> may add a <a href="#Quad">Quad</a>.</td>
+ <td><a name="SkPath_kQuad_SegmentMask"> <code><strong>SkPath::kQuad_SegmentMask </strong></code> </a></td><td>2</td><td>Set if <a href="#Verb_Array">Verb Array</a> <a href="#SkPath_contains">contains</a> <a href="#SkPath_kQuad_Verb">kQuad Verb</a>. Note that <a href="#SkPath_conicTo">conicTo</a> may add a <a href="#Quad">Quad</a>.</td>
</tr>
<tr>
- <td><a name="SkPath_kConic_SegmentMask"> <code><strong>SkPath::kConic_SegmentMask </strong></code> </a></td><td>4</td><td>Set if <a href="#Verb_Array">Verb Array</a> contains <a href="#SkPath_kConic_Verb">kConic Verb</a>.</td>
+ <td><a name="SkPath_kConic_SegmentMask"> <code><strong>SkPath::kConic_SegmentMask </strong></code> </a></td><td>4</td><td>Set if <a href="#Verb_Array">Verb Array</a> <a href="#SkPath_contains">contains</a> <a href="#SkPath_kConic_Verb">kConic Verb</a>.</td>
</tr>
<tr>
- <td><a name="SkPath_kCubic_SegmentMask"> <code><strong>SkPath::kCubic_SegmentMask </strong></code> </a></td><td>8</td><td>Set if <a href="#Verb_Array">Verb Array</a> contains <a href="#SkPath_kCubic_Verb">kCubic Verb</a>.</td>
+ <td><a name="SkPath_kCubic_SegmentMask"> <code><strong>SkPath::kCubic_SegmentMask </strong></code> </a></td><td>8</td><td>Set if <a href="#Verb_Array">Verb Array</a> <a href="#SkPath_contains">contains</a> <a href="#SkPath_kCubic_Verb">kCubic Verb</a>.</td>
</tr>
</table>
@@ -4115,14 +4147,14 @@ uint32_t getSegmentMasks() const
</pre>
Returns a mask, where each set bit corresponds to a <a href="#SkPath_SegmentMask">SegmentMask</a> constant
-if <a href="#Path">Path</a> contains one or more <a href="#Verb">Verbs</a> of that type.
-Returns zero if <a href="#Path">Path</a> contains no <a href="#Line">Lines</a>, Quads, <a href="#Conic">Conics</a>, or <a href="#Cubic">Cubics</a>.
+if <a href="#Path">Path</a> <a href="#SkPath_contains">contains</a> one or more <a href="#Verb">Verbs</a> of that type.
+Returns zero if <a href="#Path">Path</a> <a href="#SkPath_contains">contains</a> no <a href="#Line">Lines</a>, or <a href="#Curve">Curves</a>: <a href="#Quad">Quads</a>, <a href="#Conic">Conics</a>, or <a href="#Cubic">Cubics</a>.
<a href="#SkPath_getSegmentMasks">getSegmentMasks</a> returns a cached result; it is very fast.
### Return Value
-<a href="#SkPath_SegmentMask">SegmentMask</a> bits or zero.
+<a href="#SkPath_SegmentMask">SegmentMask</a> bits or zero
### Example
@@ -4162,15 +4194,15 @@ account <a href="#SkPath_FillType">FillType</a>.
### Parameters
<table> <tr> <td><a name="SkPath_contains_x"> <code><strong>x </strong></code> </a></td> <td>
-x-coordinate of containment test.</td>
+x-coordinate of containment test</td>
</tr> <tr> <td><a name="SkPath_contains_y"> <code><strong>y </strong></code> </a></td> <td>
-y-coordinate of containment test.</td>
+y-coordinate of containment test</td>
</tr>
</table>
### Return Value
-true if <a href="undocumented#Point">Point</a> is in <a href="#Path">Path</a>.
+true if <a href="undocumented#Point">Point</a> is in <a href="#Path">Path</a>
### Example
@@ -4189,19 +4221,19 @@ true if <a href="undocumented#Point">Point</a> is in <a href="#Path">Path</a>.
void dump(SkWStream* stream, bool forceClose, bool dumpAsHex) const
</pre>
-Writes text representation of <a href="#Path">Path</a> to <a href="#SkPath_dump_stream">stream</a>. If <a href="#SkPath_dump_stream">stream</a> is nullptr, <a href="#SkPath_dump">dump</a> writes to
+Writes text representation of <a href="#Path">Path</a> to <a href="#SkPath_dump_stream">stream</a>. If <a href="#SkPath_dump_stream">stream</a> is nullptr, <a href="#SkPath_dump_2">dump</a> writes to
stdout. Set <a href="#SkPath_dump_forceClose">forceClose</a> to true to get
edges used to fill <a href="#Path">Path</a>. Set <a href="#SkPath_dump_dumpAsHex">dumpAsHex</a> true to get exact binary representations
-of floating point numbers used in <a href="#Point_Array">Point Array</a> and <a href="#Weight">Weights</a>.
+of floating point numbers used in <a href="#Point_Array">Point Array</a> and <a href="#Weight">Conic Weights</a>.
### Parameters
<table> <tr> <td><a name="SkPath_dump_stream"> <code><strong>stream </strong></code> </a></td> <td>
-writable <a href="undocumented#Stream">Stream</a> receiving <a href="#Path">Path</a> text representation; may be nullptr.</td>
+writable <a href="undocumented#Stream">Stream</a> receiving <a href="#Path">Path</a> text representation; may be nullptr</td>
</tr> <tr> <td><a name="SkPath_dump_forceClose"> <code><strong>forceClose </strong></code> </a></td> <td>
-true if missing <a href="#SkPath_kClose_Verb">kClose Verb</a> is output.</td>
+true if missing <a href="#SkPath_kClose_Verb">kClose Verb</a> is output</td>
</tr> <tr> <td><a name="SkPath_dump_dumpAsHex"> <code><strong>dumpAsHex </strong></code> </a></td> <td>
-true if <a href="undocumented#SkScalar">SkScalar</a> values are written as hexidecimal.</td>
+true if <a href="undocumented#SkScalar">SkScalar</a> values are written as hexidecimal</td>
</tr>
</table>
@@ -4280,7 +4312,7 @@ directly compiled as <a href="usingBookmaker#C">C</a>++ code. Floating point val
in hexadecimal to preserve their exact bit pattern. The output reconstructs the
original <a href="#Path">Path</a>.
-Use <a href="#SkPath_dumpHex">dumpHex</a> when submittingbug reports against <a href="undocumented#Skia">Skia</a>http://bug.skia.org.
+Use instead of <a href="#SkPath_dump_2">dump</a> when submittingbug reports against <a href="undocumented#Skia">Skia</a>http://bug.skia.org.
Slight value changes in <a href="#Point_Array">Point Array</a> may cause the bug to disappear.
### Example
@@ -4300,7 +4332,7 @@ path is equal to copy
### See Also
-dump
+<a href="#SkPath_dump">dump</a>
---
@@ -4311,33 +4343,78 @@ dump
size_t writeToMemory(void* buffer) const
</pre>
-Write <a href="#Path">Path</a> to <a href="#SkPath_writeToMemory_buffer">buffer</a>, returning the number of bytes written.
+Writes <a href="#Path">Path</a> to <a href="#SkPath_writeToMemory_buffer">buffer</a>, returning the number of bytes written.
Pass nullptr to obtain the storage size.
-<a href="#SkPath_writeToMemory">writeToMemory</a> writes <a href="#Fill_Type">Fill Type</a>, <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, <a href="#Conic_Weight">Conic Weight</a>, and
+Writes <a href="#Fill_Type">Fill Type</a>, <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, <a href="#Conic_Weight">Conic Weight</a>, and
additionally writes computed information like <a href="#SkPath_Convexity">Convexity</a> and bounds.
-<a href="#SkPath_writeToMemory">writeToMemory</a> should only be used in concert with <a href="#SkPath_readFromMemory">readFromMemory</a>.
-The format used for <a href="#Path">Path</a> in memory is not guaranteed.
+Use only be used in concert with <a href="#SkPath_readFromMemory">readFromMemory</a>;
+the format used for <a href="#Path">Path</a> in memory is not guaranteed.
### Parameters
<table> <tr> <td><a name="SkPath_writeToMemory_buffer"> <code><strong>buffer </strong></code> </a></td> <td>
-storage for <a href="#Path">Path</a>; may be nullptr.</td>
+storage for <a href="#Path">Path</a>; may be nullptr</td>
</tr>
</table>
### Return Value
-size of storage required for <a href="#Path">Path</a>; always a multiple of 4.
+size of storage required for <a href="#Path">Path</a>; always a multiple of 4
+
+### Example
+
+<div><fiddle-embed name="e5f16eda6a1c2d759556285f72598445">
+
+#### Example Output
+
+~~~~
+path is equal to copy
+~~~~
+
+</fiddle-embed></div>
+
+### See Also
+
+<a href="#SkPath_serialize">serialize</a> <a href="#SkPath_readFromMemory">readFromMemory</a> <a href="#SkPath_dump">dump</a> <a href="#SkPath_dumpHex">dumpHex</a>
+
+---
+
+<a name="SkPath_serialize"></a>
+## serialize
+
+<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
+sk_sp<SkData> serialize() const
+</pre>
+
+Write <a href="#Path">Path</a> to buffer, returning the buffer written to, wrapped in <a href="undocumented#Data">Data</a>.
+
+<a href="#SkPath_serialize">serialize</a> writes <a href="#Fill_Type">Fill Type</a>, <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, <a href="#Conic_Weight">Conic Weight</a>, and
+additionally writes computed information like <a href="#SkPath_Convexity">Convexity</a> and bounds.
+
+<a href="#SkPath_serialize">serialize</a> should only be used in concert with <a href="#SkPath_readFromMemory">readFromMemory</a>.
+The format used for <a href="#Path">Path</a> in memory is not guaranteed.
+
+### Return Value
+
+<a href="#Path">Path</a> data wrapped in <a href="undocumented#Data">Data</a> buffer
### Example
-<div><fiddle-embed name="e5f16eda6a1c2d759556285f72598445"></fiddle-embed></div>
+<div><fiddle-embed name="2c6aff73608cd198659db6d1eeaaae4f">
+
+#### Example Output
+
+~~~~
+path is equal to copy
+~~~~
+
+</fiddle-embed></div>
### See Also
-<a href="#SkPath_readFromMemory">readFromMemory</a> dump <a href="#SkPath_dumpHex">dumpHex</a>
+<a href="#SkPath_writeToMemory">writeToMemory</a> <a href="#SkPath_readFromMemory">readFromMemory</a> <a href="#SkPath_dump">dump</a> <a href="#SkPath_dumpHex">dumpHex</a>
---
@@ -4351,24 +4428,24 @@ size_t readFromMemory(const void* buffer, size_t length)
Initializes <a href="#Path">Path</a> from <a href="#SkPath_readFromMemory_buffer">buffer</a> of size <a href="#SkPath_readFromMemory_length">length</a>. Returns zero if the <a href="#SkPath_readFromMemory_buffer">buffer</a> is
data is inconsistent, or the <a href="#SkPath_readFromMemory_length">length</a> is too small.
-<a href="#SkPath_readFromMemory">readFromMemory</a> reads <a href="#Fill_Type">Fill Type</a>, <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, <a href="#Conic_Weight">Conic Weight</a>, and
+Reads <a href="#Fill_Type">Fill Type</a>, <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, <a href="#Conic_Weight">Conic Weight</a>, and
additionally reads computed information like <a href="#SkPath_Convexity">Convexity</a> and bounds.
-<a href="#SkPath_readFromMemory">readFromMemory</a> should only be used in concert with <a href="#SkPath_writeToMemory">writeToMemory</a>.
-The format used for <a href="#Path">Path</a> in memory is not guaranteed.
+Used only in concert with <a href="#SkPath_writeToMemory">writeToMemory</a>;
+the format used for <a href="#Path">Path</a> in memory is not guaranteed.
### Parameters
<table> <tr> <td><a name="SkPath_readFromMemory_buffer"> <code><strong>buffer </strong></code> </a></td> <td>
-storage for <a href="#Path">Path</a>.</td>
+storage for <a href="#Path">Path</a></td>
</tr> <tr> <td><a name="SkPath_readFromMemory_length"> <code><strong>length </strong></code> </a></td> <td>
-<a href="#SkPath_readFromMemory_buffer">buffer</a> size in bytes; must be multiple of 4.</td>
+<a href="#SkPath_readFromMemory_buffer">buffer</a> size in bytes; must be multiple of 4</td>
</tr>
</table>
### Return Value
-number of bytes read, or zero on failure.
+number of bytes read, or zero on failure
### Example
@@ -4403,7 +4480,7 @@ Empty <a href="#Path">Paths</a> have a <a href="#Generation_ID">Generation ID</a
uint32_t getGenerationID() const
</pre>
-Returns a non-zero, globally unique value. A different value is returned
+Returns a non-zero, globally <a href="#SkPath_unique">unique</a> value. A different value is returned
if <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, or <a href="#Conic_Weight">Conic Weight</a> changes.
Setting <a href="#Fill_Type">Fill Type</a> does not change <a href="#Generation_ID">Generation ID</a>.
@@ -4412,7 +4489,7 @@ Each time the path is modified, a different <a href="#Generation_ID">Generation
### Return Value
-non-zero, globally unique value.
+non-zero, globally <a href="#SkPath_unique">unique</a> value
### Example
@@ -4435,6 +4512,38 @@ empty genID = 1
---
+<a name="SkPath_isValid"></a>
+## isValid
+
+<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
+bool isValid() const
+</pre>
+
+Returns if <a href="#Path">Path</a> data is consistent. Corrupt <a href="#Path">Path</a> data is detected if
+internal values are out of range or internal storage does not match
+array dimensions.
+
+### Return Value
+
+true if <a href="#Path">Path</a> data is consistent
+
+---
+
+<a name="SkPath_pathRefIsValid"></a>
+## pathRefIsValid
+
+<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
+bool pathRefIsValid() const
+</pre>
+
+Returns if <a href="#Path">Path</a> data is consistent.
+
+### Return Value
+
+true if <a href="#Path">Path</a> data is consistent
+
+---
+
<a name="SkPath_validate"></a>
## validate
@@ -4442,8 +4551,7 @@ empty genID = 1
void validate() const
</pre>
-Debugging check to see if <a href="#Path">Path</a> data is consistent.
-Not currently maintained.
+Asserts if <a href="#Path">Path</a> data is inconsistent; debug only.
---
@@ -4454,35 +4562,49 @@ Not currently maintained.
void experimentalValidateRef() const
</pre>
+Asserts if <a href="#Path">Path</a> data is inconsistent; debug only.
+
---
-# <a name="Iter"></a> Class Iter
+# <a name="SkPath::Iter"></a> Class SkPath::Iter
Iterates through <a href="#Verb_Array">Verb Array</a>, and associated <a href="#Point_Array">Point Array</a> and <a href="#Conic_Weight">Conic Weight</a>.
Provides options to treat open <a href="#Contour">Contours</a> as closed, and to ignore
degenerate data.
+<pre style="padding: 1em 1em 1em 1em;width: 44em; background-color: #f0f0f0">
+class <a href="#SkPath_Iter_Iter">Iter</a> {
+public:
+<a href="#SkPath_Iter_Iter">Iter()</a>;
+<a href="#SkPath_Iter_Iter_2">Iter(const SkPath& path, bool forceClose)</a>;
+void <a href="#SkPath_Iter_setPath">setPath(const SkPath& path, bool forceClose)</a>;
+<a href="#SkPath_Verb">Verb</a> <a href="#SkPath_Iter_next">next(SkPoint pts[4], bool doConsumeDegenerates = true, bool exact = false)</a>;
+<a href="undocumented#SkScalar">SkScalar</a> <a href="#SkPath_Iter_conicWeight">conicWeight</a> const;
+bool <a href="#SkPath_Iter_isCloseLine">isCloseLine</a> const;
+bool <a href="#SkPath_Iter_isClosedContour">isClosedContour</a> const;
+};</pre>
+
### Example
-<div><fiddle-embed name="3ca8417e2a1466bf5b3ac97780a8070c"><div>Ignoring the actual <a href="#Verb">Verbs</a> and replacing them with quads rounds the
+<div><fiddle-embed name="3ca8417e2a1466bf5b3ac97780a8070c"><div>Ignoring the actual <a href="#Verb">Verbs</a> and replacing them with <a href="#Quad">Quads</a> rounds the
path of the glyph.</div></fiddle-embed></div>
### See Also
-<a href="SkPath_Reference#RawIter">RawIter</a>
+<a href="#SkPath_RawIter">RawIter</a>
-<a name="Iter_empty_constructor"></a>
+<a name="SkPath_Iter_Iter"></a>
## Iter
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
Iter()
</pre>
-Initializes <a href="#Iter">Iter</a> with an empty <a href="#Path">Path</a>. <a href="#next">next</a> on <a href="#Iter">Iter</a> returns <a href="#SkPath_kDone_Verb">kDone Verb</a>.
-Call <a href="#setPath">setPath</a> to initialize <a href="#Iter">Iter</a> at a later time.
+Initializes <a href="#SkPath_Iter_Iter">Iter</a> with an empty <a href="#Path">Path</a>. <a href="#SkPath_Iter_next">next</a> on <a href="#SkPath_Iter_Iter">Iter</a> returns <a href="#SkPath_kDone_Verb">kDone Verb</a>.
+Call <a href="#SkPath_Iter_setPath">setPath</a> to initialize <a href="#SkPath_Iter_Iter">Iter</a> at a later time.
### Return Value
-<a href="#Iter">Iter</a> of empty <a href="#Path">Path</a>.
+<a href="#SkPath_Iter_Iter">Iter</a> of empty <a href="#Path">Path</a>
### Example
@@ -4499,33 +4621,30 @@ iter is done
### See Also
-<a href="#setPath">setPath</a>
+<a href="#SkPath_Iter_setPath">setPath</a>
---
-<a name="Iter_const_SkPath"></a>
-## Iter
-
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
Iter(const SkPath& path, bool forceClose)
</pre>
-Sets <a href="#Iter">Iter</a> to return elements of <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, and <a href="#Conic_Weight">Conic Weight</a> in <a href="#Iter_const_SkPath_path">path</a>.
-If <a href="#Iter_const_SkPath_forceClose">forceClose</a> is true, <a href="#Iter">Iter</a> will add <a href="#SkPath_kLine_Verb">kLine Verb</a> and <a href="#SkPath_kClose_Verb">kClose Verb</a> after each
-open <a href="#Contour">Contour</a>. <a href="#Iter_const_SkPath_path">path</a> is not altered.
+Sets <a href="#SkPath_Iter_Iter">Iter</a> to return elements of <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, and <a href="#Conic_Weight">Conic Weight</a> in <a href="#SkPath_Iter_Iter_2_path">path</a>.
+If <a href="#SkPath_Iter_Iter_2_forceClose">forceClose</a> is true, <a href="#SkPath_Iter_Iter">Iter</a> will add <a href="#SkPath_kLine_Verb">kLine Verb</a> and <a href="#SkPath_kClose_Verb">kClose Verb</a> after each
+open <a href="#Contour">Contour</a>. <a href="#SkPath_Iter_Iter_2_path">path</a> is not altered.
### Parameters
-<table> <tr> <td><a name="Iter_const_SkPath_path"> <code><strong>path </strong></code> </a></td> <td>
-<a href="#Path">Path</a> to iterate.</td>
- </tr> <tr> <td><a name="Iter_const_SkPath_forceClose"> <code><strong>forceClose </strong></code> </a></td> <td>
-true if open <a href="#Contour">Contours</a> generate <a href="#SkPath_kClose_Verb">kClose Verb</a>.</td>
+<table> <tr> <td><a name="SkPath_Iter_Iter_2_path"> <code><strong>path </strong></code> </a></td> <td>
+<a href="#Path">Path</a> to iterate</td>
+ </tr> <tr> <td><a name="SkPath_Iter_Iter_2_forceClose"> <code><strong>forceClose </strong></code> </a></td> <td>
+true if open <a href="#Contour">Contours</a> generate <a href="#SkPath_kClose_Verb">kClose Verb</a></td>
</tr>
</table>
### Return Value
-<a href="#Iter">Iter</a> of <a href="#Iter_const_SkPath_path">path</a>.
+<a href="#SkPath_Iter_Iter">Iter</a> of <a href="#SkPath_Iter_Iter_2_path">path</a>
### Example
@@ -4550,27 +4669,27 @@ kDone_Verb
### See Also
-<a href="#setPath">setPath</a>
+<a href="#SkPath_Iter_setPath">setPath</a>
---
-<a name="Iter_setPath"></a>
+<a name="SkPath_Iter_setPath"></a>
## setPath
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
void setPath(const SkPath& path, bool forceClose)
</pre>
-Sets <a href="#Iter">Iter</a> to return elements of <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, and <a href="#Conic_Weight">Conic Weight</a> in <a href="#Iter_setPath_path">path</a>.
-If <a href="#Iter_setPath_forceClose">forceClose</a> is true, <a href="#Iter">Iter</a> will add <a href="#SkPath_kLine_Verb">kLine Verb</a> and <a href="#SkPath_kClose_Verb">kClose Verb</a> after each
-open <a href="#Contour">Contour</a>. <a href="#Iter_setPath_path">path</a> is not altered.
+Sets <a href="#SkPath_Iter_Iter">Iter</a> to return elements of <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, and <a href="#Conic_Weight">Conic Weight</a> in <a href="#SkPath_Iter_setPath_path">path</a>.
+If <a href="#SkPath_Iter_setPath_forceClose">forceClose</a> is true, <a href="#SkPath_Iter_Iter">Iter</a> will add <a href="#SkPath_kLine_Verb">kLine Verb</a> and <a href="#SkPath_kClose_Verb">kClose Verb</a> after each
+open <a href="#Contour">Contour</a>. <a href="#SkPath_Iter_setPath_path">path</a> is not altered.
### Parameters
-<table> <tr> <td><a name="Iter_setPath_path"> <code><strong>path </strong></code> </a></td> <td>
-<a href="#Path">Path</a> to iterate.</td>
- </tr> <tr> <td><a name="Iter_setPath_forceClose"> <code><strong>forceClose </strong></code> </a></td> <td>
-true if open <a href="#Contour">Contours</a> generate <a href="#SkPath_kClose_Verb">kClose Verb</a>.</td>
+<table> <tr> <td><a name="SkPath_Iter_setPath_path"> <code><strong>path </strong></code> </a></td> <td>
+<a href="#Path">Path</a> to iterate</td>
+ </tr> <tr> <td><a name="SkPath_Iter_setPath_forceClose"> <code><strong>forceClose </strong></code> </a></td> <td>
+true if open <a href="#Contour">Contours</a> generate <a href="#SkPath_kClose_Verb">kClose Verb</a></td>
</tr>
</table>
@@ -4597,48 +4716,48 @@ kDone_Verb
### See Also
-<a href="#const_SkPath">Iter(const SkPath& path, bool forceClose)</a>
+<a href="#SkPath_Iter_Iter_2">Iter(const SkPath& path, bool forceClose)</a>
---
-<a name="Iter_next"></a>
+<a name="SkPath_Iter_next"></a>
## next
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
Verb next(SkPoint pts[4], bool doConsumeDegenerates = true, bool exact = false)
</pre>
-Returns next <a href="#SkPath_Verb">Verb</a> in <a href="#Verb_Array">Verb Array</a>, and advances <a href="#Iter">Iter</a>.
+Returns <a href="#SkPath_Iter_next">next</a> <a href="#SkPath_Verb">Verb</a> in <a href="#Verb_Array">Verb Array</a>, and advances <a href="#SkPath_Iter_Iter">Iter</a>.
When <a href="#Verb_Array">Verb Array</a> is exhausted, returns <a href="#SkPath_kDone_Verb">kDone Verb</a>.
-Zero to four <a href="#Point">Points</a> are stored in <a href="#Iter_next_pts">pts</a>, depending on the returned <a href="#SkPath_Verb">Verb</a>.
-If <a href="#Iter_next_doConsumeDegenerates">doConsumeDegenerates</a> is true, skip consecutive <a href="#SkPath_kMove_Verb">kMove Verb</a> entries, returning
-only the last in the series; and skip very small <a href="#Line">Lines</a>, Quads, and <a href="#Conic">Conics</a>; and
+Zero to four <a href="#Point">Points</a> are stored in <a href="#SkPath_Iter_next_pts">pts</a>, depending on the returned <a href="#SkPath_Verb">Verb</a>.
+If <a href="#SkPath_Iter_next_doConsumeDegenerates">doConsumeDegenerates</a> is true, skip consecutive <a href="#SkPath_kMove_Verb">kMove Verb</a> entries, returning
+only the last in the series; and skip very small <a href="#Line">Lines</a>, <a href="#Quad">Quads</a>, and <a href="#Conic">Conics</a>; and
skip <a href="#SkPath_kClose_Verb">kClose Verb</a> following <a href="#SkPath_kMove_Verb">kMove Verb</a>.
-if <a href="#Iter_next_doConsumeDegenerates">doConsumeDegenerates</a> is true and <a href="#Iter_next_exact">exact</a> is true, only skip <a href="#Line">Lines</a>, Quads, and
+if <a href="#SkPath_Iter_next_doConsumeDegenerates">doConsumeDegenerates</a> is true and <a href="#SkPath_Iter_next_exact">exact</a> is true, only skip <a href="#Line">Lines</a>, <a href="#Quad">Quads</a>, and
<a href="#Conic">Conics</a> with zero lengths.
### Parameters
-<table> <tr> <td><a name="Iter_next_pts"> <code><strong>pts </strong></code> </a></td> <td>
-Storage for <a href="undocumented#Point">Point</a> data describing returned <a href="#SkPath_Verb">Verb</a>.</td>
- </tr> <tr> <td><a name="Iter_next_doConsumeDegenerates"> <code><strong>doConsumeDegenerates </strong></code> </a></td> <td>
-If true, skip degenerate <a href="#Verb">Verbs</a>.</td>
- </tr> <tr> <td><a name="Iter_next_exact"> <code><strong>exact </strong></code> </a></td> <td>
-If true, skip zero length curves. Has no effect if <a href="#Iter_next_doConsumeDegenerates">doConsumeDegenerates</a>
-is false.</td>
+<table> <tr> <td><a name="SkPath_Iter_next_pts"> <code><strong>pts </strong></code> </a></td> <td>
+Storage for <a href="undocumented#Point">Point</a> data describing returned <a href="#SkPath_Verb">Verb</a></td>
+ </tr> <tr> <td><a name="SkPath_Iter_next_doConsumeDegenerates"> <code><strong>doConsumeDegenerates </strong></code> </a></td> <td>
+If true, skip degenerate <a href="#Verb">Verbs</a></td>
+ </tr> <tr> <td><a name="SkPath_Iter_next_exact"> <code><strong>exact </strong></code> </a></td> <td>
+If true, skip zero length curves. Has no effect if <a href="#SkPath_Iter_next_doConsumeDegenerates">doConsumeDegenerates</a>
+is false</td>
</tr>
</table>
### Return Value
-next <a href="#SkPath_Verb">Verb</a> from <a href="#Verb_Array">Verb Array</a>.
+<a href="#SkPath_Iter_next">next</a> <a href="#SkPath_Verb">Verb</a> from <a href="#Verb_Array">Verb Array</a>
### Example
<div><fiddle-embed name="00ae8984856486bdb626d0ed6587855a"><div>skip degenerate skips the first in a <a href="#SkPath_kMove_Verb">kMove Verb</a> pair, the <a href="#SkPath_kMove_Verb">kMove Verb</a>
followed by the <a href="#SkPath_kClose_Verb">kClose Verb</a>, the zero length <a href="undocumented#Line">Line</a> and the very small <a href="undocumented#Line">Line</a>.
-skip degenerate if <a href="#Iter_next_exact">exact</a> skips the same as skip degenerate, but shows
+skip degenerate if <a href="#SkPath_Iter_next_exact">exact</a> skips the same as skip degenerate, but shows
the very small <a href="undocumented#Line">Line</a>.
skip none shows all of the <a href="#Verb">Verbs</a> and <a href="#Point">Points</a> in <a href="#Path">Path</a>.</div>
@@ -4677,21 +4796,21 @@ kDone_Verb
---
-<a name="Iter_conicWeight"></a>
+<a name="SkPath_Iter_conicWeight"></a>
## conicWeight
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
SkScalar conicWeight() const
</pre>
-Returns <a href="#Conic_Weight">Conic Weight</a> if <a href="#next">next</a> returned <a href="#SkPath_kConic_Verb">kConic Verb</a>.
+Returns <a href="#Conic_Weight">Conic Weight</a> if <a href="#SkPath_Iter_next">next</a> returned <a href="#SkPath_kConic_Verb">kConic Verb</a>.
-If <a href="#next">next</a> has not been called, or <a href="#next">next</a> did not return <a href="#SkPath_kConic_Verb">kConic Verb</a>,
+If <a href="#SkPath_Iter_next">next</a> has not been called, or <a href="#SkPath_Iter_next">next</a> did not return <a href="#SkPath_kConic_Verb">kConic Verb</a>,
result is undefined.
### Return Value
-<a href="#Conic_Weight">Conic Weight</a> for <a href="#Conic">Conic</a> <a href="#Point">Points</a> returned by <a href="#next">next</a>.
+<a href="#Conic_Weight">Conic Weight</a> for <a href="#Conic">Conic</a> <a href="#Point">Points</a> returned by <a href="#SkPath_Iter_next">next</a>
### Example
@@ -4714,23 +4833,23 @@ conic weight: 0.5
---
-<a name="Iter_isCloseLine"></a>
+<a name="SkPath_Iter_isCloseLine"></a>
## isCloseLine
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
bool isCloseLine() const
</pre>
-Returns true if last <a href="#SkPath_kLine_Verb">kLine Verb</a> returned by <a href="#next">next</a> was generated
-by <a href="#SkPath_kClose_Verb">kClose Verb</a>. When true, the end point returned by <a href="#next">next</a> is
+Returns true if last <a href="#SkPath_kLine_Verb">kLine Verb</a> returned by <a href="#SkPath_Iter_next">next</a> was generated
+by <a href="#SkPath_kClose_Verb">kClose Verb</a>. When true, the end point returned by <a href="#SkPath_Iter_next">next</a> is
also the start point of <a href="#Contour">Contour</a>.
-If <a href="#next">next</a> has not been called, or <a href="#next">next</a> did not return <a href="#SkPath_kLine_Verb">kLine Verb</a>,
+If <a href="#SkPath_Iter_next">next</a> has not been called, or <a href="#SkPath_Iter_next">next</a> did not return <a href="#SkPath_kLine_Verb">kLine Verb</a>,
result is undefined.
### Return Value
-true if last <a href="#SkPath_kLine_Verb">kLine Verb</a> was generated by <a href="#SkPath_kClose_Verb">kClose Verb</a>.
+true if last <a href="#SkPath_kLine_Verb">kLine Verb</a> was generated by <a href="#SkPath_kClose_Verb">kClose Verb</a>
### Example
@@ -4756,20 +4875,20 @@ line generated by close
---
-<a name="Iter_isClosedContour"></a>
+<a name="SkPath_Iter_isClosedContour"></a>
## isClosedContour
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
bool isClosedContour() const
</pre>
-Returns true if subsequent calls to <a href="#next">next</a> return <a href="#SkPath_kClose_Verb">kClose Verb</a> before returning
-<a href="#SkPath_kMove_Verb">kMove Verb</a>. if true, <a href="#Contour">Contour</a> <a href="#Iter">Iter</a> is processing may end with <a href="#SkPath_kClose_Verb">kClose Verb</a>, or
-<a href="#Iter">Iter</a> may have been initialized with force close set to true.
+Returns true if subsequent calls to <a href="#SkPath_Iter_next">next</a> return <a href="#SkPath_kClose_Verb">kClose Verb</a> before returning
+<a href="#SkPath_kMove_Verb">kMove Verb</a>. if true, <a href="#Contour">Contour</a> <a href="#SkPath_Iter_Iter">Iter</a> is processing may end with <a href="#SkPath_kClose_Verb">kClose Verb</a>, or
+<a href="#SkPath_Iter_Iter">Iter</a> may have been initialized with force <a href="#SkPath_close">close</a> set to true.
### Return Value
-true if <a href="#Contour">Contour</a> is closed.
+true if <a href="#Contour">Contour</a> is closed
### Example
@@ -4788,91 +4907,99 @@ with close(), forceClose is true : isClosedContour returns true
### See Also
-<a href="#const_SkPath">Iter(const SkPath& path, bool forceClose)</a>
+<a href="#SkPath_Iter_Iter_2">Iter(const SkPath& path, bool forceClose)</a>
---
-# <a name="RawIter"></a> Class RawIter
+# <a name="SkPath::RawIter"></a> Class SkPath::RawIter
Iterates through <a href="#Verb_Array">Verb Array</a>, and associated <a href="#Point_Array">Point Array</a> and <a href="#Conic_Weight">Conic Weight</a>.
<a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, and <a href="#Conic_Weight">Conic Weight</a> are returned unaltered.
-<a name="RawIter_empty_constructor"></a>
+<pre style="padding: 1em 1em 1em 1em;width: 44em; background-color: #f0f0f0">
+class <a href="#SkPath_RawIter_RawIter">RawIter</a> {
+public:
+<a href="#SkPath_RawIter_RawIter">RawIter()</a>;
+<a href="#SkPath_RawIter_RawIter_2">RawIter(const SkPath& path)</a>;
+void <a href="#SkPath_RawIter_setPath">setPath(const SkPath& path)</a>;
+<a href="#SkPath_Verb">Verb</a> <a href="#SkPath_RawIter_next">next(SkPoint pts[4])</a>;
+<a href="#SkPath_Verb">Verb</a> <a href="#SkPath_RawIter_peek">peek</a> const;
+<a href="undocumented#SkScalar">SkScalar</a> <a href="#SkPath_RawIter_conicWeight">conicWeight</a> const;
+}</pre>
+
+<a name="SkPath_RawIter_RawIter"></a>
## RawIter
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
RawIter()
</pre>
-Initializes <a href="#RawIter">RawIter</a> with an empty <a href="#Path">Path</a>. <a href="#next">next</a> on <a href="#RawIter">RawIter</a> returns <a href="#SkPath_kDone_Verb">kDone Verb</a>.
-Call <a href="#setPath">setPath</a> to initialize <a href="SkPath_Reference#Iter">Iter</a> at a later time.
+Initializes <a href="#SkPath_RawIter_RawIter">RawIter</a> with an empty <a href="#Path">Path</a>. <a href="#SkPath_RawIter_next">next</a> on <a href="#SkPath_RawIter_RawIter">RawIter</a> returns <a href="#SkPath_kDone_Verb">kDone Verb</a>.
+Call <a href="#SkPath_RawIter_setPath">setPath</a> to initialize <a href="#SkPath_Iter">Iter</a> at a later time.
### Return Value
-<a href="#RawIter">RawIter</a> of empty <a href="#Path">Path</a>.
+<a href="#SkPath_RawIter_RawIter">RawIter</a> of empty <a href="#Path">Path</a>
---
-<a name="RawIter_copy_constructor"></a>
-## RawIter
-
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
RawIter(const SkPath& path)
</pre>
-Sets <a href="#RawIter">RawIter</a> to return elements of <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, and <a href="#Conic_Weight">Conic Weight</a> in <a href="#RawIter_copy_constructor_path">path</a>.
+Sets <a href="#SkPath_RawIter_RawIter">RawIter</a> to return elements of <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, and <a href="#Conic_Weight">Conic Weight</a> in <a href="#SkPath_RawIter_RawIter_2_path">path</a>.
### Parameters
-<table> <tr> <td><a name="RawIter_copy_constructor_path"> <code><strong>path </strong></code> </a></td> <td>
-<a href="#Path">Path</a> to iterate.</td>
+<table> <tr> <td><a name="SkPath_RawIter_RawIter_2_path"> <code><strong>path </strong></code> </a></td> <td>
+<a href="#Path">Path</a> to iterate</td>
</tr>
</table>
### Return Value
-<a href="#RawIter">RawIter</a> of <a href="#RawIter_copy_constructor_path">path</a>.
+<a href="#SkPath_RawIter_RawIter">RawIter</a> of <a href="#SkPath_RawIter_RawIter_2_path">path</a>
---
-<a name="RawIter_setPath"></a>
+<a name="SkPath_RawIter_setPath"></a>
## setPath
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
void setPath(const SkPath& path)
</pre>
-Sets <a href="SkPath_Reference#Iter">Iter</a> to return elements of <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, and <a href="#Conic_Weight">Conic Weight</a> in <a href="#RawIter_setPath_path">path</a>.
+Sets <a href="#SkPath_Iter">Iter</a> to return elements of <a href="#Verb_Array">Verb Array</a>, <a href="#Point_Array">Point Array</a>, and <a href="#Conic_Weight">Conic Weight</a> in <a href="#SkPath_RawIter_setPath_path">path</a>.
### Parameters
-<table> <tr> <td><a name="RawIter_setPath_path"> <code><strong>path </strong></code> </a></td> <td>
-<a href="#Path">Path</a> to iterate.</td>
+<table> <tr> <td><a name="SkPath_RawIter_setPath_path"> <code><strong>path </strong></code> </a></td> <td>
+<a href="#Path">Path</a> to iterate</td>
</tr>
</table>
---
-<a name="RawIter_next"></a>
+<a name="SkPath_RawIter_next"></a>
## next
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
Verb next(SkPoint pts[4])
</pre>
-Returns next <a href="#SkPath_Verb">Verb</a> in <a href="#Verb_Array">Verb Array</a>, and advances <a href="#RawIter">RawIter</a>.
+Returns <a href="#SkPath_RawIter_next">next</a> <a href="#SkPath_Verb">Verb</a> in <a href="#Verb_Array">Verb Array</a>, and advances <a href="#SkPath_RawIter_RawIter">RawIter</a>.
When <a href="#Verb_Array">Verb Array</a> is exhausted, returns <a href="#SkPath_kDone_Verb">kDone Verb</a>.
-Zero to four <a href="#Point">Points</a> are stored in <a href="#RawIter_next_pts">pts</a>, depending on the returned <a href="#SkPath_Verb">Verb</a>.
+Zero to four <a href="#Point">Points</a> are stored in <a href="#SkPath_RawIter_next_pts">pts</a>, depending on the returned <a href="#SkPath_Verb">Verb</a>.
### Parameters
-<table> <tr> <td><a name="RawIter_next_pts"> <code><strong>pts </strong></code> </a></td> <td>
-Storage for <a href="undocumented#Point">Point</a> data describing returned <a href="#SkPath_Verb">Verb</a>.</td>
+<table> <tr> <td><a name="SkPath_RawIter_next_pts"> <code><strong>pts </strong></code> </a></td> <td>
+Storage for <a href="undocumented#Point">Point</a> data describing returned <a href="#SkPath_Verb">Verb</a></td>
</tr>
</table>
### Return Value
-next <a href="#SkPath_Verb">Verb</a> from <a href="#Verb_Array">Verb Array</a>.
+<a href="#SkPath_RawIter_next">next</a> <a href="#SkPath_Verb">Verb</a> from <a href="#Verb_Array">Verb Array</a>
### Example
@@ -4895,22 +5022,22 @@ kDone_Verb
### See Also
-<a href="#peek">peek</a>
+<a href="#SkPath_RawIter_peek">peek</a>
---
-<a name="RawIter_peek"></a>
+<a name="SkPath_RawIter_peek"></a>
## peek
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
Verb peek() const
</pre>
-Returns next <a href="#SkPath_Verb">Verb</a>, but does not advance <a href="#RawIter">RawIter</a>.
+Returns <a href="#SkPath_RawIter_next">next</a> <a href="#SkPath_Verb">Verb</a>, but does not advance <a href="#SkPath_RawIter_RawIter">RawIter</a>.
### Return Value
-next <a href="#SkPath_Verb">Verb</a> from <a href="#Verb_Array">Verb Array</a>.
+<a href="#SkPath_RawIter_next">next</a> <a href="#SkPath_Verb">Verb</a> from <a href="#Verb_Array">Verb Array</a>
### Example
@@ -4932,25 +5059,25 @@ peek Done == verb Done
### See Also
-<a href="#next">next</a>
+<a href="#SkPath_RawIter_next">next</a>
---
-<a name="RawIter_conicWeight"></a>
+<a name="SkPath_RawIter_conicWeight"></a>
## conicWeight
<pre style="padding: 1em 1em 1em 1em;width: 50em; background-color: #f0f0f0">
SkScalar conicWeight() const
</pre>
-Returns <a href="#Conic_Weight">Conic Weight</a> if <a href="#next">next</a> returned <a href="#SkPath_kConic_Verb">kConic Verb</a>.
+Returns <a href="#Conic_Weight">Conic Weight</a> if <a href="#SkPath_RawIter_next">next</a> returned <a href="#SkPath_kConic_Verb">kConic Verb</a>.
-If <a href="#next">next</a> has not been called, or <a href="#next">next</a> did not return <a href="#SkPath_kConic_Verb">kConic Verb</a>,
+If <a href="#SkPath_RawIter_next">next</a> has not been called, or <a href="#SkPath_RawIter_next">next</a> did not return <a href="#SkPath_kConic_Verb">kConic Verb</a>,
result is undefined.
### Return Value
-<a href="#Conic_Weight">Conic Weight</a> for <a href="#Conic">Conic</a> <a href="#Point">Points</a> returned by <a href="#next">next</a>.
+<a href="#Conic_Weight">Conic Weight</a> for <a href="#Conic">Conic</a> <a href="#Point">Points</a> returned by <a href="#SkPath_RawIter_next">next</a>
### Example
diff --git a/tools/bookmaker/bookmaker.cpp b/tools/bookmaker/bookmaker.cpp
index cbb34a2a4f..0c23c7720a 100644
--- a/tools/bookmaker/bookmaker.cpp
+++ b/tools/bookmaker/bookmaker.cpp
@@ -25,7 +25,9 @@ Text Encoding anchors in paragraph are echoed instead of being linked to anchor
consts like enum members need fully qualfied refs to make a valid link
enum comments should be disallowed unless after #Enum and before first #Const
... or, should look for enum comments in other places
-
+trouble with aliases, plurals
+ need to keep first letter of includeWriter @param / @return lowercase
+ Quad -> quad, Quads -> quads
*/
static string normalized_name(string name) {
@@ -92,7 +94,8 @@ void Definition::setCanonicalFiddle() {
fMethodType = Definition::MethodType::kNone;
size_t doubleColons = fName.find("::", 0);
SkASSERT(string::npos != doubleColons);
- string result = fName.substr(0, doubleColons) + "_";
+ string base = fName.substr(0, doubleColons);
+ string result = base + "_";
doubleColons += 2;
if (string::npos != fName.find('~', doubleColons)) {
fMethodType = Definition::MethodType::kDestructor;
@@ -118,56 +121,69 @@ void Definition::setCanonicalFiddle() {
} else {
SkASSERT(0); // todo: incomplete
}
- } else if (string::npos != fName.find("()", doubleColons)) {
- if (isupper(fName[doubleColons])) {
- fMethodType = Definition::MethodType::kConstructor;
- result += "empty_constructor";
- } else {
- result += fName.substr(doubleColons, fName.length() - doubleColons - 2);
- }
} else {
- size_t comma = fName.find(',', doubleColons);
- size_t openParen = fName.find('(', doubleColons);
- if (string::npos == comma && string::npos != openParen) {
- fMethodType = Definition::MethodType::kConstructor;
- result += isMove ? "move_" : "copy_";
- result += "constructor";
- } else if (string::npos == openParen) {
- result += fName.substr(doubleColons);
+ size_t parens = fName.find("()", doubleColons);
+ if (string::npos != parens) {
+ string methodName = fName.substr(doubleColons, parens - doubleColons);
+ do {
+ size_t nextDouble = methodName.find("::");
+ if (string::npos == nextDouble) {
+ break;
+ }
+ base = methodName.substr(0, nextDouble);
+ result += base + '_';
+ methodName = methodName.substr(nextDouble + 2);
+ doubleColons += nextDouble + 2;
+ } while (true);
+ if (base == methodName) {
+ fMethodType = Definition::MethodType::kConstructor;
+ result += "empty_constructor";
+ } else {
+ result += fName.substr(doubleColons, fName.length() - doubleColons - 2);
+ }
} else {
- fMethodType = Definition::MethodType::kConstructor;
- // name them by their param types, e.g. SkCanvas__int_int_const_SkSurfaceProps_star
- SkASSERT(string::npos != openParen);
- // TODO: move forward until parens are balanced and terminator =,)
- TextParser params("", &fName[openParen] + 1, &*fName.end(), 0);
- bool underline = false;
- while (!params.eof()) {
-// SkDEBUGCODE(const char* end = params.anyOf("(),=")); // unused for now
-// SkASSERT(end[0] != '('); // fixme: put off handling nested parentheseses
- if (params.startsWith("const") || params.startsWith("int")
- || params.startsWith("Sk")) {
- const char* wordStart = params.fChar;
- params.skipToNonAlphaNum();
- if (underline) {
- result += '_';
- } else {
- underline = true;
- }
- result += string(wordStart, params.fChar - wordStart);
- } else {
- params.skipToNonAlphaNum();
+ size_t openParen = fName.find('(', doubleColons);
+ if (string::npos == openParen) {
+ result += fName.substr(doubleColons);
+ } else {
+ size_t comma = fName.find(',', doubleColons);
+ if (string::npos == comma) {
+ result += isMove ? "move_" : "copy_";
}
- if (!params.eof() && '*' == params.peek()) {
- if (underline) {
- result += '_';
+ fMethodType = Definition::MethodType::kConstructor;
+ // name them by their param types,
+ // e.g. SkCanvas__int_int_const_SkSurfaceProps_star
+ // TODO: move forward until parens are balanced and terminator =,)
+ TextParser params("", &fName[openParen] + 1, &*fName.end(), 0);
+ bool underline = false;
+ while (!params.eof()) {
+ // SkDEBUGCODE(const char* end = params.anyOf("(),=")); // unused for now
+ // SkASSERT(end[0] != '('); // fixme: put off handling nested parentheseses
+ if (params.startsWith("const") || params.startsWith("int")
+ || params.startsWith("Sk")) {
+ const char* wordStart = params.fChar;
+ params.skipToNonAlphaNum();
+ if (underline) {
+ result += '_';
+ } else {
+ underline = true;
+ }
+ result += string(wordStart, params.fChar - wordStart);
} else {
- underline = true;
+ params.skipToNonAlphaNum();
+ }
+ if (!params.eof() && '*' == params.peek()) {
+ if (underline) {
+ result += '_';
+ } else {
+ underline = true;
+ }
+ result += "star";
+ params.next();
+ params.skipSpace();
}
- result += "star";
- params.next();
- params.skipSpace();
+ params.skipToAlpha();
}
- params.skipToAlpha();
}
}
}
@@ -391,13 +407,25 @@ bool Definition::checkMethod() const {
return true;
}
-bool Definition::crossCheck(const char* tokenID, const Definition& includeToken) const {
- const char* defStart = fStart;
- SkASSERT('#' == defStart[0]); // FIXME: needs to be per definition
- ++defStart;
- SkASSERT(!strncmp(defStart, tokenID, strlen(tokenID)));
- defStart += strlen(tokenID);
- return crossCheckInside(defStart, fContentStart, includeToken);
+bool Definition::crossCheck2(const Definition& includeToken) const {
+ TextParser parser(fFileName, fStart, fContentStart, fLineCount);
+ parser.skipExact("#");
+ bool isMethod = parser.skipName("Method");
+ const char* contentEnd;
+ if (isMethod) {
+ contentEnd = fContentStart;
+ } else if (parser.skipName("DefinedBy")) {
+ contentEnd = fContentEnd;
+ while (parser.fChar < contentEnd && ' ' >= contentEnd[-1]) {
+ --contentEnd;
+ }
+ if (parser.fChar < contentEnd - 1 && ')' == contentEnd[-1] && '(' == contentEnd[-2]) {
+ contentEnd -= 2;
+ }
+ } else {
+ return parser.reportError<bool>("unexpected crosscheck marktype");
+ }
+ return crossCheckInside(parser.fChar, contentEnd, includeToken);
}
bool Definition::crossCheck(const Definition& includeToken) const {
@@ -414,6 +442,9 @@ bool Definition::crossCheckInside(const char* start, const char* end,
if (inc.startsWith("friend")) {
inc.skipWord("friend");
}
+ if (inc.startsWith("SK_API")) {
+ inc.skipWord("SK_API");
+ }
do {
bool defEof;
bool incEof;
@@ -763,6 +794,13 @@ const Definition* RootDefinition::find(const string& ref) const {
if (leafIter != fLeaves.end()) {
return &leafIter->second;
}
+ if (string::npos == ref.find("()")) {
+ string withParens = ref + "()";
+ const auto parensIter = fLeaves.find(withParens);
+ if (parensIter != fLeaves.end()) {
+ return &parensIter->second;
+ }
+ }
const auto branchIter = fBranches.find(ref);
if (branchIter != fBranches.end()) {
const RootDefinition* rootDef = branchIter->second;
@@ -1006,7 +1044,7 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy
fMarkup.emplace_front(markType, defStart, fLineCount, fParent);
definition = &fMarkup.front();
definition->fName = typeNameBuilder[0];
- definition->fFiddle = normalized_name(typeNameBuilder[0]);
+ definition->fFiddle = fParent->fFiddle;
definition->fContentStart = fChar;
definition->fContentEnd = this->trimmedBracketEnd(fMC, OneLine::kYes);
this->skipToEndBracket(fMC);
@@ -1139,6 +1177,54 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy
return true;
}
+void BmhParser::reportDuplicates(const Definition& def, const string& dup) const {
+ if (MarkType::kExample == def.fMarkType && dup == def.fFiddle) {
+ TextParser reporter(&def);
+ reporter.reportError("duplicate example name");
+ }
+ for (auto& child : def.fChildren ) {
+ reportDuplicates(*child, dup);
+ }
+}
+
+static void find_examples(const Definition& def, vector<string>* exampleNames) {
+ if (MarkType::kExample == def.fMarkType) {
+ exampleNames->push_back(def.fFiddle);
+ }
+ for (auto& child : def.fChildren ) {
+ find_examples(*child, exampleNames);
+ }
+}
+
+bool BmhParser::checkExamples() const {
+ vector<string> exampleNames;
+ for (const auto& topic : fTopicMap) {
+ if (topic.second->fParent) {
+ continue;
+ }
+ find_examples(*topic.second, &exampleNames);
+ }
+ std::sort(exampleNames.begin(), exampleNames.end());
+ string* last = nullptr;
+ string reported;
+ bool checkOK = true;
+ for (auto& nameIter : exampleNames) {
+ if (last && *last == nameIter && reported != *last) {
+ reported = *last;
+ SkDebugf("%s\n", reported.c_str());
+ for (const auto& topic : fTopicMap) {
+ if (topic.second->fParent) {
+ continue;
+ }
+ this->reportDuplicates(*topic.second, reported);
+ }
+ checkOK = false;
+ }
+ last = &nameIter;
+ }
+ return checkOK;
+}
+
bool BmhParser::childOf(MarkType markType) const {
auto childError = [this](MarkType markType) -> bool {
string errStr = "expected ";
@@ -1162,26 +1248,32 @@ bool BmhParser::childOf(MarkType markType) const {
}
string BmhParser::className(MarkType markType) {
+ const char* end = this->lineEnd();
+ const char* mc = this->strnchr(fMC, end);
+ string classID;
+ TextParser::Save savePlace(this);
+ this->skipSpace();
+ const char* wordStart = fChar;
+ this->skipToNonAlphaNum();
+ const char* wordEnd = fChar;
+ classID = string(wordStart, wordEnd - wordStart);
+ if (!mc) {
+ savePlace.restore();
+ }
string builder;
const Definition* parent = this->parentSpace();
- if (parent && (parent != fParent || MarkType::kClass != markType)) {
+ if (parent && parent->fName != classID) {
builder += parent->fName;
}
- const char* end = this->lineEnd();
- const char* mc = this->strnchr(fMC, end);
if (mc) {
- this->skipSpace();
- const char* wordStart = fChar;
- this->skipToNonAlphaNum();
- const char* wordEnd = fChar;
if (mc + 1 < fEnd && fMC == mc[1]) { // if ##
if (markType != fParent->fMarkType) {
return this->reportError<string>("unbalanced method");
}
- if (builder.length() > 0 && wordEnd > wordStart) {
+ if (builder.length() > 0 && classID.size() > 0) {
if (builder != fParent->fName) {
builder += "::";
- builder += string(wordStart, wordEnd - wordStart);
+ builder += classID;
if (builder != fParent->fName) {
return this->reportError<string>("name mismatch");
}
@@ -1241,6 +1333,49 @@ bool BmhParser::collectExternals() {
return true;
}
+static bool dump_examples(FILE* fiddleOut, const Definition& def, bool* continuation) {
+ if (MarkType::kExample == def.fMarkType) {
+ string result;
+ if (!def.exampleToScript(&result)) {
+ return false;
+ }
+ if (result.length() > 0) {
+ if (*continuation) {
+ fprintf(fiddleOut, ",\n");
+ } else {
+ *continuation = true;
+ }
+ fprintf(fiddleOut, "%s", result.c_str());
+ }
+ return true;
+ }
+ for (auto& child : def.fChildren ) {
+ if (!dump_examples(fiddleOut, *child, continuation)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool BmhParser::dumpExamples(const char* fiddleJsonFileName) const {
+ FILE* fiddleOut = fopen(fiddleJsonFileName, "wb");
+ if (!fiddleOut) {
+ SkDebugf("could not open output file %s\n", fiddleJsonFileName);
+ return false;
+ }
+ fprintf(fiddleOut, "{\n");
+ bool continuation = false;
+ for (const auto& topic : fTopicMap) {
+ if (topic.second->fParent) {
+ continue;
+ }
+ dump_examples(fiddleOut, *topic.second, &continuation);
+ }
+ fprintf(fiddleOut, "\n}\n");
+ fclose(fiddleOut);
+ return true;
+}
+
int BmhParser::endHashCount() const {
const char* end = fLine + this->lineLength();
int count = 0;
@@ -1976,30 +2111,6 @@ DEFINE_bool2(spellcheck, s, false, "Spell-check. (Requires -b)");
DEFINE_bool2(tokens, t, false, "Output include tokens. (Requires -i)");
DEFINE_bool2(crosscheck, x, false, "Check bmh against includes. (Requires -b -i)");
-static bool dump_examples(FILE* fiddleOut, const Definition& def, bool* continuation) {
- if (MarkType::kExample == def.fMarkType) {
- string result;
- if (!def.exampleToScript(&result)) {
- return false;
- }
- if (result.length() > 0) {
- if (*continuation) {
- fprintf(fiddleOut, ",\n");
- } else {
- *continuation = true;
- }
- fprintf(fiddleOut, "%s", result.c_str());
- }
- return true;
- }
- for (auto& child : def.fChildren ) {
- if (!dump_examples(fiddleOut, *child, continuation)) {
- return false;
- }
- }
- return true;
-}
-
static int count_children(const Definition& def, MarkType markType) {
int count = 0;
if (markType == def.fMarkType) {
@@ -2145,23 +2256,14 @@ int main(int argc, char** const argv) {
int examples = 0;
int methods = 0;
int topics = 0;
- FILE* fiddleOut;
if (!done && !FLAGS_examples.isEmpty()) {
- fiddleOut = fopen(FLAGS_examples[0], "wb");
- if (!fiddleOut) {
- SkDebugf("could not open output file %s\n", FLAGS_examples[0]);
+ // check to see if examples have duplicate names
+ if (!bmhParser.checkExamples()) {
return -1;
}
- fprintf(fiddleOut, "{\n");
- bool continuation = false;
- for (const auto& topic : bmhParser.fTopicMap) {
- if (topic.second->fParent) {
- continue;
- }
- dump_examples(fiddleOut, *topic.second, &continuation);
+ if (!bmhParser.dumpExamples(FLAGS_examples[0])) {
+ return -1;
}
- fprintf(fiddleOut, "\n}\n");
- fclose(fiddleOut);
}
for (const auto& topic : bmhParser.fTopicMap) {
if (topic.second->fParent) {
diff --git a/tools/bookmaker/bookmaker.h b/tools/bookmaker/bookmaker.h
index fae41c4ddd..0f0693fd77 100644
--- a/tools/bookmaker/bookmaker.h
+++ b/tools/bookmaker/bookmaker.h
@@ -40,6 +40,7 @@ using std::vector;
enum class KeyWord {
kNone,
+ kSK_API,
kBool,
kChar,
kClass,
@@ -148,6 +149,7 @@ enum class Bracket {
kSlashSlash,
kPound,
kColon,
+ kDebugCode, // parens get special treatment so SkDEBUGCODE( isn't treated as method
};
enum class Punctuation { // catch-all for misc symbols tracked in C
@@ -760,7 +762,7 @@ public:
bool checkMethod() const;
void setCanonicalFiddle();
- bool crossCheck(const char* tokenName, const Definition& includeToken) const;
+ bool crossCheck2(const Definition& includeToken) const;
bool crossCheck(const Definition& includeToken) const;
bool crossCheckInside(const char* start, const char* end, const Definition& includeToken) const;
bool exampleToScript(string* result) const;
@@ -1287,6 +1289,8 @@ public:
bool addDefinition(const char* defStart, bool hasEnd, MarkType markType,
const vector<string>& typeNameBuilder);
+ bool checkExamples() const;
+ bool dumpExamples(const char* fiddleJsonFileName) const;
bool childOf(MarkType markType) const;
string className(MarkType markType);
bool collectExternals();
@@ -1316,6 +1320,7 @@ public:
}
bool popParentStack(Definition* definition);
+ void reportDuplicates(const Definition& def, const string& dup) const;
void reset() override {
INHERITED::resetCommon();
@@ -1540,6 +1545,7 @@ public:
fRootTopic = nullptr;
fInBrace = nullptr;
fIncludeWord = nullptr;
+ fLastObject = nullptr;
fPrev = '\0';
fInChar = false;
fInCharCommentString = false;
@@ -1602,6 +1608,7 @@ protected:
unordered_map<string, Definition> fIUnionMap;
Definition* fRootTopic;
Definition* fInBrace;
+ Definition* fLastObject;
const char* fIncludeWord;
char fPrev;
bool fInChar;
@@ -1646,6 +1653,11 @@ public:
list<Definition>::iterator fDefEnd;
};
+ struct ParentPair {
+ const Definition* fParent;
+ const ParentPair* fPrev;
+ };
+
IncludeWriter() : IncludeParser() {}
~IncludeWriter() override {}
@@ -1670,7 +1682,7 @@ public:
const int start, const int run, int lastWrite, const char last,
const char* data);
void methodOut(const Definition* method, const Definition& child);
- bool populate(Definition* def, RootDefinition* root);
+ bool populate(Definition* def, ParentPair* parentPair, RootDefinition* root);
bool populate(BmhParser& bmhParser);
void reset() override {
@@ -1680,6 +1692,7 @@ public:
fEnumDef = nullptr;
fMethodDef = nullptr;
fStructDef = nullptr;
+ fAttrDeprecated = nullptr;
fAnonymousEnumCount = 1;
fInStruct = false;
}
@@ -1700,6 +1713,7 @@ private:
const Definition* fEnumDef;
const Definition* fMethodDef;
const Definition* fStructDef;
+ const Definition* fAttrDeprecated;
const char* fContinuation; // used to construct paren-qualified method name
int fAnonymousEnumCount;
int fEnumItemValueTab;
diff --git a/tools/bookmaker/includeParser.cpp b/tools/bookmaker/includeParser.cpp
index 6aed93737f..21a47d6e8a 100644
--- a/tools/bookmaker/includeParser.cpp
+++ b/tools/bookmaker/includeParser.cpp
@@ -25,6 +25,7 @@ struct IncludeKey {
const IncludeKey kKeyWords[] = {
{ "", KeyWord::kNone, KeyProperty::kNone },
+ { "SK_API", KeyWord::kSK_API, KeyProperty::kModifier },
{ "bool", KeyWord::kBool, KeyProperty::kNumber },
{ "char", KeyWord::kChar, KeyProperty::kNumber },
{ "class", KeyWord::kClass, KeyProperty::kObject },
@@ -236,7 +237,6 @@ bool IncludeParser::crossCheck(BmhParser& bmhParser) {
if (this->internalName(token)) {
continue;
}
- const char* methodID = bmhParser.fMaps[(int) token.fMarkType].fName;
if (!def) {
string paramName = className + "::";
paramName += string(token.fContentStart,
@@ -304,11 +304,27 @@ bool IncludeParser::crossCheck(BmhParser& bmhParser) {
}
}
if (!def) {
+ if ("SK_ATTR_DEPRECATED" == token.fName) {
+ break;
+ }
+ if (0 == token.fName.find("SkDEBUGCODE")) {
+ break;
+ }
+ }
+ if (!def) {
+ // simple method names inside nested classes have a bug and are missing trailing parens
+ string withParens = fullName + "()"; // FIXME: this shouldn't be necessary
+ def = root->find(withParens);
+ }
+ if (!def) {
SkDebugf("method missing from bmh: %s\n", fullName.c_str());
break;
}
- if (def->crossCheck(methodID, token)) {
+ if (def->crossCheck2(token)) {
def->fVisited = true;
+ if (MarkType::kDefinedBy == def->fMarkType) {
+ def->fParent->fVisited = true;
+ }
} else {
SkDebugf("method differs from bmh: %s\n", fullName.c_str());
}
@@ -912,11 +928,13 @@ bool IncludeParser::parseClass(Definition* includeDef, IsStruct isStruct) {
iter = std::next(iter);
++lastPublic;
}
+ fLastObject = nullptr;
while (childIter != includeDef->fChildren.end() && (*childIter)->fParentIndex < lastPublic) {
Definition* child = *childIter;
if (!this->parseObject(child, markupDef)) {
return false;
}
+ fLastObject = child;
childIter = std::next(childIter);
}
while (childIter != includeDef->fChildren.end()) {
@@ -1292,10 +1310,18 @@ bool IncludeParser::parseObject(Definition* child, Definition* markupDef) {
case Definition::Type::kBracket:
switch (child->fBracket) {
case Bracket::kParen:
+ if (fLastObject) {
+ TextParser checkDeprecated(child->fFileName, fLastObject->fTerminator + 1,
+ child->fStart, fLastObject->fLineCount);
+ checkDeprecated.skipWhiteSpace();
+ if (checkDeprecated.startsWith("SK_ATTR_DEPRECATED")) {
+ break;
+ }
+ }
if (!this->parseMethod(child, markupDef)) {
return this->reportError<bool>("failed to parse method");
}
- break;
+ break;
case Bracket::kSlashSlash:
case Bracket::kSlashStar:
// comments are picked up by parsing objects first
@@ -1336,6 +1362,9 @@ bool IncludeParser::parseObject(Definition* child, Definition* markupDef) {
case Bracket::kAngle:
// pick up templated function pieces when method is found
break;
+ case Bracket::kDebugCode:
+ // todo: handle this
+ break;
default:
return this->reportError<bool>("unhandled bracket");
}
@@ -1457,6 +1486,11 @@ bool IncludeParser::parseChar() {
case '(':
case '[':
case '{': {
+ if (fIncludeWord && '(' == test && fChar - fIncludeWord >= 10 &&
+ !strncmp("SkDEBUGCODE", fIncludeWord, 10)) {
+ this->pushBracket(Bracket::kDebugCode);
+ break;
+ }
if (fInCharCommentString) {
break;
}
@@ -1555,6 +1589,8 @@ bool IncludeParser::parseChar() {
} else {
fInFunction = '}' != test;
}
+ } else if (')' == test && Bracket::kDebugCode == this->topBracket()) {
+ this->popBracket();
} else {
return reportError<bool>("malformed close bracket");
}
diff --git a/tools/bookmaker/includeWriter.cpp b/tools/bookmaker/includeWriter.cpp
index 81fb3cc255..af2fb89fb8 100644
--- a/tools/bookmaker/includeWriter.cpp
+++ b/tools/bookmaker/includeWriter.cpp
@@ -268,6 +268,8 @@ void IncludeWriter::enumMembersOut(const RootDefinition* root, Definition& child
commentStart = privateDef->fContentStart;
commentLen = (int) (privateDef->fContentEnd - privateDef->fContentStart);
}
+ // FIXME: may assert here if there's no const value
+ // should have detected and errored on that earlier when enum fContentStart was set
SkASSERT(commentLen > 0 && commentLen < 1000);
if (!currentEnumItem->fShort) {
this->writeCommentHeader();
@@ -508,6 +510,7 @@ void IncludeWriter::methodOut(const Definition* method, const Definition& child)
}
this->indentToColumn(column);
int partLen = (int) (partEnd - partStart);
+ // FIXME : detect this earlier; assert if #Return is empty
SkASSERT(partLen > 0 && partLen < 200);
fIndent = column;
this->rewriteBlock(partLen, partStart);
@@ -673,6 +676,8 @@ void IncludeWriter::structSizeMembers(Definition& child) {
inMethod = false;
} else if (Punctuation::kLeftBrace == token.fPunctuation) {
inMethod = false;
+ } else if (Punctuation::kSemicolon == token.fPunctuation) {
+ inMethod = false;
} else {
SkASSERT(0); // incomplete
}
@@ -735,7 +740,8 @@ void IncludeWriter::structSizeMembers(Definition& child) {
}
}
-bool IncludeWriter::populate(Definition* def, RootDefinition* root) {
+bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefinition* root) {
+ ParentPair pair = { def, prevPair };
// write bulk of original include up to class, method, enum, etc., excepting preceding comment
// find associated bmh object
// write any associated comments in Doxygen form
@@ -762,7 +768,8 @@ bool IncludeWriter::populate(Definition* def, RootDefinition* root) {
}
if (fContinuation) {
if (Definition::Type::kKeyWord == child.fType) {
- if (KeyWord::kFriend == child.fKeyWord || KeyWord::kBool == child.fKeyWord) {
+ if (KeyWord::kFriend == child.fKeyWord || KeyWord::kBool == child.fKeyWord ||
+ KeyWord::kSK_API == child.fKeyWord) {
continue;
}
}
@@ -875,14 +882,27 @@ bool IncludeWriter::populate(Definition* def, RootDefinition* root) {
continue;
}
this->methodOut(method, child);
+ if (fAttrDeprecated) {
+ fStart = fAttrDeprecated->fContentStart;
+ fAttrDeprecated = nullptr;
+ }
continue;
}
if (Definition::Type::kKeyWord == child.fType) {
const Definition* structDef = nullptr;
switch (child.fKeyWord) {
case KeyWord::kStruct:
+ case KeyWord::kClass:
// if struct contains members, compute their name and comment tabs
- inStruct = fInStruct = child.fChildren.size() > 0;
+ if (child.fChildren.size() > 0) {
+ const ParentPair* testPair = &pair;
+ while ((testPair = testPair->fPrev)) {
+ if (KeyWord::kClass == testPair->fParent->fKeyWord) {
+ inStruct = fInStruct = true;
+ break;
+ }
+ }
+ }
if (fInStruct) {
fIndent += 4;
fStructDef = root->find(child.fName);
@@ -892,11 +912,10 @@ bool IncludeWriter::populate(Definition* def, RootDefinition* root) {
this->structSizeMembers(child);
fIndent -= 4;
}
- case KeyWord::kClass:
if (child.fChildren.size() > 0) {
const char* bodyEnd = fDeferComment ? fDeferComment->fContentStart - 1 :
child.fContentStart;
- this->writeBlock((int) (bodyEnd - fStart), fStart);
+ this->writeBlockTrim((int) (bodyEnd - fStart), fStart);
fStart = child.fContentStart;
if (child.fName == root->fName) {
if (Definition* parent = root->fParent) {
@@ -942,6 +961,7 @@ bool IncludeWriter::populate(Definition* def, RootDefinition* root) {
break;
}
}
+ // FIXME: trigger error earlier if inner #Struct or #Class is missing #Code
SkASSERT(nextBlock); // FIXME: check enum for correct order earlier
const char* commentStart = codeBlock->fTerminator;
const char* commentEnd = nextBlock->fStart;
@@ -962,6 +982,7 @@ bool IncludeWriter::populate(Definition* def, RootDefinition* root) {
case KeyWord::kStatic:
case KeyWord::kInt:
case KeyWord::kUint32_t:
+ case KeyWord::kUnsigned:
case KeyWord::kSize_t:
case KeyWord::kFloat:
case KeyWord::kBool:
@@ -974,6 +995,8 @@ bool IncludeWriter::populate(Definition* def, RootDefinition* root) {
case KeyWord::kPrivate:
case KeyWord::kProtected:
case KeyWord::kFriend:
+ case KeyWord::kInline:
+ case KeyWord::kSK_API:
case KeyWord::kTypedef:
break;
default:
@@ -986,7 +1009,7 @@ bool IncludeWriter::populate(Definition* def, RootDefinition* root) {
this->writeBlock((int) (fStart - child.fStart), child.fStart);
this->lf(2);
fIndent += 4;
- if (!this->populate(&child, const_cast<Definition*>(structDef)->asRoot())) {
+ if (!this->populate(&child, &pair, const_cast<Definition*>(structDef)->asRoot())) {
return false;
}
// output any remaining definitions at current indent level
@@ -1001,10 +1024,10 @@ bool IncludeWriter::populate(Definition* def, RootDefinition* root) {
fDeferComment = nullptr;
} else {
if (fInEnum && KeyWord::kClass == child.fChildren[0]->fKeyWord) {
- if (!this->populate(child.fChildren[0], root)) {
+ if (!this->populate(child.fChildren[0], &pair, root)) {
return false;
}
- } else if (!this->populate(&child, root)) {
+ } else if (!this->populate(&child, &pair, root)) {
return false;
}
}
@@ -1023,9 +1046,12 @@ bool IncludeWriter::populate(Definition* def, RootDefinition* root) {
fDeferComment = nullptr;
fInEnum = false;
continue;
- }
+ }
+ if (fAttrDeprecated) {
+ continue;
+ }
fDeferComment = nullptr;
- if (!this->populate(&child, root)) {
+ if (!this->populate(&child, &pair, root)) {
return false;
}
continue;
@@ -1039,6 +1065,12 @@ bool IncludeWriter::populate(Definition* def, RootDefinition* root) {
if (child.fMemberStart) {
memberStart = &child;
}
+ const char attrDeprecated[] = "SK_ATTR_DEPRECATED";
+ const size_t attrDeprecatedLen = sizeof(attrDeprecated) - 1;
+ if (attrDeprecatedLen == child.fContentEnd - child.fContentStart &&
+ !strncmp(attrDeprecated, child.fStart, attrDeprecatedLen)) {
+ fAttrDeprecated = &child;
+ }
continue;
}
if (Definition::Type::kPunctuation == child.fType) {
@@ -1086,7 +1118,7 @@ bool IncludeWriter::populate(BmhParser& bmhParser) {
root->clearVisited();
fStart = includeMapper.second.fContentStart;
fEnd = includeMapper.second.fContentEnd;
- allPassed &= this->populate(&includeMapper.second, root);
+ allPassed &= this->populate(&includeMapper.second, nullptr, root);
this->writeBlock((int) (fEnd - fStart), fStart);
fIndent = 0;
this->lfcr();
@@ -1409,7 +1441,7 @@ IncludeWriter::Wrote IncludeWriter::rewriteBlock(int size, const char* data) {
case '\'': // possessive apostrophe isn't treated as delimiting punctation
case '=':
case '!': // assumed not to be punctuation, but a programming symbol
- case '&': case '>': case '<': case '{': case '}': case '/': case '*':
+ case '&': case '>': case '<': case '{': case '}': case '/': case '*': case '[': case ']':
word = Word::kMixed;
embeddedSymbol = true;
break;
@@ -1442,6 +1474,10 @@ IncludeWriter::Wrote IncludeWriter::rewriteBlock(int size, const char* data) {
}
hasSymbol |= embeddedSymbol;
break;
+ case '+':
+ // hackery to allow C++
+ SkASSERT('C' == last || '+' == last); // FIXME: don't allow + outside of #Formula
+ break;
case 'A': case 'B': case 'C': case 'D': case 'E':
case 'F': case 'G': case 'H': case 'I': case 'J':
case 'K': case 'L': case 'M': case 'N': case 'O':