Flutter Engine
The Flutter Engine
Classes | Public Types | Public Member Functions | Static Public Member Functions | Friends | List of all members
SkPath Class Reference

#include <SkPath.h>

Inheritance diagram for SkPath:
SkRecords::PreCachedPath

Classes

class  Iter
 
class  RawIter
 

Public Types

enum  ArcSize { kSmall_ArcSize , kLarge_ArcSize }
 
enum  AddPathMode { kAppend_AddPathMode , kExtend_AddPathMode }
 
enum  SegmentMask { kLine_SegmentMask = kLine_SkPathSegmentMask , kQuad_SegmentMask = kQuad_SkPathSegmentMask , kConic_SegmentMask = kConic_SkPathSegmentMask , kCubic_SegmentMask = kCubic_SkPathSegmentMask }
 
enum  Verb {
  kMove_Verb = static_cast<int>(SkPathVerb::kMove) , kLine_Verb = static_cast<int>(SkPathVerb::kLine) , kQuad_Verb = static_cast<int>(SkPathVerb::kQuad) , kConic_Verb = static_cast<int>(SkPathVerb::kConic) ,
  kCubic_Verb = static_cast<int>(SkPathVerb::kCubic) , kClose_Verb = static_cast<int>(SkPathVerb::kClose) , kDone_Verb = kClose_Verb + 1
}
 
using sk_is_trivially_relocatable = std::true_type
 

Public Member Functions

 SkPath ()
 
 SkPath (const SkPath &path)
 
 ~SkPath ()
 
SkPath snapshot () const
 
SkPath detach ()
 
SkPathoperator= (const SkPath &path)
 
bool isInterpolatable (const SkPath &compare) const
 
bool interpolate (const SkPath &ending, SkScalar weight, SkPath *out) const
 
SkPathFillType getFillType () const
 
void setFillType (SkPathFillType ft)
 
bool isInverseFillType () const
 
void toggleInverseFillType ()
 
bool isConvex () const
 
bool isOval (SkRect *bounds) const
 
bool isRRect (SkRRect *rrect) const
 
bool isArc (SkArc *arc) const
 
SkPathreset ()
 
SkPathrewind ()
 
bool isEmpty () const
 
bool isLastContourClosed () const
 
bool isFinite () const
 
bool isVolatile () const
 
SkPathsetIsVolatile (bool isVolatile)
 
bool isLine (SkPoint line[2]) const
 
int countPoints () const
 
SkPoint getPoint (int index) const
 
int getPoints (SkPoint points[], int max) const
 
int countVerbs () const
 
int getVerbs (uint8_t verbs[], int max) const
 
size_t approximateBytesUsed () const
 
void swap (SkPath &other)
 
const SkRectgetBounds () const
 
void updateBoundsCache () const
 
SkRect computeTightBounds () const
 
bool conservativelyContainsRect (const SkRect &rect) const
 
void incReserve (int extraPtCount, int extraVerbCount=0, int extraConicCount=0)
 
SkPathmoveTo (SkScalar x, SkScalar y)
 
SkPathmoveTo (const SkPoint &p)
 
SkPathrMoveTo (SkScalar dx, SkScalar dy)
 
SkPathlineTo (SkScalar x, SkScalar y)
 
SkPathlineTo (const SkPoint &p)
 
SkPathrLineTo (SkScalar dx, SkScalar dy)
 
SkPathquadTo (SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2)
 
SkPathquadTo (const SkPoint &p1, const SkPoint &p2)
 
SkPathrQuadTo (SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2)
 
SkPathconicTo (SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar w)
 
SkPathconicTo (const SkPoint &p1, const SkPoint &p2, SkScalar w)
 
SkPathrConicTo (SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2, SkScalar w)
 
SkPathcubicTo (SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3)
 
SkPathcubicTo (const SkPoint &p1, const SkPoint &p2, const SkPoint &p3)
 
SkPathrCubicTo (SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2, SkScalar dx3, SkScalar dy3)
 
SkPatharcTo (const SkRect &oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo)
 
SkPatharcTo (SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar radius)
 
SkPatharcTo (const SkPoint p1, const SkPoint p2, SkScalar radius)
 
SkPatharcTo (SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc, SkPathDirection sweep, SkScalar x, SkScalar y)
 
SkPatharcTo (const SkPoint r, SkScalar xAxisRotate, ArcSize largeArc, SkPathDirection sweep, const SkPoint xy)
 
SkPathrArcTo (SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc, SkPathDirection sweep, SkScalar dx, SkScalar dy)
 
SkPathclose ()
 
bool isRect (SkRect *rect, bool *isClosed=nullptr, SkPathDirection *direction=nullptr) const
 
SkPathaddRect (const SkRect &rect, SkPathDirection dir, unsigned start)
 
SkPathaddRect (const SkRect &rect, SkPathDirection dir=SkPathDirection::kCW)
 
SkPathaddRect (SkScalar left, SkScalar top, SkScalar right, SkScalar bottom, SkPathDirection dir=SkPathDirection::kCW)
 
SkPathaddOval (const SkRect &oval, SkPathDirection dir=SkPathDirection::kCW)
 
SkPathaddOval (const SkRect &oval, SkPathDirection dir, unsigned start)
 
SkPathaddOpenOval (const SkRect &oval, SkPathDirection dir, unsigned start)
 
SkPathaddCircle (SkScalar x, SkScalar y, SkScalar radius, SkPathDirection dir=SkPathDirection::kCW)
 
SkPathaddArc (const SkRect &oval, SkScalar startAngle, SkScalar sweepAngle)
 
SkPathaddRoundRect (const SkRect &rect, SkScalar rx, SkScalar ry, SkPathDirection dir=SkPathDirection::kCW)
 
SkPathaddRoundRect (const SkRect &rect, const SkScalar radii[], SkPathDirection dir=SkPathDirection::kCW)
 
SkPathaddRRect (const SkRRect &rrect, SkPathDirection dir=SkPathDirection::kCW)
 
SkPathaddRRect (const SkRRect &rrect, SkPathDirection dir, unsigned start)
 
SkPathaddPoly (const SkPoint pts[], int count, bool close)
 
SkPathaddPoly (const std::initializer_list< SkPoint > &list, bool close)
 
SkPathaddPath (const SkPath &src, SkScalar dx, SkScalar dy, AddPathMode mode=kAppend_AddPathMode)
 
SkPathaddPath (const SkPath &src, AddPathMode mode=kAppend_AddPathMode)
 
SkPathaddPath (const SkPath &src, const SkMatrix &matrix, AddPathMode mode=kAppend_AddPathMode)
 
SkPathreverseAddPath (const SkPath &src)
 
void offset (SkScalar dx, SkScalar dy, SkPath *dst) const
 
SkPathoffset (SkScalar dx, SkScalar dy)
 
void transform (const SkMatrix &matrix, SkPath *dst, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
 
SkPathtransform (const SkMatrix &matrix, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes)
 
SkPath makeTransform (const SkMatrix &m, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
 
SkPath makeScale (SkScalar sx, SkScalar sy)
 
bool getLastPt (SkPoint *lastPt) const
 
void setLastPt (SkScalar x, SkScalar y)
 
void setLastPt (const SkPoint &p)
 
uint32_t getSegmentMasks () const
 
bool contains (SkScalar x, SkScalar y) const
 
void dump (SkWStream *stream, bool dumpAsHex) const
 
void dump () const
 
void dumpHex () const
 
void dumpArrays (SkWStream *stream, bool dumpAsHex) const
 
void dumpArrays () const
 
size_t writeToMemory (void *buffer) const
 
sk_sp< SkDataserialize () const
 
size_t readFromMemory (const void *buffer, size_t length)
 
uint32_t getGenerationID () const
 
bool isValid () const
 

Static Public Member Functions

static SkPath Make (const SkPoint[], int pointCount, const uint8_t[], int verbCount, const SkScalar[], int conicWeightCount, SkPathFillType, bool isVolatile=false)
 
static SkPath Rect (const SkRect &, SkPathDirection=SkPathDirection::kCW, unsigned startIndex=0)
 
static SkPath Oval (const SkRect &, SkPathDirection=SkPathDirection::kCW)
 
static SkPath Oval (const SkRect &, SkPathDirection, unsigned startIndex)
 
static SkPath Circle (SkScalar center_x, SkScalar center_y, SkScalar radius, SkPathDirection dir=SkPathDirection::kCW)
 
static SkPath RRect (const SkRRect &, SkPathDirection dir=SkPathDirection::kCW)
 
static SkPath RRect (const SkRRect &, SkPathDirection, unsigned startIndex)
 
static SkPath RRect (const SkRect &bounds, SkScalar rx, SkScalar ry, SkPathDirection dir=SkPathDirection::kCW)
 
static SkPath Polygon (const SkPoint pts[], int count, bool isClosed, SkPathFillType=SkPathFillType::kWinding, bool isVolatile=false)
 
static SkPath Polygon (const std::initializer_list< SkPoint > &list, bool isClosed, SkPathFillType fillType=SkPathFillType::kWinding, bool isVolatile=false)
 
static SkPath Line (const SkPoint a, const SkPoint b)
 
static bool IsLineDegenerate (const SkPoint &p1, const SkPoint &p2, bool exact)
 
static bool IsQuadDegenerate (const SkPoint &p1, const SkPoint &p2, const SkPoint &p3, bool exact)
 
static bool IsCubicDegenerate (const SkPoint &p1, const SkPoint &p2, const SkPoint &p3, const SkPoint &p4, bool exact)
 
static int ConvertConicToQuads (const SkPoint &p0, const SkPoint &p1, const SkPoint &p2, SkScalar w, SkPoint pts[], int pow2)
 

Friends

class Iter
 
class SkPathPriv
 
class SkPathStroker
 
class SkAutoPathBoundsUpdate
 
class SkAutoDisableOvalCheck
 
class SkAutoDisableDirectionCheck
 
class SkPathBuilder
 
class SkPathEdgeIter
 
class SkPathWriter
 
class SkOpBuilder
 
class SkBench_AddPathTest
 
class PathTest_Private
 
class ForceIsRRect_Private
 
class FuzzPath
 
SK_API bool operator== (const SkPath &a, const SkPath &b)
 
bool operator!= (const SkPath &a, const SkPath &b)
 

Detailed Description

SkPath contain geometry. SkPath may be empty, or contain one or more verbs that outline a figure. SkPath 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. SkPath may contain any number of contours, each beginning with a move verb.

SkPath contours may contain only a move verb, or may also contain lines, quadratic beziers, conics, and cubic beziers. SkPath contours may be open or closed.

When used to draw a filled area, SkPath describes whether the fill is inside or outside the geometry. SkPath also describes the winding rule used to fill overlapping contours.

Internally, SkPath lazily computes metrics likes bounds and convexity. Call SkPath::updateBoundsCache to make SkPath thread safe.

Definition at line 59 of file SkPath.h.

Member Typedef Documentation

◆ sk_is_trivially_relocatable

using SkPath::sk_is_trivially_relocatable = std::true_type

Definition at line 1811 of file SkPath.h.

Member Enumeration Documentation

◆ AddPathMode

Enumerator
kAppend_AddPathMode 

Contours are appended to the destination path as new contours.

kExtend_AddPathMode 

Extends the last contour of the destination path with the first countour of the source path, connecting them with a line. If the last contour is closed, a new empty contour starting at its start point is extended instead. If the destination path is empty, the result is the source path. The last path of the result is closed only if the last path of the source is.

Definition at line 1283 of file SkPath.h.

1283 {
1284 /** Contours are appended to the destination path as new contours.
1285 */
1287 /** Extends the last contour of the destination path with the first countour
1288 of the source path, connecting them with a line. If the last contour is
1289 closed, a new empty contour starting at its start point is extended instead.
1290 If the destination path is empty, the result is the source path.
1291 The last path of the result is closed only if the last path of the source is.
1292 */
1294 };
@ kExtend_AddPathMode
Definition: SkPath.h:1293
@ kAppend_AddPathMode
Definition: SkPath.h:1286

◆ ArcSize

Enumerator
kSmall_ArcSize 

smaller of arc pair

kLarge_ArcSize 

larger of arc pair

Definition at line 923 of file SkPath.h.

923 {
924 kSmall_ArcSize, //!< smaller of arc pair
925 kLarge_ArcSize, //!< larger of arc pair
926 };
@ kSmall_ArcSize
smaller of arc pair
Definition: SkPath.h:924
@ kLarge_ArcSize
larger of arc pair
Definition: SkPath.h:925

◆ SegmentMask

Enumerator
kLine_SegmentMask 
kQuad_SegmentMask 
kConic_SegmentMask 
kCubic_SegmentMask 

Definition at line 1444 of file SkPath.h.

1444 {
1449 };
@ kCubic_SkPathSegmentMask
Definition: SkPathTypes.h:45
@ kConic_SkPathSegmentMask
Definition: SkPathTypes.h:44
@ kQuad_SkPathSegmentMask
Definition: SkPathTypes.h:43
@ kLine_SkPathSegmentMask
Definition: SkPathTypes.h:42
@ kLine_SegmentMask
Definition: SkPath.h:1445
@ kQuad_SegmentMask
Definition: SkPath.h:1446
@ kCubic_SegmentMask
Definition: SkPath.h:1448
@ kConic_SegmentMask
Definition: SkPath.h:1447

◆ Verb

Enumerator
kMove_Verb 
kLine_Verb 
kQuad_Verb 
kConic_Verb 
kCubic_Verb 
kClose_Verb 
kDone_Verb 

Definition at line 1465 of file SkPath.h.

1465 {
1466 kMove_Verb = static_cast<int>(SkPathVerb::kMove),
1467 kLine_Verb = static_cast<int>(SkPathVerb::kLine),
1468 kQuad_Verb = static_cast<int>(SkPathVerb::kQuad),
1469 kConic_Verb = static_cast<int>(SkPathVerb::kConic),
1470 kCubic_Verb = static_cast<int>(SkPathVerb::kCubic),
1471 kClose_Verb = static_cast<int>(SkPathVerb::kClose),
1473 };
@ kClose
SkPath::RawIter returns 0 points.
@ kCubic
SkPath::RawIter returns 4 points.
@ kConic
SkPath::RawIter returns 3 points + 1 weight.
@ kQuad
SkPath::RawIter returns 3 points.
@ kMove
SkPath::RawIter returns 1 point.
@ kLine
SkPath::RawIter returns 2 points.
@ kClose_Verb
Definition: SkPath.h:1471
@ kMove_Verb
Definition: SkPath.h:1466
@ kConic_Verb
Definition: SkPath.h:1469
@ kDone_Verb
Definition: SkPath.h:1472
@ kCubic_Verb
Definition: SkPath.h:1470
@ kQuad_Verb
Definition: SkPath.h:1468
@ kLine_Verb
Definition: SkPath.h:1467

Constructor & Destructor Documentation

◆ SkPath() [1/2]

SkPath::SkPath ( )

Constructs an empty SkPath. By default, SkPath has no verbs, no SkPoint, and no weights. FillType is set to kWinding.

Returns
empty SkPath

example: https://fiddle.skia.org/c/@Path_empty_constructor

Definition at line 156 of file SkPath.cpp.

157 : fPathRef(SkPathRef::CreateEmpty()) {
158 this->resetFields();
159 fIsVolatile = false;
160}
static SkPathRef * CreateEmpty()
Definition: SkPathRef.cpp:77

◆ SkPath() [2/2]

SkPath::SkPath ( const SkPath path)

Constructs a copy of an existing path. Copy constructor makes two paths identical by value. Internally, path and the returned result share pointer values. The underlying verb array, SkPoint array and weights are copied when modified.

Creating a SkPath copy is very efficient and never allocates memory. SkPath are always copied by value from the interface; the underlying shared pointers are not exposed.

Parameters
pathSkPath to copy by value
Returns
copy of SkPath

example: https://fiddle.skia.org/c/@Path_copy_const_SkPath

Definition at line 180 of file SkPath.cpp.

181 : fPathRef(SkRef(that.fPathRef.get())) {
182 this->copyFields(that);
183 SkDEBUGCODE(that.validate();)
184}
static T * SkRef(T *obj)
Definition: SkRefCnt.h:132
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()

◆ ~SkPath()

SkPath::~SkPath ( )

Releases ownership of any shared data and deletes data if SkPath is sole owner.

example: https://fiddle.skia.org/c/@Path_destructor

Definition at line 186 of file SkPath.cpp.

186 {
187 SkDEBUGCODE(this->validate();)
188}

Member Function Documentation

◆ addArc()

SkPath & SkPath::addArc ( const SkRect oval,
SkScalar  startAngle,
SkScalar  sweepAngle 
)

Appends arc to SkPath, as the start of new contour. Arc added is part of ellipse bounded by oval, from startAngle through sweepAngle. Both startAngle and sweepAngle are measured in degrees, where zero degrees is aligned with the positive x-axis, and positive sweeps extends arc clockwise.

If sweepAngle <= -360, or sweepAngle >= 360; and startAngle modulo 90 is nearly zero, append oval instead of arc. Otherwise, sweepAngle values are treated modulo 360, and arc may or may not draw depending on numeric rounding.

Parameters
ovalbounds of ellipse containing arc
startAnglestarting angle of arc in degrees
sweepAnglesweep, in degrees. Positive is clockwise; treated modulo 360
Returns
reference to SkPath

example: https://fiddle.skia.org/c/@Path_addArc

Definition at line 1439 of file SkPath.cpp.

1439 {
1440 if (oval.isEmpty() || 0 == sweepAngle) {
1441 return *this;
1442 }
1443
1444 const SkScalar kFullCircleAngle = SkIntToScalar(360);
1445
1446 if (sweepAngle >= kFullCircleAngle || sweepAngle <= -kFullCircleAngle) {
1447 // We can treat the arc as an oval if it begins at one of our legal starting positions.
1448 // See SkPath::addOval() docs.
1449 SkScalar startOver90 = startAngle / 90.f;
1450 SkScalar startOver90I = SkScalarRoundToScalar(startOver90);
1451 SkScalar error = startOver90 - startOver90I;
1452 if (SkScalarNearlyEqual(error, 0)) {
1453 // Index 1 is at startAngle == 0.
1454 SkScalar startIndex = std::fmod(startOver90I + 1.f, 4.f);
1455 startIndex = startIndex < 0 ? startIndex + 4.f : startIndex;
1457 (unsigned) startIndex);
1458 }
1459 }
1460 return this->arcTo(oval, startAngle, sweepAngle, true);
1461}
static bool SkScalarNearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance=SK_ScalarNearlyZero)
Definition: SkScalar.h:107
#define SkIntToScalar(x)
Definition: SkScalar.h:57
#define SkScalarRoundToScalar(x)
Definition: SkScalar.h:32
SkPath & arcTo(const SkRect &oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo)
Definition: SkPath.cpp:1220
SkPath & addOval(const SkRect &oval, SkPathDirection dir=SkPathDirection::kCW)
Definition: SkPath.cpp:1106
float SkScalar
Definition: extension.cpp:12
const uint8_t uint32_t uint32_t GError ** error
SkRect oval
Definition: SkRecords.h:249
SkScalar startAngle
Definition: SkRecords.h:250
SkScalar sweepAngle
Definition: SkRecords.h:251
bool isEmpty() const
Definition: SkRect.h:693

◆ addCircle()

SkPath & SkPath::addCircle ( SkScalar  x,
SkScalar  y,
SkScalar  radius,
SkPathDirection  dir = SkPathDirection::kCW 
)

Adds circle centered at (x, y) of size radius to SkPath, appending kMove_Verb, four kConic_Verb, and kClose_Verb. Circle begins at: (x + radius, y), continuing clockwise if dir is kCW_Direction, and counterclockwise if dir is kCCW_Direction.

Has no effect if radius is zero or negative.

Parameters
xcenter of circle
ycenter of circle
radiusdistance from center to edge
dirSkPath::Direction to wind circle
Returns
reference to SkPath

Definition at line 1213 of file SkPath.cpp.

