Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Public Types | Public Member Functions | Static Public Member Functions | Friends | List of all members
SkPathRef Class Referencefinal

#include <SkPathRef.h>

Inheritance diagram for SkPathRef:
SkNVRefCnt< SkPathRef >

Classes

class  Editor
 
class  Iter
 

Public Types

enum class  PathType : uint8_t { kGeneral , kOval , kRRect , kArc }
 
using PointsArray = skia_private::STArray< 4, SkPoint >
 
using VerbsArray = skia_private::STArray< 4, uint8_t >
 
using ConicWeightsArray = skia_private::STArray< 2, SkScalar >
 

Public Member Functions

 SkPathRef (PointsArray points, VerbsArray verbs, ConicWeightsArray weights, unsigned segmentMask)
 
bool isFinite () const
 
uint32_t getSegmentMasks () const
 
bool isOval (SkRect *rect, bool *isCCW, unsigned *start) const
 
bool isRRect (SkRRect *rrect, bool *isCCW, unsigned *start) const
 
bool isArc (SkArc *arc) const
 
bool hasComputedBounds () const
 
const SkRectgetBounds () const
 
SkRRect getRRect () const
 
 ~SkPathRef ()
 
int countPoints () const
 
int countVerbs () const
 
int countWeights () const
 
size_t approximateBytesUsed () const
 
const uint8_t * verbsBegin () const
 
const uint8_t * verbsEnd () const
 
const SkPointpoints () const
 
const SkPointpointsEnd () const
 
const SkScalarconicWeights () const
 
const SkScalarconicWeightsEnd () const
 
uint8_t atVerb (int index) const
 
const SkPointatPoint (int index) const
 
bool operator== (const SkPathRef &ref) const
 
void interpolate (const SkPathRef &ending, SkScalar weight, SkPathRef *out) const
 
uint32_t genID (uint8_t fillType) const
 
void addGenIDChangeListener (sk_sp< SkIDChangeListener >)
 
int genIDChangeListenerCount ()
 
bool dataMatchesVerbs () const
 
bool isValid () const
 
 SkDEBUGCODE (void validate() const { SkASSERT(this->isValid());}) void reset()
 
bool isInitialEmptyPathRef () const
 
- Public Member Functions inherited from SkNVRefCnt< SkPathRef >
 SkNVRefCnt ()
 
 ~SkNVRefCnt ()
 
bool unique () const
 
void ref () const
 
void unref () const
 
void deref () const
 
bool refCntGreaterThan (int32_t threadIsolatedTestCnt) const
 

Static Public Member Functions

static SkPathRefCreateEmpty ()
 
static void CreateTransformedCopy (sk_sp< SkPathRef > *dst, const SkPathRef &src, const SkMatrix &matrix)
 
static void Rewind (sk_sp< SkPathRef > *pathRef)
 

Friends

class PathRefTest_Private
 
class ForceIsRRect_Private
 
class SkPath
 
class SkPathBuilder
 
class SkPathPriv
 
SkPathRefsk_create_empty_pathref ()
 

Detailed Description

Holds the path verbs and points. It is versioned by a generation ID. None of its public methods modify the contents. To modify or append to the verbs/points wrap the SkPathRef in an SkPathRef::Editor object. Installing the editor resets the generation ID. It also performs copy-on-write if the SkPathRef is shared by multiple SkPaths. The caller passes the Editor's constructor a pointer to a sk_sp<SkPathRef>, which may be updated to point to a new SkPathRef after the editor's constructor returns.

The points and verbs are stored in a single allocation. The points are at the begining of the allocation while the verbs are stored at end of the allocation, in reverse order. Thus the points and verbs both grow into the middle of the allocation until the meet. To access verb i in the verb array use ref.verbs()[~i] (because verbs() returns a pointer just beyond the first logical verb or the last verb in memory).

Definition at line 55 of file SkPathRef.h.

Member Typedef Documentation

◆ ConicWeightsArray

Definition at line 61 of file SkPathRef.h.

◆ PointsArray

Definition at line 59 of file SkPathRef.h.

◆ VerbsArray

Definition at line 60 of file SkPathRef.h.

Member Enumeration Documentation

◆ PathType

enum class SkPathRef::PathType : uint8_t
strong
Enumerator
kGeneral 
kOval 
kRRect 
kArc 

