Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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)
 
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 1803 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 1275 of file SkPath.h.

1275 {
1276 /** Contours are appended to the destination path as new contours.
1277 */
1279 /** Extends the last contour of the destination path with the first countour
1280 of the source path, connecting them with a line. If the last contour is
1281 closed, a new empty contour starting at its start point is extended instead.
1282 If the destination path is empty, the result is the source path.
1283 The last path of the result is closed only if the last path of the source is.
1284 */
1286 };
@ kExtend_AddPathMode
Definition SkPath.h:1285
@ kAppend_AddPathMode
Definition SkPath.h:1278

◆ 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 1436 of file SkPath.h.

1436 {
1441 };
@ 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:1437
@ kQuad_SegmentMask
Definition SkPath.h:1438
@ kCubic_SegmentMask
Definition SkPath.h:1440
@ kConic_SegmentMask
Definition SkPath.h:1439

◆ Verb

Enumerator
kMove_Verb 
kLine_Verb 
kQuad_Verb 
kConic_Verb 
kCubic_Verb 
kClose_Verb 
kDone_Verb 

Definition at line 1457 of file SkPath.h.

1457 {
1458 kMove_Verb = static_cast<int>(SkPathVerb::kMove),
1459 kLine_Verb = static_cast<int>(SkPathVerb::kLine),
1460 kQuad_Verb = static_cast<int>(SkPathVerb::kQuad),
1461 kConic_Verb = static_cast<int>(SkPathVerb::kConic),
1462 kCubic_Verb = static_cast<int>(SkPathVerb::kCubic),
1463 kClose_Verb = static_cast<int>(SkPathVerb::kClose),
1465 };
@ 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:1463
@ kMove_Verb
Definition SkPath.h:1458
@ kConic_Verb
Definition SkPath.h:1461
@ kDone_Verb
Definition SkPath.h:1464
@ kCubic_Verb
Definition SkPath.h:1462
@ kQuad_Verb
Definition SkPath.h:1460
@ kLine_Verb
Definition SkPath.h:1459

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 154 of file SkPath.cpp.

155 : fPathRef(SkPathRef::CreateEmpty()) {
156 this->resetFields();
157 fIsVolatile = false;
158}
static SkPathRef * CreateEmpty()
Definition SkPathRef.cpp:76

◆ 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 178 of file SkPath.cpp.

179 : fPathRef(SkRef(that.fPathRef.get())) {
180 this->copyFields(that);
181 SkDEBUGCODE(that.validate();)
182}
#define SkDEBUGCODE(...)
Definition SkDebug.h:23
static T * SkRef(T *obj)
Definition SkRefCnt.h:132

◆ ~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 184 of file SkPath.cpp.

184 {
185 SkDEBUGCODE(this->validate();)
186}

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 1375 of file SkPath.cpp.

1375 {
1376 if (oval.isEmpty() || 0 == sweepAngle) {
1377 return *this;
1378 }
1379
1380 const SkScalar kFullCircleAngle = SkIntToScalar(360);
1381
1382 if (sweepAngle >= kFullCircleAngle || sweepAngle <= -kFullCircleAngle) {
1383 // We can treat the arc as an oval if it begins at one of our legal starting positions.
1384 // See SkPath::addOval() docs.
1385 SkScalar startOver90 = startAngle / 90.f;
1386 SkScalar startOver90I = SkScalarRoundToScalar(startOver90);
1387 SkScalar error = startOver90 - startOver90I;
1388 if (SkScalarNearlyEqual(error, 0)) {
1389 // Index 1 is at startAngle == 0.
1390 SkScalar startIndex = std::fmod(startOver90I + 1.f, 4.f);
1391 startIndex = startIndex < 0 ? startIndex + 4.f : startIndex;
1392 return this->addOval(oval, sweepAngle > 0 ? SkPathDirection::kCW : SkPathDirection::kCCW,
1393 (unsigned) startIndex);
1394 }
1395 }
1396 return this->arcTo(oval, startAngle, sweepAngle, true);
1397}
SkPathDirection
Definition SkPathTypes.h:34
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:1156
SkPath & addOval(const SkRect &oval, SkPathDirection dir=SkPathDirection::kCW)
Definition SkPath.cpp:1101
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
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 1149 of file SkPath.cpp.

1149 {
1150 if (r > 0) {
1151 this->addOval(SkRect::MakeLTRB(x - r, y - r, x + r, y + r), dir);
1152 }
1153 return *this;
1154}
double y
double x
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition SkRect.h:646

◆ 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 1106 of file SkPath.cpp.

1106 {
1108
1109 /* If addOval() is called after previous moveTo(),
1110 this path is still marked as an oval. This is used to
1111 fit into WebKit's calling sequences.
1112 We can't simply check isEmpty() in this case, as additional
1113 moveTo() would mark the path non empty.
1114 */
1115 bool isOval = hasOnlyMoveTos();
1116 if (isOval) {
1117 this->setFirstDirection((SkPathFirstDirection)dir);
1118 } else {
1119 this->setFirstDirection(SkPathFirstDirection::kUnknown);
1120 }
1121
1122 SkAutoDisableDirectionCheck addc(this);
1123 SkAutoPathBoundsUpdate apbu(this, oval);
1124
1125 SkDEBUGCODE(int initialVerbCount = this->countVerbs());
1126 const int kVerbs = 6; // moveTo + 4x conicTo + close
1127 this->incReserve(kVerbs);
1128
1129 SkPath_OvalPointIterator ovalIter(oval, dir, startPointIndex);
1130 // The corner iterator pts are tracking "behind" the oval/radii pts.
1131 SkPath_RectPointIterator rectIter(oval, dir, startPointIndex + (dir == SkPathDirection::kCW ? 0 : 1));
1132 const SkScalar weight = SK_ScalarRoot2Over2;
1133
1134 this->moveTo(ovalIter.current());
1135 for (unsigned i = 0; i < 4; ++i) {
1136 this->conicTo(rectIter.next(), ovalIter.next(), weight);
1137 }
1138 this->close();
1139
1140 SkASSERT(this->countVerbs() == initialVerbCount + kVerbs);
1141
1142 if (isOval) {
1143 SkPathRef::Editor ed(&fPathRef);
1144 ed.setIsOval(SkPathDirection::kCCW == dir, startPointIndex % 4);
1145 }
1146 return *this;
1147}
#define SkASSERT(cond)
Definition SkAssert.h:116
SkPathFirstDirection
Definition SkPathEnums.h:19
static void assert_known_direction(SkPathDirection dir)
Definition SkPath.cpp:850
#define SK_ScalarRoot2Over2
Definition SkScalar.h:23
const SkPoint & next()
SkPath & moveTo(SkScalar x, SkScalar y)
Definition SkPath.cpp:678
bool isOval(SkRect *bounds) const
Definition SkPath.cpp:513
int countVerbs() const
Definition SkPath.cpp:546
SkPath & conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar w)
Definition SkPath.cpp:756
SkPath & close()
Definition SkPath.cpp:813
void incReserve(int extraPtCount, int extraVerbCount=0, int extraConicCount=0)
Definition SkPath.cpp:668

◆ 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 1101 of file SkPath.cpp.

1101 {
1102 // legacy start index: 1
1103 return this->addOval(oval, dir, 1);
1104}

◆ 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 1313 of file SkPath.h.

1313 {
1314 SkMatrix m;
1315 m.reset();
1316 return this->addPath(src, m, mode);
1317 }
SkPath & addPath(const SkPath &src, SkScalar dx, SkScalar dy, AddPathMode mode=kAppend_AddPathMode)
Definition SkPath.cpp:1442

◆ 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 1449 of file SkPath.cpp.

