Flutter Engine
The Flutter Engine
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 , kOpenOval , 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 (SkSpan< const SkPoint > points, SkSpan< const uint8_t > verbs, SkSpan< const SkScalar > 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 
kOpenOval 
kRRect 
kArc 

Definition at line 63 of file SkPathRef.h.

63 : uint8_t {
65 kOval,
66 kOpenOval, // An unclosed oval, as is generated by canvas2d ellipse or arc
67 kRRect,
68 kArc,
69 };
@ kGeneral
@ kRRect

Constructor & Destructor Documentation

◆ SkPathRef()

SkPathRef::SkPathRef ( SkSpan< const SkPoint points,
SkSpan< const uint8_t >  verbs,
SkSpan< const SkScalar weights,
unsigned  segmentMask 
)
inline

Definition at line 71 of file SkPathRef.h.

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

◆ ~SkPathRef()

SkPathRef::~SkPathRef ( )

Definition at line 68 of file SkPathRef.cpp.

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

Member Function Documentation

◆ addGenIDChangeListener()

void SkPathRef::addGenIDChangeListener ( sk_sp< SkIDChangeListener listener)

Definition at line 467 of file SkPathRef.cpp.

467 {
468 if (this == gEmpty) {
469 return;
470 }
471 fGenIDChangeListeners.add(std::move(listener));
472}
static SkPathRef * gEmpty
Definition: SkPathRef.cpp:75
void add(sk_sp< SkIDChangeListener > listener) SK_EXCLUDES(fMutex)

◆ approximateBytesUsed()

size_t SkPathRef::approximateBytesUsed ( ) const

Definition at line 61 of file SkPathRef.cpp.

61 {
62 return sizeof(SkPathRef)
63 + fPoints .capacity() * sizeof(fPoints [0])
64 + fVerbs .capacity() * sizeof(fVerbs [0])
65 + fConicWeights.capacity() * sizeof(fConicWeights[0]);
66}
SkPathRef(SkSpan< const SkPoint > points, SkSpan< const uint8_t > verbs, SkSpan< const SkScalar > weights, unsigned segmentMask)
Definition: SkPathRef.h:71
int capacity() const
Definition: SkTArray.h:518

◆ atPoint()

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

Definition at line 340 of file SkPathRef.h.

340{ 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 339 of file SkPathRef.h.

339{ return fVerbs[index]; }

◆ conicWeights()

const SkScalar * SkPathRef::conicWeights ( ) const
inline

Definition at line 333 of file SkPathRef.h.

333{ return fConicWeights.begin(); }

◆ conicWeightsEnd()

const SkScalar * SkPathRef::conicWeightsEnd ( ) const
inline

Definition at line 334 of file SkPathRef.h.

334{ return fConicWeights.end(); }

◆ countPoints()

int SkPathRef::countPoints ( ) const
inline

Definition at line 307 of file SkPathRef.h.

307{ return fPoints.size(); }
int size() const
Definition: SkTArray.h:421

◆ countVerbs()

int SkPathRef::countVerbs ( ) const
inline

Definition at line 308 of file SkPathRef.h.

308{ return fVerbs.size(); }

◆ countWeights()

int SkPathRef::countWeights ( ) const
inline

Definition at line 309 of file SkPathRef.h.

309{ return fConicWeights.size(); }

◆ CreateEmpty()

SkPathRef * SkPathRef::CreateEmpty ( )
static

Gets a path ref with no verbs or points.

Definition at line 77 of file SkPathRef.cpp.

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

◆ 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 141 of file SkPathRef.cpp.

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

◆ dataMatchesVerbs()

bool SkPathRef::dataMatchesVerbs ( ) const

Definition at line 687 of file SkPathRef.cpp.

687 {
688 const auto info = sk_path_analyze_verbs(fVerbs.begin(), fVerbs.size());
689 return info.valid &&
690 info.segmentMask == fSegmentMask &&
691 info.points == fPoints.size() &&
692 info.weights == fConicWeights.size();
693}
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:3515

◆ 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 446 of file SkPathRef.cpp.

446 {
447 SkASSERT(fEditorsAttached.load() == 0);
448 static const uint32_t kMask = (static_cast<int64_t>(1) << kPathRefGenIDBitCnt) - 1;
449
450 if (fGenerationID == 0) {
451 if (fPoints.empty() && fVerbs.empty()) {
452 fGenerationID = kEmptyGenID;
453 } else {
454 static std::atomic<uint32_t> nextID{kEmptyGenID + 1};
455 do {
456 fGenerationID = nextID.fetch_add(1, std::memory_order_relaxed) & kMask;
457 } while (fGenerationID == 0 || fGenerationID == kEmptyGenID);
458 }
459 }
460 #if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK)
461 SkASSERT((unsigned)fillType < (1 << (32 - kPathRefGenIDBitCnt)));
462 fGenerationID |= static_cast<uint32_t>(fillType) << kPathRefGenIDBitCnt;
463 #endif
464 return fGenerationID;
465}
#define SkASSERT(cond)
Definition: SkAssert.h:116
static constexpr int kPathRefGenIDBitCnt
Definition: SkPathRef.cpp:23
bool empty() const
Definition: SkTArray.h:199

◆ genIDChangeListenerCount()

int SkPathRef::genIDChangeListenerCount ( )

Definition at line 474 of file SkPathRef.cpp.

474{ 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 281 of file SkPathRef.h.

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

◆ getRRect()

SkRRect SkPathRef::getRRect ( ) const

Definition at line 481 of file SkPathRef.cpp.

481 {
482 const SkRect& bounds = this->getBounds();
483 SkVector radii[4] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}};
484 Iter iter(*this);
485 SkPoint pts[4];
486 uint8_t verb = iter.next(pts);
488 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
489 if (SkPath::kConic_Verb == verb) {
490 SkVector v1_0 = pts[1] - pts[0];
491 SkVector v2_1 = pts[2] - pts[1];
492 SkVector dxdy;
493 if (v1_0.fX) {
494 SkASSERT(!v2_1.fX && !v1_0.fY);
495 dxdy.set(SkScalarAbs(v1_0.fX), SkScalarAbs(v2_1.fY));
496 } else if (!v1_0.fY) {
497 SkASSERT(!v2_1.fX || !v2_1.fY);
498 dxdy.set(SkScalarAbs(v2_1.fX), SkScalarAbs(v2_1.fY));
499 } else {
500 SkASSERT(!v2_1.fY);
501 dxdy.set(SkScalarAbs(v2_1.fX), SkScalarAbs(v1_0.fY));
502 }
503 SkRRect::Corner corner =
504 pts[1].fX == bounds.fLeft ?
505 pts[1].fY == bounds.fTop ?
507 pts[1].fY == bounds.fTop ?
509 SkASSERT(!radii[corner].fX && !radii[corner].fY);
510 radii[corner] = dxdy;
511 } else {
513 && (!(pts[1].fX - pts[0].fX) || !(pts[1].fY - pts[0].fY)))
514 || verb == SkPath::kClose_Verb);
515 }
516 }
518 rrect.setRectRadii(bounds, radii);
519 return rrect;
520}
#define SkScalarAbs(x)
Definition: SkScalar.h:39
const SkRect & getBounds() const
Definition: SkPathRef.h:281
@ kClose_Verb
Definition: SkPath.h:1471
@ kMove_Verb
Definition: SkPath.h:1466
@ kConic_Verb
Definition: SkPath.h:1469
@ kDone_Verb
Definition: SkPath.h:1472
@ kLine_Verb
Definition: SkPath.h:1467
@ 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
Definition: SkPoint_impl.h:164
void set(float x, float y)
Definition: SkPoint_impl.h:200
float fY
y-axis value
Definition: SkPoint_impl.h:165