Definition at line 63 of file SkPathRef.h.

Constructor & Destructor Documentation

◆ SkPathRef()

SkPathRef::SkPathRef ( PointsArray  points,
VerbsArray  verbs,
ConicWeightsArray  weights,
unsigned  segmentMask 
)
inline

Definition at line 70 of file SkPathRef.h.

72 : fPoints(std::move(points))
73 , fVerbs(std::move(verbs))
74 , fConicWeights(std::move(weights))
75 {
76 fBoundsIsDirty = true; // this also invalidates fIsFinite
77 fGenerationID = 0; // recompute
78 fSegmentMask = segmentMask;
79 fType = PathType::kGeneral;
80 // The next two values don't matter unless fType is kOval or kRRect
81 fRRectOrOvalIsCCW = false;
82 fRRectOrOvalStartIdx = 0xAC;
83 fArcOval.setEmpty();
84 fArcStartAngle = fArcSweepAngle = 0.0f;
85 fArcUseCenter = false;
86 SkDEBUGCODE(fEditorsAttached.store(0);)
87
88 this->computeBounds(); // do this now, before we worry about multiple owners/threads
89 SkDEBUGCODE(this->validate();)
90 }
#define SkDEBUGCODE(...)
Definition SkDebug.h:23
const SkPoint * points() const
Definition SkPathRef.h:328
void setEmpty()
Definition SkRect.h:842

◆ ~SkPathRef()

SkPathRef::~SkPathRef ( )

Definition at line 67 of file SkPathRef.cpp.

67 {
68 // Deliberately don't validate() this path ref, otherwise there's no way
69 // to read one that's not valid and then free its memory without asserting.
70 SkDEBUGCODE(fGenerationID = 0xEEEEEEEE;)
71 SkDEBUGCODE(fEditorsAttached.store(0x7777777);)
72}

Member Function Documentation

◆ addGenIDChangeListener()

void SkPathRef::addGenIDChangeListener ( sk_sp< SkIDChangeListener listener)

Definition at line 461 of file SkPathRef.cpp.

461 {
462 if (this == gEmpty) {
463 return;
464 }
465 fGenIDChangeListeners.add(std::move(listener));
466}
static SkPathRef * gEmpty
Definition SkPathRef.cpp:74
void add(sk_sp< SkIDChangeListener > listener) SK_EXCLUDES(fMutex)

◆ approximateBytesUsed()

size_t SkPathRef::approximateBytesUsed ( ) const

Definition at line 60 of file SkPathRef.cpp.

60 {
61 return sizeof(SkPathRef)
62 + fPoints .capacity() * sizeof(fPoints [0])
63 + fVerbs .capacity() * sizeof(fVerbs [0])
64 + fConicWeights.capacity() * sizeof(fConicWeights[0]);
65}
int capacity() const
Definition SkTArray.h:513

◆ atPoint()

const SkPoint & SkPathRef::atPoint ( int  index) const
inline

Definition at line 342 of file SkPathRef.h.

342{ return fPoints[index]; }

◆ atVerb()

uint8_t SkPathRef::atVerb ( int  index) const
inline

Convenience methods for getting to a verb or point by index.

Definition at line 341 of file SkPathRef.h.

341{ return fVerbs[index]; }

◆ conicWeights()

const SkScalar * SkPathRef::conicWeights ( ) const
inline

Definition at line 335 of file SkPathRef.h.

335{ return fConicWeights.begin(); }

◆ conicWeightsEnd()

const SkScalar * SkPathRef::conicWeightsEnd ( ) const
inline

Definition at line 336 of file SkPathRef.h.

336{ return fConicWeights.end(); }

◆ countPoints()

int SkPathRef::countPoints ( ) const
inline

Definition at line 309 of file SkPathRef.h.

309{ return fPoints.size(); }
int size() const
Definition SkTArray.h:416

◆ countVerbs()

int SkPathRef::countVerbs ( ) const
inline

Definition at line 310 of file SkPathRef.h.

310{ return fVerbs.size(); }

◆ countWeights()

int SkPathRef::countWeights ( ) const
inline

Definition at line 311 of file SkPathRef.h.

311{ return fConicWeights.size(); }

◆ CreateEmpty()

SkPathRef * SkPathRef::CreateEmpty ( )
static

Gets a path ref with no verbs or points.