1449 {
1450 if (srcPath.isEmpty()) {
1451 return *this;
1452 }
1453
1454 if (this->isEmpty() && matrix.isIdentity()) {
1455 const uint8_t fillType = fFillType;
1456 *this = srcPath;
1457 fFillType = fillType;
1458 return *this;
1459 }
1460
1461 // Detect if we're trying to add ourself
1462 const SkPath* src = &srcPath;
1463 SkTLazy<SkPath> tmp;
1464 if (this == src) {
1465 src = tmp.set(srcPath);
1466 }
1467
1468 if (kAppend_AddPathMode == mode && !matrix.hasPerspective()) {
1469 if (src->fLastMoveToIndex >= 0) {
1470 fLastMoveToIndex = src->fLastMoveToIndex + this->countPoints();
1471 } else {
1472 fLastMoveToIndex = src->fLastMoveToIndex - this->countPoints();
1473 }
1474 SkPathRef::Editor ed(&fPathRef);
1475 auto [newPts, newWeights] = ed.growForVerbsInPath(*src->fPathRef);
1476 matrix.mapPoints(newPts, src->fPathRef->points(), src->countPoints());
1477 if (int numWeights = src->fPathRef->countWeights()) {
1478 memcpy(newWeights, src->fPathRef->conicWeights(), numWeights * sizeof(newWeights[0]));
1479 }
1480 return this->dirtyAfterEdit();
1481 }
1482
1484 bool firstVerb = true;
1485 for (auto [verb, pts, w] : SkPathPriv::Iterate(*src)) {
1486 SkPoint mappedPts[3];
1487 switch (verb) {
1488 case SkPathVerb::kMove:
1489 mapPtsProc(matrix, mappedPts, &pts[0], 1);
1490 if (firstVerb && mode == kExtend_AddPathMode && !isEmpty()) {
1491 injectMoveToIfNeeded(); // In case last contour is closed
1492 SkPoint lastPt;
1493 // don't add lineTo if it is degenerate
1494 if (!this->getLastPt(&lastPt) || lastPt != mappedPts[0]) {
1495 this->lineTo(mappedPts[0]);
1496 }
1497 } else {
1498 this->moveTo(mappedPts[0]);
1499 }
1500 break;
1501 case SkPathVerb::kLine:
1502 mapPtsProc(matrix, mappedPts, &pts[1], 1);
1503 this->lineTo(mappedPts[0]);
1504 break;
1505 case SkPathVerb::kQuad:
1506 mapPtsProc(matrix, mappedPts, &pts[1], 2);
1507 this->quadTo(mappedPts[0], mappedPts[1]);
1508 break;
1509 case SkPathVerb::kConic:
1510 mapPtsProc(matrix, mappedPts, &pts[1], 2);
1511 this->conicTo(mappedPts[0], mappedPts[1], *w);
1512 break;
1513 case SkPathVerb::kCubic:
1514 mapPtsProc(matrix, mappedPts, &pts[1], 3);
1515 this->cubicTo(mappedPts[0], mappedPts[1], mappedPts[2]);
1516 break;
1517 case SkPathVerb::kClose:
1518 this->close();
1519 break;
1520 }
1521 firstVerb = false;
1522 }
1523 return *this;
1524}
static MapPtsProc GetMapPtsProc(const SkMatrix &matrix)
SkMatrix::MapPtsProc MapPtsProc
bool isIdentity() const
Definition SkMatrix.h:223
bool isEmpty() const
Definition SkPath.cpp:406
int countPoints() const
Definition SkPath.cpp:525
bool getLastPt(SkPoint *lastPt) const
Definition SkPath.cpp:570
SkPath & lineTo(SkScalar x, SkScalar y)
Definition SkPath.cpp:718
SkPath & quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2)
Definition SkPath.cpp:736
SkPath & cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3)
Definition SkPath.cpp:789
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 1442 of file SkPath.cpp.

1442 {
1444
1445 matrix.setTranslate(dx, dy);
1446 return this->addPath(path, matrix, mode);
1447}

◆ 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 880 of file SkPath.cpp.

880 {
881 SkDEBUGCODE(this->validate();)
882 if (count <= 0) {
883 return *this;
884 }
885
886 fLastMoveToIndex = fPathRef->countPoints();
887
888 // +close makes room for the extra kClose_Verb
889 SkPathRef::Editor ed(&fPathRef, count+close, count);
890
891 ed.growForVerb(kMove_Verb)->set(pts[0].fX, pts[0].fY);
892 if (count > 1) {
893 SkPoint* p = ed.growForRepeatedVerb(kLine_Verb, count - 1);
894 memcpy(p, &pts[1], (count-1) * sizeof(SkPoint));
895 }
896
897 if (close) {
898 ed.growForVerb(kClose_Verb);
899 fLastMoveToIndex ^= ~fLastMoveToIndex >> (8 * sizeof(fLastMoveToIndex) - 1);
900 }
901
902 (void)this->dirtyAfterEdit();
903 SkDEBUGCODE(this->validate();)
904 return *this;
905}
int count
int countPoints() const
Definition SkPathRef.h:309

◆ 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 1263 of file SkPath.h.

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

◆ 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 854 of file SkPath.cpp.

854 {
856 this->setFirstDirection(this->hasOnlyMoveTos() ? (SkPathFirstDirection)dir
859 SkAutoPathBoundsUpdate apbu(this, rect);
860
861 SkDEBUGCODE(int initialVerbCount = this->countVerbs());
862
863 const int kVerbs = 5; // moveTo + 3x lineTo + close
864 SkPathRef::Editor ed(&fPathRef, kVerbs, /* points */ 4);
865
866 SkPath_RectPointIterator iter(rect, dir, startIndex);
867 fLastMoveToIndex = fPathRef->countPoints();
868
869 *ed.growForVerb(kMove_Verb) = iter.current();
870 *ed.growForVerb(kLine_Verb) = iter.next();
871 *ed.growForVerb(kLine_Verb) = iter.next();
872 *ed.growForVerb(kLine_Verb) = iter.next();
873 this->close();
874 (void)this->dirtyAfterEdit();
875
876 SkASSERT(this->countVerbs() == initialVerbCount + kVerbs);
877 return *this;
878}

◆ 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:854

◆ 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)
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

◆ 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 983 of file SkPath.cpp.

984 {
986 rrect.setRectRadii(rect, (const SkVector*) radii);
987 return this->addRRect(rrect, dir);
988}
SkPath & addRRect(const SkRRect &rrect, SkPathDirection dir=SkPathDirection::kCW)
Definition SkPath.cpp:990
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 1088 of file SkPath.cpp.

1089 {
1091
1092 if (rx < 0 || ry < 0) {
1093 return *this;
1094 }
1095
1096 SkRRect rrect;
1097 rrect.setRectXY(rect, rx, ry);
1098 return this->addRRect(rrect, dir);
1099}
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 995 of file SkPath.cpp.