◆ 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 229 of file SkPathRef.h.

229{ return fSegmentMask; }

◆ hasComputedBounds()

bool SkPathRef::hasComputedBounds ( ) const
inline

Definition at line 272 of file SkPathRef.h.

272 {
273 return !fBoundsIsDirty;
274 }

◆ interpolate()

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

Definition at line 302 of file SkPathRef.cpp.

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

◆ isArc()

bool SkPathRef::isArc ( SkArc arc) const
inline

Definition at line 262 of file SkPathRef.h.

262 {
263 if (fType == PathType::kArc) {
264 if (arc) {
265 *arc = SkArc::Make(fArcOval, fArcStartAngle, fArcSweepAngle, fArcType);
266 }
267 }
268
269 return fType == PathType::kArc;
270 }
static SkArc Make(const SkRect &oval, SkScalar startAngleDegrees, SkScalar sweepAngleDegrees, Type type)
Definition: SkArc.h:38

◆ 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 217 of file SkPathRef.h.

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

◆ isInitialEmptyPathRef()

bool SkPathRef::isInitialEmptyPathRef ( ) const
inline

Definition at line 366 of file SkPathRef.h.

366 {
367 return fGenerationID == kEmptyGenID;
368 }

◆ 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 244 of file SkPathRef.h.

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