1213 {
1214 if (r > 0) {
1215 this->addOval(SkRect::MakeLTRB(x - r, y - r, x + r, y + r), dir);
1216 }
1217 return *this;
1218}
double y
double x
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets dir
Definition: switches.h:145
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition: SkRect.h:646

◆ addOpenOval()

SkPath & SkPath::addOpenOval ( const SkRect oval,
SkPathDirection  dir,
unsigned  start 
)

Experimental, subject to change or removal.

Adds an "open" oval to SkPath. This follows canvas2D semantics: The oval is not a separate contour. If the path was empty, then kMove_Verb is appended. Otherwise, kLine_Verb is appended. Four kConic_Verbs are appended. kClose_Verb is not appended.

Definition at line 1161 of file SkPath.cpp.

1161 {
1163
1164 // Canvas2D semantics are different than our standard addOval. In the case of an empty
1165 // initial path, we inject a moveTo. In any other case, we actually start with a lineTo
1166 // (as if we simply called arcTo). Thus, we only treat the result as an (open) oval for
1167 // future queries if we started out empty.
1168 bool wasEmpty = this->isEmpty();
1169 if (wasEmpty) {
1170 this->setFirstDirection((SkPathFirstDirection)dir);
1171 } else {
1172 this->setFirstDirection(SkPathFirstDirection::kUnknown);
1173 }
1174
1175 SkAutoDisableDirectionCheck addc(this);
1176 SkAutoPathBoundsUpdate apbu(this, oval);
1177
1178 SkDEBUGCODE(int initialVerbCount = fPathRef->countVerbs());
1179 SkDEBUGCODE(int initialPointCount = fPathRef->countPoints());
1180 SkDEBUGCODE(int initialWeightCount = fPathRef->countWeights());
1181 // We reserve space for one extra verb. The caller usually adds kClose immediately
1182 const int kVerbs = 6; // moveTo/lineTo + 4x conicTo + (kClose)?
1183 const int kPoints = 9;
1184 const int kWeights = 4;
1185 this->incReserve(kPoints, kVerbs, kWeights);
1186
1187 SkPath_OvalPointIterator ovalIter(oval, dir, startPointIndex);
1188 // The corner iterator pts are tracking "behind" the oval/radii pts.
1189 SkPath_RectPointIterator rectIter(
1190 oval, dir, startPointIndex + (dir == SkPathDirection::kCW ? 0 : 1));
1191 const SkScalar kConicWeight = SK_ScalarRoot2Over2;
1192
1193 if (wasEmpty) {
1194 this->moveTo(ovalIter.current());
1195 } else {
1196 this->lineTo(ovalIter.current());
1197 }
1198 for (unsigned i = 0; i < 4; ++i) {
1199 this->conicTo(rectIter.next(), ovalIter.next(), kConicWeight);
1200 }
1201
1202 SkASSERT(fPathRef->countVerbs() == initialVerbCount + kVerbs - 1); // See comment above
1203 SkASSERT(fPathRef->countPoints() == initialPointCount + kPoints);
1204 SkASSERT(fPathRef->countWeights() == initialWeightCount + kWeights);
1205
1206 if (wasEmpty) {
1207 SkPathRef::Editor ed(&fPathRef);
1208 ed.setIsOval(SkPathDirection::kCCW == dir, startPointIndex % 4, /*isClosed=*/false);
1209 }
1210 return *this;
1211}
#define SkASSERT(cond)
Definition: SkAssert.h:116
SkPathFirstDirection
Definition: SkPathEnums.h:19
static void assert_known_direction(SkPathDirection dir)
Definition: SkPath.cpp:860
#define SK_ScalarRoot2Over2
Definition: SkScalar.h:23
int countWeights() const
Definition: SkPathRef.h:309
int countPoints() const
Definition: SkPathRef.h:307
int countVerbs() const
Definition: SkPathRef.h:308
bool isEmpty() const
Definition: SkPath.cpp:416
SkPath & moveTo(SkScalar x, SkScalar y)
Definition: SkPath.cpp:688
SkPath & lineTo(SkScalar x, SkScalar y)
Definition: SkPath.cpp:728
SkPath & conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar w)
Definition: SkPath.cpp:766
void incReserve(int extraPtCount, int extraVerbCount=0, int extraConicCount=0)
Definition: SkPath.cpp:678

◆ addOval() [1/2]

SkPath & SkPath::addOval ( const SkRect oval,
SkPathDirection  dir,
unsigned  start 
)

Adds oval to SkPath, appending kMove_Verb, four kConic_Verb, and kClose_Verb. Oval is upright ellipse bounded by SkRect oval with radii equal to half oval width and half oval height. Oval begins at start and continues clockwise if dir is kCW_Direction, counterclockwise if dir is kCCW_Direction.

Parameters
ovalbounds of ellipse added
dirSkPath::Direction to wind ellipse
startindex of initial point of ellipse
Returns
reference to SkPath

example: https://fiddle.skia.org/c/@Path_addOval_2

Definition at line 1111 of file SkPath.cpp.

1111 {
1113
1114 /* If addOval() is called after previous moveTo(),
1115 this path is still marked as an oval. This is used to
1116 fit into WebKit's calling sequences.
1117 We can't simply check isEmpty() in this case, as additional
1118 moveTo() would mark the path non empty.
1119 */
1120 bool isOval = hasOnlyMoveTos();
1121 if (isOval) {
1122 this->setFirstDirection((SkPathFirstDirection)dir);
1123 } else {
1124 this->setFirstDirection(SkPathFirstDirection::kUnknown);
1125 }
1126
1127 SkAutoDisableDirectionCheck addc(this);
1128 SkAutoPathBoundsUpdate apbu(this, oval);
1129
1130 SkDEBUGCODE(int initialVerbCount = fPathRef->countVerbs());
1131 SkDEBUGCODE(int initialPointCount = fPathRef->countPoints());
1132 SkDEBUGCODE(int initialWeightCount = fPathRef->countWeights());
1133 const int kVerbs = 6; // moveTo + 4x conicTo + close
1134 const int kPoints = 9;
1135 const int kWeights = 4;
1136 this->incReserve(kPoints, kVerbs, kWeights);
1137
1138 SkPath_OvalPointIterator ovalIter(oval, dir, startPointIndex);
1139 // The corner iterator pts are tracking "behind" the oval/radii pts.
1140 SkPath_RectPointIterator rectIter(
1141 oval, dir, startPointIndex + (dir == SkPathDirection::kCW ? 0 : 1));
1142 const SkScalar kConicWeight = SK_ScalarRoot2Over2;
1143
1144 this->moveTo(ovalIter.current());
1145 for (unsigned i = 0; i < 4; ++i) {
1146 this->conicTo(rectIter.next(), ovalIter.next(), kConicWeight);
1147 }
1148 this->close();
1149
1150 SkASSERT(fPathRef->countVerbs() == initialVerbCount + kVerbs);
1151 SkASSERT(fPathRef->countPoints() == initialPointCount + kPoints);
1152 SkASSERT(fPathRef->countWeights() == initialWeightCount + kWeights);
1153
1154 if (isOval) {
1155 SkPathRef::Editor ed(&fPathRef);
1156 ed.setIsOval(SkPathDirection::kCCW == dir, startPointIndex % 4, /*isClosed=*/true);
1157 }
1158 return *this;
1159}
bool isOval(SkRect *bounds) const
Definition: SkPath.cpp:523
SkPath & close()
Definition: SkPath.cpp:823

◆ addOval() [2/2]

SkPath & SkPath::addOval ( const SkRect oval,
SkPathDirection  dir = SkPathDirection::kCW 
)

Adds oval to path, appending kMove_Verb, four kConic_Verb, and kClose_Verb. Oval is upright ellipse bounded by SkRect oval with radii equal to half oval width and half oval height. Oval begins at (oval.fRight, oval.centerY()) and continues clockwise if dir is kCW_Direction, counterclockwise if dir is kCCW_Direction.

Parameters
ovalbounds of ellipse added
dirSkPath::Direction to wind ellipse
Returns
reference to SkPath

example: https://fiddle.skia.org/c/@Path_addOval

Definition at line 1106 of file SkPath.cpp.

1106 {
1107 // legacy start index: 1
1108 return this->addOval(oval, dir, 1);
1109}

◆ addPath() [1/3]

SkPath & SkPath::addPath ( const SkPath src,
AddPathMode  mode = kAppend_AddPathMode 
)
inline

Appends src to SkPath.

If mode is kAppend_AddPathMode, src verb array, SkPoint array, and conic weights are added unaltered. If mode is kExtend_AddPathMode, add line before appending verbs, SkPoint, and conic weights.

Parameters
srcSkPath verbs, SkPoint, and conic weights to add
modekAppend_AddPathMode or kExtend_AddPathMode
Returns
reference to SkPath

Definition at line 1321 of file SkPath.h.

1321 {
1322 SkMatrix m;
1323 m.reset();
1324 return this->addPath(src, m, mode);
1325 }
SkPath & addPath(const SkPath &src, SkScalar dx, SkScalar dy, AddPathMode mode=kAppend_AddPathMode)
Definition: SkPath.cpp:1506
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
Definition: switches.h:228

◆ addPath() [2/3]

SkPath & SkPath::addPath ( const SkPath src,
const SkMatrix matrix,
AddPathMode  mode = kAppend_AddPathMode 
)

Appends src to SkPath, transformed by matrix. Transformed curves may have different verbs, SkPoint, and conic weights.

If mode is kAppend_AddPathMode, src verb array, SkPoint array, and conic weights are added unaltered. If mode is kExtend_AddPathMode, add line before appending verbs, SkPoint, and conic weights.

Parameters
srcSkPath verbs, SkPoint, and conic weights to add
matrixtransform applied to src
modekAppend_AddPathMode or kExtend_AddPathMode
Returns
reference to SkPath

Definition at line 1513 of file SkPath.cpp.

1513 {
1514 if (srcPath.isEmpty()) {
1515 return *this;
1516 }
1517
1518 if (this->isEmpty() && matrix.isIdentity()) {
1519 const uint8_t fillType = fFillType;
1520 *this = srcPath;
1521 fFillType = fillType;
1522 return *this;
1523 }
1524
1525 // Detect if we're trying to add ourself
1526 const SkPath* src = &srcPath;
1527 SkTLazy<SkPath> tmp;
1528 if (this == src) {
1529 src = tmp.set(srcPath);
1530 }
1531
1532 if (kAppend_AddPathMode == mode && !matrix.hasPerspective()) {
1533 if (src->fLastMoveToIndex >= 0) {
1534 fLastMoveToIndex = src->fLastMoveToIndex + this->countPoints();
1535 } else {
1536 fLastMoveToIndex = src->fLastMoveToIndex - this->countPoints();
1537 }
1538 SkPathRef::Editor ed(&fPathRef);
1539 auto [newPts, newWeights] = ed.growForVerbsInPath(*src->fPathRef);
1540 matrix.mapPoints(newPts, src->fPathRef->points(), src->countPoints());
1541 if (int numWeights = src->fPathRef->countWeights()) {
1542 memcpy(newWeights, src->fPathRef->conicWeights(), numWeights * sizeof(newWeights[0]));
1543 }
1544 return this->dirtyAfterEdit();
1545 }
1546
1548 bool firstVerb = true;
1549 for (auto [verb, pts, w] : SkPathPriv::Iterate(*src)) {
1550 SkPoint mappedPts[3];
1551 switch (verb) {
1552 case SkPathVerb::kMove:
1553 mapPtsProc(matrix, mappedPts, &pts[0], 1);
1554 if (firstVerb && mode == kExtend_AddPathMode && !isEmpty()) {
1555 injectMoveToIfNeeded(); // In case last contour is closed
1556 SkPoint lastPt;
1557 // don't add lineTo if it is degenerate
1558 if (!this->getLastPt(&lastPt) || lastPt != mappedPts[0]) {
1559 this->lineTo(mappedPts[0]);
1560 }
1561 } else {
1562 this->moveTo(mappedPts[0]);
1563 }
1564 break;
1565 case SkPathVerb::kLine:
1566 mapPtsProc(matrix, mappedPts, &pts[1], 1);
1567 this->lineTo(mappedPts[0]);
1568 break;
1569 case SkPathVerb::kQuad:
1570 mapPtsProc(matrix, mappedPts, &pts[1], 2);
1571 this->quadTo(mappedPts[0], mappedPts[1]);
1572 break;
1573 case SkPathVerb::kConic:
1574 mapPtsProc(matrix, mappedPts, &pts[1], 2);
1575 this->conicTo(mappedPts[0], mappedPts[1], *w);
1576 break;
1577 case SkPathVerb::kCubic:
1578 mapPtsProc(matrix, mappedPts, &pts[1], 3);
1579 this->cubicTo(mappedPts[0], mappedPts[1], mappedPts[2]);
1580 break;
1581 case SkPathVerb::kClose:
1582 this->close();
1583 break;
1584 }
1585 firstVerb = false;
1586 }
1587 return *this;
1588}
static MapPtsProc GetMapPtsProc(const SkMatrix &matrix)
Definition: SkMatrixPriv.h:42
SkMatrix::MapPtsProc MapPtsProc
Definition: SkMatrixPriv.h:39
bool isIdentity() const
Definition: SkMatrix.h:223
Definition: SkPath.h:59
int countPoints() const
Definition: SkPath.cpp:535
bool getLastPt(SkPoint *lastPt) const
Definition: SkPath.cpp:580
SkPath & quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2)
Definition: SkPath.cpp:746
SkPath & cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3)
Definition: SkPath.cpp:799
T * set(const T &src)
Definition: SkTLazy.h:56
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258
SkScalar w

◆ addPath() [3/3]

SkPath & SkPath::addPath ( const SkPath src,
SkScalar  dx,
SkScalar  dy,
AddPathMode  mode = kAppend_AddPathMode 
)

Appends src to SkPath, offset by (dx, dy).

If mode is kAppend_AddPathMode, src verb array, SkPoint array, and conic weights are added unaltered. If mode is kExtend_AddPathMode, add line before appending verbs, SkPoint, and conic weights.

Parameters
srcSkPath verbs, SkPoint, and conic weights to add
dxoffset added to src SkPoint array x-axis coordinates
dyoffset added to src SkPoint array y-axis coordinates
modekAppend_AddPathMode or kExtend_AddPathMode
Returns
reference to SkPath

Definition at line 1506 of file SkPath.cpp.

1506 {
1508
1509 matrix.setTranslate(dx, dy);
1510 return this->addPath(path, matrix, mode);
1511}
skia_private::AutoTArray< sk_sp< SkImageFilter > > filters TypedMatrix matrix TypedMatrix matrix SkScalar dx
Definition: SkRecords.h:208
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57

◆ addPoly() [1/2]

SkPath & SkPath::addPoly ( const SkPoint  pts[],
int  count,
bool  close 
)

Adds contour created from line array, adding (count - 1) line segments. Contour added starts at pts[0], then adds a line for every additional SkPoint in pts array. If close is true, appends kClose_Verb to SkPath, 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.

Parameters
ptsarray of line sharing end and start SkPoint
countlength of SkPoint array
closetrue to add line connecting contour end and start
Returns
reference to SkPath

example: https://fiddle.skia.org/c/@Path_addPoly

Definition at line 890 of file SkPath.cpp.

890 {
891 SkDEBUGCODE(this->validate();)
892 if (count <= 0) {
893 return *this;
894 }
895
896 fLastMoveToIndex = fPathRef->countPoints();
897
898 // +close makes room for the extra kClose_Verb
899 SkPathRef::Editor ed(&fPathRef, count+close, count);
900
901 ed.growForVerb(kMove_Verb)->set(pts[0].fX, pts[0].fY);
902 if (count > 1) {
903 SkPoint* p = ed.growForRepeatedVerb(kLine_Verb, count - 1);
904 memcpy(p, &pts[1], (count-1) * sizeof(SkPoint));
905 }
906
907 if (close) {
908 ed.growForVerb(kClose_Verb);
909 fLastMoveToIndex ^= ~fLastMoveToIndex >> (8 * sizeof(fLastMoveToIndex) - 1);
910 }
911
912 (void)this->dirtyAfterEdit();
913 SkDEBUGCODE(this->validate();)
914 return *this;
915}
int count
Definition: FontMgrTest.cpp:50

◆ addPoly() [2/2]

SkPath & SkPath::addPoly ( const std::initializer_list< SkPoint > &  list,
bool  close 
)
inline

Adds contour created from list. Contour added starts at list[0], then adds a line for every additional SkPoint in list. If close is true, appends kClose_Verb to SkPath, connecting last and first SkPoint in list.

If list is empty, append kMove_Verb to path.

Parameters
listarray of SkPoint
closetrue to add line connecting contour end and start
Returns
reference to SkPath

Definition at line 1271 of file SkPath.h.

1271 {
1272 return this->addPoly(list.begin(), SkToInt(list.size()), close);
1273 }
constexpr int SkToInt(S x)
Definition: SkTo.h:29
SkPath & addPoly(const SkPoint pts[], int count, bool close)
Definition: SkPath.cpp:890

◆ addRect() [1/3]

SkPath & SkPath::addRect ( const SkRect rect,
SkPathDirection  dir,
unsigned  start 
)

Adds a new contour to the path, defined by the rect, and wound in the specified direction. The verbs added to the path will be:

kMove, kLine, kLine, kLine, kClose

start specifies which corner to begin the contour: 0: upper-left corner 1: upper-right corner 2: lower-right corner 3: lower-left corner

This start point also acts as the implied beginning of the subsequent, contour, if it does not have an explicit moveTo(). e.g.

path.addRect(...)

if we don't say moveTo() here, we will use the rect's start point path.lineTo(...)

Parameters
rectSkRect to add as a closed contour
dirSkPath::Direction to orient the new contour
startinitial corner of SkRect to add
Returns
reference to SkPath

example: https://fiddle.skia.org/c/@Path_addRect_2

Definition at line 864 of file SkPath.cpp.