995 {
997
998 bool isRRect = hasOnlyMoveTos();
999 const SkRect& bounds = rrect.getBounds();
1000
1001 if (rrect.isRect() || rrect.isEmpty()) {
1002 // degenerate(rect) => radii points are collapsing
1003 this->addRect(bounds, dir, (startIndex + 1) / 2);
1004 } else if (rrect.isOval()) {
1005 // degenerate(oval) => line points are collapsing
1006 this->addOval(bounds, dir, startIndex / 2);
1007 } else {
1008 this->setFirstDirection(this->hasOnlyMoveTos() ? (SkPathFirstDirection)dir
1010
1011 SkAutoPathBoundsUpdate apbu(this, bounds);
1012 SkAutoDisableDirectionCheck addc(this);
1013
1014 // we start with a conic on odd indices when moving CW vs. even indices when moving CCW
1015 const bool startsWithConic = ((startIndex & 1) == (dir == SkPathDirection::kCW));
1016 const SkScalar weight = SK_ScalarRoot2Over2;
1017
1018 SkDEBUGCODE(int initialVerbCount = this->countVerbs());
1019 const int kVerbs = startsWithConic
1020 ? 9 // moveTo + 4x conicTo + 3x lineTo + close
1021 : 10; // moveTo + 4x lineTo + 4x conicTo + close
1022 this->incReserve(kVerbs);
1023
1024 SkPath_RRectPointIterator rrectIter(rrect, dir, startIndex);
1025 // Corner iterator indices follow the collapsed radii model,
1026 // adjusted such that the start pt is "behind" the radii start pt.
1027 const unsigned rectStartIndex = startIndex / 2 + (dir == SkPathDirection::kCW ? 0 : 1);
1028 SkPath_RectPointIterator rectIter(bounds, dir, rectStartIndex);
1029
1030 this->moveTo(rrectIter.current());
1031 if (startsWithConic) {
1032 for (unsigned i = 0; i < 3; ++i) {
1033 this->conicTo(rectIter.next(), rrectIter.next(), weight);
1034 this->lineTo(rrectIter.next());
1035 }
1036 this->conicTo(rectIter.next(), rrectIter.next(), weight);
1037 // final lineTo handled by close().
1038 } else {
1039 for (unsigned i = 0; i < 4; ++i) {
1040 this->lineTo(rrectIter.next());
1041 this->conicTo(rectIter.next(), rrectIter.next(), weight);
1042 }
1043 }
1044 this->close();
1045
1046 if (isRRect) {
1047 SkPathRef::Editor ed(&fPathRef);
1048 ed.setIsRRect(dir == SkPathDirection::kCCW, startIndex % 8);
1049 }
1050
1051 SkASSERT(this->countVerbs() == initialVerbCount + kVerbs);
1052 }
1053
1054 SkDEBUGCODE(fPathRef->validate();)
1055 return *this;
1056}
bool isRRect(SkRRect *rrect) const
Definition SkPath.cpp:517
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 990 of file SkPath.cpp.

990 {
991 // legacy start indices: 6 (CW) and 7(CCW)
992 return this->addRRect(rrect, dir, dir == SkPathDirection::kCW ? 6 : 7);
993}

◆ approximateBytesUsed()

size_t SkPath::approximateBytesUsed ( ) const

Returns the approximate byte size of the SkPath in memory.

Returns
approximate size

Definition at line 562 of file SkPath.cpp.

562 {
563 size_t size = sizeof (SkPath);
564 if (fPathRef != nullptr) {
565 size += fPathRef->approximateBytesUsed();
566 }
567 return size;
568}
size_t approximateBytesUsed() const
Definition SkPathRef.cpp:60
SkPath()
Definition SkPath.cpp:154
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
float fY
y-axis value

◆ 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 1156 of file SkPath.cpp.

1157 {
1158 if (oval.width() < 0 || oval.height() < 0) {
1159 return *this;
1160 }
1161
1162 startAngle = SkScalarMod(startAngle, 360.0f);
1163
1164 if (fPathRef->countVerbs() == 0) {
1165 forceMoveTo = true;
1166 }
1167
1168 SkPoint lonePt;
1169 if (arc_is_lone_point(oval, startAngle, sweepAngle, &lonePt)) {
1170 return forceMoveTo ? this->moveTo(lonePt) : this->lineTo(lonePt);
1171 }
1172
1173 SkVector startV, stopV;
1175 angles_to_unit_vectors(startAngle, sweepAngle, &startV, &stopV, &dir);
1176
1177 SkPoint singlePt;
1178
1179 bool isArc = this->hasOnlyMoveTos();
1180
1181 // Adds a move-to to 'pt' if forceMoveTo is true. Otherwise a lineTo unless we're sufficiently
1182 // close to 'pt' currently. This prevents spurious lineTos when adding a series of contiguous
1183 // arcs from the same oval.
1184 auto addPt = [&forceMoveTo, &isArc, this](const SkPoint& pt) {
1185 SkPoint lastPt;
1186 if (forceMoveTo) {
1187 this->moveTo(pt);
1188 } else if (!this->getLastPt(&lastPt) ||
1189 !SkScalarNearlyEqual(lastPt.fX, pt.fX) ||
1190 !SkScalarNearlyEqual(lastPt.fY, pt.fY)) {
1191 this->lineTo(pt);
1192 isArc = false;
1193 }
1194 };
1195
1196 // At this point, we know that the arc is not a lone point, but startV == stopV
1197 // indicates that the sweepAngle is too small such that angles_to_unit_vectors
1198 // cannot handle it.
1199 if (startV == stopV) {
1200 SkScalar endAngle = SkDegreesToRadians(startAngle + sweepAngle);
1201 SkScalar radiusX = oval.width() / 2;
1202 SkScalar radiusY = oval.height() / 2;
1203 // We do not use SkScalar[Sin|Cos]SnapToZero here. When sin(startAngle) is 0 and sweepAngle
1204 // is very small and radius is huge, the expected behavior here is to draw a line. But
1205 // calling SkScalarSinSnapToZero will make sin(endAngle) be 0 which will then draw a dot.
1206 singlePt.set(oval.centerX() + radiusX * SkScalarCos(endAngle),
1207 oval.centerY() + radiusY * SkScalarSin(endAngle));
1208 addPt(singlePt);
1209 return *this;
1210 }
1211
1213 int count = build_arc_conics(oval, startV, stopV, dir, conics, &singlePt);
1214 if (count) {
1215 // Conics take two points. Add one to the verb in case there is a moveto.
1216 this->incReserve(count * 2 + 1, count + 1, count);
1217 const SkPoint& pt = conics[0].fPts[0];
1218 addPt(pt);
1219 for (int i = 0; i < count; ++i) {
1220 this->conicTo(conics[i].fPts[1], conics[i].fPts[2], conics[i].fW);
1221 }
1222 if (isArc) {
1223 SkPathRef::Editor ed(&fPathRef);
1224 ed.setIsArc({oval, startAngle, sweepAngle, false});
1225 }
1226 } else {
1227 addPt(singlePt);
1228 }
1229 return *this;
1230}
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:968
static bool arc_is_lone_point(const SkRect &oval, SkScalar startAngle, SkScalar sweepAngle, SkPoint *pt)
Definition SkPath.cpp:907
static void angles_to_unit_vectors(SkScalar startAngle, SkScalar sweepAngle, SkVector *startV, SkVector *stopV, SkRotationDirection *dir)
Definition SkPath.cpp:930
#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
int countVerbs() const
Definition SkPathRef.h:310
bool isArc(SkArc *arc) const
Definition SkPath.cpp:521
SkScalar sweepAngle
Definition SkRecords.h:251
SkPoint fPts[3]
Definition SkGeometry.h:336
@ kMaxConicsForArc
Definition SkGeometry.h:411
void set(float x, float y)
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 1238 of file SkPath.cpp.

1239 {
1240 this->injectMoveToIfNeeded();
1241 SkPoint srcPts[2];
1242 this->getLastPt(&srcPts[0]);
1243 // If rx = 0 or ry = 0 then this arc is treated as a straight line segment (a "lineto")
1244 // joining the endpoints.
1245 // http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters
1246 if (!rx || !ry) {
1247 return this->lineTo(x, y);
1248 }
1249 // If the current point and target point for the arc are identical, it should be treated as a
1250 // zero length path. This ensures continuity in animations.
1251 srcPts[1].set(x, y);
1252 if (srcPts[0] == srcPts[1]) {
1253 return this->lineTo(x, y);
1254 }
1255 rx = SkScalarAbs(rx);
1256 ry = SkScalarAbs(ry);
1257 SkVector midPointDistance = srcPts[0] - srcPts[1];
1258 midPointDistance *= 0.5f;
1259
1260 SkMatrix pointTransform;
1261 pointTransform.setRotate(-angle);
1262
1263 SkPoint transformedMidPoint;
1264 pointTransform.mapPoints(&transformedMidPoint, &midPointDistance, 1);
1265 SkScalar squareRx = rx * rx;
1266 SkScalar squareRy = ry * ry;
1267 SkScalar squareX = transformedMidPoint.fX * transformedMidPoint.fX;
1268 SkScalar squareY = transformedMidPoint.fY * transformedMidPoint.fY;
1269
1270 // Check if the radii are big enough to draw the arc, scale radii if not.
1271 // http://www.w3.org/TR/SVG/implnote.html#ArcCorrectionOutOfRangeRadii
1272 SkScalar radiiScale = squareX / squareRx + squareY / squareRy;
1273 if (radiiScale > 1) {
1274 radiiScale = SkScalarSqrt(radiiScale);
1275 rx *= radiiScale;
1276 ry *= radiiScale;
1277 }
1278
1279 pointTransform.setScale(1 / rx, 1 / ry);
1280 pointTransform.preRotate(-angle);
1281
1282 SkPoint unitPts[2];
1283 pointTransform.mapPoints(unitPts, srcPts, (int) std::size(unitPts));
1284 SkVector delta = unitPts[1] - unitPts[0];
1285
1286 SkScalar d = delta.fX * delta.fX + delta.fY * delta.fY;
1287 SkScalar scaleFactorSquared = std::max(1 / d - 0.25f, 0.f);
1288
1289 SkScalar scaleFactor = SkScalarSqrt(scaleFactorSquared);
1290 if ((arcSweep == SkPathDirection::kCCW) != SkToBool(arcLarge)) { // flipped from the original implementation
1291 scaleFactor = -scaleFactor;
1292 }
1293 delta.scale(scaleFactor);
1294 SkPoint centerPoint = unitPts[0] + unitPts[1];
1295 centerPoint *= 0.5f;
1296 centerPoint.offset(-delta.fY, delta.fX);
1297 unitPts[0] -= centerPoint;
1298 unitPts[1] -= centerPoint;
1299 SkScalar theta1 = SkScalarATan2(unitPts[0].fY, unitPts[0].fX);
1300 SkScalar theta2 = SkScalarATan2(unitPts[1].fY, unitPts[1].fX);
1301 SkScalar thetaArc = theta2 - theta1;
1302 if (thetaArc < 0 && (arcSweep == SkPathDirection::kCW)) { // arcSweep flipped from the original implementation
1303 thetaArc += SK_ScalarPI * 2;
1304 } else if (thetaArc > 0 && (arcSweep != SkPathDirection::kCW)) { // arcSweep flipped from the original implementation
1305 thetaArc -= SK_ScalarPI * 2;
1306 }
1307
1308 // Very tiny angles cause our subsequent math to go wonky (skbug.com/9272)
1309 // so we do a quick check here. The precise tolerance amount is just made up.
1310 // PI/million happens to fix the bug in 9272, but a larger value is probably
1311 // ok too.
1312 if (SkScalarAbs(thetaArc) < (SK_ScalarPI / (1000 * 1000))) {
1313 return this->lineTo(x, y);
1314 }
1315
1316 pointTransform.setRotate(angle);
1317 pointTransform.preScale(rx, ry);
1318
1319 // the arc may be slightly bigger than 1/4 circle, so allow up to 1/3rd
1320 int segments = SkScalarCeilToInt(SkScalarAbs(thetaArc / (2 * SK_ScalarPI / 3)));
1321 SkScalar thetaWidth = thetaArc / segments;
1322 SkScalar t = SkScalarTan(0.5f * thetaWidth);
1323 if (!SkIsFinite(t)) {
1324 return *this;
1325 }
1326 SkScalar startTheta = theta1;
1328 auto scalar_is_integer = [](SkScalar scalar) -> bool {
1329 return scalar == SkScalarFloorToScalar(scalar);
1330 };
1331 bool expectIntegers = SkScalarNearlyZero(SK_ScalarPI/2 - SkScalarAbs(thetaWidth)) &&
1332 scalar_is_integer(rx) && scalar_is_integer(ry) &&
1333 scalar_is_integer(x) && scalar_is_integer(y);
1334
1335 for (int i = 0; i < segments; ++i) {
1336 SkScalar endTheta = startTheta + thetaWidth,
1337 sinEndTheta = SkScalarSinSnapToZero(endTheta),
1338 cosEndTheta = SkScalarCosSnapToZero(endTheta);
1339
1340 unitPts[1].set(cosEndTheta, sinEndTheta);
1341 unitPts[1] += centerPoint;
1342 unitPts[0] = unitPts[1];
1343 unitPts[0].offset(t * sinEndTheta, -t * cosEndTheta);
1344 SkPoint mapped[2];
1345 pointTransform.mapPoints(mapped, unitPts, (int) std::size(unitPts));
1346 /*
1347 Computing the arc width introduces rounding errors that cause arcs to start
1348 outside their marks. A round rect may lose convexity as a result. If the input
1349 values are on integers, place the conic on integers as well.
1350 */
1351 if (expectIntegers) {
1352 for (SkPoint& point : mapped) {
1353 point.fX = SkScalarRoundToScalar(point.fX);
1354 point.fY = SkScalarRoundToScalar(point.fY);
1355 }
1356 }
1357 this->conicTo(mapped[0], mapped[1], w);
1358 startTheta = endTheta;
1359 }
1360
1361 // The final point should match the input point (by definition); replace it to
1362 // ensure that rounding errors in the above math don't cause any problems.
1363 this->setLastPt(x, y);
1364 return *this;
1365}
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:598
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition main.cc:19
void offset(float dx, float dy)

◆ 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 1403 of file SkPath.cpp.

1403 {
1404 this->injectMoveToIfNeeded();
1405
1406 if (radius == 0) {
1407 return this->lineTo(x1, y1);
1408 }
1409
1410 // need to know our prev pt so we can construct tangent vectors
1411 SkPoint start;
1412 this->getLastPt(&start);
1413
1414 // need double precision for these calcs.
1415 skvx::double2 befored = normalize(skvx::double2{x1 - start.fX, y1 - start.fY});
1416 skvx::double2 afterd = normalize(skvx::double2{x2 - x1, y2 - y1});
1417 double cosh = dot(befored, afterd);
1418 double sinh = cross(befored, afterd);
1419
1420 // If the previous point equals the first point, befored will be denormalized.
1421 // If the two points equal, afterd will be denormalized.
1422 // If the second point equals the first point, sinh will be zero.
1423 // In all these cases, we cannot construct an arc, so we construct a line to the first point.
1424 if (!isfinite(befored) || !isfinite(afterd) || SkScalarNearlyZero(SkDoubleToScalar(sinh))) {
1425 return this->lineTo(x1, y1);
1426 }
1427
1428 // safe to convert back to floats now
1429 SkScalar dist = SkScalarAbs(SkDoubleToScalar(radius * (1 - cosh) / sinh));
1430 SkScalar xx = x1 - dist * befored[0];
1431 SkScalar yy = y1 - dist * befored[1];
1432
1433 SkVector after = SkVector::Make(afterd[0], afterd[1]);
1434 after.setLength(dist);
1435 this->lineTo(xx, yy);
1436 SkScalar weight = SkScalarSqrt(SkDoubleToScalar(SK_ScalarHalf + cosh * 0.5));
1437 return this->conicTo(x1, y1, x1 + after.fX, y1 + after.fY, weight);
1438}
static void normalize(int n, double *gauss)
#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
bool setLength(float length)
Definition SkPoint.cpp:30
static constexpr SkPoint Make(float x, float y)

◆ Circle()

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

Definition at line 3530 of file SkPath.cpp.

3530 {
3531 return SkPathBuilder().addCircle(x, y, r, dir).detach();
3532}
friend class SkPathBuilder
Definition SkPath.h:1925

◆ 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 813 of file SkPath.cpp.

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

◆ 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 3378 of file SkPath.cpp.

3378 {
3379 if (0 == this->countVerbs()) {
3380 return SkRect::MakeEmpty();
3381 }
3382
3384 return this->getBounds();
3385 }
3386
3387 SkPoint extremas[5]; // big enough to hold worst-case curve type (cubic) extremas + 1
3388
3389 // initial with the first MoveTo, so we don't have to check inside the switch
3391 min = max = from_point(this->getPoint(0));
3392 for (auto [verb, pts, w] : SkPathPriv::Iterate(*this)) {
3393 int count = 0;
3394 switch (verb) {
3395 case SkPathVerb::kMove:
3396 extremas[0] = pts[0];
3397 count = 1;
3398 break;
3399 case SkPathVerb::kLine:
3400 extremas[0] = pts[1];
3401 count = 1;
3402 break;
3403 case SkPathVerb::kQuad:
3404 count = compute_quad_extremas(pts, extremas);
3405 break;
3406 case SkPathVerb::kConic:
3407 count = compute_conic_extremas(pts, *w, extremas);
3408 break;
3409 case SkPathVerb::kCubic:
3410 count = compute_cubic_extremas(pts, extremas);
3411 break;
3412 case SkPathVerb::kClose:
3413 break;
3414 }
3415 for (int i = 0; i < count; ++i) {
3416 skvx::float2 tmp = from_point(extremas[i]);
3417 min = skvx::min(min, tmp);
3418 max = skvx::max(max, tmp);
3419 }
3420 }
3421 SkRect bounds;
3422 min.store((SkPoint*)&bounds.fLeft);
3423 max.store((SkPoint*)&bounds.fRight);
3424 return bounds;
3425}
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:3366
static int compute_conic_extremas(const SkPoint src[3], SkScalar w, SkPoint extremas[3])
Definition SkPath.cpp:3353
static int compute_quad_extremas(const SkPoint src[3], SkPoint extremas[3])
Definition SkPath.cpp:3341
SkPoint getPoint(int index) const
Definition SkPath.cpp:539
const SkRect & getBounds() const
Definition SkPath.cpp:420
uint32_t getSegmentMasks() const
Definition SkPath.cpp:424
static float max(float r, float g, float b)
Definition hsl.cpp:49
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 756 of file SkPath.cpp.