◆ isRRect()

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

Definition at line 522 of file SkPathRef.cpp.

522 {
523 if (fType == PathType::kRRect) {
524 if (rrect) {
525 *rrect = this->getRRect();
526 }
527 if (isCCW) {
528 *isCCW = SkToBool(fRRectOrOvalIsCCW);
529 }
530 if (start) {
531 *start = fRRectOrOvalStartIdx;
532 }
533 }
534 return fType == PathType::kRRect;
535}
SkRRect getRRect() const
Definition: SkPathRef.cpp:481

◆ isValid()

bool SkPathRef::isValid ( ) const

Definition at line 624 of file SkPathRef.cpp.

624 {
625 switch (fType) {
627 break;
628 case PathType::kOval:
630 if (fRRectOrOvalStartIdx >= 4) {
631 return false;
632 }
633 break;
634 case PathType::kRRect:
635 if (fRRectOrOvalStartIdx >= 8) {
636 return false;
637 }
638 break;
639 case PathType::kArc:
640 if (!(fArcOval.isFinite() && SkIsFinite(fArcStartAngle, fArcSweepAngle))) {
641 return false;
642 }
643 break;
644 }
645
646 if (!fBoundsIsDirty && !fBounds.isEmpty()) {
647 bool isFinite = true;
648 auto leftTop = skvx::float2(fBounds.fLeft, fBounds.fTop);
649 auto rightBot = skvx::float2(fBounds.fRight, fBounds.fBottom);
650 for (int i = 0; i < fPoints.size(); ++i) {
651 auto point = skvx::float2(fPoints[i].fX, fPoints[i].fY);
652#ifdef SK_DEBUG
653 if (fPoints[i].isFinite() && (any(point < leftTop)|| any(point > rightBot))) {
654 SkDebugf("bad SkPathRef bounds: %g %g %g %g\n",
655 fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom);
656 for (int j = 0; j < fPoints.size(); ++j) {
657 if (i == j) {
658 SkDebugf("*** bounds do not contain: ");
659 }
660 SkDebugf("%g %g\n", fPoints[j].fX, fPoints[j].fY);
661 }
662 return false;
663 }
664#endif
665
666 if (fPoints[i].isFinite() && any(point < leftTop) && !any(point > rightBot))
667 return false;
668 if (!fPoints[i].isFinite()) {
669 isFinite = false;
670 }
671 }
672 if (SkToBool(fIsFinite) != isFinite) {
673 return false;
674 }
675 }
676 return true;
677}
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static bool SkIsFinite(T x, Pack... values)
bool isFinite() const
Definition: SkPathRef.h:217
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 249 of file SkPathRef.cpp.

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

◆ points()

const SkPoint * SkPathRef::points ( ) const
inline

Returns a const pointer to the first point.

Definition at line 326 of file SkPathRef.h.

326{ return fPoints.begin(); }

◆ pointsEnd()

const SkPoint * SkPathRef::pointsEnd ( ) const
inline

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

Definition at line 331 of file SkPathRef.h.

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

◆ 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 229 of file SkPathRef.cpp.

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

◆ 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 316 of file SkPathRef.h.

316{ 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 321 of file SkPathRef.h.

321{ return fVerbs.end(); }

Friends And Related Function Documentation

◆ ForceIsRRect_Private

friend class ForceIsRRect_Private
friend

Definition at line 576 of file SkPathRef.h.

◆ PathRefTest_Private

friend class PathRefTest_Private
friend

Definition at line 575 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 577 of file SkPathRef.h.

◆ SkPathBuilder

friend class SkPathBuilder
friend

Definition at line 578 of file SkPathRef.h.

◆ SkPathPriv

friend class SkPathPriv
friend

Definition at line 579 of file SkPathRef.h.


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