864 {
866 this->setFirstDirection(this->hasOnlyMoveTos() ? (SkPathFirstDirection)dir
869 SkAutoPathBoundsUpdate apbu(this, rect);
870
871 SkDEBUGCODE(int initialVerbCount = this->countVerbs());
872
873 const int kVerbs = 5; // moveTo + 3x lineTo + close
874 SkPathRef::Editor ed(&fPathRef, kVerbs, /* points */ 4);
875
876 SkPath_RectPointIterator iter(rect, dir, startIndex);
877 fLastMoveToIndex = fPathRef->countPoints();
878
879 *ed.growForVerb(kMove_Verb) = iter.current();
880 *ed.growForVerb(kLine_Verb) = iter.next();
881 *ed.growForVerb(kLine_Verb) = iter.next();
882 *ed.growForVerb(kLine_Verb) = iter.next();
883 this->close();
884 (void)this->dirtyAfterEdit();
885
886 SkASSERT(this->countVerbs() == initialVerbCount + kVerbs);
887 return *this;
888}
int countVerbs() const
Definition: SkPath.cpp:556
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350

◆ addRect() [2/3]

SkPath & SkPath::addRect ( const SkRect rect,
SkPathDirection  dir = SkPathDirection::kCW 
)
inline

Definition at line 1106 of file SkPath.h.

1106 {
1107 return this->addRect(rect, dir, 0);
1108 }
SkPath & addRect(const SkRect &rect, SkPathDirection dir, unsigned start)
Definition: SkPath.cpp:864

◆ addRect() [3/3]

SkPath & SkPath::addRect ( SkScalar  left,
SkScalar  top,
SkScalar  right,
SkScalar  bottom,
SkPathDirection  dir = SkPathDirection::kCW 
)
inline

Definition at line 1110 of file SkPath.h.

1111 {
1112 return this->addRect({left, top, right, bottom}, dir, 0);
1113 }
static bool left(const SkPoint &p0, const SkPoint &p1)
static bool right(const SkPoint &p0, const SkPoint &p1)

◆ addRoundRect() [1/2]

SkPath & SkPath::addRoundRect ( const SkRect rect,
const SkScalar  radii[],
SkPathDirection  dir = SkPathDirection::kCW 
)

Appends SkRRect to SkPath, creating a new closed contour. SkRRect has bounds equal to rect; each corner is 90 degrees of an ellipse with radii from the array.

Parameters
rectbounds of SkRRect
radiiarray of 8 SkScalar values, a radius pair for each corner
dirSkPath::Direction to wind SkRRect
Returns
reference to SkPath

Definition at line 993 of file SkPath.cpp.

994 {
996 rrect.setRectRadii(rect, (const SkVector*) radii);
997 return this->addRRect(rrect, dir);
998}
SkPath & addRRect(const SkRRect &rrect, SkPathDirection dir=SkPathDirection::kCW)
Definition: SkPath.cpp:1000
void setRectRadii(const SkRect &rect, const SkVector radii[4])
Definition: SkRRect.cpp:189
SkRRect rrect
Definition: SkRecords.h:232

◆ addRoundRect() [2/2]

SkPath & SkPath::addRoundRect ( const SkRect rect,
SkScalar  rx,
SkScalar  ry,
SkPathDirection  dir = SkPathDirection::kCW 
)

Appends SkRRect to SkPath, creating a new closed contour. SkRRect has bounds equal to rect; each corner is 90 degrees of an ellipse with radii (rx, ry). If dir is kCW_Direction, SkRRect starts at top-left of the lower-left corner and winds clockwise. If dir is kCCW_Direction, SkRRect starts at the bottom-left of the upper-left corner and winds counterclockwise.

If either rx or ry is too large, rx and ry are scaled uniformly until the corners fit. If rx or ry is less than or equal to zero, addRoundRect() appends SkRect rect to SkPath.

After appending, SkPath may be empty, or may contain: SkRect, oval, or SkRRect.

Parameters
rectbounds of SkRRect
rxx-axis radius of rounded corners on the SkRRect
ryy-axis radius of rounded corners on the SkRRect
dirSkPath::Direction to wind SkRRect
Returns
reference to SkPath

Definition at line 1093 of file SkPath.cpp.

1094 {
1096
1097 if (rx < 0 || ry < 0) {
1098 return *this;
1099 }
1100
1101 SkRRect rrect;
1102 rrect.setRectXY(rect, rx, ry);
1103 return this->addRRect(rrect, dir);
1104}
void setRectXY(const SkRect &rect, SkScalar xRad, SkScalar yRad)
Definition: SkRRect.cpp:52

◆ addRRect() [1/2]

SkPath & SkPath::addRRect ( const SkRRect rrect,
SkPathDirection  dir,
unsigned  start 
)

Adds rrect to SkPath, creating a new closed contour. If dir is kCW_Direction, rrect winds clockwise; if dir is kCCW_Direction, rrect winds counterclockwise. start determines the first point of rrect to add.

Parameters
rrectbounds and radii of rounded rectangle
dirSkPath::Direction to wind SkRRect
startindex of initial point of SkRRect
Returns
reference to SkPath

example: https://fiddle.skia.org/c/@Path_addRRect_2

Definition at line 1005 of file SkPath.cpp.

1005 {
1007
1008 bool isRRect = hasOnlyMoveTos();
1009 const SkRect& bounds = rrect.getBounds();
1010
1011 if (rrect.isRect() || rrect.isEmpty()) {
1012 // degenerate(rect) => radii points are collapsing
1013 this->addRect(bounds, dir, (startIndex + 1) / 2);
1014 } else if (rrect.isOval()) {
1015 // degenerate(oval) => line points are collapsing
1016 this->addOval(bounds, dir, startIndex / 2);
1017 } else {
1018 this->setFirstDirection(this->hasOnlyMoveTos() ? (SkPathFirstDirection)dir
1020
1021 SkAutoPathBoundsUpdate apbu(this, bounds);
1022 SkAutoDisableDirectionCheck addc(this);
1023
1024 // we start with a conic on odd indices when moving CW vs. even indices when moving CCW
1025 const bool startsWithConic = ((startIndex & 1) == (dir == SkPathDirection::kCW));
1026 const SkScalar weight = SK_ScalarRoot2Over2;
1027
1028 SkDEBUGCODE(int initialVerbCount = fPathRef->countVerbs());
1029 SkDEBUGCODE(int initialPointCount = fPathRef->countPoints());
1030 SkDEBUGCODE(int initialWeightCount = fPathRef->countWeights());
1031 const int kVerbs = startsWithConic
1032 ? 9 // moveTo + 4x conicTo + 3x lineTo + close
1033 : 10; // moveTo + 4x lineTo + 4x conicTo + close
1034 const int kPoints = startsWithConic
1035 ? 12 // moveTo (1) + 4x conicTo (2) + 3x lineTo (1) + close
1036 : 13; // moveTo (1) + 4x lineTo (1) + 4x conicTo (2) + close
1037 const int kWeights = 4; // 4x conicTo
1038 this->incReserve(kPoints, kVerbs, kWeights);
1039
1040 SkPath_RRectPointIterator rrectIter(rrect, dir, startIndex);
1041 // Corner iterator indices follow the collapsed radii model,
1042 // adjusted such that the start pt is "behind" the radii start pt.
1043 const unsigned rectStartIndex = startIndex / 2 + (dir == SkPathDirection::kCW ? 0 : 1);
1044 SkPath_RectPointIterator rectIter(bounds, dir, rectStartIndex);
1045
1046 this->moveTo(rrectIter.current());
1047 if (startsWithConic) {
1048 for (unsigned i = 0; i < 3; ++i) {
1049 this->conicTo(rectIter.next(), rrectIter.next(), weight);
1050 this->lineTo(rrectIter.next());
1051 }
1052 this->conicTo(rectIter.next(), rrectIter.next(), weight);
1053 // final lineTo handled by close().
1054 } else {
1055 for (unsigned i = 0; i < 4; ++i) {
1056 this->lineTo(rrectIter.next());
1057 this->conicTo(rectIter.next(), rrectIter.next(), weight);
1058 }
1059 }
1060 this->close();
1061
1062 if (isRRect) {
1063 SkPathRef::Editor ed(&fPathRef);
1064 ed.setIsRRect(dir == SkPathDirection::kCCW, startIndex % 8);
1065 }
1066
1067 SkASSERT(fPathRef->countVerbs() == initialVerbCount + kVerbs);
1068 SkASSERT(fPathRef->countPoints() == initialPointCount + kPoints);
1069 SkASSERT(fPathRef->countWeights() == initialWeightCount + kWeights);
1070 }
1071
1072 SkDEBUGCODE(fPathRef->validate();)
1073 return *this;
1074}
bool isRRect(SkRRect *rrect) const
Definition: SkPath.cpp:527
bool isOval() const
Definition: SkRRect.h:85
bool isRect() const
Definition: SkRRect.h:84
bool isEmpty() const
Definition: SkRRect.h:83
const SkRect & getBounds() const
Definition: SkRRect.h:279
Optional< SkRect > bounds
Definition: SkRecords.h:189

◆ addRRect() [2/2]

SkPath & SkPath::addRRect ( const SkRRect rrect,
SkPathDirection  dir = SkPathDirection::kCW 
)

Adds rrect to SkPath, creating a new closed contour. If dir is kCW_Direction, rrect starts at top-left of the lower-left corner and winds clockwise. If dir is kCCW_Direction, rrect starts at the bottom-left of the upper-left corner and winds counterclockwise.

After appending, SkPath may be empty, or may contain: SkRect, oval, or SkRRect.

Parameters
rrectbounds and radii of rounded rectangle
dirSkPath::Direction to wind SkRRect
Returns
reference to SkPath

example: https://fiddle.skia.org/c/@Path_addRRect

Definition at line 1000 of file SkPath.cpp.

1000 {
1001 // legacy start indices: 6 (CW) and 7(CCW)
1002 return this->addRRect(rrect, dir, dir == SkPathDirection::kCW ? 6 : 7);
1003}

◆ approximateBytesUsed()

size_t SkPath::approximateBytesUsed ( ) const

Returns the approximate byte size of the SkPath in memory.

Returns
approximate size

Definition at line 572 of file SkPath.cpp.

572 {
573 size_t size = sizeof (SkPath);
574 if (fPathRef != nullptr) {
575 size += fPathRef->approximateBytesUsed();
576 }
577 return size;
578}
size_t approximateBytesUsed() const
Definition: SkPathRef.cpp:61
SkPath()
Definition: SkPath.cpp:156
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259

◆ arcTo() [1/5]

SkPath & SkPath::arcTo ( const SkPoint  p1,
const SkPoint  p2,
SkScalar  radius 
)
inline

Appends arc to SkPath, after appending line if needed. Arc is implemented by conic weighted to describe part of circle. Arc is contained by tangent from last SkPath point to p1, and tangent from p1 to p2. Arc is part of circle sized to radius, positioned so it touches both tangent lines.

If last SkPath SkPoint does not start arc, arcTo() appends connecting line to SkPath. The length of 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 SkPath SkPoint to p1.

arcTo() appends at most one line and one conic. arcTo() implements the functionality of PostScript arct and HTML Canvas arcTo.

Parameters
p1SkPoint common to pair of tangents
p2end of second tangent
radiusdistance from arc to circle center
Returns
reference to SkPath

Definition at line 915 of file SkPath.h.

915 {
916 return this->arcTo(p1.fX, p1.fY, p2.fX, p2.fY, radius);
917 }
float fX
x-axis value
Definition: SkPoint_impl.h:164
float fY
y-axis value
Definition: SkPoint_impl.h:165

◆ arcTo() [2/5]

SkPath & SkPath::arcTo ( const SkPoint  r,
SkScalar  xAxisRotate,
ArcSize  largeArc,
SkPathDirection  sweep,
const SkPoint  xy 
)
inline

Appends arc to SkPath. Arc is implemented by one or more conic weighted to describe part of oval with radii (r.fX, r.fY) rotated by xAxisRotate degrees. Arc curves from last SkPath SkPoint to (xy.fX, xy.fY), choosing one of four possible routes: clockwise or counterclockwise, and smaller or larger.

Arc sweep is always less than 360 degrees. arcTo() appends line to xy if either radii are zero, or if last SkPath SkPoint equals (xy.fX, xy.fY). arcTo() scales radii r to fit last SkPath SkPoint and xy if both are greater than zero but too small to describe an arc.

arcTo() appends up to four conic curves. arcTo() implements the functionality of SVG arc, although SVG sweep-flag value is opposite the integer value of sweep; SVG sweep-flag uses 1 for clockwise, while kCW_Direction cast to int is zero.

Parameters
rradii on axes before x-axis rotation
xAxisRotatex-axis rotation in degrees; positive values are clockwise
largeArcchooses smaller or larger arc
sweepchooses clockwise or counterclockwise arc
xyend of arc
Returns
reference to SkPath

Definition at line 978 of file SkPath.h.

979 {
980 return this->arcTo(r.fX, r.fY, xAxisRotate, largeArc, sweep, xy.fX, xy.fY);
981 }

◆ arcTo() [3/5]

SkPath & SkPath::arcTo ( const SkRect oval,
SkScalar  startAngle,
SkScalar  sweepAngle,
bool  forceMoveTo 
)

Appends arc to SkPath. Arc added is part of ellipse bounded by oval, from startAngle through sweepAngle. Both startAngle and sweepAngle are measured in degrees, where zero degrees is aligned with the positive x-axis, and positive sweeps extends arc clockwise.

arcTo() adds line connecting SkPath last SkPoint to initial arc SkPoint if forceMoveTo is false and SkPath is not empty. Otherwise, added contour begins with first point of arc. Angles greater than -360 and less than 360 are treated modulo 360.

Parameters
ovalbounds of ellipse containing arc
startAnglestarting angle of arc in degrees
sweepAnglesweep, in degrees. Positive is clockwise; treated modulo 360
forceMoveTotrue to start a new contour with arc
Returns
reference to SkPath

example: https://fiddle.skia.org/c/@Path_arcTo

Definition at line 1220 of file SkPath.cpp.

1221 {
1222 if (oval.width() < 0 || oval.height() < 0) {
1223 return *this;
1224 }
1225
1227
1228 if (fPathRef->countVerbs() == 0) {
1229 forceMoveTo = true;
1230 }
1231
1232 SkPoint lonePt;
1233 if (arc_is_lone_point(oval, startAngle, sweepAngle, &lonePt)) {
1234 return forceMoveTo ? this->moveTo(lonePt) : this->lineTo(lonePt);
1235 }
1236
1237 SkVector startV, stopV;
1239 angles_to_unit_vectors(startAngle, sweepAngle, &startV, &stopV, &dir);
1240
1241 SkPoint singlePt;
1242
1243 bool isArc = this->hasOnlyMoveTos();
1244
1245 // Adds a move-to to 'pt' if forceMoveTo is true. Otherwise a lineTo unless we're sufficiently
1246 // close to 'pt' currently. This prevents spurious lineTos when adding a series of contiguous
1247 // arcs from the same oval.
1248 auto addPt = [&forceMoveTo, &isArc, this](const SkPoint& pt) {
1249 SkPoint lastPt;
1250 if (forceMoveTo) {
1251 this->moveTo(pt);
1252 } else if (!this->getLastPt(&lastPt) ||
1253 !SkScalarNearlyEqual(lastPt.fX, pt.fX) ||
1254 !SkScalarNearlyEqual(lastPt.fY, pt.fY)) {
1255 this->lineTo(pt);
1256 isArc = false;
1257 }
1258 };
1259
1260 // At this point, we know that the arc is not a lone point, but startV == stopV
1261 // indicates that the sweepAngle is too small such that angles_to_unit_vectors
1262 // cannot handle it.
1263 if (startV == stopV) {
1265 SkScalar radiusX = oval.width() / 2;
1266 SkScalar radiusY = oval.height() / 2;
1267 // We do not use SkScalar[Sin|Cos]SnapToZero here. When sin(startAngle) is 0 and sweepAngle
1268 // is very small and radius is huge, the expected behavior here is to draw a line. But
1269 // calling SkScalarSinSnapToZero will make sin(endAngle) be 0 which will then draw a dot.
1270 singlePt.set(oval.centerX() + radiusX * SkScalarCos(endAngle),
1271 oval.centerY() + radiusY * SkScalarSin(endAngle));
1272 addPt(singlePt);
1273 return *this;
1274 }
1275
1277 int count = build_arc_conics(oval, startV, stopV, dir, conics, &singlePt);
1278 if (count) {
1279 // Conics take two points. Add one to the verb in case there is a moveto.
1280 this->incReserve(count * 2 + 1, count + 1, count);
1281 const SkPoint& pt = conics[0].fPts[0];
1282 addPt(pt);
1283 for (int i = 0; i < count; ++i) {
1284 this->conicTo(conics[i].fPts[1], conics[i].fPts[2], conics[i].fW);
1285 }
1286 if (isArc) {
1287 SkPathRef::Editor ed(&fPathRef);
1289 }
1290 } else {
1291 addPt(singlePt);
1292 }
1293 return *this;
1294}
SkPoint fPts[2]
SkRotationDirection
Definition: SkGeometry.h:321
static int build_arc_conics(const SkRect &oval, const SkVector &start, const SkVector &stop, SkRotationDirection dir, SkConic conics[SkConic::kMaxConicsForArc], SkPoint *singlePt)
Definition: SkPath.cpp:978
static bool arc_is_lone_point(const SkRect &oval, SkScalar startAngle, SkScalar sweepAngle, SkPoint *pt)
Definition: SkPath.cpp:917
static void angles_to_unit_vectors(SkScalar startAngle, SkScalar sweepAngle, SkVector *startV, SkVector *stopV, SkRotationDirection *dir)
Definition: SkPath.cpp:940
#define SkDegreesToRadians(degrees)
Definition: SkScalar.h:77
#define SkScalarMod(x, y)
Definition: SkScalar.h:41
#define SkScalarSin(radians)
Definition: SkScalar.h:45
#define SkScalarCos(radians)
Definition: SkScalar.h:46
bool isArc(SkArc *arc) const
Definition: SkPath.cpp:531
static SkArc Make(const SkRect &oval, SkScalar startAngleDegrees, SkScalar sweepAngleDegrees, Type type)
Definition: SkArc.h:38
@ kMaxConicsForArc
Definition: SkGeometry.h:411
SkPoint fPts[3]
Definition: SkGeometry.h:336
void set(float x, float y)
Definition: SkPoint_impl.h:200
constexpr float centerX() const
Definition: SkRect.h:776
constexpr float height() const
Definition: SkRect.h:769
constexpr float centerY() const
Definition: SkRect.h:785
constexpr float width() const
Definition: SkRect.h:762

◆ arcTo() [4/5]

SkPath & SkPath::arcTo ( SkScalar  rx,
SkScalar  ry,
SkScalar  xAxisRotate,
SkPath::ArcSize  arcLarge,
SkPathDirection  sweep,
SkScalar  x,
SkScalar  y 
)

Appends arc to SkPath. Arc is implemented by one or more conics weighted to describe part of oval with radii (rx, ry) rotated by xAxisRotate degrees. Arc curves from last SkPath SkPoint to (x, y), choosing one of four possible routes: clockwise or counterclockwise, and smaller or larger.

Arc sweep is always less than 360 degrees. arcTo() appends line to (x, y) if either radii are zero, or if last SkPath SkPoint equals (x, y). arcTo() scales radii (rx, ry) to fit last SkPath SkPoint and (x, y) if both are greater than zero but too small.

arcTo() appends up to four conic curves. arcTo() implements the functionality of SVG arc, although SVG sweep-flag value is opposite the integer value of sweep; SVG sweep-flag uses 1 for clockwise, while kCW_Direction cast to int is zero.

Parameters
rxradius on x-axis before x-axis rotation
ryradius on y-axis before x-axis rotation
xAxisRotatex-axis rotation in degrees; positive values are clockwise
largeArcchooses smaller or larger arc
sweepchooses clockwise or counterclockwise arc
xend of arc
yend of arc
Returns
reference to SkPath

Definition at line 1302 of file SkPath.cpp.

1303 {
1304 this->injectMoveToIfNeeded();
1305 SkPoint srcPts[2];
1306 this->getLastPt(&srcPts[0]);
1307 // If rx = 0 or ry = 0 then this arc is treated as a straight line segment (a "lineto")
1308 // joining the endpoints.
1309 // http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters
1310 if (!rx || !ry) {
1311 return this->lineTo(x, y);
1312 }
1313 // If the current point and target point for the arc are identical, it should be treated as a
1314 // zero length path. This ensures continuity in animations.
1315 srcPts[1].set(x, y);
1316 if (srcPts[0] == srcPts[1]) {
1317 return this->lineTo(x, y);
1318 }
1319 rx = SkScalarAbs(rx);
1320 ry = SkScalarAbs(ry);
1321 SkVector midPointDistance = srcPts[0] - srcPts[1];
1322 midPointDistance *= 0.5f;
1323
1324 SkMatrix pointTransform;
1325 pointTransform.setRotate(-angle);
1326
1327 SkPoint transformedMidPoint;
1328 pointTransform.mapPoints(&transformedMidPoint, &midPointDistance, 1);
1329 SkScalar squareRx = rx * rx;
1330 SkScalar squareRy = ry * ry;
1331 SkScalar squareX = transformedMidPoint.fX * transformedMidPoint.fX;
1332 SkScalar squareY = transformedMidPoint.fY * transformedMidPoint.fY;
1333
1334 // Check if the radii are big enough to draw the arc, scale radii if not.
1335 // http://www.w3.org/TR/SVG/implnote.html#ArcCorrectionOutOfRangeRadii
1336 SkScalar radiiScale = squareX / squareRx + squareY / squareRy;
1337 if (radiiScale > 1) {
1338 radiiScale = SkScalarSqrt(radiiScale);
1339 rx *= radiiScale;
1340 ry *= radiiScale;
1341 }
1342
1343 pointTransform.setScale(1 / rx, 1 / ry);
1344 pointTransform.preRotate(-angle);
1345
1346 SkPoint unitPts[2];
1347 pointTransform.mapPoints(unitPts, srcPts, (int) std::size(unitPts));
1348 SkVector delta = unitPts[1] - unitPts[0];
1349
1350 SkScalar d = delta.fX * delta.fX + delta.fY * delta.fY;
1351 SkScalar scaleFactorSquared = std::max(1 / d - 0.25f, 0.f);
1352
1353 SkScalar scaleFactor = SkScalarSqrt(scaleFactorSquared);
1354 if ((arcSweep == SkPathDirection::kCCW) != SkToBool(arcLarge)) { // flipped from the original implementation
1355 scaleFactor = -scaleFactor;
1356 }
1357 delta.scale(scaleFactor);
1358 SkPoint centerPoint = unitPts[0] + unitPts[1];
1359 centerPoint *= 0.5f;
1360 centerPoint.offset(-delta.fY, delta.fX);
1361 unitPts[0] -= centerPoint;
1362 unitPts[1] -= centerPoint;
1363 SkScalar theta1 = SkScalarATan2(unitPts[0].fY, unitPts[0].fX);
1364 SkScalar theta2 = SkScalarATan2(unitPts[1].fY, unitPts[1].fX);
1365 SkScalar thetaArc = theta2 - theta1;
1366 if (thetaArc < 0 && (arcSweep == SkPathDirection::kCW)) { // arcSweep flipped from the original implementation
1367 thetaArc += SK_ScalarPI * 2;
1368 } else if (thetaArc > 0 && (arcSweep != SkPathDirection::kCW)) { // arcSweep flipped from the original implementation
1369 thetaArc -= SK_ScalarPI * 2;
1370 }
1371
1372 // Very tiny angles cause our subsequent math to go wonky (skbug.com/9272)
1373 // so we do a quick check here. The precise tolerance amount is just made up.
1374 // PI/million happens to fix the bug in 9272, but a larger value is probably
1375 // ok too.
1376 if (SkScalarAbs(thetaArc) < (SK_ScalarPI / (1000 * 1000))) {
1377 return this->lineTo(x, y);
1378 }
1379
1380 pointTransform.setRotate(angle);
1381 pointTransform.preScale(rx, ry);
1382
1383 // the arc may be slightly bigger than 1/4 circle, so allow up to 1/3rd
1384 int segments = SkScalarCeilToInt(SkScalarAbs(thetaArc / (2 * SK_ScalarPI / 3)));
1385 SkScalar thetaWidth = thetaArc / segments;
1386 SkScalar t = SkScalarTan(0.5f * thetaWidth);
1387 if (!SkIsFinite(t)) {
1388 return *this;
1389 }
1390 SkScalar startTheta = theta1;
1392 auto scalar_is_integer = [](SkScalar scalar) -> bool {
1393 return scalar == SkScalarFloorToScalar(scalar);
1394 };
1395 bool expectIntegers = SkScalarNearlyZero(SK_ScalarPI/2 - SkScalarAbs(thetaWidth)) &&
1396 scalar_is_integer(rx) && scalar_is_integer(ry) &&
1397 scalar_is_integer(x) && scalar_is_integer(y);
1398
1399 for (int i = 0; i < segments; ++i) {
1400 SkScalar endTheta = startTheta + thetaWidth,
1401 sinEndTheta = SkScalarSinSnapToZero(endTheta),
1402 cosEndTheta = SkScalarCosSnapToZero(endTheta);
1403
1404 unitPts[1].set(cosEndTheta, sinEndTheta);
1405 unitPts[1] += centerPoint;
1406 unitPts[0] = unitPts[1];
1407 unitPts[0].offset(t * sinEndTheta, -t * cosEndTheta);
1408 SkPoint mapped[2];
1409 pointTransform.mapPoints(mapped, unitPts, (int) std::size(unitPts));
1410 /*
1411 Computing the arc width introduces rounding errors that cause arcs to start
1412 outside their marks. A round rect may lose convexity as a result. If the input
1413 values are on integers, place the conic on integers as well.
1414 */
1415 if (expectIntegers) {
1416 for (SkPoint& point : mapped) {
1417 point.fX = SkScalarRoundToScalar(point.fX);
1418 point.fY = SkScalarRoundToScalar(point.fY);
1419 }
1420 }
1421 this->conicTo(mapped[0], mapped[1], w);
1422 startTheta = endTheta;
1423 }
1424
1425 // The final point should match the input point (by definition); replace it to
1426 // ensure that rounding errors in the above math don't cause any problems.
1427 this->setLastPt(x, y);
1428 return *this;
1429}
static bool SkIsFinite(T x, Pack... values)
#define SkScalarFloorToScalar(x)
Definition: SkScalar.h:30
static float SkScalarSinSnapToZero(SkScalar radians)
Definition: SkScalar.h:115
#define SkScalarTan(radians)
Definition: SkScalar.h:47
#define SkScalarATan2(y, x)
Definition: SkScalar.h:50
static bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
Definition: SkScalar.h:101
#define SK_ScalarHalf
Definition: SkScalar.h:19
#define SkScalarCeilToInt(x)
Definition: SkScalar.h:36
#define SkScalarSqrt(x)
Definition: SkScalar.h:42
#define SkScalarAbs(x)
Definition: SkScalar.h:39
static float SkScalarCosSnapToZero(SkScalar radians)
Definition: SkScalar.h:120
#define SK_ScalarPI
Definition: SkScalar.h:21
static constexpr bool SkToBool(const T &x)
Definition: SkTo.h:35
void mapPoints(SkPoint dst[], const SkPoint src[], int count) const
Definition: SkMatrix.cpp:770
SkMatrix & setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
Definition: SkMatrix.cpp:296
SkMatrix & setRotate(SkScalar degrees, SkScalar px, SkScalar py)
Definition: SkMatrix.cpp:452
SkMatrix & preRotate(SkScalar degrees, SkScalar px, SkScalar py)
Definition: SkMatrix.cpp:462
SkMatrix & preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
Definition: SkMatrix.cpp:315
void setLastPt(SkScalar x, SkScalar y)
Definition: SkPath.cpp:608
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition: main.cc:19
static float max(float r, float g, float b)
Definition: hsl.cpp:49
void offset(float dx, float dy)
Definition: SkPoint_impl.h:269

◆ arcTo() [5/5]

SkPath & SkPath::arcTo ( SkScalar  x1,
SkScalar  y1,
SkScalar  x2,
SkScalar  y2,
SkScalar  radius 
)

Appends arc to SkPath, after appending line if needed. Arc is implemented by conic weighted to describe part of circle. Arc is contained by tangent from last SkPath point to (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.

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.

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.

Parameters
x1x-axis value common to pair of tangents
y1y-axis value common to pair of tangents
x2x-axis value end of second tangent
y2y-axis value end of second tangent
radiusdistance from arc to circle center
Returns
reference to SkPath

example: https://fiddle.skia.org/c/@Path_arcTo_2_a example: https://fiddle.skia.org/c/@Path_arcTo_2_b example: https://fiddle.skia.org/c/@Path_arcTo_2_c

Definition at line 1467 of file SkPath.cpp.

1467 {
1468 this->injectMoveToIfNeeded();
1469
1470 if (radius == 0) {
1471 return this->lineTo(x1, y1);
1472 }
1473
1474 // need to know our prev pt so we can construct tangent vectors
1475 SkPoint start;
1476 this->getLastPt(&start);
1477
1478 // need double precision for these calcs.
1479 skvx::double2 befored = normalize(skvx::double2{x1 - start.fX, y1 - start.fY});
1480 skvx::double2 afterd = normalize(skvx::double2{x2 - x1, y2 - y1});
1481 double cosh = dot(befored, afterd);
1482 double sinh = cross(befored, afterd);
1483
1484 // If the previous point equals the first point, befored will be denormalized.
1485 // If the two points equal, afterd will be denormalized.
1486 // If the second point equals the first point, sinh will be zero.
1487 // In all these cases, we cannot construct an arc, so we construct a line to the first point.
1488 if (!isfinite(befored) || !isfinite(afterd) || SkScalarNearlyZero(SkDoubleToScalar(sinh))) {
1489 return this->lineTo(x1, y1);
1490 }
1491
1492 // safe to convert back to floats now
1493 SkScalar dist = SkScalarAbs(SkDoubleToScalar(radius * (1 - cosh) / sinh));
1494 SkScalar xx = x1 - dist * befored[0];
1495 SkScalar yy = y1 - dist * befored[1];
1496
1497 SkVector after = SkVector::Make(afterd[0], afterd[1]);
1498 after.setLength(dist);
1499 this->lineTo(xx, yy);
1500 SkScalar weight = SkScalarSqrt(SkDoubleToScalar(SK_ScalarHalf + cosh * 0.5));
1501 return this->conicTo(x1, y1, x1 + after.fX, y1 + after.fY, weight);
1502}
#define SkDoubleToScalar(x)
Definition: SkScalar.h:64
int64_t cross(Point d0, Point d1)
Definition: Myers.cpp:55
SINT bool isfinite(const Vec< N, T > &v)
Definition: SkVx.h:1003
SINT T dot(const Vec< N, T > &a, const Vec< N, T > &b)
Definition: SkVx.h:964
SIN Vec< N, float > normalize(const Vec< N, float > &v)
Definition: SkVx.h:995
bool setLength(float length)
Definition: SkPoint.cpp:30
static constexpr SkPoint Make(float x, float y)
Definition: SkPoint_impl.h:173
Definition: SkVx.h:83

◆ Circle()

SkPath SkPath::Circle ( SkScalar  center_x,
SkScalar  center_y,
SkScalar  radius,
SkPathDirection  dir = SkPathDirection::kCW 
)
static

Definition at line 3598 of file SkPath.cpp.

3598 {
3599 return SkPathBuilder().addCircle(x, y, r, dir).detach();
3600}
friend class SkPathBuilder
Definition: SkPath.h:1932

◆ close()

SkPath & SkPath::close ( )

Appends kClose_Verb to SkPath. A closed contour connects the first and last SkPoint with line, forming a continuous loop. Open and closed contour draw the same with SkPaint::kFill_Style. With SkPaint::kStroke_Style, open contour draws SkPaint::Cap at contour start and end; closed contour draws SkPaint::Join at contour start and end.

close() has no effect if SkPath is empty or last SkPath SkPath::Verb is kClose_Verb.

Returns
reference to SkPath

example: https://fiddle.skia.org/c/@Path_close

Definition at line 823 of file SkPath.cpp.

823 {
824 SkDEBUGCODE(this->validate();)
825
826 int count = fPathRef->countVerbs();
827 if (count > 0) {
828 switch (fPathRef->atVerb(count - 1)) {
829 case kLine_Verb:
830 case kQuad_Verb:
831 case kConic_Verb:
832 case kCubic_Verb:
833 case kMove_Verb: {
834 SkPathRef::Editor ed(&fPathRef);
835 ed.growForVerb(kClose_Verb);
836 break;
837 }
838 case kClose_Verb:
839 // don't add a close if it's the first verb or a repeat
840 break;
841 default:
842 SkDEBUGFAIL("unexpected verb");
843 break;
844 }
845 }
846
847 // signal that we need a moveTo to follow us (unless we're done)
848#if 0
849 if (fLastMoveToIndex >= 0) {
850 fLastMoveToIndex = ~fLastMoveToIndex;
851 }
852#else
853 fLastMoveToIndex ^= ~fLastMoveToIndex >> (8 * sizeof(fLastMoveToIndex) - 1);
854#endif
855 return *this;
856}
#define SkDEBUGFAIL(message)
Definition: SkAssert.h:118
uint8_t atVerb(int index) const
Definition: SkPathRef.h:339

◆ computeTightBounds()

SkRect SkPath::computeTightBounds ( ) const

Returns minimum and maximum axes values of the lines and curves in SkPath. Returns (0, 0, 0, 0) if SkPath contains no points. Returned bounds width and height may be larger or smaller than area affected when SkPath is drawn.

Includes SkPoint associated with kMove_Verb that define empty contours.

Behaves identically to getBounds() when SkPath contains only lines. If SkPath contains curves, computed bounds includes the maximum extent of the quad, conic, or cubic; is slower than getBounds(); and unlike getBounds(), does not cache the result.

Returns
tight bounds of curves in SkPath

example: https://fiddle.skia.org/c/@Path_computeTightBounds

Definition at line 3446 of file SkPath.cpp.

3446 {
3447 if (0 == this->countVerbs()) {
3448 return SkRect::MakeEmpty();
3449 }
3450
3452 return this->getBounds();
3453 }
3454
3455 SkPoint extremas[5]; // big enough to hold worst-case curve type (cubic) extremas + 1
3456
3457 // initial with the first MoveTo, so we don't have to check inside the switch
3459 min = max = from_point(this->getPoint(0));
3460 for (auto [verb, pts, w] : SkPathPriv::Iterate(*this)) {
3461 int count = 0;
3462 switch (verb) {
3463 case SkPathVerb::kMove:
3464 extremas[0] = pts[0];
3465 count = 1;
3466 break;
3467 case SkPathVerb::kLine:
3468 extremas[0] = pts[1];
3469 count = 1;
3470 break;
3471 case SkPathVerb::kQuad:
3472 count = compute_quad_extremas(pts, extremas);
3473 break;
3474 case SkPathVerb::kConic:
3475 count = compute_conic_extremas(pts, *w, extremas);
3476 break;
3477 case SkPathVerb::kCubic:
3478 count = compute_cubic_extremas(pts, extremas);
3479 break;
3480 case SkPathVerb::kClose:
3481 break;
3482 }
3483 for (int i = 0; i < count; ++i) {
3484 skvx::float2 tmp = from_point(extremas[i]);
3485 min = skvx::min(min, tmp);
3486 max = skvx::max(max, tmp);
3487 }
3488 }
3489 SkRect bounds;
3490 min.store((SkPoint*)&bounds.fLeft);
3491 max.store((SkPoint*)&bounds.fRight);
3492 return bounds;
3493}
static skvx::float2 from_point(const SkPoint &point)
Definition: SkGeometry.h:22
static int compute_cubic_extremas(const SkPoint src[4], SkPoint extremas[5])
Definition: SkPath.cpp:3434
static int compute_conic_extremas(const SkPoint src[3], SkScalar w, SkPoint extremas[3])
Definition: SkPath.cpp:3421
static int compute_quad_extremas(const SkPoint src[3], SkPoint extremas[3])
Definition: SkPath.cpp:3409
SkPoint getPoint(int index) const
Definition: SkPath.cpp:549
const SkRect & getBounds() const
Definition: SkPath.cpp:430
uint32_t getSegmentMasks() const
Definition: SkPath.cpp:434
static float min(float r, float g, float b)
Definition: hsl.cpp:48
SIT T max(const Vec< 1, T > &x)
Definition: SkVx.h:641
SIT T min(const Vec< 1, T > &x)
Definition: SkVx.h:640
static constexpr SkRect MakeEmpty()
Definition: SkRect.h:595

◆ conicTo() [1/2]

SkPath & SkPath::conicTo ( const SkPoint p1,
const SkPoint p2,
SkScalar  w 
)
inline

Adds conic from last point towards SkPoint p1, to SkPoint p2, weighted by w. If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0) before adding conic.

Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.

If w is finite and not one, appends kConic_Verb to verb array; and SkPoint p1, p2 to SkPoint array; and w to conic weights.

If w is one, appends kQuad_Verb to verb array, and SkPoint p1, p2 to SkPoint array.

If w is not finite, appends kLine_Verb twice to verb array, and SkPoint p1, p2 to SkPoint array.

Parameters
p1control SkPoint of added conic
p2end SkPoint of added conic
wweight of added conic
Returns
reference to SkPath

Definition at line 759 of file SkPath.h.

759 {
760 return this->conicTo(p1.fX, p1.fY, p2.fX, p2.fY, w);
761 }

◆ conicTo() [2/2]

SkPath & SkPath::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 SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0) before adding conic.

Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.