757 {
758 // check for <= 0 or NaN with this test
759 if (!(w > 0)) {
760 this->lineTo(x2, y2);
761 } else if (!SkIsFinite(w)) {
762 this->lineTo(x1, y1);
763 this->lineTo(x2, y2);
764 } else if (SK_Scalar1 == w) {
765 this->quadTo(x1, y1, x2, y2);
766 } else {
767 SkDEBUGCODE(this->validate();)
768
769 this->injectMoveToIfNeeded();
770
771 SkPathRef::Editor ed(&fPathRef);
772 SkPoint* pts = ed.growForVerb(kConic_Verb, w);
773 pts[0].set(x1, y1);
774 pts[1].set(x2, y2);
775
776 (void)this->dirtyAfterEdit();
777 }
778 return *this;
779}
#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 289 of file SkPath.cpp.

289 {
290 // This only handles non-degenerate convex paths currently.
291 if (!this->isConvex()) {
292 return false;
293 }
294
296 if (direction == SkPathFirstDirection::kUnknown) {
297 return false;
298 }
299
300 SkPoint firstPt;
301 SkPoint prevPt;
302 int segmentCount = 0;
303 SkDEBUGCODE(int moveCnt = 0;)
304
305 for (auto [verb, pts, weight] : SkPathPriv::Iterate(*this)) {
306 if (verb == SkPathVerb::kClose || (segmentCount > 0 && verb == SkPathVerb::kMove)) {
307 // Closing the current contour; but since convexity is a precondition, it's the only
308 // contour that matters.
309 SkASSERT(moveCnt);
310 segmentCount++;
311 break;
312 } else if (verb == SkPathVerb::kMove) {
313 // A move at the start of the contour (or multiple leading moves, in which case we
314 // keep the last one before a non-move verb).
315 SkASSERT(!segmentCount);
316 SkDEBUGCODE(++moveCnt);
317 firstPt = prevPt = pts[0];
318 } else {
319 int pointCount = SkPathPriv::PtsInVerb((unsigned) verb);
320 SkASSERT(pointCount > 0);
321
322 if (!SkPathPriv::AllPointsEq(pts, pointCount + 1)) {
323 SkASSERT(moveCnt);
324 int nextPt = pointCount;
325 segmentCount++;
326
327 if (SkPathVerb::kConic == verb) {
328 SkConic orig;
329 orig.set(pts, *weight);
330 SkPoint quadPts[5];
331 int count = orig.chopIntoQuadsPOW2(quadPts, 1);
333
334 if (!check_edge_against_rect(quadPts[0], quadPts[2], rect, direction)) {
335 return false;
336 }
337 if (!check_edge_against_rect(quadPts[2], quadPts[4], rect, direction)) {
338 return false;
339 }
340 } else {
341 if (!check_edge_against_rect(prevPt, pts[nextPt], rect, direction)) {
342 return false;
343 }
344 }
345 prevPt = pts[nextPt];
346 }
347 }
348 }
349
350 if (segmentCount) {
351 return check_edge_against_rect(prevPt, firstPt, rect, direction);
352 }
353 return false;
354}
#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:263
static int PtsInVerb(unsigned verb)
Definition SkPathPriv.h:322
static SkPathFirstDirection ComputeFirstDirection(const SkPath &)
Definition SkPath.cpp:2563
static bool AllPointsEq(const SkPoint pts[], int count)
Definition SkPathPriv.h:339
bool isConvex() const
Definition SkPath.cpp:416
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 3054 of file SkPath.cpp.