Definition at line 76 of file SkPathRef.cpp.

76 {
77 static SkOnce once;
78 once([]{
79 gEmpty = new SkPathRef;
80 gEmpty->computeBounds(); // Avoids races later to be the first to do this.
81 });
82 return SkRef(gEmpty);
83}
static T * SkRef(T *obj)
Definition SkRefCnt.h:132

◆ CreateTransformedCopy()

void SkPathRef::CreateTransformedCopy ( sk_sp< SkPathRef > *  dst,
const SkPathRef src,
const SkMatrix matrix 
)
static

Transforms a path ref by a matrix, allocating a new one only if necessary.

Definition at line 140 of file SkPathRef.cpp.

142 {
143 SkDEBUGCODE(src.validate();)
144 if (matrix.isIdentity()) {
145 if (dst->get() != &src) {
146 src.ref();
147 dst->reset(const_cast<SkPathRef*>(&src));
148 SkDEBUGCODE((*dst)->validate();)
149 }
150 return;
151 }
152
153 sk_sp<const SkPathRef> srcKeepAlive;
154 if (!(*dst)->unique()) {
155 // If dst and src are the same then we are about to drop our only ref on the common path
156 // ref. Some other thread may have owned src when we checked unique() above but it may not
157 // continue to do so. Add another ref so we continue to be an owner until we're done.
158 if (dst->get() == &src) {
159 srcKeepAlive.reset(SkRef(&src));
160 }
161 dst->reset(new SkPathRef);
162 }
163
164 if (dst->get() != &src) {
165 (*dst)->fVerbs = src.fVerbs;
166 (*dst)->fConicWeights = src.fConicWeights;
167 (*dst)->callGenIDChangeListeners();
168 (*dst)->fGenerationID = 0; // mark as dirty
169 // don't copy, just allocate the points
170 (*dst)->fPoints.resize(src.fPoints.size());
171 }
172 matrix.mapPoints((*dst)->fPoints.begin(), src.fPoints.begin(), src.fPoints.size());
173
174 // Need to check this here in case (&src == dst)
175 bool canXformBounds = !src.fBoundsIsDirty && matrix.rectStaysRect() && src.countPoints() > 1;
176
177 /*
178 * Here we optimize the bounds computation, by noting if the bounds are
179 * already known, and if so, we just transform those as well and mark
180 * them as "known", rather than force the transformed path to have to
181 * recompute them.
182 *
183 * Special gotchas if the path is effectively empty (<= 1 point) or
184 * if it is non-finite. In those cases bounds need to stay empty,
185 * regardless of the matrix.
186 */
187 if (canXformBounds) {
188 (*dst)->fBoundsIsDirty = false;
189 if (src.fIsFinite) {
190 matrix.mapRect(&(*dst)->fBounds, src.fBounds);
191 if (!((*dst)->fIsFinite = (*dst)->fBounds.isFinite())) {
192 (*dst)->fBounds.setEmpty();
193 }
194 } else {
195 (*dst)->fIsFinite = false;
196 (*dst)->fBounds.setEmpty();
197 }
198 } else {
199 (*dst)->fBoundsIsDirty = true;
200 }
201
202 (*dst)->fSegmentMask = src.fSegmentMask;
203
204 // It's an oval only if it stays a rect. Technically if scale is uniform, then it would stay an
205 // arc. For now, don't bother handling that (we'd also need to fixup the angles for negative
206 // scale, etc.)
207 bool rectStaysRect = matrix.rectStaysRect();
208 const PathType newType =
209 (rectStaysRect && src.fType != PathType::kArc) ? src.fType : PathType::kGeneral;
210 (*dst)->fType = newType;
211 if (newType == PathType::kOval || newType == PathType::kRRect) {
212 unsigned start = src.fRRectOrOvalStartIdx;
213 bool isCCW = SkToBool(src.fRRectOrOvalIsCCW);
214 transform_dir_and_start(matrix, newType == PathType::kRRect, &isCCW, &start);
215 (*dst)->fRRectOrOvalIsCCW = isCCW;
216 (*dst)->fRRectOrOvalStartIdx = start;
217 }
218
219 if (dst->get() == &src) {
220 (*dst)->callGenIDChangeListeners();
221 (*dst)->fGenerationID = 0;
222 }
223
224 SkDEBUGCODE((*dst)->validate();)
225}
static void transform_dir_and_start(const SkMatrix &matrix, bool isRRect, bool *isCCW, unsigned *start)
Definition SkPathRef.cpp:85
static constexpr bool SkToBool(const T &x)
Definition SkTo.h:35
void reset(T *ptr=nullptr)
Definition SkRefCnt.h:310
unsigned useCenter Optional< SkMatrix > matrix
Definition SkRecords.h:258
dst
Definition cp.py:12