If w is finite and not one, appends kConic_Verb to verb array; and (x1, y1), (x2, y2) to SkPoint array; and w to conic weights.

If w is one, appends kQuad_Verb to verb array, and (x1, y1), (x2, y2) to SkPoint array.

If w is not finite, appends kLine_Verb twice to verb array, and (x1, y1), (x2, y2) to SkPoint array.

Parameters
x1control SkPoint of conic on x-axis
y1control SkPoint of conic on y-axis
x2end SkPoint of conic on x-axis
y2end SkPoint of conic on y-axis
wweight of added conic
Returns
reference to SkPath

Definition at line 766 of file SkPath.cpp.

767 {
768 // check for <= 0 or NaN with this test
769 if (!(w > 0)) {
770 this->lineTo(x2, y2);
771 } else if (!SkIsFinite(w)) {
772 this->lineTo(x1, y1);
773 this->lineTo(x2, y2);
774 } else if (SK_Scalar1 == w) {
775 this->quadTo(x1, y1, x2, y2);
776 } else {
777 SkDEBUGCODE(this->validate();)
778
779 this->injectMoveToIfNeeded();
780
781 SkPathRef::Editor ed(&fPathRef);
782 SkPoint* pts = ed.growForVerb(kConic_Verb, w);
783 pts[0].set(x1, y1);
784 pts[1].set(x2, y2);
785
786 (void)this->dirtyAfterEdit();
787 }
788 return *this;
789}
#define SK_Scalar1
Definition: SkScalar.h:18

◆ conservativelyContainsRect()

bool SkPath::conservativelyContainsRect ( const SkRect rect) const

Returns true if rect is contained by SkPath. May return false when rect is contained by SkPath.

For now, only returns true if SkPath has one contour and is convex. rect may share points and edges with SkPath and be contained. Returns true if rect is empty, that is, it has zero width or height; and the SkPoint or line described by rect is contained by SkPath.

Parameters
rectSkRect, line, or SkPoint checked for containment
Returns
true if rect is contained

example: https://fiddle.skia.org/c/@Path_conservativelyContainsRect

Definition at line 291 of file SkPath.cpp.

291 {
292 // This only handles non-degenerate convex paths currently.
293 if (!this->isConvex()) {
294 return false;
295 }
296
298 if (direction == SkPathFirstDirection::kUnknown) {
299 return false;
300 }
301
302 SkPoint firstPt;
303 SkPoint prevPt;
304 int segmentCount = 0;
305 SkDEBUGCODE(int moveCnt = 0;)
306
307 for (auto [verb, pts, weight] : SkPathPriv::Iterate(*this)) {
308 if (verb == SkPathVerb::kClose || (segmentCount > 0 && verb == SkPathVerb::kMove)) {
309 // Closing the current contour; but since convexity is a precondition, it's the only
310 // contour that matters.
311 SkASSERT(moveCnt);
312 segmentCount++;
313 break;
314 } else if (verb == SkPathVerb::kMove) {
315 // A move at the start of the contour (or multiple leading moves, in which case we
316 // keep the last one before a non-move verb).
317 SkASSERT(!segmentCount);
318 SkDEBUGCODE(++moveCnt);
319 firstPt = prevPt = pts[0];
320 } else {
321 int pointCount = SkPathPriv::PtsInVerb((unsigned) verb);
322 SkASSERT(pointCount > 0);
323
324 if (!SkPathPriv::AllPointsEq(pts, pointCount + 1)) {
325 SkASSERT(moveCnt);
326 int nextPt = pointCount;
327 segmentCount++;
328
329 if (prevPt == pts[nextPt]) {
330 // A pre-condition to getting here is that the path is convex, so if a
331 // verb's start and end points are the same, it means it's the only
332 // verb in the contour (and the only contour). While it's possible for
333 // such a single verb to be a convex curve, we do not have any non-zero
334 // length edges to conservatively test against without splitting or
335 // evaluating the curve. For simplicity, just reject the rectangle.
336 return false;
337 } else if (SkPathVerb::kConic == verb) {
338 SkConic orig;
339 orig.set(pts, *weight);
340 SkPoint quadPts[5];
341 int count = orig.chopIntoQuadsPOW2(quadPts, 1);
343
344 if (!check_edge_against_rect(quadPts[0], quadPts[2], rect, direction)) {
345 return false;
346 }
347 if (!check_edge_against_rect(quadPts[2], quadPts[4], rect, direction)) {
348 return false;
349 }
350 } else {
351 if (!check_edge_against_rect(prevPt, pts[nextPt], rect, direction)) {
352 return false;
353 }
354 }
355 prevPt = pts[nextPt];
356 }
357 }
358 }
359
360 if (segmentCount) {
361 return check_edge_against_rect(prevPt, firstPt, rect, direction);
362 }
363 return false;
364}
#define SkASSERT_RELEASE(cond)
Definition: SkAssert.h:100
static bool check_edge_against_rect(const SkPoint &p0, const SkPoint &p1, const SkRect &rect, SkPathFirstDirection dir)
Definition: SkPath.cpp:265
static int PtsInVerb(unsigned verb)
Definition: SkPathPriv.h:322
static SkPathFirstDirection ComputeFirstDirection(const SkPath &)
Definition: SkPath.cpp:2627
static bool AllPointsEq(const SkPoint pts[], int count)
Definition: SkPathPriv.h:339
bool isConvex() const
Definition: SkPath.cpp:426
int SK_SPI chopIntoQuadsPOW2(SkPoint pts[], int pow2) const
void set(const SkPoint pts[3], SkScalar w)
Definition: SkGeometry.h:339