3054 {
3055 bool isInverse = this->isInverseFillType();
3056 if (this->isEmpty()) {
3057 return isInverse;
3058 }
3059
3060 if (!contains_inclusive(this->getBounds(), x, y)) {
3061 return isInverse;
3062 }
3063
3064 SkPath::Iter iter(*this, true);
3065 bool done = false;
3066 int w = 0;
3067 int onCurveCount = 0;
3068 do {
3069 SkPoint pts[4];
3070 switch (iter.next(pts)) {
3071 case SkPath::kMove_Verb:
3073 break;
3074 case SkPath::kLine_Verb:
3075 w += winding_line(pts, x, y, &onCurveCount);
3076 break;
3077 case SkPath::kQuad_Verb:
3078 w += winding_quad(pts, x, y, &onCurveCount);
3079 break;
3081 w += winding_conic(pts, x, y, iter.conicWeight(), &onCurveCount);
3082 break;
3084 w += winding_cubic(pts, x, y, &onCurveCount);
3085 break;
3086 case SkPath::kDone_Verb:
3087 done = true;
3088 break;
3089 }
3090 } while (!done);
3091 bool evenOddFill = SkPathFillType::kEvenOdd == this->getFillType()
3093 if (evenOddFill) {
3094 w &= 1;
3095 }
3096 if (w) {
3097 return !isInverse;
3098 }
3099 if (onCurveCount <= 1) {
3100 return SkToBool(onCurveCount) ^ isInverse;
3101 }
3102 if ((onCurveCount & 1) || evenOddFill) {
3103 return SkToBool(onCurveCount & 1) ^ isInverse;
3104 }
3105 // If the point touches an even number of curves, and the fill is winding, check for
3106 // coincidence. Count coincidence as places where the on curve points have identical tangents.
3107 iter.setPath(*this, true);
3108 done = false;
3109 SkTDArray<SkVector> tangents;
3110 do {
3111 SkPoint pts[4];
3112 int oldCount = tangents.size();
3113 switch (iter.next(pts)) {
3114 case SkPath::kMove_Verb:
3116 break;
3117 case SkPath::kLine_Verb:
3118 tangent_line(pts, x, y, &tangents);
3119 break;
3120 case SkPath::kQuad_Verb:
3121 tangent_quad(pts, x, y, &tangents);
3122 break;
3124 tangent_conic(pts, x, y, iter.conicWeight(), &tangents);
3125 break;
3127 tangent_cubic(pts, x, y, &tangents);
3128 break;
3129 case SkPath::kDone_Verb:
3130 done = true;
3131 break;
3132 }
3133 if (tangents.size() > oldCount) {
3134 int last = tangents.size() - 1;
3135 const SkVector& tangent = tangents[last];
3137 tangents.remove(last);
3138 } else {
3139 for (int index = 0; index < last; ++index) {
3140 const SkVector& test = tangents[index];
3141 if (SkScalarNearlyZero(test.cross(tangent))
3142 && SkScalarSignAsInt(tangent.fX * test.fX) <= 0
3143 && SkScalarSignAsInt(tangent.fY * test.fY) <= 0) {
3144 tangents.remove(last);
3145 tangents.removeShuffle(index);
3146 break;
3147 }
3148 }
3149 }
3150 }
3151 } while (!done);
3152 return SkToBool(tangents.size()) ^ isInverse;
3153}
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:3028
static int winding_quad(const SkPoint pts[], SkScalar x, SkScalar y, int *onCurveCount)
Definition SkPath.cpp:2892
static int winding_line(const SkPoint pts[], SkScalar x, SkScalar y, int *onCurveCount)
Definition SkPath.cpp:2907
static bool contains_inclusive(const SkRect &r, SkScalar x, SkScalar y)
Definition SkPath.cpp:3050
static void tangent_cubic(const SkPoint pts[], SkScalar x, SkScalar y, SkTDArray< SkVector > *tangents)
Definition SkPath.cpp:2947
static int winding_conic(const SkPoint pts[], SkScalar x, SkScalar y, SkScalar weight, int *onCurveCount)
Definition SkPath.cpp:2823
static void tangent_conic(const SkPoint pts[], SkScalar x, SkScalar y, SkScalar w, SkTDArray< SkVector > *tangents)
Definition SkPath.cpp:2975
static void tangent_quad(const SkPoint pts[], SkScalar x, SkScalar y, SkTDArray< SkVector > *tangents)
Definition SkPath.cpp:3002
static int winding_cubic(const SkPoint pts[], SkScalar x, SkScalar y, int *onCurveCount)
Definition SkPath.cpp:2733
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 3174 of file SkPath.cpp.

3175 {
3176 const SkConic conic(p0, p1, p2, w);
3177 return conic.chopIntoQuadsPOW2(pts, pow2);
3178}
AI float conic(float tolerance, const SkPoint pts[], float w, const VectorXform &vectorXform=VectorXform())

◆ 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 525 of file SkPath.cpp.

525 {
526 return fPathRef->countPoints();
527}

◆ 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 546 of file SkPath.cpp.

546 {
547 return fPathRef->countVerbs();
548}

◆ 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 789 of file SkPath.cpp.

790 {
791 SkDEBUGCODE(this->validate();)
792
793 this->injectMoveToIfNeeded();
794
795 SkPathRef::Editor ed(&fPathRef);
796 SkPoint* pts = ed.growForVerb(kCubic_Verb);
797 pts[0].set(x1, y1);
798 pts[1].set(x2, y2);
799 pts[2].set(x3, y3);
800
801 return this->dirtyAfterEdit();
802}

◆ 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:360
GAsyncResult * result

◆ dump() [1/2]

void SkPath::dump ( ) const
inline

Definition at line 1726 of file SkPath.h.

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

◆ 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 1976 of file SkPath.cpp.

1976 {
1978 Iter iter(*this, false);
1979 SkPoint pts[4];
1980 Verb verb;
1981
1983 char const * const gFillTypeStrs[] = {
1984 "Winding",
1985 "EvenOdd",
1986 "InverseWinding",
1987 "InverseEvenOdd",
1988 };
1989 builder.printf("path.setFillType(SkPathFillType::k%s);\n",
1990 gFillTypeStrs[(int) this->getFillType()]);
1991 while ((verb = iter.next(pts)) != kDone_Verb) {
1992 switch (verb) {
1993 case kMove_Verb:
1994 append_params(&builder, "path.moveTo", &pts[0], 1, asType);
1995 break;
1996 case kLine_Verb:
1997 append_params(&builder, "path.lineTo", &pts[1], 1, asType);
1998 break;
1999 case kQuad_Verb:
2000 append_params(&builder, "path.quadTo", &pts[1], 2, asType);
2001 break;
2002 case kConic_Verb:
2003 append_params(&builder, "path.conicTo", &pts[1], 2, asType, iter.conicWeight());
2004 break;
2005 case kCubic_Verb:
2006 append_params(&builder, "path.cubicTo", &pts[1], 3, asType);
2007 break;
2008 case kClose_Verb:
2009 builder.append("path.close();\n");
2010 break;
2011 default:
2012 SkDebugf(" path: UNKNOWN VERB %d, aborting dump...\n", verb);
2013 verb = kDone_Verb; // stop the loop
2014 break;
2015 }
2016 if (!wStream && builder.size()) {
2017 SkDebugf("%s", builder.c_str());
2018 builder.reset();
2019 }
2020 }
2021 if (wStream) {
2022 wStream->writeText(builder.c_str());
2023 }
2024}
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:1941
SkScalarAsStringType
@ kHex_SkScalarAsStringType
@ kDec_SkScalarAsStringType
friend class Iter
Definition SkPath.h:1833

◆ dumpArrays() [1/2]

void SkPath::dumpArrays ( ) const
inline

Definition at line 1731 of file SkPath.h.

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

◆ dumpArrays() [2/2]

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

Definition at line 2026 of file SkPath.cpp.