◆ dataMatchesVerbs()

bool SkPathRef::dataMatchesVerbs ( ) const

Definition at line 680 of file SkPathRef.cpp.

680 {
681 const auto info = sk_path_analyze_verbs(fVerbs.begin(), fVerbs.size());
682 return info.valid &&
683 info.segmentMask == fSegmentMask &&
684 info.points == fPoints.size() &&
685 info.weights == fConicWeights.size();
686}
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

◆ genID()

uint32_t SkPathRef::genID ( uint8_t  fillType) const

Gets an ID that uniquely identifies the contents of the path ref. If two path refs have the same ID then they have the same verbs and points. However, two path refs may have the same contents but different genIDs. skbug.com/1762 for background on why fillType is necessary (for now).

Definition at line 440 of file SkPathRef.cpp.

440 {
441 SkASSERT(fEditorsAttached.load() == 0);
442 static const uint32_t kMask = (static_cast<int64_t>(1) << kPathRefGenIDBitCnt) - 1;
443
444 if (fGenerationID == 0) {
445 if (fPoints.empty() && fVerbs.empty()) {
446 fGenerationID = kEmptyGenID;
447 } else {
448 static std::atomic<uint32_t> nextID{kEmptyGenID + 1};
449 do {
450 fGenerationID = nextID.fetch_add(1, std::memory_order_relaxed) & kMask;
451 } while (fGenerationID == 0 || fGenerationID == kEmptyGenID);
452 }
453 }
454 #if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK)
455 SkASSERT((unsigned)fillType < (1 << (32 - kPathRefGenIDBitCnt)));
456 fGenerationID |= static_cast<uint32_t>(fillType) << kPathRefGenIDBitCnt;
457 #endif
458 return fGenerationID;
459}
static constexpr uint64_t kMask
Definition DrawPass.cpp:53
#define SkASSERT(cond)
Definition SkAssert.h:116
static constexpr int kPathRefGenIDBitCnt
Definition SkPathRef.cpp:22
bool empty() const
Definition SkTArray.h:194

◆ genIDChangeListenerCount()

int SkPathRef::genIDChangeListenerCount ( )

Definition at line 468 of file SkPathRef.cpp.

468{ return fGenIDChangeListeners.count(); }
int count() const SK_EXCLUDES(fMutex)

◆ getBounds()

const SkRect & SkPathRef::getBounds ( ) const
inline

Returns the bounds of the path's points. If the path contains 0 or 1 points, the bounds is set to (0,0,0,0), and isEmpty() will return true. Note: this bounds may be larger than the actual shape, since curves do not extend as far as their control points.

Definition at line 283 of file SkPathRef.h.

283 {
284 if (fBoundsIsDirty) {
285 this->computeBounds();
286 }
287 return fBounds;
288 }

◆ getRRect()

SkRRect SkPathRef::getRRect ( ) const

Definition at line 475 of file SkPathRef.cpp.