◆ contains()

bool SkPath::contains ( SkScalar  x,
SkScalar  y 
) const

Returns true if the point (x, y) is contained by SkPath, taking into account FillType.

Parameters
xx-axis value of containment test
yy-axis value of containment test
Returns
true if SkPoint is in SkPath

example: https://fiddle.skia.org/c/@Path_contains

Definition at line 3118 of file SkPath.cpp.

3118 {
3119 bool isInverse = this->isInverseFillType();
3120 if (this->isEmpty()) {
3121 return isInverse;
3122 }
3123
3124 if (!contains_inclusive(this->getBounds(), x, y)) {
3125 return isInverse;
3126 }
3127
3128 SkPath::Iter iter(*this, true);
3129 bool done = false;
3130 int w = 0;
3131 int onCurveCount = 0;
3132 do {
3133 SkPoint pts[4];
3134 switch (iter.next(pts)) {
3135 case SkPath::kMove_Verb:
3137 break;
3138 case SkPath::kLine_Verb:
3139 w += winding_line(pts, x, y, &onCurveCount);
3140 break;
3141 case SkPath::kQuad_Verb:
3142 w += winding_quad(pts, x, y, &onCurveCount);
3143 break;
3145 w += winding_conic(pts, x, y, iter.conicWeight(), &onCurveCount);
3146 break;
3148 w += winding_cubic(pts, x, y, &onCurveCount);
3149 break;
3150 case SkPath::kDone_Verb:
3151 done = true;
3152 break;
3153 }
3154 } while (!done);
3155 bool evenOddFill = SkPathFillType::kEvenOdd == this->getFillType()
3157 if (evenOddFill) {
3158 w &= 1;
3159 }
3160 if (w) {
3161 return !isInverse;
3162 }
3163 if (onCurveCount <= 1) {
3164 return SkToBool(onCurveCount) ^ isInverse;
3165 }
3166 if ((onCurveCount & 1) || evenOddFill) {
3167 return SkToBool(onCurveCount & 1) ^ isInverse;
3168 }
3169 // If the point touches an even number of curves, and the fill is winding, check for
3170 // coincidence. Count coincidence as places where the on curve points have identical tangents.
3171 iter.setPath(*this, true);
3172 done = false;
3173 SkTDArray<SkVector> tangents;
3174 do {
3175 SkPoint pts[4];
3176 int oldCount = tangents.size();
3177 switch (iter.next(pts)) {
3178 case SkPath::kMove_Verb:
3180 break;
3181 case SkPath::kLine_Verb:
3182 tangent_line(pts, x, y, &tangents);
3183 break;
3184 case SkPath::kQuad_Verb:
3185 tangent_quad(pts, x, y, &tangents);
3186 break;
3188 tangent_conic(pts, x, y, iter.conicWeight(), &tangents);
3189 break;
3191 tangent_cubic(pts, x, y, &tangents);
3192 break;
3193 case SkPath::kDone_Verb:
3194 done = true;
3195 break;
3196 }
3197 if (tangents.size() > oldCount) {
3198 int last = tangents.size() - 1;
3199 const SkVector& tangent = tangents[last];
3201 tangents.remove(last);
3202 } else {
3203 for (int index = 0; index < last; ++index) {
3204 const SkVector& test = tangents[index];
3205 if (SkScalarNearlyZero(test.cross(tangent))
3206 && SkScalarSignAsInt(tangent.fX * test.fX) <= 0
3207 && SkScalarSignAsInt(tangent.fY * test.fY) <= 0) {
3208 tangents.remove(last);
3209 tangents.removeShuffle(index);
3210 break;
3211 }
3212 }
3213 }
3214 }
3215 } while (!done);
3216 return SkToBool(tangents.size()) ^ isInverse;
3217}
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
Definition: DM.cpp:263
static void tangent_line(const SkPoint pts[], SkScalar x, SkScalar y, SkTDArray< SkVector > *tangents)
Definition: SkPath.cpp:3092
static int winding_quad(const SkPoint pts[], SkScalar x, SkScalar y, int *onCurveCount)
Definition: SkPath.cpp:2956
static int winding_line(const SkPoint pts[], SkScalar x, SkScalar y, int *onCurveCount)
Definition: SkPath.cpp:2971
static bool contains_inclusive(const SkRect &r, SkScalar x, SkScalar y)
Definition: SkPath.cpp:3114
static void tangent_cubic(const SkPoint pts[], SkScalar x, SkScalar y, SkTDArray< SkVector > *tangents)
Definition: SkPath.cpp:3011
static int winding_conic(const SkPoint pts[], SkScalar x, SkScalar y, SkScalar weight, int *onCurveCount)
Definition: SkPath.cpp:2887
static void tangent_conic(const SkPoint pts[], SkScalar x, SkScalar y, SkScalar w, SkTDArray< SkVector > *tangents)
Definition: SkPath.cpp:3039
static void tangent_quad(const SkPoint pts[], SkScalar x, SkScalar y, SkTDArray< SkVector > *tangents)
Definition: SkPath.cpp:3066
static int winding_cubic(const SkPoint pts[], SkScalar x, SkScalar y, int *onCurveCount)
Definition: SkPath.cpp:2797
static int SkScalarSignAsInt(SkScalar x)
Definition: SkScalar.h:90
bool isInverseFillType() const
Definition: SkPath.h:244
SkPathFillType getFillType() const
Definition: SkPath.h:230
static SkScalar LengthSqd(const SkPoint &pt)
Definition: SkPointPriv.h:63
int size() const
Definition: SkTDArray.h:138
void remove(int index, int count=1)
Definition: SkTDArray.h:210
void removeShuffle(int index)
Definition: SkTDArray.h:214

◆ ConvertConicToQuads()

int SkPath::ConvertConicToQuads ( const SkPoint p0,
const SkPoint p1,
const SkPoint p2,
SkScalar  w,
SkPoint  pts[],
int  pow2 
)
static

Approximates conic with quad array. Conic is constructed from start SkPoint p0, control SkPoint p1, end SkPoint p2, and weight w. Quad array is stored in pts; this storage is supplied by caller. Maximum quad count is 2 to the pow2. Every third point in array shares last SkPoint of previous quad and first SkPoint of next quad. Maximum pts storage size is given by: (1 + 2 * (1 << pow2)) * sizeof(SkPoint).

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.

Parameters
p0conic start SkPoint
p1conic control SkPoint
p2conic end SkPoint
wconic weight
ptsstorage for quad array
pow2quad count, as power of two, normally 0 to 5 (1 to 32 quad curves)
Returns
number of quad curves written to pts

Definition at line 3238 of file SkPath.cpp.

3239 {
3240 const SkConic conic(p0, p1, p2, w);
3241 return conic.chopIntoQuadsPOW2(pts, pow2);
3242}
AI float conic(float tolerance, const SkPoint pts[], float w, const VectorXform &vectorXform=VectorXform())
Definition: WangsFormula.h:287

◆ countPoints()

int SkPath::countPoints ( ) const

Returns the number of points in SkPath. SkPoint count is initially zero.

Returns
SkPath SkPoint array length

example: https://fiddle.skia.org/c/@Path_countPoints

Definition at line 535 of file SkPath.cpp.

535 {
536 return fPathRef->countPoints();
537}

◆ countVerbs()

int SkPath::countVerbs ( ) const

Returns the number of verbs: kMove_Verb, kLine_Verb, kQuad_Verb, kConic_Verb, kCubic_Verb, and kClose_Verb; added to SkPath.

Returns
length of verb array

example: https://fiddle.skia.org/c/@Path_countVerbs

Definition at line 556 of file SkPath.cpp.

556 {
557 return fPathRef->countVerbs();
558}

◆ cubicTo() [1/2]

SkPath & SkPath::cubicTo ( const SkPoint p1,
const SkPoint p2,
const SkPoint p3 
)
inline

Adds cubic from last point towards SkPoint p1, then towards SkPoint p2, ending at SkPoint p3. If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0) before adding cubic.

Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed; then appends kCubic_Verb to verb array; and SkPoint p1, p2, p3 to SkPoint array.

Parameters
p1first control SkPoint of cubic
p2second control SkPoint of cubic
p3end SkPoint of cubic
Returns
reference to SkPath

Definition at line 823 of file SkPath.h.

823 {
824 return this->cubicTo(p1.fX, p1.fY, p2.fX, p2.fY, p3.fX, p3.fY);
825 }

◆ cubicTo() [2/2]

SkPath & SkPath::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 SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0) before adding cubic.

Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed; then appends kCubic_Verb to verb array; and (x1, y1), (x2, y2), (x3, y3) to SkPoint array.

Parameters
x1first control SkPoint of cubic on x-axis
y1first control SkPoint of cubic on y-axis
x2second control SkPoint of cubic on x-axis
y2second control SkPoint of cubic on y-axis
x3end SkPoint of cubic on x-axis
y3end SkPoint of cubic on y-axis
Returns
reference to SkPath

Definition at line 799 of file SkPath.cpp.

800 {
801 SkDEBUGCODE(this->validate();)
802
803 this->injectMoveToIfNeeded();
804
805 SkPathRef::Editor ed(&fPathRef);
806 SkPoint* pts = ed.growForVerb(kCubic_Verb);
807 pts[0].set(x1, y1);
808 pts[1].set(x2, y2);
809 pts[2].set(x3, y3);
810
811 return this->dirtyAfterEdit();
812}

◆ detach()

SkPath SkPath::detach ( )
inline

Returns a copy of this path in the current state, and resets the path to empty.

Definition at line 147 of file SkPath.h.

147 {
148 SkPath result = *this;
149 this->reset();
150 return result;
151 }
SkPath & reset()
Definition: SkPath.cpp:370
GAsyncResult * result

◆ dump() [1/2]

void SkPath::dump ( ) const
inline

Definition at line 1734 of file SkPath.h.

1734{ this->dump(nullptr, false); }
void dump() const
Definition: SkPath.h:1734

◆ dump() [2/2]

void SkPath::dump ( SkWStream stream,
bool  dumpAsHex 
) const

Writes text representation of SkPath to stream. If stream is nullptr, writes to standard output. Set dumpAsHex true to generate exact binary representations of floating point numbers used in SkPoint array and conic weights.

Parameters
streamwritable SkWStream receiving SkPath text representation; may be nullptr
dumpAsHextrue if SkScalar values are written as hexadecimal

example: https://fiddle.skia.org/c/@Path_dump

Definition at line 2040 of file SkPath.cpp.

2040 {
2042 Iter iter(*this, false);
2043 SkPoint pts[4];
2044 Verb verb;
2045
2047 char const * const gFillTypeStrs[] = {
2048 "Winding",
2049 "EvenOdd",
2050 "InverseWinding",
2051 "InverseEvenOdd",
2052 };
2053 builder.printf("path.setFillType(SkPathFillType::k%s);\n",
2054 gFillTypeStrs[(int) this->getFillType()]);
2055 while ((verb = iter.next(pts)) != kDone_Verb) {
2056 switch (verb) {
2057 case kMove_Verb:
2058 append_params(&builder, "path.moveTo", &pts[0], 1, asType);
2059 break;
2060 case kLine_Verb:
2061 append_params(&builder, "path.lineTo", &pts[1], 1, asType);
2062 break;
2063 case kQuad_Verb:
2064 append_params(&builder, "path.quadTo", &pts[1], 2, asType);
2065 break;
2066 case kConic_Verb:
2067 append_params(&builder, "path.conicTo", &pts[1], 2, asType, iter.conicWeight());
2068 break;
2069 case kCubic_Verb:
2070 append_params(&builder, "path.cubicTo", &pts[1], 3, asType);
2071 break;
2072 case kClose_Verb:
2073 builder.append("path.close();\n");
2074 break;
2075 default:
2076 SkDebugf(" path: UNKNOWN VERB %d, aborting dump...\n", verb);
2077 verb = kDone_Verb; // stop the loop
2078 break;
2079 }
2080 if (!wStream && builder.size()) {
2081 SkDebugf("%s", builder.c_str());
2082 builder.reset();
2083 }
2084 }
2085 if (wStream) {
2086 wStream->writeText(builder.c_str());
2087 }
2088}
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static void append_params(SkString *str, const char label[], const SkPoint pts[], int count, SkScalarAsStringType strType, SkScalar conicWeight=-12345)
Definition: SkPath.cpp:2005
SkScalarAsStringType
Definition: SkStringUtils.h:18
@ kHex_SkScalarAsStringType
Definition: SkStringUtils.h:20
@ kDec_SkScalarAsStringType
Definition: SkStringUtils.h:19
friend class Iter
Definition: SkPath.h:1840

◆ dumpArrays() [1/2]

void SkPath::dumpArrays ( ) const
inline

Definition at line 1739 of file SkPath.h.

1739{ this->dumpArrays(nullptr, false); }
void dumpArrays() const
Definition: SkPath.h:1739

◆ dumpArrays() [2/2]

void SkPath::dumpArrays ( SkWStream stream,
bool  dumpAsHex 
) const

Definition at line 2090 of file SkPath.cpp.

2090 {
2092
2093 auto bool_str = [](bool v) { return v ? "true" : "false"; };
2094
2095 builder.appendf("// fBoundsIsDirty = %s\n", bool_str(fPathRef->fBoundsIsDirty));
2096 builder.appendf("// fGenerationID = %u\n", fPathRef->fGenerationID);
2097 builder.appendf("// fSegmentMask = %d\n", fPathRef->fSegmentMask);
2098
2099 const char* gTypeStrs[] = {
2100 "General", "Oval", "RRect",
2101 };
2102 builder.appendf("// fType = %s\n", gTypeStrs[static_cast<int>(fPathRef->fType)]);
2103
2104 auto append_scalar = [&](SkScalar v) {
2105 if (dumpAsHex) {
2106 builder.appendf("SkBits2Float(0x%08X) /* %g */", SkFloat2Bits(v), v);
2107 } else {
2108 builder.appendf("%g", v);
2109 }
2110 };
2111
2112 builder.append("const SkPoint path_points[] = {\n");
2113 for (int i = 0; i < this->countPoints(); ++i) {
2114 SkPoint p = this->getPoint(i);
2115 builder.append(" { ");
2116 append_scalar(p.fX);
2117 builder.append(", ");
2118 append_scalar(p.fY);
2119 builder.append(" },\n");
2120 }
2121 builder.append("};\n");
2122
2123 const char* gVerbStrs[] = {
2124 "Move", "Line", "Quad", "Conic", "Cubic", "Close"
2125 };
2126 builder.append("const uint8_t path_verbs[] = {\n ");
2127 for (auto v = fPathRef->verbsBegin(); v != fPathRef->verbsEnd(); ++v) {
2128 builder.appendf("(uint8_t)SkPathVerb::k%s, ", gVerbStrs[*v]);
2129 }
2130 builder.append("\n};\n");
2131
2132 const int nConics = fPathRef->conicWeightsEnd() - fPathRef->conicWeights();
2133 if (nConics) {
2134 builder.append("const SkScalar path_conics[] = {\n ");
2135 for (auto c = fPathRef->conicWeights(); c != fPathRef->conicWeightsEnd(); ++c) {
2136 append_scalar(*c);
2137 builder.append(", ");
2138 }
2139 builder.append("\n};\n");
2140 }
2141
2142 char const * const gFillTypeStrs[] = {
2143 "Winding",
2144 "EvenOdd",
2145 "InverseWinding",
2146 "InverseEvenOdd",
2147 };
2148
2149 builder.appendf("SkPath path = SkPath::Make(path_points, %d, path_verbs, %d, %s, %d,\n",
2150 this->countPoints(), this->countVerbs(),
2151 nConics ? "path_conics" : "nullptr", nConics);
2152 builder.appendf(" SkPathFillType::k%s, %s);\n",
2153 gFillTypeStrs[(int)this->getFillType()],
2154 bool_str(fIsVolatile));
2155
2156 if (wStream) {
2157 wStream->writeText(builder.c_str());
2158 } else {
2159 SkDebugf("%s\n", builder.c_str());
2160 }
2161}
static uint32_t SkFloat2Bits(float value)
Definition: SkFloatBits.h:41
const uint8_t * verbsEnd() const
Definition: SkPathRef.h:321
const SkScalar * conicWeightsEnd() const
Definition: SkPathRef.h:334
const SkScalar * conicWeights() const
Definition: SkPathRef.h:333
const uint8_t * verbsBegin() const
Definition: SkPathRef.h:316
void append(const char text[])
Definition: SkString.h:203

◆ dumpHex()

void SkPath::dumpHex ( ) const
inline

Definition at line 1735 of file SkPath.h.

1735{ this->dump(nullptr, true); }

◆ getBounds()

const SkRect & SkPath::getBounds ( ) const

Returns minimum and maximum axes values of SkPoint array. Returns (0, 0, 0, 0) if SkPath contains no points. Returned bounds width and height may be larger or smaller than area affected when SkPath is drawn.

SkRect returned includes all SkPoint added to SkPath, including SkPoint associated with kMove_Verb that define empty contours.

Returns
bounds of all SkPoint in SkPoint array

Definition at line 430 of file SkPath.cpp.

430 {
431 return fPathRef->getBounds();
432}
const SkRect & getBounds() const
Definition: SkPathRef.h:281

◆ getFillType()

SkPathFillType SkPath::getFillType ( ) const
inline

Returns SkPathFillType, the rule used to fill SkPath.

Returns
current SkPathFillType setting

Definition at line 230 of file SkPath.h.

230{ return (SkPathFillType)fFillType; }
SkPathFillType
Definition: SkPathTypes.h:11

◆ getGenerationID()

uint32_t SkPath::getGenerationID ( ) const

(See Skia bug 1762.) Returns a non-zero, globally unique value. A different value is returned if verb array, SkPoint array, or conic weight changes.

Setting SkPath::FillType does not change generation identifier.

Each time the path is modified, a different generation identifier will be returned. SkPath::FillType does affect generation identifier on Android framework.

Returns
non-zero, globally unique value

example: https://fiddle.skia.org/c/@Path_getGenerationID

Definition at line 366 of file SkPath.cpp.

366 {
367 return fPathRef->genID(fFillType);
368}
uint32_t genID(uint8_t fillType) const
Definition: SkPathRef.cpp:446

◆ getLastPt()

bool SkPath::getLastPt ( SkPoint lastPt) const

Returns last point on SkPath in lastPt. Returns false if SkPoint array is empty, storing (0, 0) if lastPt is not nullptr.

Parameters
lastPtstorage for final SkPoint in SkPoint array; may be nullptr
Returns
true if SkPoint array contains one or more SkPoint