2026 {
2028
2029 auto bool_str = [](bool v) { return v ? "true" : "false"; };
2030
2031 builder.appendf("// fBoundsIsDirty = %s\n", bool_str(fPathRef->fBoundsIsDirty));
2032 builder.appendf("// fGenerationID = %u\n", fPathRef->fGenerationID);
2033 builder.appendf("// fSegmentMask = %d\n", fPathRef->fSegmentMask);
2034
2035 const char* gTypeStrs[] = {
2036 "General", "Oval", "RRect",
2037 };
2038 builder.appendf("// fType = %s\n", gTypeStrs[static_cast<int>(fPathRef->fType)]);
2039
2040 auto append_scalar = [&](SkScalar v) {
2041 if (dumpAsHex) {
2042 builder.appendf("SkBits2Float(0x%08X) /* %g */", SkFloat2Bits(v), v);
2043 } else {
2044 builder.appendf("%g", v);
2045 }
2046 };
2047
2048 builder.append("const SkPoint path_points[] = {\n");
2049 for (int i = 0; i < this->countPoints(); ++i) {
2050 SkPoint p = this->getPoint(i);
2051 builder.append(" { ");
2052 append_scalar(p.fX);
2053 builder.append(", ");
2054 append_scalar(p.fY);
2055 builder.append(" },\n");
2056 }
2057 builder.append("};\n");
2058
2059 const char* gVerbStrs[] = {
2060 "Move", "Line", "Quad", "Conic", "Cubic", "Close"
2061 };
2062 builder.append("const uint8_t path_verbs[] = {\n ");
2063 for (auto v = fPathRef->verbsBegin(); v != fPathRef->verbsEnd(); ++v) {
2064 builder.appendf("(uint8_t)SkPathVerb::k%s, ", gVerbStrs[*v]);
2065 }
2066 builder.append("\n};\n");
2067
2068 const int nConics = fPathRef->conicWeightsEnd() - fPathRef->conicWeights();
2069 if (nConics) {
2070 builder.append("const SkScalar path_conics[] = {\n ");
2071 for (auto c = fPathRef->conicWeights(); c != fPathRef->conicWeightsEnd(); ++c) {
2072 append_scalar(*c);
2073 builder.append(", ");
2074 }
2075 builder.append("\n};\n");
2076 }
2077
2078 char const * const gFillTypeStrs[] = {
2079 "Winding",
2080 "EvenOdd",
2081 "InverseWinding",
2082 "InverseEvenOdd",
2083 };
2084
2085 builder.appendf("SkPath path = SkPath::Make(path_points, %d, path_verbs, %d, %s, %d,\n",
2086 this->countPoints(), this->countVerbs(),
2087 nConics ? "path_conics" : "nullptr", nConics);
2088 builder.appendf(" SkPathFillType::k%s, %s);\n",
2089 gFillTypeStrs[(int)this->getFillType()],
2090 bool_str(fIsVolatile));
2091
2092 if (wStream) {
2093 wStream->writeText(builder.c_str());
2094 } else {
2095 SkDebugf("%s\n", builder.c_str());
2096 }
2097}
static uint32_t SkFloat2Bits(float value)
Definition SkFloatBits.h:41
const uint8_t * verbsEnd() const
Definition SkPathRef.h:323
const SkScalar * conicWeightsEnd() const
Definition SkPathRef.h:336
const SkScalar * conicWeights() const
Definition SkPathRef.h:335
const uint8_t * verbsBegin() const
Definition SkPathRef.h:318

◆ dumpHex()

void SkPath::dumpHex ( ) const
inline

Definition at line 1727 of file SkPath.h.