475 {
476 const SkRect& bounds = this->getBounds();
477 SkVector radii[4] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}};
478 Iter iter(*this);
479 SkPoint pts[4];
480 uint8_t verb = iter.next(pts);
482 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
483 if (SkPath::kConic_Verb == verb) {
484 SkVector v1_0 = pts[1] - pts[0];
485 SkVector v2_1 = pts[2] - pts[1];
486 SkVector dxdy;
487 if (v1_0.fX) {
488 SkASSERT(!v2_1.fX && !v1_0.fY);
489 dxdy.set(SkScalarAbs(v1_0.fX), SkScalarAbs(v2_1.fY));
490 } else if (!v1_0.fY) {
491 SkASSERT(!v2_1.fX || !v2_1.fY);
492 dxdy.set(SkScalarAbs(v2_1.fX), SkScalarAbs(v2_1.fY));
493 } else {
494 SkASSERT(!v2_1.fY);
495 dxdy.set(SkScalarAbs(v2_1.fX), SkScalarAbs(v1_0.fY));
496 }
497 SkRRect::Corner corner =
498 pts[1].fX == bounds.fLeft ?
499 pts[1].fY == bounds.fTop ?
501 pts[1].fY == bounds.fTop ?
503 SkASSERT(!radii[corner].fX && !radii[corner].fY);
504 radii[corner] = dxdy;
505 } else {
507 && (!(pts[1].fX - pts[0].fX) || !(pts[1].fY - pts[0].fY)))
508 || verb == SkPath::kClose_Verb);
509 }
510 }
512 rrect.setRectRadii(bounds, radii);
513 return rrect;
514}
#define SkScalarAbs(x)
Definition SkScalar.h:39
const SkRect & getBounds() const
Definition SkPathRef.h:283
@ kClose_Verb
Definition SkPath.h:1463
@ kMove_Verb
Definition SkPath.h:1458
@ kConic_Verb
Definition SkPath.h:1461
@ kDone_Verb
Definition SkPath.h:1464
@ kLine_Verb
Definition SkPath.h:1459
@ kUpperLeft_Corner
index of top-left corner radii
Definition SkRRect.h:252
@ kLowerRight_Corner
index of bottom-right corner radii
Definition SkRRect.h:254
@ kUpperRight_Corner
index of top-right corner radii
Definition SkRRect.h:253
@ kLowerLeft_Corner
index of bottom-left corner radii
Definition SkRRect.h:255
void setRectRadii(const SkRect &rect, const SkVector radii[4])
Definition SkRRect.cpp:189
Optional< SkRect > bounds
Definition SkRecords.h:189
SkRRect rrect
Definition SkRecords.h:232
float fX
x-axis value
void set(float x, float y)
float fY
y-axis value

◆ getSegmentMasks()

uint32_t SkPathRef::getSegmentMasks ( ) const
inline

Returns a mask, where each bit corresponding to a SegmentMask is set if the path contains 1 or more segments of that type. Returns 0 for an empty path (no segments).

Definition at line 228 of file SkPathRef.h.

228{ return fSegmentMask; }

◆ hasComputedBounds()

bool SkPathRef::hasComputedBounds ( ) const
inline

Definition at line 274 of file SkPathRef.h.

274 {
275 return !fBoundsIsDirty;
276 }

◆ interpolate()

void SkPathRef::interpolate ( const SkPathRef ending,
SkScalar  weight,
SkPathRef out 
) const

Definition at line 300 of file SkPathRef.cpp.

300 {
301 const SkScalar* inValues = &ending.getPoints()->fX;
302 SkScalar* outValues = &out->getWritablePoints()->fX;
303 int count = out->countPoints() * 2;
304 for (int index = 0; index < count; ++index) {
305 outValues[index] = outValues[index] * weight + inValues[index] * (1 - weight);
306 }
307 out->fBoundsIsDirty = true;
308 out->fType = PathType::kGeneral;
309}
int count
float SkScalar
Definition extension.cpp:12

◆ isArc()

bool SkPathRef::isArc ( SkArc arc) const
inline

Definition at line 261 of file SkPathRef.h.

261 {
262 if (fType == PathType::kArc) {
263 if (arc) {
264 arc->fOval = fArcOval;
265 arc->fStartAngle = fArcStartAngle;
266 arc->fSweepAngle = fArcSweepAngle;
267 arc->fUseCenter = fArcUseCenter;
268 }
269 }
270
271 return fType == PathType::kArc;
272 }
bool fUseCenter
Definition SkArc.h:26
SkScalar fSweepAngle
Definition SkArc.h:22
SkScalar fStartAngle
Definition SkArc.h:20
SkRect fOval
Definition SkArc.h:17

◆ isFinite()

bool SkPathRef::isFinite ( ) const
inline

Returns true if all of the points in this path are finite, meaning there are no infinities and no NaNs.

Definition at line 216 of file SkPathRef.h.

216 {
217 if (fBoundsIsDirty) {
218 this->computeBounds();
219 }
220 return SkToBool(fIsFinite);
221 }

◆ isInitialEmptyPathRef()

bool SkPathRef::isInitialEmptyPathRef ( ) const
inline

Definition at line 368 of file SkPathRef.h.

368 {
369 return fGenerationID == kEmptyGenID;
370 }