example: https://fiddle.skia.org/c/@Path_getLastPt

Definition at line 580 of file SkPath.cpp.

580 {
581 SkDEBUGCODE(this->validate();)
582
583 int count = fPathRef->countPoints();
584 if (count > 0) {
585 if (lastPt) {
586 *lastPt = fPathRef->atPoint(count - 1);
587 }
588 return true;
589 }
590 if (lastPt) {
591 lastPt->set(0, 0);
592 }
593 return false;
594}
const SkPoint & atPoint(int index) const
Definition: SkPathRef.h:340

◆ getPoint()

SkPoint SkPath::getPoint ( int  index) const

Returns SkPoint at index in SkPoint array. Valid range for index is 0 to countPoints() - 1. Returns (0, 0) if index is out of range.

Parameters
indexSkPoint array element selector
Returns
SkPoint array value or (0, 0)

example: https://fiddle.skia.org/c/@Path_getPoint

Definition at line 549 of file SkPath.cpp.

549 {
550 if ((unsigned)index < (unsigned)fPathRef->countPoints()) {
551 return fPathRef->atPoint(index);
552 }
553 return SkPoint::Make(0, 0);
554}

◆ getPoints()

int SkPath::getPoints ( SkPoint  points[],
int  max 
) const

Returns number of points in SkPath. Up to max points are copied. points may be nullptr; then, max must be zero. If max is greater than number of points, excess points storage is unaltered.

Parameters
pointsstorage for SkPath SkPoint array. May be nullptr
maxmaximum to copy; must be greater than or equal to zero
Returns
SkPath SkPoint array length

example: https://fiddle.skia.org/c/@Path_getPoints

Definition at line 539 of file SkPath.cpp.

539 {
540 SkDEBUGCODE(this->validate();)
541
542 SkASSERT(max >= 0);
543 SkASSERT(!max || dst);
544 int count = std::min(max, fPathRef->countPoints());
545 sk_careful_memcpy(dst, fPathRef->points(), count * sizeof(SkPoint));
546 return fPathRef->countPoints();
547}
static void * sk_careful_memcpy(void *dst, const void *src, size_t len)
Definition: SkMalloc.h:125
const SkPoint * points() const
Definition: SkPathRef.h:326
dst
Definition: cp.py:12

◆ getSegmentMasks()

uint32_t SkPath::getSegmentMasks ( ) const

Returns a mask, where each set bit corresponds to a SegmentMask constant if SkPath contains one or more verbs of that type. Returns zero if SkPath contains no lines, or curves: quads, conics, or cubics.

getSegmentMasks() returns a cached result; it is very fast.

Returns
SegmentMask bits or zero

Definition at line 434 of file SkPath.cpp.

434 {
435 return fPathRef->getSegmentMasks();
436}
uint32_t getSegmentMasks() const
Definition: SkPathRef.h:229

◆ getVerbs()

int SkPath::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.

Parameters
verbsstorage for verbs, may be nullptr
maxmaximum number to copy into verbs
Returns
the actual number of verbs in the path

example: https://fiddle.skia.org/c/@Path_getVerbs

Definition at line 560 of file SkPath.cpp.

560 {
561 SkDEBUGCODE(this->validate();)
562
563 SkASSERT(max >= 0);
564 SkASSERT(!max || dst);
565 int count = std::min(max, fPathRef->countVerbs());
566 if (count) {
567 memcpy(dst, fPathRef->verbsBegin(), count);
568 }
569 return fPathRef->countVerbs();
570}

◆ incReserve()

void SkPath::incReserve ( int  extraPtCount,
int  extraVerbCount = 0,
int  extraConicCount = 0 
)

Grows SkPath verb array, SkPoint array, and conics to contain additional space. May improve performance and use less memory by reducing the number and size of allocations when creating SkPath.

Parameters
extraPtCountnumber of additional SkPoint to allocate
extraVerbCountnumber of additional verbs
extraConicCountnumber of additional conics

example: https://fiddle.skia.org/c/@Path_incReserve

Definition at line 678 of file SkPath.cpp.

678 {
679 SkDEBUGCODE(this->validate();)
680 if (extraPtCount > 0) {
681 // For compat with when this function only took a single argument, use
682 // extraPtCount if extraVerbCount is 0 (default value).
683 SkPathRef::Editor(&fPathRef, extraVerbCount == 0 ? extraPtCount : extraVerbCount, extraPtCount, extraConicCount);
684 }
685 SkDEBUGCODE(this->validate();)
686}

◆ interpolate()

bool SkPath::interpolate ( const SkPath ending,
SkScalar  weight,
SkPath out 
) const

Interpolates between SkPath with SkPoint array of equal size. Copy verb array and weights to out, and set out SkPoint array to a weighted average of this SkPoint array and ending SkPoint array, using the formula: (Path Point * weight) + ending Point * (1 - weight).

weight is most useful when between zero (ending SkPoint array) and one (this Point_Array); will work with values outside of this range.

interpolate() returns false and leaves out unchanged if SkPoint array is not the same size as ending SkPoint array. Call isInterpolatable() to check SkPath compatibility prior to calling interpolate().

Parameters
endingSkPoint array averaged with this SkPoint array
weightcontribution of this SkPoint array, and one minus contribution of ending SkPoint array
outSkPath replaced by interpolated averages
Returns
true if SkPath contain same number of SkPoint

example: https://fiddle.skia.org/c/@Path_interpolate

Definition at line 250 of file SkPath.cpp.

250 {
251 int pointCount = fPathRef->countPoints();
252 if (pointCount != ending.fPathRef->countPoints()) {
253 return false;
254 }
255 if (!pointCount) {
256 return true;
257 }
258 out->reset();
259 out->addPath(*this);
260 SkPathRef::Editor editor(&(out->fPathRef));
261 fPathRef->interpolate(*ending.fPathRef, weight, out->fPathRef.get());
262 return true;
263}
void interpolate(const SkPathRef &ending, SkScalar weight, SkPathRef *out) const
Definition: SkPathRef.cpp:302

◆ isArc()

bool SkPath::isArc ( SkArc arc) const

Returns true if path is representable as an oval arc. In other words, could this path be drawn using SkCanvas::drawArc.

arc receives parameters of arc

Parameters
arcstorage for arc; may be nullptr
Returns
true if SkPath contains only a single arc from an oval

Definition at line 531 of file SkPath.cpp.

531 {
532 return fPathRef->isArc(arc);
533}
bool isArc(SkArc *arc) const
Definition: SkPathRef.h:262

◆ isConvex()

bool SkPath::isConvex ( ) const

Returns true if the path is convex. If necessary, it will first compute the convexity.

Definition at line 426 of file SkPath.cpp.

426 {
427 return SkPathConvexity::kConvex == this->getConvexity();
428}

◆ IsCubicDegenerate()

bool SkPath::IsCubicDegenerate ( const SkPoint p1,
const SkPoint p2,
const SkPoint p3,
const SkPoint p4,
bool  exact 
)
static

Tests if cubic is degenerate. Cubic with no length or that moves a very short distance is degenerate; it is treated as a point.

Parameters
p1cubic start point
p2cubic control point 1
p3cubic control point 2
p4cubic end point
exactif 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
Returns
true if cubic is degenerate; its length is effectively zero

Definition at line 3505 of file SkPath.cpp.

3506 {
3507 return exact ? p1 == p2 && p2 == p3 && p3 == p4 :
3511}
static bool EqualsWithinTolerance(const SkPoint &p1, const SkPoint &p2)
Definition: SkPointPriv.h:54

◆ isEmpty()

bool SkPath::isEmpty ( ) const

Returns if SkPath is empty. Empty SkPath may have FillType but has no SkPoint, SkPath::Verb, or conic weight. SkPath() constructs empty SkPath; reset() and rewind() make SkPath empty.

Returns
true if the path contains no SkPath::Verb array

Definition at line 416 of file SkPath.cpp.

416 {
417 SkDEBUGCODE(this->validate();)
418 return 0 == fPathRef->countVerbs();
419}

◆ isFinite()

bool SkPath::isFinite ( ) const

Returns true for finite SkPoint array values between negative SK_ScalarMax and positive SK_ScalarMax. Returns false for any SkPoint array value of SK_ScalarInfinity, SK_ScalarNegativeInfinity, or SK_ScalarNaN.

Returns
true if all SkPoint values are finite

Definition at line 421 of file SkPath.cpp.

421 {
422 SkDEBUGCODE(this->validate();)
423 return fPathRef->isFinite();
424}
bool isFinite() const
Definition: SkPathRef.h:217

◆ isInterpolatable()

bool SkPath::isInterpolatable ( const SkPath compare) const

Returns true if SkPath contain equal verbs and equal weights. If SkPath contain one or more conics, the weights must match.

conicTo() may add different verbs depending on conic weight, so it is not trivial to interpolate a pair of SkPath containing conics with different conic weight values.

Parameters
compareSkPath to compare
Returns
true if SkPath verb array and weights are equivalent

example: https://fiddle.skia.org/c/@Path_isInterpolatable

Definition at line 243 of file SkPath.cpp.

243 {
244 // need the same structure (verbs, conicweights) and same point-count
245 return fPathRef->fPoints.size() == compare.fPathRef->fPoints.size() &&
246 fPathRef->fVerbs == compare.fPathRef->fVerbs &&
247 fPathRef->fConicWeights == compare.fPathRef->fConicWeights;
248}
int size() const
Definition: SkTArray.h:421
int compare(const void *untyped_lhs, const void *untyped_rhs)
Definition: skdiff.h:161

◆ isInverseFillType()

bool SkPath::isInverseFillType ( ) const
inline

Returns if FillType describes area outside SkPath geometry. The inverse fill area extends indefinitely.

Returns
true if FillType is kInverseWinding or kInverseEvenOdd

Definition at line 244 of file SkPath.h.

244{ return SkPathFillType_IsInverse(this->getFillType()); }
static bool SkPathFillType_IsInverse(SkPathFillType ft)
Definition: SkPathTypes.h:26

◆ isLastContourClosed()

bool SkPath::isLastContourClosed ( ) const

Returns if contour is closed. Contour is closed if SkPath SkPath::Verb array was last modified by close(). When stroked, closed contour draws SkPaint::Join instead of SkPaint::Cap at first and last SkPoint.

Returns
true if the last contour ends with a kClose_Verb

example: https://fiddle.skia.org/c/@Path_isLastContourClosed

Definition at line 390 of file SkPath.cpp.

390 {
391 int verbCount = fPathRef->countVerbs();
392 if (0 == verbCount) {
393 return false;
394 }
395 return kClose_Verb == fPathRef->atVerb(verbCount - 1);
396}

◆ isLine()

bool SkPath::isLine ( SkPoint  line[2]) const

Returns true if SkPath contains only one line; SkPath::Verb array has two entries: kMove_Verb, kLine_Verb. If SkPath contains one line and line is not nullptr, line is set to line start point and line end point. Returns false if SkPath is not one line; line is unaltered.

Parameters
linestorage for line. May be nullptr
Returns
true if SkPath contains exactly one line

example: https://fiddle.skia.org/c/@Path_isLine

Definition at line 398 of file SkPath.cpp.

398 {
399 int verbCount = fPathRef->countVerbs();
400
401 if (2 == verbCount) {
402 SkASSERT(kMove_Verb == fPathRef->atVerb(0));
403 if (kLine_Verb == fPathRef->atVerb(1)) {
404 SkASSERT(2 == fPathRef->countPoints());
405 if (line) {
406 const SkPoint* pts = fPathRef->points();
407 line[0] = pts[0];
408 line[1] = pts[1];
409 }
410 return true;
411 }
412 }
413 return false;
414}

◆ IsLineDegenerate()

bool SkPath::IsLineDegenerate ( const SkPoint p1,
const SkPoint p2,
bool  exact 
)
static

Tests if line between SkPoint pair is degenerate. Line with no length or that moves a very short distance is degenerate; it is treated as a point.

exact changes the equality test. If true, returns true only if p1 equals p2. If false, returns true if p1 equals or nearly equals p2.

Parameters
p1line start point
p2line end point
exactif false, allow nearly equals
Returns
true if line is degenerate; its length is effectively zero

example: https://fiddle.skia.org/c/@Path_IsLineDegenerate

Definition at line 3495 of file SkPath.cpp.

3495 {
3496 return exact ? p1 == p2 : SkPointPriv::EqualsWithinTolerance(p1, p2);
3497}

◆ isOval()

bool SkPath::isOval ( SkRect bounds) const

Returns true if this path is recognized as an oval or circle.

bounds receives bounds of oval.

bounds is unmodified if oval is not found.

Parameters
boundsstorage for bounding SkRect of oval; may be nullptr
Returns
true if SkPath is recognized as an oval or circle

example: https://fiddle.skia.org/c/@Path_isOval

Definition at line 523 of file SkPath.cpp.

523 {
524 return SkPathPriv::IsOval(*this, bounds, nullptr, nullptr);
525}
static bool IsOval(const SkPath &path, SkRect *rect, SkPathDirection *dir, unsigned *start)
Definition: SkPathPriv.h:245

◆ IsQuadDegenerate()

bool SkPath::IsQuadDegenerate ( const SkPoint p1,
const SkPoint p2,
const SkPoint p3,
bool  exact 
)
static

Tests if quad is degenerate. Quad with no length or that moves a very short distance is degenerate; it is treated as a point.

Parameters
p1quad start point
p2quad control point
p3quad end point
exactif 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
Returns
true if quad is degenerate; its length is effectively zero

Definition at line 3499 of file SkPath.cpp.

3500 {
3501 return exact ? p1 == p2 && p2 == p3 : SkPointPriv::EqualsWithinTolerance(p1, p2) &&
3503}

◆ isRect()

bool SkPath::isRect ( SkRect rect,
bool *  isClosed = nullptr,
SkPathDirection direction = nullptr 
) const

Returns true if SkPath is equivalent to SkRect when filled. If false: rect, isClosed, and direction are unchanged. If true: rect, isClosed, and direction are written to if not nullptr.

rect may be smaller than the SkPath bounds. SkPath bounds may include kMove_Verb points that do not alter the area drawn by the returned rect.

Parameters
rectstorage for bounds of SkRect; may be nullptr
isClosedstorage set to true if SkPath is closed; may be nullptr
directionstorage set to SkRect direction; may be nullptr
Returns
true if SkPath contains SkRect

example: https://fiddle.skia.org/c/@Path_isRect

Definition at line 516 of file SkPath.cpp.

516 {
517 SkDEBUGCODE(this->validate();)
518 int currVerb = 0;
519 const SkPoint* pts = fPathRef->points();
520 return SkPathPriv::IsRectContour(*this, false, &currVerb, &pts, isClosed, direction, rect);
521}
static bool IsRectContour(const SkPath &, bool allowPartial, int *currVerb, const SkPoint **ptsPtr, bool *isClosed, SkPathDirection *direction, SkRect *rect)
Definition: SkPath.cpp:3639

◆ isRRect()

bool SkPath::isRRect ( SkRRect rrect) const

Returns true if path is representable as SkRRect. Returns false if path is representable as oval, circle, or SkRect.

rrect receives bounds of SkRRect.

rrect is unmodified if SkRRect is not found.

Parameters
rrectstorage for bounding SkRect of SkRRect; may be nullptr
Returns
true if SkPath contains only SkRRect

example: https://fiddle.skia.org/c/@Path_isRRect

Definition at line 527 of file SkPath.cpp.

527 {
528 return SkPathPriv::IsRRect(*this, rrect, nullptr, nullptr);
529}
static bool IsRRect(const SkPath &path, SkRRect *rrect, SkPathDirection *dir, unsigned *start)
Definition: SkPathPriv.h:272

◆ isValid()

bool SkPath::isValid ( ) const

Returns if SkPath data is consistent. Corrupt SkPath data is detected if internal values are out of range or internal storage does not match array dimensions.

Returns
true if SkPath data is consistent

Definition at line 438 of file SkPath.cpp.

438 {
439 return this->isValidImpl() && fPathRef->isValid();
440}
bool isValid() const
Definition: SkPathRef.cpp:624

◆ isVolatile()

bool SkPath::isVolatile ( ) const
inline

Returns true if the path is volatile; it will not be altered or discarded by the caller after it is drawn. SkPath by default have volatile set false, allowing SkSurface to attach a cache of data which speeds repeated drawing. If true, SkSurface may not speed repeated drawing.

Returns
true if caller will alter SkPath after drawing

Definition at line 350 of file SkPath.h.

350 {
351 return SkToBool(fIsVolatile);
352 }

◆ Line()

static SkPath SkPath::Line ( const SkPoint  a,
const SkPoint  b 
)
inlinestatic

Definition at line 106 of file SkPath.h.

106 {
107 return Polygon({a, b}, false);
108 }
static SkPath Polygon(const SkPoint pts[], int count, bool isClosed, SkPathFillType=SkPathFillType::kWinding, bool isVolatile=false)
Definition: SkPath.cpp:3614
static bool b
struct MyStruct a[10]

◆ lineTo() [1/2]

SkPath & SkPath::lineTo ( const SkPoint p)
inline

Adds line from last point to SkPoint p. If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0) before adding line.

lineTo() first appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed. lineTo() then appends kLine_Verb to verb array and SkPoint p to SkPoint array.

Parameters
pend SkPoint of added line
Returns
reference to SkPath

Definition at line 634 of file SkPath.h.

634 {
635 return this->lineTo(p.fX, p.fY);
636 }

◆ lineTo() [2/2]

SkPath & SkPath::lineTo ( SkScalar  x,
SkScalar  y 
)

Adds line from last point to (x, y). If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0) before adding line.

lineTo() appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed. lineTo() then appends kLine_Verb to verb array and (x, y) to SkPoint array.

Parameters
xend of added line on x-axis
yend of added line on y-axis
Returns
reference to SkPath

example: https://fiddle.skia.org/c/@Path_lineTo

Definition at line 728 of file SkPath.cpp.

728 {
729 SkDEBUGCODE(this->validate();)
730
731 this->injectMoveToIfNeeded();
732
733 SkPathRef::Editor ed(&fPathRef);
734 ed.growForVerb(kLine_Verb)->set(x, y);
735
736 return this->dirtyAfterEdit();
737}

◆ Make()

SkPath SkPath::Make ( const SkPoint  pts[],
int  pointCount,
const uint8_t  vbs[],
int  verbCount,
const SkScalar  ws[],
int  conicWeightCount,
SkPathFillType  ft,
bool  isVolatile = false 
)
static

Create a new path with the specified segments.

The points and weights arrays are read in order, based on the sequence of verbs.

Move 1 point Line 1 point Quad 2 points Conic 2 points and 1 weight Cubic 3 points Close 0 points

If an illegal sequence of verbs is encountered, or the specified number of points or weights is not sufficient given the verbs, an empty Path is returned.

A legal sequence of verbs consists of any number of Contours. A contour always begins with a Move verb, followed by 0 or more segments: Line, Quad, Conic, Cubic, followed by an optional Close.

Definition at line 3569 of file SkPath.cpp.

3572 {
3573 if (verbCount <= 0) {
3574 return SkPath();
3575 }
3576
3577 const auto info = sk_path_analyze_verbs(vbs, verbCount);
3578 if (!info.valid || info.points > pointCount || info.weights > wCount) {
3579 SkDEBUGFAIL("invalid verbs and number of points/weights");
3580 return SkPath();
3581 }
3582
3583 return MakeInternal(info, pts, vbs, verbCount, ws, ft, isVolatile);
3584}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
SkPathVerbAnalysis sk_path_analyze_verbs(const uint8_t vbs[], int verbCount)
Definition: SkPath.cpp:3515
bool isVolatile() const
Definition: SkPath.h:350

◆ makeScale()

SkPath SkPath::makeScale ( SkScalar  sx,
SkScalar  sy 
)
inline

Definition at line 1407 of file SkPath.h.