1727{ 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 420 of file SkPath.cpp.

420 {
421 return fPathRef->getBounds();
422}
const SkRect & getBounds() const
Definition SkPathRef.h:283

◆ 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 356 of file SkPath.cpp.

356 {
357 return fPathRef->genID(fFillType);
358}
uint32_t genID(uint8_t fillType) const

◆ 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 570 of file SkPath.cpp.

570 {
571 SkDEBUGCODE(this->validate();)
572
573 int count = fPathRef->countPoints();
574 if (count > 0) {
575 if (lastPt) {
576 *lastPt = fPathRef->atPoint(count - 1);
577 }
578 return true;
579 }
580 if (lastPt) {
581 lastPt->set(0, 0);
582 }
583 return false;
584}
const SkPoint & atPoint(int index) const
Definition SkPathRef.h:342

◆ 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 539 of file SkPath.cpp.

539 {
540 if ((unsigned)index < (unsigned)fPathRef->countPoints()) {
541 return fPathRef->atPoint(index);
542 }
543 return SkPoint::Make(0, 0);
544}

◆ 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 529 of file SkPath.cpp.

529 {
530 SkDEBUGCODE(this->validate();)
531
532 SkASSERT(max >= 0);
533 SkASSERT(!max || dst);
534 int count = std::min(max, fPathRef->countPoints());
535 sk_careful_memcpy(dst, fPathRef->points(), count * sizeof(SkPoint));
536 return fPathRef->countPoints();
537}
static void * sk_careful_memcpy(void *dst, const void *src, size_t len)
Definition SkMalloc.h:125
const SkPoint * points() const
Definition SkPathRef.h:328

◆ 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 424 of file SkPath.cpp.

424 {
425 return fPathRef->getSegmentMasks();
426}
uint32_t getSegmentMasks() const
Definition SkPathRef.h:228

◆ 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 550 of file SkPath.cpp.

550 {
551 SkDEBUGCODE(this->validate();)
552
553 SkASSERT(max >= 0);
554 SkASSERT(!max || dst);
555 int count = std::min(max, fPathRef->countVerbs());
556 if (count) {
557 memcpy(dst, fPathRef->verbsBegin(), count);
558 }
559 return fPathRef->countVerbs();
560}

◆ 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 668 of file SkPath.cpp.

668 {
669 SkDEBUGCODE(this->validate();)
670 if (extraPtCount > 0) {
671 // For compat with when this function only took a single argument, use
672 // extraPtCount if extraVerbCount is 0 (default value).
673 SkPathRef::Editor(&fPathRef, extraVerbCount == 0 ? extraPtCount : extraVerbCount, extraPtCount, extraConicCount);
674 }
675 SkDEBUGCODE(this->validate();)
676}

◆ 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 248 of file SkPath.cpp.

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

◆ 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 521 of file SkPath.cpp.

521 {
522 return fPathRef->isArc(arc);
523}
bool isArc(SkArc *arc) const
Definition SkPathRef.h:261

◆ isConvex()

bool SkPath::isConvex ( ) const

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

Definition at line 416 of file SkPath.cpp.

416 {
417 return SkPathConvexity::kConvex == this->getConvexity();
418}

◆ 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 3437 of file SkPath.cpp.

3438 {
3439 return exact ? p1 == p2 && p2 == p3 && p3 == p4 :
3443}
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 406 of file SkPath.cpp.

406 {
407 SkDEBUGCODE(this->validate();)
408 return 0 == fPathRef->countVerbs();
409}

◆ 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 411 of file SkPath.cpp.

411 {
412 SkDEBUGCODE(this->validate();)
413 return fPathRef->isFinite();
414}
bool isFinite() const
Definition SkPathRef.h:216

◆ 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 241 of file SkPath.cpp.

241 {
242 // need the same structure (verbs, conicweights) and same point-count
243 return fPathRef->fPoints.size() == compare.fPathRef->fPoints.size() &&
244 fPathRef->fVerbs == compare.fPathRef->fVerbs &&
245 fPathRef->fConicWeights == compare.fPathRef->fConicWeights;
246}
static bool compare(const SkBitmap &ref, const SkIRect &iref, const SkBitmap &test, const SkIRect &itest)
Definition BlurTest.cpp:100
int size() const
Definition SkTArray.h:416

◆ 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 380 of file SkPath.cpp.

380 {
381 int verbCount = fPathRef->countVerbs();
382 if (0 == verbCount) {
383 return false;
384 }
385 return kClose_Verb == fPathRef->atVerb(verbCount - 1);
386}

◆ 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 388 of file SkPath.cpp.

388 {
389 int verbCount = fPathRef->countVerbs();
390
391 if (2 == verbCount) {
392 SkASSERT(kMove_Verb == fPathRef->atVerb(0));
393 if (kLine_Verb == fPathRef->atVerb(1)) {
394 SkASSERT(2 == fPathRef->countPoints());
395 if (line) {
396 const SkPoint* pts = fPathRef->points();
397 line[0] = pts[0];
398 line[1] = pts[1];
399 }
400 return true;
401 }
402 }
403 return false;
404}

◆ 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 3427 of file SkPath.cpp.

3427 {
3428 return exact ? p1 == p2 : SkPointPriv::EqualsWithinTolerance(p1, p2);
3429}

◆ 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 513 of file SkPath.cpp.

513 {
514 return SkPathPriv::IsOval(*this, bounds, nullptr, nullptr);
515}
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 3431 of file SkPath.cpp.

3432 {
3433 return exact ? p1 == p2 && p2 == p3 : SkPointPriv::EqualsWithinTolerance(p1, p2) &&
3435}

◆ 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 506 of file SkPath.cpp.

506 {
507 SkDEBUGCODE(this->validate();)
508 int currVerb = 0;
509 const SkPoint* pts = fPathRef->points();
510 return SkPathPriv::IsRectContour(*this, false, &currVerb, &pts, isClosed, direction, rect);
511}
static bool IsRectContour(const SkPath &, bool allowPartial, int *currVerb, const SkPoint **ptsPtr, bool *isClosed, SkPathDirection *direction, SkRect *rect)
Definition SkPath.cpp:3571

◆ 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 517 of file SkPath.cpp.

517 {
518 return SkPathPriv::IsRRect(*this, rrect, nullptr, nullptr);
519}
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 428 of file SkPath.cpp.

428 {
429 return this->isValidImpl() && fPathRef->isValid();
430}
bool isValid() const

◆ 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:3546
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 718 of file SkPath.cpp.

718 {
719 SkDEBUGCODE(this->validate();)
720
721 this->injectMoveToIfNeeded();
722
723 SkPathRef::Editor ed(&fPathRef);
724 ed.growForVerb(kLine_Verb)->set(x, y);
725
726 return this->dirtyAfterEdit();
727}

◆ 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 3501 of file SkPath.cpp.

3504 {
3505 if (verbCount <= 0) {
3506 return SkPath();
3507 }
3508
3509 const auto info = sk_path_analyze_verbs(vbs, verbCount);
3510 if (!info.valid || info.points > pointCount || info.weights > wCount) {
3511 SkDEBUGFAIL("invalid verbs and number of points/weights");
3512 return SkPath();
3513 }
3514
3515 return MakeInternal(info, pts, vbs, verbCount, ws, ft, isVolatile);
3516}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
SkPathVerbAnalysis sk_path_analyze_verbs(const uint8_t verbs[], int count)
Definition SkPath.cpp:3447
bool isVolatile() const
Definition SkPath.h:350

◆ makeScale()

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

Definition at line 1399 of file SkPath.h.

1399 {
1401 }
@ 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:1392

◆ makeTransform()

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

Definition at line 1392 of file SkPath.h.

1393 {
1394 SkPath dst;
1395 this->transform(m, &dst, pc);
1396 return dst;
1397 }
void transform(const SkMatrix &matrix, SkPath *dst, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
Definition SkPath.cpp:1647
dst
Definition cp.py:12

◆ 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 678 of file SkPath.cpp.

678 {
679 SkDEBUGCODE(this->validate();)
680
681 SkPathRef::Editor ed(&fPathRef);
682
683 // remember our index
684 fLastMoveToIndex = fPathRef->countPoints();
685
686 ed.growForVerb(kMove_Verb)->set(x, y);
687
688 return this->dirtyAfterEdit();
689}

◆ 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 1360 of file SkPath.h.

1360 {
1361 this->offset(dx, dy, this);
1362 return *this;
1363 }
Point offset

◆ 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 1627 of file SkPath.cpp.

1627 {
1629
1630 matrix.setTranslate(dx, dy);
1631 this->transform(matrix, dst);
1632}

◆ 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 188 of file SkPath.cpp.

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

◆ Oval() [1/2]

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

Definition at line 3526 of file SkPath.cpp.

3526 {
3527 return SkPathBuilder().addOval(r, dir, startIndex).detach();
3528}

◆ Oval() [2/2]

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

Definition at line 3522 of file SkPath.cpp.

3522 {
3523 return SkPathBuilder().addOval(r, dir).detach();
3524}

◆ Polygon() [1/2]

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

Definition at line 3546 of file SkPath.cpp.

3547 {
3548 return SkPathBuilder().addPolygon(pts, count, isClosed)
3549 .setFillType(ft)
3550 .setIsVolatile(isVolatile)
3551 .detach();
3552}

◆ 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 736 of file SkPath.cpp.

736 {
737 SkDEBUGCODE(this->validate();)
738
739 this->injectMoveToIfNeeded();
740
741 SkPathRef::Editor ed(&fPathRef);
742 SkPoint* pts = ed.growForVerb(kQuad_Verb);
743 pts[0].set(x1, y1);
744 pts[1].set(x2, y2);
745
746 return this->dirtyAfterEdit();
747}

◆ 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 1367 of file SkPath.cpp.

1368 {
1369 SkPoint currentPoint;
1370 this->getLastPt(&currentPoint);
1371 return this->arcTo(rx, ry, xAxisRotate, largeArc, sweep,
1372 currentPoint.fX + dx, currentPoint.fY + dy);
1373}

◆ 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 781 of file SkPath.cpp.

782 {
783 this->injectMoveToIfNeeded(); // This can change the result of this->getLastPt().
784 SkPoint pt;
785 this->getLastPt(&pt);
786 return this->conicTo(pt.fX + dx1, pt.fY + dy1, pt.fX + dx2, pt.fY + dy2, w);
787}

◆ 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 804 of file SkPath.cpp.

805 {
806 this->injectMoveToIfNeeded(); // This can change the result of this->getLastPt().
807 SkPoint pt;
808 this->getLastPt(&pt);
809 return this->cubicTo(pt.fX + x1, pt.fY + y1, pt.fX + x2, pt.fY + y2,
810 pt.fX + x3, pt.fY + y3);
811}

◆ 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 155 of file SkPath_serial.cpp.

155 {
156 SkRBuffer buffer(storage, length);
157 uint32_t packed;
158 if (!buffer.readU32(&packed)) {
159 return 0;
160 }
161 unsigned version = extract_version(packed);
162 if (version < kMin_Version || version > kCurrent_Version) {
163 return 0;
164 }
165
166 if (version == kJustPublicData_Version || version == kVerbsAreStoredForward_Version) {
167 return this->readFromMemory_EQ4Or5(storage, length);
168 }
169 return 0;
170}
@ kCurrent_Version
static unsigned extract_version(uint32_t packed)
@ kJustPublicData_Version
@ kVerbsAreStoredForward_Version
static const uint8_t buffer[]
size_t length

◆ Rect()

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

Definition at line 3518 of file SkPath.cpp.

3518 {
3519 return SkPathBuilder().addRect(r, dir, startIndex).detach();
3520}

◆ 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 360 of file SkPath.cpp.

360 {
361 SkDEBUGCODE(this->validate();)
362
363 if (fPathRef->unique()) {
364 fPathRef->reset();
365 } else {
366 fPathRef.reset(SkPathRef::CreateEmpty());
367 }
368 this->resetFields();
369 return *this;
370}
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 1569 of file SkPath.cpp.

1569 {
1570 // Detect if we're trying to add ourself
1571 const SkPath* src = &srcPath;
1572 SkTLazy<SkPath> tmp;
1573 if (this == src) {
1574 src = tmp.set(srcPath);
1575 }
1576
1577 const uint8_t* verbsBegin = src->fPathRef->verbsBegin();
1578 const uint8_t* verbs = src->fPathRef->verbsEnd();
1579 const SkPoint* pts = src->fPathRef->pointsEnd();
1580 const SkScalar* conicWeights = src->fPathRef->conicWeightsEnd();
1581
1582 bool needMove = true;
1583 bool needClose = false;
1584 while (verbs > verbsBegin) {
1585 uint8_t v = *--verbs;
1586 int n = SkPathPriv::PtsInVerb(v);
1587
1588 if (needMove) {
1589 --pts;
1590 this->moveTo(pts->fX, pts->fY);
1591 needMove = false;
1592 }
1593 pts -= n;
1594 switch (v) {
1595 case kMove_Verb:
1596 if (needClose) {
1597 this->close();
1598 needClose = false;
1599 }
1600 needMove = true;
1601 pts += 1; // so we see the point in "if (needMove)" above
1602 break;
1603 case kLine_Verb:
1604 this->lineTo(pts[0]);
1605 break;
1606 case kQuad_Verb:
1607 this->quadTo(pts[1], pts[0]);
1608 break;
1609 case kConic_Verb:
1610 this->conicTo(pts[1], pts[0], *--conicWeights);
1611 break;
1612 case kCubic_Verb:
1613 this->cubicTo(pts[2], pts[1], pts[0]);
1614 break;
1615 case kClose_Verb:
1616 needClose = true;
1617 break;
1618 default:
1619 SkDEBUGFAIL("unexpected verb");
1620 }
1621 }
1622 return *this;
1623}

◆ 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 372 of file SkPath.cpp.

372 {
373 SkDEBUGCODE(this->validate();)
374
375 SkPathRef::Rewind(&fPathRef);
376 this->resetFields();
377 return *this;
378}
static void Rewind(sk_sp< SkPathRef > *pathRef)

◆ 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 729 of file SkPath.cpp.

729 {
730 this->injectMoveToIfNeeded(); // This can change the result of this->getLastPt().
731 SkPoint pt;
732 this->getLastPt(&pt);
733 return this->lineTo(pt.fX + x, pt.fY + y);
734}

◆ 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 691 of file SkPath.cpp.

691 {
692 SkPoint pt = {0,0};
693 int count = fPathRef->countPoints();
694 if (count > 0) {
695 if (fLastMoveToIndex >= 0) {
696 pt = fPathRef->atPoint(count - 1);
697 } else {
698 pt = fPathRef->atPoint(~fLastMoveToIndex);
699 }
700 }
701 return this->moveTo(pt.fX + x, pt.fY + y);
702}

◆ 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 749 of file SkPath.cpp.

749 {
750 this->injectMoveToIfNeeded(); // This can change the result of this->getLastPt().
751 SkPoint pt;
752 this->getLastPt(&pt);
753 return this->quadTo(pt.fX + x1, pt.fY + y1, pt.fX + x2, pt.fY + y2);
754}

◆ RRect() [1/3]

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

Definition at line 3542 of file SkPath.cpp.

3542 {
3543 return SkPathBuilder().addRRect(SkRRect::MakeRectXY(r, rx, ry), dir).detach();
3544}
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 3534 of file SkPath.cpp.

3534 {
3535 return SkPathBuilder().addRRect(rr, dir).detach();
3536}

◆ RRect() [3/3]

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

Definition at line 3538 of file SkPath.cpp.

3538 {
3539 return SkPathBuilder().addRRect(rr, dir, startIndex).detach();
3540}

◆ 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
size_t writeToMemory(void *buffer) const
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switches.h:41

◆ 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 1428 of file SkPath.h.

1428 {
1429 this->setLastPt(p.fX, p.fY);
1430 }

◆ 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 598 of file SkPath.cpp.

598 {
599 SkDEBUGCODE(this->validate();)
600
601 int count = fPathRef->countPoints();
602 if (count == 0) {
603 this->moveTo(x, y);
604 } else {
605 SkPathRef::Editor ed(&fPathRef);
606 ed.atPoint(count-1)->set(x, y);
607 }
608}

◆ 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 217 of file SkPath.cpp.

217 {
218 if (this != &that) {
219 fPathRef.swap(that.fPathRef);
220 std::swap(fLastMoveToIndex, that.fLastMoveToIndex);
221
222 const auto ft = fFillType;
223 fFillType = that.fFillType;
224 that.fFillType = ft;
225
226 const auto iv = fIsVolatile;
227 fIsVolatile = that.fIsVolatile;
228 that.fIsVolatile = iv;
229
230 // Non-atomic swaps of atomic values.
231 SkPathConvexity c = this->getConvexityOrUnknown();
232 this->setConvexity(that.getConvexityOrUnknown());
233 that.setConvexity(c);
234
235 SkPathFirstDirection fd = this->getFirstDirection();
236 this->setFirstDirection(that.getFirstDirection());
237 that.setFirstDirection(fd);
238 }
239}
SkPathConvexity
Definition SkPathEnums.h:13
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 1386 of file SkPath.h.

1387 {
1388 this->transform(matrix, this, pc);
1389 return *this;
1390 }

◆ 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 1647 of file SkPath.cpp.

1647 {
1648 if (matrix.isIdentity()) {
1649 if (dst != nullptr && dst != this) {
1650 *dst = *this;
1651 }
1652 return;
1653 }
1654
1655 SkDEBUGCODE(this->validate();)
1656 if (dst == nullptr) {
1657 dst = const_cast<SkPath*>(this);
1658 }
1659
1660 if (matrix.hasPerspective()) {
1661 SkPath tmp;
1662 tmp.fFillType = fFillType;
1663
1664 SkPath clipped;
1665 const SkPath* src = this;
1666 if (pc == SkApplyPerspectiveClip::kYes &&
1667 SkPathPriv::PerspectiveClip(*this, matrix, &clipped))
1668 {
1669 src = &clipped;
1670 }
1671
1672 SkPath::Iter iter(*src, false);
1673 SkPoint pts[4];
1674 SkPath::Verb verb;
1675
1676 while ((verb = iter.next(pts)) != kDone_Verb) {
1677 switch (verb) {
1678 case kMove_Verb:
1679 tmp.moveTo(pts[0]);
1680 break;
1681 case kLine_Verb:
1682 tmp.lineTo(pts[1]);
1683 break;
1684 case kQuad_Verb:
1685 // promote the quad to a conic
1686 tmp.conicTo(pts[1], pts[2],
1687 SkConic::TransformW(pts, SK_Scalar1, matrix));
1688 break;
1689 case kConic_Verb:
1690 tmp.conicTo(pts[1], pts[2],
1691 SkConic::TransformW(pts, iter.conicWeight(), matrix));
1692 break;
1693 case kCubic_Verb:
1694 subdivide_cubic_to(&tmp, pts);
1695 break;
1696 case kClose_Verb:
1697 tmp.close();
1698 break;
1699 default:
1700 SkDEBUGFAIL("unknown verb");
1701 break;
1702 }
1703 }
1704
1705 dst->swap(tmp);
1706 SkPathRef::Editor ed(&dst->fPathRef);
1707 matrix.mapPoints(ed.writablePoints(), ed.pathRef()->countPoints());
1708 dst->setFirstDirection(SkPathFirstDirection::kUnknown);
1709 } else {
1710 SkPathConvexity convexity = this->getConvexityOrUnknown();
1711
1712 SkPathRef::CreateTransformedCopy(&dst->fPathRef, *fPathRef, matrix);
1713
1714 if (this != dst) {
1715 dst->fLastMoveToIndex = fLastMoveToIndex;
1716 dst->fFillType = fFillType;
1717 dst->fIsVolatile = fIsVolatile;
1718 }
1719
1720 // Due to finite/fragile float numerics, we can't assume that a convex path remains
1721 // convex after a transformation, so mark it as unknown here.
1722 // However, some transformations are thought to be safe:
1723 // axis-aligned values under scale/translate.
1724 //
1725 if (convexity == SkPathConvexity::kConvex &&
1726 (!matrix.isScaleTranslate() || !SkPathPriv::IsAxisAligned(*this))) {
1727 // Not safe to still assume we're convex...
1728 convexity = SkPathConvexity::kUnknown;
1729 }
1730 dst->setConvexity(convexity);
1731
1732 if (this->getFirstDirection() == SkPathFirstDirection::kUnknown) {
1733 dst->setFirstDirection(SkPathFirstDirection::kUnknown);
1734 } else {
1735 SkScalar det2x2 =
1738 if (det2x2 < 0) {
1739 dst->setFirstDirection(
1741 (SkPathFirstDirection)this->getFirstDirection()));
1742 } else if (det2x2 > 0) {
1743 dst->setFirstDirection(this->getFirstDirection());
1744 } else {
1745 dst->setFirstDirection(SkPathFirstDirection::kUnknown);
1746 }
1747 }
1748
1749 SkDEBUGCODE(dst->validate();)
1750 }
1751}
@ 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:1634
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:3924
static bool PerspectiveClip(const SkPath &src, const SkMatrix &, SkPath *result)
Definition SkPath.cpp:3894
static SkPathFirstDirection OppositeFirstDirection(SkPathFirstDirection dir)
Definition SkPathPriv.h:51
static void CreateTransformedCopy(sk_sp< SkPathRef > *dst, const SkPathRef &src, const SkMatrix &matrix)
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}
@ kGeneral
@ kType_SerializationShift
@ kFillType_SerializationShift
int countWeights() const
Definition SkPathRef.h:311
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 Symbol Documentation