◆ isOval()

bool SkPathRef::isOval ( SkRect rect,
bool *  isCCW,
unsigned *  start 
) const
inline

Returns true if the path is an oval.

Parameters
rectreturns the bounding rect of this oval. It's a circle if the height and width are the same.
isCCWis the oval CCW (or CW if false).
startindicates where the contour starts on the oval (see SkPath::addOval for intepretation of the index).
Returns
true if this path is an oval. Tracking whether a path is an oval is considered an optimization for performance and so some paths that are in fact ovals can report false.

Definition at line 243 of file SkPathRef.h.

243 {
244 if (fType == PathType::kOval) {
245 if (rect) {
246 *rect = this->getBounds();
247 }
248 if (isCCW) {
249 *isCCW = SkToBool(fRRectOrOvalIsCCW);
250 }
251 if (start) {
252 *start = fRRectOrOvalStartIdx;
253 }
254 }
255
256 return fType == PathType::kOval;
257 }
sk_sp< SkBlender > blender SkRect rect
Definition SkRecords.h:350

◆ isRRect()

bool SkPathRef::isRRect ( SkRRect rrect,
bool *  isCCW,
unsigned *  start 
) const

Definition at line 516 of file SkPathRef.cpp.

516 {
517 if (fType == PathType::kRRect) {
518 if (rrect) {
519 *rrect = this->getRRect();
520 }
521 if (isCCW) {
522 *isCCW = SkToBool(fRRectOrOvalIsCCW);
523 }
524 if (start) {
525 *start = fRRectOrOvalStartIdx;
526 }
527 }
528 return fType == PathType::kRRect;
529}
SkRRect getRRect() const

◆ isValid()

bool SkPathRef::isValid ( ) const

Definition at line 618 of file SkPathRef.cpp.

618 {
619 switch (fType) {
621 break;
622 case PathType::kOval:
623 if (fRRectOrOvalStartIdx >= 4) {
624 return false;
625 }
626 break;
627 case PathType::kRRect:
628 if (fRRectOrOvalStartIdx >= 8) {
629 return false;
630 }
631 break;
632 case PathType::kArc:
633 if (!(fArcOval.isFinite() && SkIsFinite(fArcStartAngle, fArcSweepAngle))) {
634 return false;
635 }
636 break;
637 }
638
639 if (!fBoundsIsDirty && !fBounds.isEmpty()) {
640 bool isFinite = true;
641 auto leftTop = skvx::float2(fBounds.fLeft, fBounds.fTop);
642 auto rightBot = skvx::float2(fBounds.fRight, fBounds.fBottom);
643 for (int i = 0; i < fPoints.size(); ++i) {
644 auto point = skvx::float2(fPoints[i].fX, fPoints[i].fY);
645#ifdef SK_DEBUG
646 if (fPoints[i].isFinite() && (any(point < leftTop)|| any(point > rightBot))) {
647 SkDebugf("bad SkPathRef bounds: %g %g %g %g\n",
648 fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom);
649 for (int j = 0; j < fPoints.size(); ++j) {
650 if (i == j) {
651 SkDebugf("*** bounds do not contain: ");
652 }
653 SkDebugf("%g %g\n", fPoints[j].fX, fPoints[j].fY);
654 }
655 return false;
656 }
657#endif
658
659 if (fPoints[i].isFinite() && any(point < leftTop) && !any(point > rightBot))
660 return false;
661 if (!fPoints[i].isFinite()) {
662 isFinite = false;
663 }
664 }
665 if (SkToBool(fIsFinite) != isFinite) {
666 return false;
667 }
668 }
669 return true;
670}
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static bool SkIsFinite(T x, Pack... values)
bool isFinite() const
Definition SkPathRef.h:216
Vec< 2, float > float2
Definition SkVx.h:1145
SIT bool any(const Vec< 1, T > &x)
Definition SkVx.h:530
SkScalar fBottom
larger y-axis bounds
Definition extension.cpp:17
bool isFinite() const
Definition SkRect.h:711
SkScalar fLeft
smaller x-axis bounds
Definition extension.cpp:14
SkScalar fRight
larger x-axis bounds
Definition extension.cpp:16
bool isEmpty() const
Definition SkRect.h:693
SkScalar fTop
smaller y-axis bounds
Definition extension.cpp:15

◆ operator==()