1407 {
1409 }
@ kNo
Don't pre-clip the geometry before applying the (perspective) matrix.
static SkMatrix Scale(SkScalar sx, SkScalar sy)
Definition: SkMatrix.h:75
SkPath makeTransform(const SkMatrix &m, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
Definition: SkPath.h:1400

◆ makeTransform()

SkPath SkPath::makeTransform ( const SkMatrix m,
SkApplyPerspectiveClip  pc = SkApplyPerspectiveClip::kYes 
) const
inline

Definition at line 1400 of file SkPath.h.

1401 {
1402 SkPath dst;
1403 this->transform(m, &dst, pc);
1404 return dst;
1405 }
void transform(const SkMatrix &matrix, SkPath *dst, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
Definition: SkPath.cpp:1711

◆ moveTo() [1/2]

SkPath & SkPath::moveTo ( const SkPoint p)
inline

Adds beginning of contour at SkPoint p.

Parameters
pcontour start
Returns
reference to SkPath

Definition at line 594 of file SkPath.h.

594 {
595 return this->moveTo(p.fX, p.fY);
596 }

◆ moveTo() [2/2]

SkPath & SkPath::moveTo ( SkScalar  x,
SkScalar  y 
)

Adds beginning of contour at SkPoint (x, y).

Parameters
xx-axis value of contour start
yy-axis value of contour start
Returns
reference to SkPath

example: https://fiddle.skia.org/c/@Path_moveTo

Definition at line 688 of file SkPath.cpp.

688 {
689 SkDEBUGCODE(this->validate();)
690
691 SkPathRef::Editor ed(&fPathRef);
692
693 // remember our index
694 fLastMoveToIndex = fPathRef->countPoints();
695
696 ed.growForVerb(kMove_Verb)->set(x, y);
697
698 return this->dirtyAfterEdit();
699}

◆ offset() [1/2]

SkPath & SkPath::offset ( SkScalar  dx,
SkScalar  dy 
)
inline

Offsets SkPoint array by (dx, dy). SkPath is replaced by offset data.

Parameters
dxoffset added to SkPoint array x-axis coordinates
dyoffset added to SkPoint array y-axis coordinates

Definition at line 1368 of file SkPath.h.

1368 {
1369 this->offset(dx, dy, this);
1370 return *this;
1371 }
void offset(SkScalar dx, SkScalar dy, SkPath *dst) const
Definition: SkPath.cpp:1691

◆ offset() [2/2]

void SkPath::offset ( SkScalar  dx,
SkScalar  dy,
SkPath dst 
) const

Offsets SkPoint array by (dx, dy). Offset SkPath replaces dst. If dst is nullptr, SkPath is replaced by offset data.

Parameters
dxoffset added to SkPoint array x-axis coordinates
dyoffset added to SkPoint array y-axis coordinates
dstoverwritten, translated copy of SkPath; may be nullptr

example: https://fiddle.skia.org/c/@Path_offset

Definition at line 1691 of file SkPath.cpp.

1691 {
1693
1694 matrix.setTranslate(dx, dy);
1695 this->transform(matrix, dst);
1696}

◆ operator=()

SkPath & SkPath::operator= ( const SkPath path)

Constructs a copy of an existing path. SkPath assignment makes two paths identical by value. Internally, assignment shares pointer values. The underlying verb array, SkPoint array and weights are copied when modified.

Copying SkPath by assignment is very efficient and never allocates memory. SkPath are always copied by value from the interface; the underlying shared pointers are not exposed.

Parameters
pathverb array, SkPoint array, weights, and SkPath::FillType to copy
Returns
SkPath copied by value

example: https://fiddle.skia.org/c/@Path_copy_operator

Definition at line 190 of file SkPath.cpp.

190 {
191 SkDEBUGCODE(that.validate();)
192
193 if (this != &that) {
194 fPathRef.reset(SkRef(that.fPathRef.get()));
195 this->copyFields(that);
196 }
197 SkDEBUGCODE(this->validate();)
198 return *this;
199}
void reset(T *ptr=nullptr)
Definition: SkRefCnt.h:310
if(end==-1)

◆ Oval() [1/2]

SkPath SkPath::Oval ( const SkRect r,
SkPathDirection  dir,
unsigned  startIndex 
)
static

Definition at line 3594 of file SkPath.cpp.

3594 {
3595 return SkPathBuilder().addOval(r, dir, startIndex).detach();
3596}

◆ Oval() [2/2]

SkPath SkPath::Oval ( const SkRect r,
SkPathDirection  dir = SkPathDirection::kCW 
)
static

Definition at line 3590 of file SkPath.cpp.

3590 {
3591 return SkPathBuilder().addOval(r, dir).detach();
3592}

◆ Polygon() [1/2]

SkPath SkPath::Polygon ( const SkPoint  pts[],
int  count,
bool  isClosed,
SkPathFillType  ft = SkPathFillType::kWinding,
bool  isVolatile = false 
)
static

Definition at line 3614 of file SkPath.cpp.

3615 {
3616 return SkPathBuilder().addPolygon(pts, count, isClosed)
3617 .setFillType(ft)
3618 .setIsVolatile(isVolatile)
3619 .detach();
3620}

◆ Polygon() [2/2]

static SkPath SkPath::Polygon ( const std::initializer_list< SkPoint > &  list,
bool  isClosed,
SkPathFillType  fillType = SkPathFillType::kWinding,
bool  isVolatile = false 
)
inlinestatic

Definition at line 100 of file SkPath.h.

102 {
103 return Polygon(list.begin(), SkToInt(list.size()), isClosed, fillType, isVolatile);
104 }

◆ quadTo() [1/2]

SkPath & SkPath::quadTo ( const SkPoint p1,
const SkPoint p2 
)
inline

Adds quad from last point towards SkPoint p1, to SkPoint p2. If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0) before adding quad.

Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed; then appends kQuad_Verb to verb array; and SkPoint p1, p2 to SkPoint array.

Parameters
p1control SkPoint of added quad
p2end SkPoint of added quad
Returns
reference to SkPath

Definition at line 686 of file SkPath.h.

686 {
687 return this->quadTo(p1.fX, p1.fY, p2.fX, p2.fY);
688 }

◆ quadTo() [2/2]

SkPath & SkPath::quadTo ( SkScalar  x1,
SkScalar  y1,
SkScalar  x2,
SkScalar  y2 
)

Adds quad from last point towards (x1, y1), to (x2, y2). If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0) before adding quad.

Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed; then appends kQuad_Verb to verb array; and (x1, y1), (x2, y2) to SkPoint array.

Parameters
x1control SkPoint of quad on x-axis
y1control SkPoint of quad on y-axis
x2end SkPoint of quad on x-axis
y2end SkPoint of quad on y-axis
Returns
reference to SkPath

example: https://fiddle.skia.org/c/@Path_quadTo

Definition at line 746 of file SkPath.cpp.

746 {
747 SkDEBUGCODE(this->validate();)
748
749 this->injectMoveToIfNeeded();
750
751 SkPathRef::Editor ed(&fPathRef);
752 SkPoint* pts = ed.growForVerb(kQuad_Verb);
753 pts[0].set(x1, y1);
754 pts[1].set(x2, y2);
755
756 return this->dirtyAfterEdit();
757}

◆ rArcTo()

SkPath & SkPath::rArcTo ( SkScalar  rx,
SkScalar  ry,
SkScalar  xAxisRotate,
SkPath::ArcSize  largeArc,
SkPathDirection  sweep,
SkScalar  dx,
SkScalar  dy 
)

Appends arc to SkPath, relative to last SkPath SkPoint. Arc is implemented by one or more conic, weighted to describe part of oval with radii (rx, ry) rotated by xAxisRotate degrees. Arc curves from last SkPath SkPoint to relative end SkPoint: (dx, dy), choosing one of four possible routes: clockwise or counterclockwise, and smaller or larger. If SkPath is empty, the start arc SkPoint is (0, 0).

Arc sweep is always less than 360 degrees. arcTo() appends line to end SkPoint if either radii are zero, or if last SkPath SkPoint equals end SkPoint. arcTo() scales radii (rx, ry) to fit last SkPath SkPoint and end SkPoint if both are greater than zero but too small to describe an arc.

arcTo() appends up to four conic curves. arcTo() implements the functionality of svg arc, although SVG "sweep-flag" value is opposite the integer value of sweep; SVG "sweep-flag" uses 1 for clockwise, while kCW_Direction cast to int is zero.

Parameters
rxradius before x-axis rotation
ryradius before x-axis rotation
xAxisRotatex-axis rotation in degrees; positive values are clockwise
largeArcchooses smaller or larger arc
sweepchooses clockwise or counterclockwise arc
dxx-axis offset end of arc from last SkPath SkPoint
dyy-axis offset end of arc from last SkPath SkPoint
Returns
reference to SkPath

Definition at line 1431 of file SkPath.cpp.

1432 {
1433 SkPoint currentPoint;
1434 this->getLastPt(&currentPoint);
1435 return this->arcTo(rx, ry, xAxisRotate, largeArc, sweep,
1436 currentPoint.fX + dx, currentPoint.fY + dy);
1437}

◆ rConicTo()

SkPath & SkPath::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 SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0) before adding conic.

Appends kMove_Verb to verb array and (0, 0) to SkPoint 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 SkPoint control and end to SkPoint array. control is last point plus vector (dx1, dy1). end is last point plus vector (dx2, dy2).

Function name stands for "relative conic to".

Parameters
dx1offset from last point to conic control on x-axis
dy1offset from last point to conic control on y-axis
dx2offset from last point to conic end on x-axis
dy2offset from last point to conic end on y-axis
wweight of added conic
Returns
reference to SkPath

Definition at line 791 of file SkPath.cpp.

792 {
793 this->injectMoveToIfNeeded(); // This can change the result of this->getLastPt().
794 SkPoint pt;
795 this->getLastPt(&pt);
796 return this->conicTo(pt.fX + dx1, pt.fY + dy1, pt.fX + dx2, pt.fY + dy2, w);
797}

◆ rCubicTo()

SkPath & SkPath::rCubicTo ( SkScalar  dx1,
SkScalar  dy1,
SkScalar  dx2,
SkScalar  dy2,
SkScalar  dx3,
SkScalar  dy3 
)

Adds cubic from last point towards vector (dx1, dy1), then towards vector (dx2, dy2), to vector (dx3, dy3). If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0) before adding cubic.

Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed; then appends kCubic_Verb to verb array; and appends cubic control and cubic end to SkPoint 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".

Parameters
dx1offset from last point to first cubic control on x-axis
dy1offset from last point to first cubic control on y-axis
dx2offset from last point to second cubic control on x-axis
dy2offset from last point to second cubic control on y-axis
dx3offset from last point to cubic end on x-axis
dy3offset from last point to cubic end on y-axis
Returns
reference to SkPath

Definition at line 814 of file SkPath.cpp.

815 {
816 this->injectMoveToIfNeeded(); // This can change the result of this->getLastPt().
817 SkPoint pt;
818 this->getLastPt(&pt);
819 return this->cubicTo(pt.fX + x1, pt.fY + y1, pt.fX + x2, pt.fY + y2,
820 pt.fX + x3, pt.fY + y3);
821}

◆ readFromMemory()

size_t SkPath::readFromMemory ( const void *  buffer,
size_t  length 
)

Initializes SkPath from buffer of size length. Returns zero if the buffer is data is inconsistent, or the length is too small.

Reads SkPath::FillType, verb array, SkPoint array, conic weight, and additionally reads computed information like SkPath::Convexity and bounds.

Used only in concert with writeToMemory(); the format used for SkPath in memory is not guaranteed.

Parameters
bufferstorage for SkPath
lengthbuffer size in bytes; must be multiple of 4
Returns
number of bytes read, or zero on failure

example: https://fiddle.skia.org/c/@Path_readFromMemory

Definition at line 193 of file SkPath_serial.cpp.

193 {
194 SkRBuffer buffer(storage, length);
195 uint32_t packed;
196 if (!buffer.readU32(&packed)) {
197 return 0;
198 }
199 unsigned version = extract_version(packed);
200
201 const bool verbsAreForward = (version == kVerbsAreStoredForward_Version);
202 if (!verbsAreForward && version != kJustPublicData_Version) SK_UNLIKELY {
203 // Old/unsupported version.
204 return 0;
205 }
206
207 switch (extract_serializationtype(packed)) {
209 return this->readAsRRect(storage, length);
211 break; // fall out
212 default:
213 return 0;
214 }
215
216 // To minimize the number of reads done a structure with the counts is used.
217 struct {
218 int32_t pts, cnx, vbs;
219 } counts;
220 if (!buffer.read(&counts, sizeof(counts))) {
221 return 0;
222 }
223
224 const SkPoint* points = buffer.skipCount<SkPoint>(counts.pts);
225 const SkScalar* conics = buffer.skipCount<SkScalar>(counts.cnx);
226 const uint8_t* verbs = buffer.skipCount<uint8_t>(counts.vbs);
227 buffer.skipToAlign4();
228 if (!buffer.isValid()) {
229 return 0;
230 }
231 SkASSERT(buffer.pos() <= length);
232
233 if (counts.vbs == 0) {
234 if (counts.pts == 0 && counts.cnx == 0) {
235 reset();
237 return buffer.pos();
238 }
239 // No verbs but points and/or conic weights is a not a valid path.
240 return 0;
241 }
242
243 SkAutoMalloc reversedStorage;
244 if (!verbsAreForward) SK_UNLIKELY {
245 uint8_t* tmpVerbs = (uint8_t*)reversedStorage.reset(counts.vbs);
246 for (int i = 0; i < counts.vbs; ++i) {
247 tmpVerbs[i] = verbs[counts.vbs - i - 1];
248 }
249 verbs = tmpVerbs;
250 }
251
252 SkPathVerbAnalysis analysis = sk_path_analyze_verbs(verbs, counts.vbs);
253 if (!analysis.valid || analysis.points != counts.pts || analysis.weights != counts.cnx) {
254 return 0;
255 }
256 *this = SkPathPriv::MakePath(analysis, points, verbs, counts.vbs, conics,
257 extract_filltype(packed), false);
258 return buffer.pos();
259}
static const int points[]
#define SK_UNLIKELY
Definition: SkAssert.h:28
SkPathVerbAnalysis sk_path_analyze_verbs(const uint8_t verbs[], int count)
Definition: SkPath.cpp:3515
static unsigned extract_version(uint32_t packed)
@ kGeneral
@ kRRect
static SkPathFillType extract_filltype(uint32_t packed)
@ kJustPublicData_Version
@ kVerbsAreStoredForward_Version
static SerializationType extract_serializationtype(uint32_t packed)
void * reset(size_t size=0, OnShrink shrink=kAlloc_OnShrink)
Definition: SkAutoMalloc.h:53
static SkPath MakePath(const SkPathVerbAnalysis &analysis, const SkPoint points[], const uint8_t verbs[], int verbCount, const SkScalar conics[], SkPathFillType fillType, bool isVolatile)
Definition: SkPathPriv.h:425
void setFillType(SkPathFillType ft)
Definition: SkPath.h:235
size_t length
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core counts
Definition: switches.h:239
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126

◆ Rect()

SkPath SkPath::Rect ( const SkRect r,
SkPathDirection  dir = SkPathDirection::kCW,
unsigned  startIndex = 0 
)
static

Definition at line 3586 of file SkPath.cpp.

3586 {
3587 return SkPathBuilder().addRect(r, dir, startIndex).detach();
3588}

◆ reset()

SkPath & SkPath::reset ( )

Sets SkPath to its initial state. Removes verb array, SkPoint array, and weights, and sets FillType to kWinding. Internal storage associated with SkPath is released.

Returns
reference to SkPath

example: https://fiddle.skia.org/c/@Path_reset

Definition at line 370 of file SkPath.cpp.

370 {
371 SkDEBUGCODE(this->validate();)
372
373 if (fPathRef->unique()) {
374 fPathRef->reset();
375 } else {
376 fPathRef.reset(SkPathRef::CreateEmpty());
377 }
378 this->resetFields();
379 return *this;
380}
bool unique() const
Definition: SkRefCnt.h:175

◆ reverseAddPath()

SkPath & SkPath::reverseAddPath ( const SkPath src)

Appends src to SkPath, from back to front. Reversed src always appends a new contour to SkPath.

Parameters
srcSkPath verbs, SkPoint, and conic weights to add
Returns
reference to SkPath

example: https://fiddle.skia.org/c/@Path_reverseAddPath

Definition at line 1633 of file SkPath.cpp.

1633 {
1634 // Detect if we're trying to add ourself
1635 const SkPath* src = &srcPath;
1636 SkTLazy<SkPath> tmp;
1637 if (this == src) {
1638 src = tmp.set(srcPath);
1639 }
1640
1641 const uint8_t* verbsBegin = src->fPathRef->verbsBegin();
1642 const uint8_t* verbs = src->fPathRef->verbsEnd();
1643 const SkPoint* pts = src->fPathRef->pointsEnd();
1644 const SkScalar* conicWeights = src->fPathRef->conicWeightsEnd();
1645
1646 bool needMove = true;
1647 bool needClose = false;
1648 while (verbs > verbsBegin) {
1649 uint8_t v = *--verbs;
1650 int n = SkPathPriv::PtsInVerb(v);
1651
1652 if (needMove) {
1653 --pts;
1654 this->moveTo(pts->fX, pts->fY);
1655 needMove = false;
1656 }
1657 pts -= n;
1658 switch (v) {
1659 case kMove_Verb:
1660 if (needClose) {
1661 this->close();
1662 needClose = false;
1663 }
1664 needMove = true;
1665 pts += 1; // so we see the point in "if (needMove)" above
1666 break;
1667 case kLine_Verb:
1668 this->lineTo(pts[0]);
1669 break;
1670 case kQuad_Verb:
1671 this->quadTo(pts[1], pts[0]);
1672 break;
1673 case kConic_Verb:
1674 this->conicTo(pts[1], pts[0], *--conicWeights);
1675 break;
1676 case kCubic_Verb:
1677 this->cubicTo(pts[2], pts[1], pts[0]);
1678 break;
1679 case kClose_Verb:
1680 needClose = true;
1681 break;
1682 default:
1683 SkDEBUGFAIL("unexpected verb");
1684 }
1685 }
1686 return *this;
1687}

◆ rewind()

SkPath & SkPath::rewind ( )

Sets SkPath to its initial state, preserving internal storage. Removes verb array, SkPoint array, and weights, and sets FillType to kWinding. Internal storage associated with SkPath is retained.

Use rewind() instead of reset() if SkPath storage will be reused and performance is critical.

Returns
reference to SkPath

example: https://fiddle.skia.org/c/@Path_rewind

Definition at line 382 of file SkPath.cpp.

382 {
383 SkDEBUGCODE(this->validate();)
384
385 SkPathRef::Rewind(&fPathRef);
386 this->resetFields();
387 return *this;
388}
static void Rewind(sk_sp< SkPathRef > *pathRef)
Definition: SkPathRef.cpp:229

◆ rLineTo()

SkPath & SkPath::rLineTo ( SkScalar  dx,
SkScalar  dy 
)

Adds line from last point to vector (dx, dy). If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0) before adding line.

Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed; then appends kLine_Verb to verb array and line end to SkPoint array. Line end is last point plus vector (dx, dy). Function name stands for "relative line to".

Parameters
dxoffset from last point to line end on x-axis
dyoffset from last point to line end on y-axis
Returns
reference to SkPath

example: https://fiddle.skia.org/c/@Path_rLineTo example: https://fiddle.skia.org/c/@Quad_a example: https://fiddle.skia.org/c/@Quad_b

Definition at line 739 of file SkPath.cpp.

739 {
740 this->injectMoveToIfNeeded(); // This can change the result of this->getLastPt().
741 SkPoint pt;
742 this->getLastPt(&pt);
743 return this->lineTo(pt.fX + x, pt.fY + y);
744}

◆ rMoveTo()

SkPath & SkPath::rMoveTo ( SkScalar  dx,
SkScalar  dy 
)

Adds beginning of contour relative to last point. If SkPath is empty, starts contour at (dx, dy). Otherwise, start contour at last point offset by (dx, dy). Function name stands for "relative move to".