◆ ForceIsRRect_Private

friend class ForceIsRRect_Private
friend

Definition at line 1931 of file SkPath.h.

◆ FuzzPath

friend class FuzzPath
friend

Definition at line 1932 of file SkPath.h.

◆ Iter

friend class Iter
friend

Definition at line 1833 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 210 of file SkPath.cpp.

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

◆ PathTest_Private

friend class PathTest_Private
friend

Definition at line 1930 of file SkPath.h.

◆ SkAutoDisableDirectionCheck

friend class SkAutoDisableDirectionCheck
friend

Definition at line 1924 of file SkPath.h.

◆ SkAutoDisableOvalCheck

friend class SkAutoDisableOvalCheck
friend

Definition at line 1923 of file SkPath.h.

◆ SkAutoPathBoundsUpdate

friend class SkAutoPathBoundsUpdate
friend

Definition at line 1922 of file SkPath.h.

◆ SkBench_AddPathTest

friend class SkBench_AddPathTest
friend

Definition at line 1929 of file SkPath.h.

◆ SkOpBuilder

friend class SkOpBuilder
friend

Definition at line 1928 of file SkPath.h.

◆ SkPathBuilder

friend class SkPathBuilder
friend

Definition at line 1925 of file SkPath.h.

◆ SkPathEdgeIter

friend class SkPathEdgeIter
friend

Definition at line 1926 of file SkPath.h.

◆ SkPathPriv

friend class SkPathPriv
friend

Definition at line 1834 of file SkPath.h.

◆ SkPathStroker

friend class SkPathStroker
friend

Definition at line 1835 of file SkPath.h.

◆ SkPathWriter

friend class SkPathWriter
friend

Definition at line 1927 of file SkPath.h.


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