bool SkPathRef::operator== ( const SkPathRef ref) const

Definition at line 247 of file SkPathRef.cpp.

247 {
248 SkDEBUGCODE(this->validate();)
249 SkDEBUGCODE(ref.validate();)
250
251 // We explicitly check fSegmentMask as a quick-reject. We could skip it,
252 // since it is only a cache of info in the fVerbs, but its a fast way to
253 // notice a difference
254 if (fSegmentMask != ref.fSegmentMask) {
255 return false;
256 }
257
258 bool genIDMatch = fGenerationID && fGenerationID == ref.fGenerationID;
259#ifdef SK_RELEASE
260 if (genIDMatch) {
261 return true;
262 }
263#endif
264 if (fPoints != ref.fPoints || fConicWeights != ref.fConicWeights || fVerbs != ref.fVerbs) {
265 SkASSERT(!genIDMatch);
266 return false;
267 }
268 if (ref.fVerbs.empty()) {
269 SkASSERT(ref.fPoints.empty());
270 }
271 return true;
272}

◆ points()

const SkPoint * SkPathRef::points ( ) const
inline

Returns a const pointer to the first point.

Definition at line 328 of file SkPathRef.h.

328{ return fPoints.begin(); }

◆ pointsEnd()

const SkPoint * SkPathRef::pointsEnd ( ) const
inline

Shortcut for this->points() + this->countPoints()

Definition at line 333 of file SkPathRef.h.

333{ return this->points() + this->countPoints(); }
int countPoints() const
Definition SkPathRef.h:309

◆ Rewind()

void SkPathRef::Rewind ( sk_sp< SkPathRef > *  pathRef)
static

Rollsback a path ref to zero verbs and points with the assumption that the path ref will be repopulated with approximately the same number of verbs and points. A new path ref is created only if necessary.

Definition at line 227 of file SkPathRef.cpp.

227 {
228 if ((*pathRef)->unique()) {
229 SkDEBUGCODE((*pathRef)->validate();)
230 (*pathRef)->callGenIDChangeListeners();
231 (*pathRef)->fBoundsIsDirty = true; // this also invalidates fIsFinite
232 (*pathRef)->fGenerationID = 0;
233 (*pathRef)->fPoints.clear();
234 (*pathRef)->fVerbs.clear();
235 (*pathRef)->fConicWeights.clear();
236 (*pathRef)->fSegmentMask = 0;
237 (*pathRef)->fType = PathType::kGeneral;
238 SkDEBUGCODE((*pathRef)->validate();)
239 } else {
240 int oldVCnt = (*pathRef)->countVerbs();
241 int oldPCnt = (*pathRef)->countPoints();
242 pathRef->reset(new SkPathRef);
243 (*pathRef)->resetToSize(0, 0, 0, oldVCnt, oldPCnt);
244 }
245}

◆ SkDEBUGCODE()

SkPathRef::SkDEBUGCODE ( void validate() const { SkASSERT(this->isValid());}  )

Resets this SkPathRef to a clean state.

◆ verbsBegin()

const uint8_t * SkPathRef::verbsBegin ( ) const
inline

Returns a pointer one beyond the first logical verb (last verb in memory order).

Definition at line 318 of file SkPathRef.h.

318{ return fVerbs.begin(); }

◆ verbsEnd()

const uint8_t * SkPathRef::verbsEnd ( ) const
inline

Returns a const pointer to the first verb in memory (which is the last logical verb).

Definition at line 323 of file SkPathRef.h.

323{ return fVerbs.end(); }

Friends And Related Symbol Documentation

◆ ForceIsRRect_Private

friend class ForceIsRRect_Private
friend

Definition at line 578 of file SkPathRef.h.

◆ PathRefTest_Private

friend class PathRefTest_Private
friend

Definition at line 577 of file SkPathRef.h.

◆ sk_create_empty_pathref

SkPathRef * sk_create_empty_pathref ( )
friend

Called the first time someone calls CreateEmpty to actually create the singleton.

◆ SkPath

friend class SkPath
friend

Definition at line 579 of file SkPathRef.h.

◆ SkPathBuilder

friend class SkPathBuilder
friend

Definition at line 580 of file SkPathRef.h.

◆ SkPathPriv

friend class SkPathPriv
friend

Definition at line 581 of file SkPathRef.h.


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