Parameters
dxoffset from last point to contour start on x-axis
dyoffset from last point to contour start on y-axis
Returns
reference to SkPath

example: https://fiddle.skia.org/c/@Path_rMoveTo

Definition at line 701 of file SkPath.cpp.

701 {
702 SkPoint pt = {0,0};
703 int count = fPathRef->countPoints();
704 if (count > 0) {
705 if (fLastMoveToIndex >= 0) {
706 pt = fPathRef->atPoint(count - 1);
707 } else {
708 pt = fPathRef->atPoint(~fLastMoveToIndex);
709 }
710 }
711 return this->moveTo(pt.fX + x, pt.fY + y);
712}

◆ rQuadTo()

SkPath & SkPath::rQuadTo ( SkScalar  dx1,
SkScalar  dy1,
SkScalar  dx2,
SkScalar  dy2 
)

Adds quad from last point towards vector (dx1, dy1), to vector (dx2, dy2). If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0) before adding quad.

Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed; then appends kQuad_Verb to verb array; and appends quad control and quad end to SkPoint 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".

Parameters
dx1offset from last point to quad control on x-axis
dy1offset from last point to quad control on y-axis
dx2offset from last point to quad end on x-axis
dy2offset from last point to quad end on y-axis
Returns
reference to SkPath

example: https://fiddle.skia.org/c/@Conic_Weight_a example: https://fiddle.skia.org/c/@Conic_Weight_b example: https://fiddle.skia.org/c/@Conic_Weight_c example: https://fiddle.skia.org/c/@Path_rQuadTo

Definition at line 759 of file SkPath.cpp.

759 {
760 this->injectMoveToIfNeeded(); // This can change the result of this->getLastPt().
761 SkPoint pt;
762 this->getLastPt(&pt);
763 return this->quadTo(pt.fX + x1, pt.fY + y1, pt.fX + x2, pt.fY + y2);
764}

◆ RRect() [1/3]

SkPath SkPath::RRect ( const SkRect bounds,
SkScalar  rx,
SkScalar  ry,
SkPathDirection  dir = SkPathDirection::kCW 
)
static

Definition at line 3610 of file SkPath.cpp.

3610 {
3611 return SkPathBuilder().addRRect(SkRRect::MakeRectXY(r, rx, ry), dir).detach();
3612}
static SkRRect MakeRectXY(const SkRect &rect, SkScalar xRad, SkScalar yRad)
Definition: SkRRect.h:180

◆ RRect() [2/3]

SkPath SkPath::RRect ( const SkRRect rr,
SkPathDirection  dir = SkPathDirection::kCW 
)
static

Definition at line 3602 of file SkPath.cpp.

3602 {
3603 return SkPathBuilder().addRRect(rr, dir).detach();
3604}

◆ RRect() [3/3]

SkPath SkPath::RRect ( const SkRRect rr,
SkPathDirection  dir,
unsigned  startIndex 
)
static

Definition at line 3606 of file SkPath.cpp.

3606 {
3607 return SkPathBuilder().addRRect(rr, dir, startIndex).detach();
3608}

◆ serialize()

sk_sp< SkData > SkPath::serialize ( ) const

Writes SkPath to buffer, returning the buffer written to, wrapped in SkData.

serialize() writes SkPath::FillType, verb array, SkPoint array, conic weight, and additionally writes computed information like SkPath::Convexity and bounds.

serialize() should only be used in concert with readFromMemory(). The format used for SkPath in memory is not guaranteed.

Returns
SkPath data wrapped in SkData buffer

example: https://fiddle.skia.org/c/@Path_serialize

Definition at line 145 of file SkPath_serial.cpp.

145 {
146 size_t size = this->writeToMemory(nullptr);
148 this->writeToMemory(data->writable_data());
149 return data;
150}
static sk_sp< SkData > MakeUninitialized(size_t length)
Definition: SkData.cpp:116
void * writable_data()
Definition: SkData.h:52
size_t writeToMemory(void *buffer) const
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63

◆ setFillType()

void SkPath::setFillType ( SkPathFillType  ft)
inline

Sets FillType, the rule used to fill SkPath. While there is no check that ft is legal, values outside of FillType are not supported.

Definition at line 235 of file SkPath.h.

235 {
236 fFillType = SkToU8(ft);
237 }
constexpr uint8_t SkToU8(S x)
Definition: SkTo.h:22

◆ setIsVolatile()

SkPath & SkPath::setIsVolatile ( bool  isVolatile)
inline

Specifies whether SkPath is volatile; whether it will be altered or discarded by the caller after it is drawn. SkPath by default have volatile set false, allowing Skia to attach a cache of data which speeds repeated drawing.

Mark temporary paths, discarded or modified after use, as volatile to inform Skia that the path need not be cached.

Mark animating SkPath volatile to improve performance. Mark unchanging SkPath non-volatile to improve repeated rendering.

raster surface SkPath draws are affected by volatile for some shadows. GPU surface SkPath draws are affected by volatile for some shadows and concave geometries.

Parameters
isVolatiletrue if caller will alter SkPath after drawing
Returns
reference to SkPath

Definition at line 370 of file SkPath.h.

370 {
371 fIsVolatile = isVolatile;
372 return *this;
373 }

◆ setLastPt() [1/2]

void SkPath::setLastPt ( const SkPoint p)
inline

Sets the last point on the path. If SkPoint array is empty, append kMove_Verb to verb array and append p to SkPoint array.

Parameters
pset value of last point

Definition at line 1436 of file SkPath.h.

1436 {
1437 this->setLastPt(p.fX, p.fY);
1438 }

◆ setLastPt() [2/2]

void SkPath::setLastPt ( SkScalar  x,
SkScalar  y 
)

Sets last point to (x, y). If SkPoint array is empty, append kMove_Verb to verb array and append (x, y) to SkPoint array.

Parameters
xset x-axis value of last point
yset y-axis value of last point

example: https://fiddle.skia.org/c/@Path_setLastPt

Definition at line 608 of file SkPath.cpp.

608 {
609 SkDEBUGCODE(this->validate();)
610
611 int count = fPathRef->countPoints();
612 if (count == 0) {
613 this->moveTo(x, y);
614 } else {
615 SkPathRef::Editor ed(&fPathRef);
616 ed.atPoint(count-1)->set(x, y);
617 }
618}

◆ snapshot()

SkPath SkPath::snapshot ( ) const
inline

Returns a copy of this path in the current state.

Definition at line 142 of file SkPath.h.

142 {
143 return *this;
144 }

◆ swap()

void SkPath::swap ( SkPath other)

Exchanges the verb array, SkPoint array, weights, and SkPath::FillType with other. Cached state is also exchanged. swap() internally exchanges pointers, so it is lightweight and does not allocate memory.

swap() usage has largely been replaced by operator=(const SkPath& path). SkPath do not copy their content on assignment until they are written to, making assignment as efficient as swap().

Parameters
otherSkPath exchanged by value

example: https://fiddle.skia.org/c/@Path_swap

Definition at line 219 of file SkPath.cpp.

219 {
220 if (this != &that) {
221 fPathRef.swap(that.fPathRef);
222 std::swap(fLastMoveToIndex, that.fLastMoveToIndex);
223
224 const auto ft = fFillType;
225 fFillType = that.fFillType;
226 that.fFillType = ft;
227
228 const auto iv = fIsVolatile;
229 fIsVolatile = that.fIsVolatile;
230 that.fIsVolatile = iv;
231
232 // Non-atomic swaps of atomic values.
233 SkPathConvexity c = this->getConvexityOrUnknown();
234 this->setConvexity(that.getConvexityOrUnknown());
235 that.setConvexity(c);
236
237 SkPathFirstDirection fd = this->getFirstDirection();
238 this->setFirstDirection(that.getFirstDirection());
239 that.setFirstDirection(fd);
240 }
241}
SkPathConvexity
Definition: SkPathEnums.h:13
void swap(sk_sp< T > &a, sk_sp< T > &b)
Definition: SkRefCnt.h:341
void swap(sk_sp< T > &that)
Definition: SkRefCnt.h:330

◆ toggleInverseFillType()

void SkPath::toggleInverseFillType ( )
inline

Replaces FillType with its inverse. The inverse of FillType describes the area unmodified by the original FillType.

Definition at line 249 of file SkPath.h.

249 {
250 fFillType ^= 2;
251 }

◆ transform() [1/2]

SkPath & SkPath::transform ( const SkMatrix matrix,
SkApplyPerspectiveClip  pc = SkApplyPerspectiveClip::kYes 
)
inline

Transforms verb array, SkPoint array, and weight by matrix. transform may change verbs and increase their number. SkPath is replaced by transformed data.

Parameters
matrixSkMatrix to apply to SkPath
pcwhether to apply perspective clipping

Definition at line 1394 of file SkPath.h.

1395 {
1396 this->transform(matrix, this, pc);
1397 return *this;
1398 }

◆ transform() [2/2]

void SkPath::transform ( const SkMatrix matrix,
SkPath dst,
SkApplyPerspectiveClip  pc = SkApplyPerspectiveClip::kYes 
) const

Transforms verb array, SkPoint array, and weight by matrix. transform may change verbs and increase their number. Transformed SkPath replaces dst; if dst is nullptr, original data is replaced.

Parameters
matrixSkMatrix to apply to SkPath
dstoverwritten, transformed copy of SkPath; may be nullptr
pcwhether to apply perspective clipping

example: https://fiddle.skia.org/c/@Path_transform

Definition at line 1711 of file SkPath.cpp.

1711 {
1712 if (matrix.isIdentity()) {
1713 if (dst != nullptr && dst != this) {
1714 *dst = *this;
1715 }
1716 return;
1717 }
1718
1719 SkDEBUGCODE(this->validate();)
1720 if (dst == nullptr) {
1721 dst = const_cast<SkPath*>(this);
1722 }
1723
1724 if (matrix.hasPerspective()) {
1725 SkPath tmp;
1726 tmp.fFillType = fFillType;
1727
1728 SkPath clipped;
1729 const SkPath* src = this;
1730 if (pc == SkApplyPerspectiveClip::kYes &&
1731 SkPathPriv::PerspectiveClip(*this, matrix, &clipped))
1732 {
1733 src = &clipped;
1734 }
1735
1736 SkPath::Iter iter(*src, false);
1737 SkPoint pts[4];
1738 SkPath::Verb verb;
1739
1740 while ((verb = iter.next(pts)) != kDone_Verb) {
1741 switch (verb) {
1742 case kMove_Verb:
1743 tmp.moveTo(pts[0]);
1744 break;
1745 case kLine_Verb:
1746 tmp.lineTo(pts[1]);
1747 break;
1748 case kQuad_Verb:
1749 // promote the quad to a conic
1750 tmp.conicTo(pts[1], pts[2],
1752 break;
1753 case kConic_Verb:
1754 tmp.conicTo(pts[1], pts[2],
1755 SkConic::TransformW(pts, iter.conicWeight(), matrix));
1756 break;
1757 case kCubic_Verb:
1758 subdivide_cubic_to(&tmp, pts);
1759 break;
1760 case kClose_Verb:
1761 tmp.close();
1762 break;
1763 default:
1764 SkDEBUGFAIL("unknown verb");
1765 break;
1766 }
1767 }
1768
1769 dst->swap(tmp);
1770 SkPathRef::Editor ed(&dst->fPathRef);
1771 matrix.mapPoints(ed.writablePoints(), ed.pathRef()->countPoints());
1772 dst->setFirstDirection(SkPathFirstDirection::kUnknown);
1773 } else {
1774 SkPathConvexity convexity = this->getConvexityOrUnknown();
1775
1776 SkPathRef::CreateTransformedCopy(&dst->fPathRef, *fPathRef, matrix);
1777
1778 if (this != dst) {
1779 dst->fLastMoveToIndex = fLastMoveToIndex;
1780 dst->fFillType = fFillType;
1781 dst->fIsVolatile = fIsVolatile;
1782 }
1783
1784 // Due to finite/fragile float numerics, we can't assume that a convex path remains
1785 // convex after a transformation, so mark it as unknown here.
1786 // However, some transformations are thought to be safe:
1787 // axis-aligned values under scale/translate.
1788 //
1789 if (convexity == SkPathConvexity::kConvex &&
1790 (!matrix.isScaleTranslate() || !SkPathPriv::IsAxisAligned(*this))) {
1791 // Not safe to still assume we're convex...
1792 convexity = SkPathConvexity::kUnknown;
1793 }
1794 dst->setConvexity(convexity);
1795
1796 if (this->getFirstDirection() == SkPathFirstDirection::kUnknown) {
1797 dst->setFirstDirection(SkPathFirstDirection::kUnknown);
1798 } else {
1799 SkScalar det2x2 =
1802 if (det2x2 < 0) {
1803 dst->setFirstDirection(
1805 (SkPathFirstDirection)this->getFirstDirection()));
1806 } else if (det2x2 > 0) {
1807 dst->setFirstDirection(this->getFirstDirection());
1808 } else {
1809 dst->setFirstDirection(SkPathFirstDirection::kUnknown);
1810 }
1811 }
1812
1813 SkDEBUGCODE(dst->validate();)
1814 }
1815}
@ kYes
Do pre-clip the geometry before applying the (perspective) matrix.
static void subdivide_cubic_to(SkPath *path, const SkPoint pts[4], int level=2)
Definition: SkPath.cpp:1698
static constexpr int kMScaleX
horizontal scale factor
Definition: SkMatrix.h:353
static constexpr int kMSkewY
vertical skew factor
Definition: SkMatrix.h:356
static constexpr int kMScaleY
vertical scale factor
Definition: SkMatrix.h:357
static constexpr int kMSkewX
horizontal skew factor
Definition: SkMatrix.h:354
static bool IsAxisAligned(const SkPath &path)
Definition: SkPath.cpp:3992
static bool PerspectiveClip(const SkPath &src, const SkMatrix &, SkPath *result)
Definition: SkPath.cpp:3962
static SkPathFirstDirection OppositeFirstDirection(SkPathFirstDirection dir)
Definition: SkPathPriv.h:52
static void CreateTransformedCopy(sk_sp< SkPathRef > *dst, const SkPathRef &src, const SkMatrix &matrix)
Definition: SkPathRef.cpp:141
static SkScalar TransformW(const SkPoint[3], SkScalar w, const SkMatrix &)

◆ updateBoundsCache()

void SkPath::updateBoundsCache ( ) const
inline

Updates internal bounds so that subsequent calls to getBounds() are instantaneous. Unaltered copies of SkPath may also access cached bounds through getBounds().

For now, identical to calling getBounds() and ignoring the returned value.

Call to prepare SkPath subsequently drawn from multiple threads, to avoid a race condition where each draw separately computes the bounds.

Definition at line 524 of file SkPath.h.

524 {
525 // for now, just calling getBounds() is sufficient
526 this->getBounds();
527 }

◆ writeToMemory()

size_t SkPath::writeToMemory ( void *  buffer) const

Writes SkPath to buffer, returning the number of bytes written. Pass nullptr to obtain the storage size.

Writes SkPath::FillType, verb array, SkPoint array, conic weight, and additionally writes computed information like SkPath::Convexity and bounds.

Use only be used in concert with readFromMemory(); the format used for SkPath in memory is not guaranteed.

Parameters
bufferstorage for SkPath; may be nullptr
Returns
size of storage required for SkPath; always a multiple of 4

example: https://fiddle.skia.org/c/@Path_writeToMemory

Definition at line 103 of file SkPath_serial.cpp.

103 {
104 SkDEBUGCODE(this->validate();)
105
106 if (size_t bytes = this->writeToMemoryAsRRect(storage)) {
107 return bytes;
108 }
109
110 int32_t packed = (fFillType << kFillType_SerializationShift) |
113
114 int32_t pts = fPathRef->countPoints();
115 int32_t cnx = fPathRef->countWeights();
116 int32_t vbs = fPathRef->countVerbs();
117
118 SkSafeMath safe;
119 size_t size = 4 * sizeof(int32_t);
120 size = safe.add(size, safe.mul(pts, sizeof(SkPoint)));
121 size = safe.add(size, safe.mul(cnx, sizeof(SkScalar)));
122 size = safe.add(size, safe.mul(vbs, sizeof(uint8_t)));
123 size = safe.alignUp(size, 4);
124 if (!safe) {
125 return 0;
126 }
127 if (!storage) {
128 return size;
129 }
130
131 SkWBuffer buffer(storage);
132 buffer.write32(packed);
133 buffer.write32(pts);
134 buffer.write32(cnx);
135 buffer.write32(vbs);
136 buffer.write(fPathRef->points(), pts * sizeof(SkPoint));
137 buffer.write(fPathRef->conicWeights(), cnx * sizeof(SkScalar));
138 buffer.write(fPathRef->verbsBegin(), vbs * sizeof(uint8_t));
139 buffer.padToAlign4();
140
141 SkASSERT(buffer.pos() == size);
142 return size;
143}
@ kCurrent_Version
@ kType_SerializationShift
@ kFillType_SerializationShift
size_t add(size_t x, size_t y)
Definition: SkSafeMath.h:33
size_t alignUp(size_t x, size_t alignment)
Definition: SkSafeMath.h:54
size_t mul(size_t x, size_t y)
Definition: SkSafeMath.h:29

Friends And Related Function Documentation

◆ ForceIsRRect_Private

friend class ForceIsRRect_Private
friend

Definition at line 1938 of file SkPath.h.

◆ FuzzPath

friend class FuzzPath
friend

Definition at line 1939 of file SkPath.h.

◆ Iter

friend class Iter
friend

Definition at line 1840 of file SkPath.h.

◆ operator!=

bool operator!= ( const SkPath a,
const SkPath b 
)
friend

Compares a and b; returns true if SkPath::FillType, verb array, SkPoint array, and weights are not equivalent.

Parameters
aSkPath to compare
bSkPath to compare
Returns
true if SkPath pair are not equivalent

Definition at line 185 of file SkPath.h.

185 {
186 return !(a == b);
187 }

◆ operator==

SK_API bool operator== ( const SkPath a,
const SkPath b 
)
friend

Compares a and b; returns true if SkPath::FillType, verb array, SkPoint array, and weights are equivalent.

Parameters
aSkPath to compare
bSkPath to compare
Returns
true if SkPath pair are equivalent

Definition at line 212 of file SkPath.cpp.

212 {
213 // note: don't need to look at isConvex or bounds, since just comparing the
214 // raw data is sufficient.
215 return &a == &b ||
216 (a.fFillType == b.fFillType && *a.fPathRef == *b.fPathRef);
217}

◆ PathTest_Private

friend class PathTest_Private
friend

Definition at line 1937 of file SkPath.h.

◆ SkAutoDisableDirectionCheck

friend class SkAutoDisableDirectionCheck
friend

Definition at line 1931 of file SkPath.h.

◆ SkAutoDisableOvalCheck

friend class SkAutoDisableOvalCheck
friend

Definition at line 1930 of file SkPath.h.

◆ SkAutoPathBoundsUpdate

friend class SkAutoPathBoundsUpdate
friend

Definition at line 1929 of file SkPath.h.

◆ SkBench_AddPathTest

friend class SkBench_AddPathTest
friend

Definition at line 1936 of file SkPath.h.

◆ SkOpBuilder

friend class SkOpBuilder
friend

Definition at line 1935 of file SkPath.h.

◆ SkPathBuilder

friend class SkPathBuilder
friend

Definition at line 1932 of file SkPath.h.

◆ SkPathEdgeIter

friend class SkPathEdgeIter
friend

Definition at line 1933 of file SkPath.h.

◆ SkPathPriv

friend class SkPathPriv
friend

Definition at line 1841 of file SkPath.h.

◆ SkPathStroker

friend class SkPathStroker
friend

Definition at line 1842 of file SkPath.h.

◆ SkPathWriter

friend class SkPathWriter
friend

Definition at line 1934 of file SkPath.h.


The documentation for this class was generated from the following files: