From 6c5418e6c25141cc3a1cc798d55219012bc881ec Mon Sep 17 00:00:00 2001 From: "bsalomon@google.com" Date: Fri, 14 Sep 2012 20:30:37 +0000 Subject: Temporarily revert r5433 due to http://www.crbug.com/148637 until after M23 branch. git-svn-id: http://skia.googlecode.com/svn/trunk@5557 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/core/SkPath.cpp | 367 ++++++++++++++++------------------- src/core/SkPathRef.h | 531 --------------------------------------------------- 2 files changed, 161 insertions(+), 737 deletions(-) delete mode 100644 src/core/SkPathRef.h (limited to 'src') diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp index 00d3772b57..c6e349bd95 100644 --- a/src/core/SkPath.cpp +++ b/src/core/SkPath.cpp @@ -10,8 +10,6 @@ #include "SkPath.h" #include "SkBuffer.h" #include "SkMath.h" -#include "SkPathRef.h" -#include "SkThread.h" SK_DEFINE_INST_COUNT(SkPath); @@ -111,13 +109,13 @@ private: }; // Return true if the computed bounds are finite. -static bool compute_pt_bounds(SkRect* bounds, const SkPathRef& ref) { - int count = ref.countPoints(); +static bool compute_pt_bounds(SkRect* bounds, const SkTDArray& pts) { + int count = pts.count(); if (count <= 1) { // we ignore just 1 point (moveto) bounds->setEmpty(); - return count ? ref.points()->isFinite() : true; + return count ? pts.begin()->isFinite() : true; } else { - return bounds->setBoundsCheck(ref.points(), count); + return bounds->setBoundsCheck(pts.begin(), pts.count()); } } @@ -141,8 +139,7 @@ static bool compute_pt_bounds(SkRect* bounds, const SkPathRef& ref) { #define INITIAL_LASTMOVETOINDEX_VALUE ~0 SkPath::SkPath() - : fPathRef(SkPathRef::CreateEmpty()) - , fFillType(kWinding_FillType) + : fFillType(kWinding_FillType) , fBoundsIsDirty(true) { fConvexity = kUnknown_Convexity; fSegmentMask = 0; @@ -157,17 +154,9 @@ SkPath::SkPath() SkPath::SkPath(const SkPath& src) { SkDEBUGCODE(src.validate();) - src.fPathRef.get()->ref(); - fPathRef.reset(src.fPathRef.get()); - fBounds = src.fBounds; - fFillType = src.fFillType; - fBoundsIsDirty = src.fBoundsIsDirty; - fConvexity = src.fConvexity; - fIsFinite = src.fIsFinite; - fSegmentMask = src.fSegmentMask; - fLastMoveToIndex = src.fLastMoveToIndex; - fIsOval = src.fIsOval; + *this = src; #ifdef SK_BUILD_FOR_ANDROID + // the assignment operator above increments the ID so correct for that here fGenerationID = src.fGenerationID; fSourcePath = NULL; #endif @@ -181,9 +170,9 @@ SkPath& SkPath::operator=(const SkPath& src) { SkDEBUGCODE(src.validate();) if (this != &src) { - src.fPathRef.get()->ref(); - fPathRef.reset(src.fPathRef.get()); fBounds = src.fBounds; + fPts = src.fPts; + fVerbs = src.fVerbs; fFillType = src.fFillType; fBoundsIsDirty = src.fBoundsIsDirty; fConvexity = src.fConvexity; @@ -207,7 +196,7 @@ SK_API bool operator==(const SkPath& a, const SkPath& b) { return &a == &b || (a.fFillType == b.fFillType && a.fSegmentMask == b.fSegmentMask && - *a.fPathRef.get() == *b.fPathRef.get()); + a.fVerbs == b.fVerbs && a.fPts == b.fPts); } void SkPath::swap(SkPath& other) { @@ -215,7 +204,8 @@ void SkPath::swap(SkPath& other) { if (this != &other) { SkTSwap(fBounds, other.fBounds); - fPathRef.swap(&other.fPathRef); + fPts.swap(other.fPts); + fVerbs.swap(other.fVerbs); SkTSwap(fFillType, other.fFillType); SkTSwap(fBoundsIsDirty, other.fBoundsIsDirty); SkTSwap(fConvexity, other.fConvexity); @@ -244,7 +234,8 @@ void SkPath::setSourcePath(const SkPath* path) { void SkPath::reset() { SkDEBUGCODE(this->validate();) - fPathRef.reset(SkPathRef::CreateEmpty()); + fPts.reset(); + fVerbs.reset(); GEN_ID_INC; fBoundsIsDirty = true; fConvexity = kUnknown_Convexity; @@ -256,7 +247,8 @@ void SkPath::reset() { void SkPath::rewind() { SkDEBUGCODE(this->validate();) - SkPathRef::Rewind(&fPathRef); + fPts.rewind(); + fVerbs.rewind(); GEN_ID_INC; fConvexity = kUnknown_Convexity; fBoundsIsDirty = true; @@ -267,18 +259,18 @@ void SkPath::rewind() { bool SkPath::isEmpty() const { SkDEBUGCODE(this->validate();) - return 0 == fPathRef->countVerbs(); + return 0 == fVerbs.count(); } bool SkPath::isLine(SkPoint line[2]) const { - int verbCount = fPathRef->countVerbs(); - int ptCount = fPathRef->countVerbs(); + int verbCount = fVerbs.count(); + int ptCount = fPts.count(); if (2 == verbCount && 2 == ptCount) { - if (kMove_Verb == fPathRef->atVerb(0) && - kLine_Verb == fPathRef->atVerb(1)) { + const uint8_t* verbs = fVerbs.begin(); + if (kMove_Verb == verbs[0] && kLine_Verb == verbs[1]) { if (line) { - const SkPoint* pts = fPathRef->points(); + const SkPoint* pts = fPts.begin(); line[0] = pts[0]; line[1] = pts[1]; } @@ -335,13 +327,13 @@ bool SkPath::isRect(SkRect* rect) const { int nextDirection = 0; bool closedOrMoved = false; bool autoClose = false; - const SkPoint* pts = fPathRef->points(); - int verbCnt = fPathRef->countVerbs(); - int currVerb = 0; - while (currVerb < verbCnt) { - switch (fPathRef->atVerb(currVerb++)) { + const uint8_t* verbs = fVerbs.begin(); + const uint8_t* verbStop = fVerbs.end(); + const SkPoint* pts = fPts.begin(); + while (verbs != verbStop) { + switch (*verbs++) { case kClose_Verb: - pts = fPathRef->points(); + pts = fPts.begin(); autoClose = true; case kLine_Verb: { SkScalar left = last.fX; @@ -406,56 +398,39 @@ bool SkPath::isRect(SkRect* rect) const { return result; } -int SkPath::countPoints() const { - return fPathRef->countPoints(); -} - int SkPath::getPoints(SkPoint dst[], int max) const { SkDEBUGCODE(this->validate();) SkASSERT(max >= 0); SkASSERT(!max || dst); - int count = SkMin32(max, fPathRef->countPoints()); - memcpy(dst, fPathRef->points(), count * sizeof(SkPoint)); - return fPathRef->countPoints(); + int count = fPts.count(); + fPts.copyRange(dst, 0, max); + return count; } SkPoint SkPath::getPoint(int index) const { - if ((unsigned)index < (unsigned)fPathRef->countPoints()) { - return fPathRef->atPoint(index); + if ((unsigned)index < (unsigned)fPts.count()) { + return fPts[index]; } return SkPoint::Make(0, 0); } -int SkPath::countVerbs() const { - return fPathRef->countVerbs(); -} - -static inline void copy_verbs_reverse(uint8_t* inorderDst, - const uint8_t* reversedSrc, - int count) { - for (int i = 0; i < count; ++i) { - inorderDst[i] = reversedSrc[~i]; - } -} - int SkPath::getVerbs(uint8_t dst[], int max) const { SkDEBUGCODE(this->validate();) SkASSERT(max >= 0); SkASSERT(!max || dst); - int count = SkMin32(max, fPathRef->countVerbs()); - copy_verbs_reverse(dst, fPathRef->verbs(), count); - return fPathRef->countVerbs(); + fVerbs.copyRange(dst, 0, max); + return fVerbs.count(); } bool SkPath::getLastPt(SkPoint* lastPt) const { SkDEBUGCODE(this->validate();) - int count = fPathRef->countPoints(); + int count = fPts.count(); if (count > 0) { if (lastPt) { - *lastPt = fPathRef->atPoint(count - 1); + *lastPt = fPts[count - 1]; } return true; } @@ -468,13 +443,12 @@ bool SkPath::getLastPt(SkPoint* lastPt) const { void SkPath::setLastPt(SkScalar x, SkScalar y) { SkDEBUGCODE(this->validate();) - int count = fPathRef->countPoints(); + int count = fPts.count(); if (count == 0) { this->moveTo(x, y); } else { fIsOval = false; - SkPathRef::Editor ed(&fPathRef); - ed.atPoint(count-1)->set(x, y); + fPts[count - 1].set(x, y); GEN_ID_INC; } } @@ -483,7 +457,7 @@ void SkPath::computeBounds() const { SkDEBUGCODE(this->validate();) SkASSERT(fBoundsIsDirty); - fIsFinite = compute_pt_bounds(&fBounds, *fPathRef.get()); + fIsFinite = compute_pt_bounds(&fBounds, fPts); fBoundsIsDirty = false; } @@ -511,19 +485,24 @@ void SkPath::setConvexity(Convexity c) { void SkPath::incReserve(U16CPU inc) { SkDEBUGCODE(this->validate();) - SkPathRef::Editor(&fPathRef, inc, inc); + + fVerbs.setReserve(fVerbs.count() + inc); + fPts.setReserve(fPts.count() + inc); + SkDEBUGCODE(this->validate();) } void SkPath::moveTo(SkScalar x, SkScalar y) { SkDEBUGCODE(this->validate();) - SkPathRef::Editor ed(&fPathRef); + SkPoint* pt; // remember our index - fLastMoveToIndex = ed.pathRef()->countPoints(); + fLastMoveToIndex = fPts.count(); - ed.growForVerb(kMove_Verb)->set(x, y); + pt = fPts.append(); + *fVerbs.append() = kMove_Verb; + pt->set(x, y); GEN_ID_INC; DIRTY_AFTER_EDIT_NO_CONVEXITY_CHANGE; @@ -538,10 +517,10 @@ void SkPath::rMoveTo(SkScalar x, SkScalar y) { void SkPath::injectMoveToIfNeeded() { if (fLastMoveToIndex < 0) { SkScalar x, y; - if (fPathRef->countVerbs() == 0) { + if (fVerbs.count() == 0) { x = y = 0; } else { - const SkPoint& pt = fPathRef->atPoint(~fLastMoveToIndex); + const SkPoint& pt = fPts[~fLastMoveToIndex]; x = pt.fX; y = pt.fY; } @@ -554,8 +533,8 @@ void SkPath::lineTo(SkScalar x, SkScalar y) { this->injectMoveToIfNeeded(); - SkPathRef::Editor ed(&fPathRef); - ed.growForVerb(kLine_Verb)->set(x, y); + fPts.append()->set(x, y); + *fVerbs.append() = kLine_Verb; fSegmentMask |= kLine_SegmentMask; GEN_ID_INC; @@ -573,10 +552,10 @@ void SkPath::quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) { this->injectMoveToIfNeeded(); - SkPathRef::Editor ed(&fPathRef); - SkPoint* pts = ed.growForVerb(kQuad_Verb); + SkPoint* pts = fPts.append(2); pts[0].set(x1, y1); pts[1].set(x2, y2); + *fVerbs.append() = kQuad_Verb; fSegmentMask |= kQuad_SegmentMask; GEN_ID_INC; @@ -595,11 +574,11 @@ void SkPath::cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, this->injectMoveToIfNeeded(); - SkPathRef::Editor ed(&fPathRef); - SkPoint* pts = ed.growForVerb(kCubic_Verb); + SkPoint* pts = fPts.append(3); pts[0].set(x1, y1); pts[1].set(x2, y2); pts[2].set(x3, y3); + *fVerbs.append() = kCubic_Verb; fSegmentMask |= kCubic_SegmentMask; GEN_ID_INC; @@ -617,18 +596,16 @@ void SkPath::rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, void SkPath::close() { SkDEBUGCODE(this->validate();) - int count = fPathRef->countVerbs(); + int count = fVerbs.count(); if (count > 0) { - switch (fPathRef->atVerb(count - 1)) { + switch (fVerbs[count - 1]) { case kLine_Verb: case kQuad_Verb: case kCubic_Verb: - case kMove_Verb: { - SkPathRef::Editor ed(&fPathRef); - ed.growForVerb(kClose_Verb); + case kMove_Verb: + *fVerbs.append() = kClose_Verb; GEN_ID_INC; break; - } default: // don't add a close if it's the first verb or a repeat break; @@ -676,34 +653,31 @@ void SkPath::addPoly(const SkPoint pts[], int count, bool close) { return; } - SkPathRef::Editor ed(&fPathRef); - fLastMoveToIndex = ed.pathRef()->countPoints(); - uint8_t* vb; - SkPoint* p; + fLastMoveToIndex = fPts.count(); + fPts.append(count, pts); + // +close makes room for the extra kClose_Verb - ed.grow(count + close, count, &vb, &p); + uint8_t* vb = fVerbs.append(count + close); + vb[0] = kMove_Verb; - memcpy(p, pts, count * sizeof(SkPoint)); - vb[~0] = kMove_Verb; if (count > 1) { // cast to unsigned, so if MIN_COUNT_FOR_MEMSET_TO_BE_FAST is defined to // be 0, the compiler will remove the test/branch entirely. if ((unsigned)count >= MIN_COUNT_FOR_MEMSET_TO_BE_FAST) { - memset(vb - count, kLine_Verb, count - 1); + memset(&vb[1], kLine_Verb, count - 1); } else { for (int i = 1; i < count; ++i) { - vb[~i] = kLine_Verb; + vb[i] = kLine_Verb; } } fSegmentMask |= kLine_SegmentMask; } if (close) { - vb[~count] = kClose_Verb; + vb[count] = kClose_Verb; } GEN_ID_INC; DIRTY_AFTER_EDIT; - SkDEBUGCODE(this->validate();) } #define CUBIC_ARC_FACTOR ((SK_ScalarSqrt2 - SK_Scalar1) * 4 / 3) @@ -849,9 +823,9 @@ void SkPath::addRoundRect(const SkRect& rect, const SkScalar rad[], } bool SkPath::hasOnlyMoveTos() const { - int count = fPathRef->countVerbs(); - const uint8_t* verbs = const_cast(fPathRef.get())->verbsMemBegin(); - for (int i = 0; i < count; ++i) { + const uint8_t* verbs = fVerbs.begin(); + const uint8_t* verbStop = fVerbs.end(); + while (verbs != verbStop) { if (*verbs == kLine_Verb || *verbs == kQuad_Verb || *verbs == kCubic_Verb) { @@ -1017,7 +991,7 @@ void SkPath::arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, int count = build_arc_points(oval, startAngle, sweepAngle, pts); SkASSERT((count & 1) == 1); - if (fPathRef->countVerbs() == 0) { + if (fVerbs.count() == 0) { forceMoveTo = true; } this->incReserve(count); @@ -1129,7 +1103,7 @@ void SkPath::addPath(const SkPath& path, SkScalar dx, SkScalar dy) { } void SkPath::addPath(const SkPath& path, const SkMatrix& matrix) { - SkPathRef::Editor(&fPathRef, path.countVerbs(), path.countPoints()); + this->incReserve(path.fPts.count()); fIsOval = false; @@ -1179,23 +1153,21 @@ static const uint8_t gPtsInVerb[] = { // ignore the initial moveto, and stop when the 1st contour ends void SkPath::pathTo(const SkPath& path) { - int i, vcount = path.fPathRef->countVerbs(); - // exit early if the path is empty, or just has a moveTo. - if (vcount < 2) { + int i, vcount = path.fVerbs.count(); + if (vcount == 0) { return; } - SkPathRef::Editor(&fPathRef, vcount, path.countPoints()); + this->incReserve(vcount); fIsOval = false; - const uint8_t* verbs = path.fPathRef->verbs(); - // skip the initial moveTo - const SkPoint* pts = path.fPathRef->points() + 1; + const uint8_t* verbs = path.fVerbs.begin(); + const SkPoint* pts = path.fPts.begin() + 1; // 1 for the initial moveTo - SkASSERT(verbs[~0] == kMove_Verb); + SkASSERT(verbs[0] == kMove_Verb); for (i = 1; i < vcount; i++) { - switch (verbs[~i]) { + switch (verbs[i]) { case kLine_Verb: this->lineTo(pts[0].fX, pts[0].fY); break; @@ -1203,33 +1175,33 @@ void SkPath::pathTo(const SkPath& path) { this->quadTo(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY); break; case kCubic_Verb: - this->cubicTo(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY); + this->cubicTo(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, + pts[2].fX, pts[2].fY); break; case kClose_Verb: return; } - pts += gPtsInVerb[verbs[~i]]; + pts += gPtsInVerb[verbs[i]]; } } // ignore the last point of the 1st contour void SkPath::reversePathTo(const SkPath& path) { - int i, vcount = path.fPathRef->countVerbs(); - // exit early if the path is empty, or just has a moveTo. - if (vcount < 2) { + int i, vcount = path.fVerbs.count(); + if (vcount == 0) { return; } - SkPathRef::Editor(&fPathRef, vcount, path.countPoints()); + this->incReserve(vcount); fIsOval = false; - const uint8_t* verbs = path.fPathRef->verbs(); - const SkPoint* pts = path.fPathRef->points(); + const uint8_t* verbs = path.fVerbs.begin(); + const SkPoint* pts = path.fPts.begin(); - SkASSERT(verbs[~0] == kMove_Verb); - for (i = 1; i < vcount; ++i) { - int n = gPtsInVerb[verbs[~i]]; + SkASSERT(verbs[0] == kMove_Verb); + for (i = 1; i < vcount; i++) { + int n = gPtsInVerb[verbs[i]]; if (n == 0) { break; } @@ -1237,7 +1209,7 @@ void SkPath::reversePathTo(const SkPath& path) { } while (--i > 0) { - switch (verbs[~i]) { + switch (verbs[i]) { case kLine_Verb: this->lineTo(pts[-1].fX, pts[-1].fY); break; @@ -1252,24 +1224,23 @@ void SkPath::reversePathTo(const SkPath& path) { SkDEBUGFAIL("bad verb"); break; } - pts -= gPtsInVerb[verbs[~i]]; + pts -= gPtsInVerb[verbs[i]]; } } void SkPath::reverseAddPath(const SkPath& src) { - SkPathRef::Editor ed(&fPathRef, src.fPathRef->countPoints(), src.fPathRef->countVerbs()); + this->incReserve(src.fPts.count()); - const SkPoint* pts = src.fPathRef->pointsEnd(); - // we will iterator through src's verbs backwards - const uint8_t* verbs = src.fPathRef->verbsMemBegin(); // points at the last verb - const uint8_t* verbsEnd = src.fPathRef->verbs(); // points just past the first verb + const SkPoint* pts = src.fPts.end(); + const uint8_t* startVerbs = src.fVerbs.begin(); + const uint8_t* verbs = src.fVerbs.end(); fIsOval = false; bool needMove = true; bool needClose = false; - while (verbs < verbsEnd) { - uint8_t v = *(verbs++); + while (verbs > startVerbs) { + uint8_t v = *--verbs; int n = gPtsInVerb[v]; if (needMove) { @@ -1380,8 +1351,7 @@ void SkPath::transform(const SkMatrix& matrix, SkPath* dst) const { } dst->swap(tmp); - SkPathRef::Editor ed(&dst->fPathRef); - matrix.mapPoints(ed.points(), ed.pathRef()->countPoints()); + matrix.mapPoints(dst->fPts.begin(), dst->fPts.count()); } else { /* * If we're not in perspective, we can transform all of the points at @@ -1396,7 +1366,7 @@ void SkPath::transform(const SkMatrix& matrix, SkPath* dst) const { * if it is non-finite. In those cases bounds need to stay empty, * regardless of the matrix. */ - if (!fBoundsIsDirty && matrix.rectStaysRect() && fPathRef->countPoints() > 1) { + if (!fBoundsIsDirty && matrix.rectStaysRect() && fPts.count() > 1) { dst->fBoundsIsDirty = false; if (fIsFinite) { matrix.mapRect(&dst->fBounds, fBounds); @@ -1412,16 +1382,21 @@ void SkPath::transform(const SkMatrix& matrix, SkPath* dst) const { dst->fBoundsIsDirty = true; } - SkPathRef::CreateTransformedCopy(&dst->fPathRef, *fPathRef.get(), matrix); - if (this != dst) { + dst->fVerbs = fVerbs; + dst->fPts.setCount(fPts.count()); dst->fFillType = fFillType; dst->fSegmentMask = fSegmentMask; dst->fConvexity = fConvexity; + dst->fIsOval = fIsOval; } - // It's an oval only if it stays a rect. - dst->fIsOval = fIsOval && matrix.rectStaysRect(); + matrix.mapPoints(dst->fPts.begin(), fPts.begin(), fPts.count()); + + if (fIsOval) { + // It's an oval only if it stays a rect. + dst->fIsOval = matrix.rectStaysRect(); + } SkDEBUGCODE(dst->validate();) } @@ -1457,9 +1432,9 @@ SkPath::Iter::Iter(const SkPath& path, bool forceClose) { } void SkPath::Iter::setPath(const SkPath& path, bool forceClose) { - fPts = path.fPathRef->points(); - fVerbs = path.fPathRef->verbs(); - fVerbStop = path.fPathRef->verbsMemBegin(); + fPts = path.fPts.begin(); + fVerbs = path.fVerbs.begin(); + fVerbStop = path.fVerbs.end(); fLastPt.fX = fLastPt.fY = 0; fMoveTo.fX = fMoveTo.fY = 0; fForceClose = SkToU8(forceClose); @@ -1478,13 +1453,12 @@ bool SkPath::Iter::isClosedContour() const { const uint8_t* verbs = fVerbs; const uint8_t* stop = fVerbStop; - if (kMove_Verb == *(verbs - 1)) { - verbs -= 1; // skip the initial moveto + if (kMove_Verb == *verbs) { + verbs += 1; // skip the initial moveto } - while (verbs > stop) { - // verbs points one beyond the current verb, decrement first. - unsigned v = *(--verbs); + while (verbs < stop) { + unsigned v = *verbs++; if (kMove_Verb == v) { break; } @@ -1536,14 +1510,14 @@ void SkPath::Iter::consumeDegenerateSegments() { const SkPoint* lastMovePt = 0; SkPoint lastPt = fLastPt; while (fVerbs != fVerbStop) { - unsigned verb = *(fVerbs - 1); // fVerbs is one beyond the current verb + unsigned verb = *fVerbs; switch (verb) { case kMove_Verb: // Keep a record of this most recent move lastMoveVerb = fVerbs; lastMovePt = fPts; lastPt = fPts[0]; - fVerbs--; + fVerbs++; fPts++; break; @@ -1554,7 +1528,7 @@ void SkPath::Iter::consumeDegenerateSegments() { return; } // A close at any other time must be ignored - fVerbs--; + fVerbs++; break; case kLine_Verb: @@ -1567,7 +1541,7 @@ void SkPath::Iter::consumeDegenerateSegments() { return; } // Ignore this line and continue - fVerbs--; + fVerbs++; fPts++; break; @@ -1581,7 +1555,7 @@ void SkPath::Iter::consumeDegenerateSegments() { return; } // Ignore this line and continue - fVerbs--; + fVerbs++; fPts += 2; break; @@ -1595,7 +1569,7 @@ void SkPath::Iter::consumeDegenerateSegments() { return; } // Ignore this line and continue - fVerbs--; + fVerbs++; fPts += 3; break; @@ -1620,15 +1594,14 @@ SkPath::Verb SkPath::Iter::doNext(SkPoint ptsParam[4]) { return kDone_Verb; } - // fVerbs is one beyond the current verb, decrement first - unsigned verb = *(--fVerbs); + unsigned verb = *fVerbs++; const SkPoint* SK_RESTRICT srcPts = fPts; SkPoint* SK_RESTRICT pts = ptsParam; switch (verb) { case kMove_Verb: if (fNeedClose) { - fVerbs++; // move back one verb + fVerbs -= 1; verb = this->autoClose(pts); if (verb == kClose_Verb) { fNeedClose = false; @@ -1667,7 +1640,7 @@ SkPath::Verb SkPath::Iter::doNext(SkPoint ptsParam[4]) { case kClose_Verb: verb = this->autoClose(pts); if (verb == kLine_Verb) { - fVerbs++; // move back one verb + fVerbs -= 1; } else { fNeedClose = false; fSegmentState = kEmptyContour_SegmentState; @@ -1696,9 +1669,9 @@ SkPath::RawIter::RawIter(const SkPath& path) { } void SkPath::RawIter::setPath(const SkPath& path) { - fPts = path.fPathRef->points(); - fVerbs = path.fPathRef->verbs(); - fVerbStop = path.fPathRef->verbsMemBegin(); + fPts = path.fPts.begin(); + fVerbs = path.fVerbs.begin(); + fVerbStop = path.fVerbs.end(); fMoveTo.fX = fMoveTo.fY = 0; fLastPt.fX = fLastPt.fY = 0; } @@ -1709,9 +1682,8 @@ SkPath::Verb SkPath::RawIter::next(SkPoint pts[4]) { return kDone_Verb; } - // fVerbs points one beyond next verb so decrement first. - unsigned verb = *(--fVerbs); - const SkPoint* srcPts = fPts; + unsigned verb = *fVerbs++; + const SkPoint* srcPts = fPts; switch (verb) { case kMove_Verb: @@ -1757,23 +1729,16 @@ uint32_t SkPath::writeToMemory(void* storage) const { SkDEBUGCODE(this->validate();) if (NULL == storage) { - const int byteCount = sizeof(int32_t) -#if NEW_PICTURE_FORMAT - + fPathRef->writeSize() -#else - + 2 * sizeof(int32_t) - + sizeof(SkPoint) * fPathRef->countPoints() - + sizeof(uint8_t) * fPathRef->countVerbs() -#endif + const int byteCount = 3 * sizeof(int32_t) + + sizeof(SkPoint) * fPts.count() + + sizeof(uint8_t) * fVerbs.count() + sizeof(SkRect); return SkAlign4(byteCount); } SkWBuffer buffer(storage); -#if !NEW_PICTURE_FORMAT - buffer.write32(fPathRef->countPoints()); - buffer.write32(fPathRef->countVerbs()); -#endif + buffer.write32(fPts.count()); + buffer.write32(fVerbs.count()); // Call getBounds() to ensure (as a side-effect) that fBounds // and fIsFinite are computed. @@ -1788,7 +1753,8 @@ uint32_t SkPath::writeToMemory(void* storage) const { buffer.write32(packed); - fPathRef->writeToBuffer(&buffer); + buffer.write(fPts.begin(), sizeof(SkPoint) * fPts.count()); + buffer.write(fVerbs.begin(), fVerbs.count()); buffer.write(&bounds, sizeof(bounds)); @@ -1798,10 +1764,8 @@ uint32_t SkPath::writeToMemory(void* storage) const { uint32_t SkPath::readFromMemory(const void* storage) { SkRBuffer buffer(storage); -#if !NEW_PICTURE_FORMAT - int32_t pcount = buffer.readS32(); - int32_t vcount = buffer.readS32(); -#endif + fPts.setCount(buffer.readS32()); + fVerbs.setCount(buffer.readS32()); uint32_t packed = buffer.readS32(); fIsFinite = (packed >> kIsFinite_SerializationShift) & 1; @@ -1810,11 +1774,8 @@ uint32_t SkPath::readFromMemory(const void* storage) { fFillType = (packed >> kFillType_SerializationShift) & 0xFF; fSegmentMask = (packed >> kSegmentMask_SerializationShift) & 0xFF; -#if NEW_PICTURE_FORMAT - fPathRef.reset(SkPathRef::CreateFromBuffer(&buffer)); -#else - fPathRef.reset(SkPathRef::CreateFromBuffer(vcount, pcount, &buffer)); -#endif + buffer.read(fPts.begin(), sizeof(SkPoint) * fPts.count()); + buffer.read(fVerbs.begin(), fVerbs.count()); buffer.read(&fBounds, sizeof(fBounds)); fBoundsIsDirty = false; @@ -1878,14 +1839,16 @@ void SkPath::dump() const { void SkPath::validate() const { SkASSERT(this != NULL); SkASSERT((fFillType & ~3) == 0); + fPts.validate(); + fVerbs.validate(); if (!fBoundsIsDirty) { SkRect bounds; - bool isFinite = compute_pt_bounds(&bounds, *fPathRef.get()); + bool isFinite = compute_pt_bounds(&bounds, fPts); SkASSERT(SkToBool(fIsFinite) == isFinite); - if (fPathRef->countPoints() <= 1) { + if (fPts.count() <= 1) { // if we're empty, fBounds may be empty but translated, so we can't // necessarily compare to bounds directly // try path.addOval(2, 2, 2, 2) which is empty, but the bounds will @@ -1904,9 +1867,8 @@ void SkPath::validate() const { } uint32_t mask = 0; - const uint8_t* verbs = const_cast(fPathRef.get())->verbs(); - for (int i = 0; i < fPathRef->countVerbs(); i++) { - switch (verbs[~i]) { + for (int i = 0; i < fVerbs.count(); i++) { + switch (fVerbs[i]) { case kLine_Verb: mask |= kLine_SegmentMask; break; @@ -1915,15 +1877,6 @@ void SkPath::validate() const { break; case kCubic_Verb: mask |= kCubic_SegmentMask; - case kMove_Verb: // these verbs aren't included in the segment mask. - case kClose_Verb: - break; - case kDone_Verb: - SkDEBUGFAIL("Done verb shouldn't be recorded."); - break; - default: - SkDEBUGFAIL("Unknown Verb"); - break; } } SkASSERT(mask == fSegmentMask); @@ -2062,7 +2015,7 @@ SkPath::Convexity SkPath::ComputeConvexity(const SkPath& path) { class ContourIter { public: - ContourIter(const SkPathRef& pathRef); + ContourIter(const SkTDArray& verbs, const SkTDArray& pts); bool done() const { return fDone; } // if !done() then these may be called @@ -2079,18 +2032,20 @@ private: SkDEBUGCODE(int fContourCounter;) }; -ContourIter::ContourIter(const SkPathRef& pathRef) { - fStopVerbs = pathRef.verbsMemBegin(); +ContourIter::ContourIter(const SkTDArray& verbs, + const SkTDArray& pts) { + fStopVerbs = verbs.begin() + verbs.count(); + fDone = false; - fCurrPt = pathRef.points(); - fCurrVerb = pathRef.verbs(); + fCurrPt = pts.begin(); + fCurrVerb = verbs.begin(); fCurrPtCount = 0; SkDEBUGCODE(fContourCounter = 0;) this->next(); } void ContourIter::next() { - if (fCurrVerb <= fStopVerbs) { + if (fCurrVerb >= fStopVerbs) { fDone = true; } if (fDone) { @@ -2100,12 +2055,12 @@ void ContourIter::next() { // skip pts of prev contour fCurrPt += fCurrPtCount; - SkASSERT(SkPath::kMove_Verb == fCurrVerb[~0]); + SkASSERT(SkPath::kMove_Verb == fCurrVerb[0]); int ptCount = 1; // moveTo const uint8_t* verbs = fCurrVerb; - for (--verbs; verbs > fStopVerbs; --verbs) { - switch (verbs[~0]) { + for (++verbs; verbs < fStopVerbs; ++verbs) { + switch (*verbs) { case SkPath::kMove_Verb: goto CONTOUR_END; case SkPath::kLine_Verb: @@ -2282,7 +2237,7 @@ bool SkPath::cheapComputeDirection(Direction* dir) const { // is unknown, so we don't call isConvex() const Convexity conv = this->getConvexityOrUnknown(); - ContourIter iter(*fPathRef.get()); + ContourIter iter(fVerbs, fPts); // initialize with our logical y-min SkScalar ymax = this->getBounds().fTop; diff --git a/src/core/SkPathRef.h b/src/core/SkPathRef.h deleted file mode 100644 index 339166340e..0000000000 --- a/src/core/SkPathRef.h +++ /dev/null @@ -1,531 +0,0 @@ - -/* - * Copyright 2012 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef SkPathRef_DEFINED -#define SkPathRef_DEFINED - -#include "SkRefCnt.h" -#include // ptrdiff_t - -// When we're ready to break the picture format. Changes: -// * Write genID. -// * SkPathRef read/write counts (which will change the field order) -// * SkPathRef reads/writes verbs backwards. -#define NEW_PICTURE_FORMAT 0 - -/** - * 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 multipls SkPaths. The caller passes the Editor's - * constructor a SkAutoTUnref, 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). - */ -class SkPathRef : public ::SkRefCnt { -public: - SK_DECLARE_INST_COUNT(SkPathRef); - - class Editor { - public: - Editor(SkAutoTUnref* pathRef, - int incReserveVerbs = 0, - int incReservePoints = 0) { - if (pathRef->get()->getRefCnt() > 1) { - SkPathRef* copy = SkNEW(SkPathRef); - copy->copy(*pathRef->get(), incReserveVerbs, incReservePoints); - pathRef->reset(copy); - } else { - (*pathRef)->incReserve(incReserveVerbs, incReservePoints); - } - fPathRef = pathRef->get(); - fPathRef->fGenerationID = 0; - SkDEBUGCODE(sk_atomic_inc(&fPathRef->fEditorsAttached);) - } - - ~Editor() { SkDEBUGCODE(sk_atomic_dec(&fPathRef->fEditorsAttached);) } - - /** - * Returns the array of points. - */ - SkPoint* points() { return fPathRef->fPoints; } - - /** - * Gets the ith point. Shortcut for this->points() + i - */ - SkPoint* atPoint(int i) { - SkASSERT((unsigned) i < (unsigned) fPathRef->fPointCnt); - return this->points() + i; - }; - - /** - * Adds the verb and allocates space for the number of points indicated by the verb. The - * return value is a pointer to where the points for the verb should be written. - */ - SkPoint* growForVerb(SkPath::Verb verb) { - fPathRef->validate(); - return fPathRef->growForVerb(verb); - } - - /** - * Allocates space for additional verbs and points and returns pointers to the new verbs and - * points. verbs will point one beyond the first new verb (index it using [~]). pts points - * at the first new point (indexed normally []). - */ - void grow(int newVerbs, int newPts, uint8_t** verbs, SkPoint** pts) { - SkASSERT(NULL != verbs); - SkASSERT(NULL != pts); - fPathRef->validate(); - int oldVerbCnt = fPathRef->fVerbCnt; - int oldPointCnt = fPathRef->fPointCnt; - SkASSERT(verbs && pts); - fPathRef->grow(newVerbs, newPts); - *verbs = fPathRef->fVerbs - oldVerbCnt; - *pts = fPathRef->fPoints + oldPointCnt; - fPathRef->validate(); - } - - /** - * Resets the path ref to a new verb and point count. The new verbs and points are - * uninitialized. - */ - void resetToSize(int newVerbCnt, int newPointCnt) { - fPathRef->resetToSize(newVerbCnt, newPointCnt); - } - /** - * Gets the path ref that is wrapped in the Editor. - */ - SkPathRef* pathRef() { return fPathRef; } - - private: - SkPathRef* fPathRef; - }; - -public: - - /** - * Gets a path ref with no verbs or points. - */ - static SkPathRef* CreateEmpty() { - static SkAutoTUnref gEmptyPathRef(SkNEW(SkPathRef)); - gEmptyPathRef.get()->ref(); - return gEmptyPathRef.get(); - } - - /** - * Transforms a path ref by a matrix, allocating a new one only if necessary. - */ - static void CreateTransformedCopy(SkAutoTUnref* dst, - const SkPathRef& src, - const SkMatrix& matrix) { - src.validate(); - if (matrix.isIdentity()) { - if (dst->get() != &src) { - dst->reset(const_cast(&src)); - (*dst)->validate(); - src.ref(); - } - return; - } - int32_t rcnt = dst->get()->getRefCnt(); - if (&src == dst->get() && 1 == rcnt) { - matrix.mapPoints((*dst)->fPoints, (*dst)->fPointCnt); - return; - } else if (rcnt > 1) { - dst->reset(SkNEW(SkPathRef)); - } - (*dst)->resetToSize(src.fVerbCnt, src.fPointCnt); - memcpy((*dst)->verbsMemWritable(), src.verbsMemBegin(), src.fVerbCnt * sizeof(uint8_t)); - matrix.mapPoints((*dst)->fPoints, src.points(), src.fPointCnt); - (*dst)->validate(); - } - -#if NEW_PICTURE_FORMAT - static SkPathRef* CreateFromBuffer(SkRBuffer* buffer) { - SkPathRef* ref = SkNEW(SkPathRef); - ref->fGenerationID = buffer->readU32(); - int32_t verbCount = buffer->readS32(); - int32_t pointCount = buffer->readS32(); - ref->resetToSize(verbCount, pointCount); - - SkASSERT(verbCount == ref->countVerbs()); - SkASSERT(pointCount == ref->countPoints()); - buffer->read(ref->verbsMemWritable(), verbCount * sizeof(uint8_t)); - buffer->read(ref->fPoints, pointCount * sizeof(SkPoint)); - return ref; - } -#else - static SkPathRef* CreateFromBuffer(int verbCount, int pointCount, SkRBuffer* buffer) { - SkPathRef* ref = SkNEW(SkPathRef); - - ref->resetToSize(verbCount, pointCount); - SkASSERT(verbCount == ref->countVerbs()); - SkASSERT(pointCount == ref->countPoints()); - buffer->read(ref->fPoints, pointCount * sizeof(SkPoint)); - for (int i = 0; i < verbCount; ++i) { - ref->fVerbs[~i] = buffer->readU8(); - } - return ref; - } -#endif - - /** - * 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. - */ - static void Rewind(SkAutoTUnref* pathRef) { - if (1 == (*pathRef)->getRefCnt()) { - (*pathRef)->validate(); - (*pathRef)->fVerbCnt = 0; - (*pathRef)->fPointCnt = 0; - (*pathRef)->fFreeSpace = (*pathRef)->currSize(); - (*pathRef)->fGenerationID = 0; - (*pathRef)->validate(); - } else { - int oldVCnt = (*pathRef)->countVerbs(); - int oldPCnt = (*pathRef)->countPoints(); - pathRef->reset(SkNEW(SkPathRef)); - (*pathRef)->resetToSize(0, 0, oldVCnt, oldPCnt); - } - } - - virtual ~SkPathRef() { - this->validate(); - sk_free(fPoints); - } - - int countPoints() const { this->validate(); return fPointCnt; } - int countVerbs() const { this->validate(); return fVerbCnt; } - - /** - * Returns a pointer one beyond the first logical verb (last verb in memory order). - */ - const uint8_t* verbs() const { this->validate(); return fVerbs; } - - /** - * Returns a const pointer to the first verb in memory (which is the last logical verb). - */ - const uint8_t* verbsMemBegin() const { return this->verbs() - fVerbCnt; } - - /** - * Returns a const pointer to the first point. - */ - const SkPoint* points() const { this->validate(); return fPoints; } - - /** - * Shortcut for this->points() + this->countPoints() - */ - const SkPoint* pointsEnd() const { return this->points() + this->countPoints(); } - - /** - * Convenience methods for getting to a verb or point by index. - */ - uint8_t atVerb(int index) { - SkASSERT((unsigned) index < (unsigned) fVerbCnt); - return this->verbs()[~index]; - } - const SkPoint& atPoint(int index) const { - SkASSERT((unsigned) index < (unsigned) fPointCnt); - return this->points()[index]; - } - - bool operator== (const SkPathRef& ref) const { - this->validate(); - ref.validate(); - bool genIDMatch = fGenerationID && fGenerationID == ref.fGenerationID; -#ifdef SK_RELEASE - if (genIDMatch) { - return true; - } -#endif - if (fPointCnt != ref.fPointCnt || - fVerbCnt != ref.fVerbCnt) { - SkASSERT(!genIDMatch); - return false; - } - if (0 != memcmp(this->verbsMemBegin(), - ref.verbsMemBegin(), - ref.fVerbCnt * sizeof(uint8_t))) { - SkASSERT(!genIDMatch); - return false; - } - if (0 != memcmp(this->points(), - ref.points(), - ref.fPointCnt * sizeof(SkPoint))) { - SkASSERT(!genIDMatch); - return false; - } - // We've done the work to determine that these are equal. If either has a zero genID, copy - // the other's. If both are 0 then genID() will compute the next ID. - if (0 == fGenerationID) { - fGenerationID = ref.genID(); - } else if (0 == ref.fGenerationID) { - ref.fGenerationID = this->genID(); - } - return true; - } - - /** - * Writes the path points and verbs to a buffer. - */ -#if NEW_PICTURE_FORMAT - void writeToBuffer(SkWBuffer* buffer) { - this->validate(); - SkDEBUGCODE(size_t beforePos = buffer->pos();) - - // TODO: write gen ID here. Problem: We don't know if we're cross process or not from - // SkWBuffer. Until this is fixed we write 0. - buffer->write32(0); - buffer->write32(this->fVerbCnt); - buffer->write32(this->fPointCnt); - buffer->write(this->verbsMemBegin(), fVerbCnt * sizeof(uint8_t)); - buffer->write(fPoints, fPointCnt * sizeof(SkPoint)); - - SkASSERT(buffer->pos() - beforePos == (size_t) this->writeSize()); - } - - /** - * Gets the number of bytes that would be written in writeBuffer() - */ - uint32_t writeSize() { - return 3 * sizeof(uint32_t) + fVerbCnt * sizeof(uint8_t) + fPointCnt * sizeof(SkPoint); - } -#else - void writeToBuffer(SkWBuffer* buffer) { - this->validate(); - buffer->write(fPoints, fPointCnt * sizeof(SkPoint)); - for (int i = 0; i < fVerbCnt; ++i) { - buffer->write8(fVerbs[~i]); - } - } -#endif - -private: - SkPathRef() { - fPointCnt = 0; - fVerbCnt = 0; - fVerbs = NULL; - fPoints = NULL; - fFreeSpace = 0; - fGenerationID = kEmptyGenID; - SkDEBUGCODE(fEditorsAttached = 0;) - this->validate(); - } - - void copy(const SkPathRef& ref, int additionalReserveVerbs, int additionalReservePoints) { - this->validate(); - this->resetToSize(ref.fVerbCnt, ref.fPointCnt, - additionalReserveVerbs, additionalReservePoints); - memcpy(this->verbsMemWritable(), ref.verbsMemBegin(), ref.fVerbCnt * sizeof(uint8_t)); - memcpy(this->fPoints, ref.fPoints, ref.fPointCnt * sizeof(SkPoint)); - // We could call genID() here to force a real ID (instead of 0). However, if we're making - // a copy then presumably we intend to make a modification immediately afterwards. - fGenerationID = ref.fGenerationID; - this->validate(); - } - - /** Makes additional room but does not change the counts or change the genID */ - void incReserve(int additionalVerbs, int additionalPoints) { - this->validate(); - size_t space = additionalVerbs * sizeof(uint8_t) + additionalPoints * sizeof (SkPoint); - this->makeSpace(space); - this->validate(); - } - - /** Resets the path ref with verbCount verbs and pointCount points, all unitialized. Also - * allocates space for reserveVerb additional verbs and reservePoints additional points.*/ - void resetToSize(int verbCount, int pointCount, int reserveVerbs = 0, int reservePoints = 0) { - this->validate(); - fGenerationID = 0; - - size_t newSize = sizeof(uint8_t) * verbCount + sizeof(SkPoint) * pointCount; - size_t newReserve = sizeof(uint8_t) * reserveVerbs + sizeof(SkPoint) * reservePoints; - size_t minSize = newSize + newReserve; - - ptrdiff_t sizeDelta = this->currSize() - minSize; - - if (sizeDelta < 0 || static_cast(sizeDelta) >= 3 * minSize) { - sk_free(fPoints); - fPoints = NULL; - fVerbs = NULL; - fFreeSpace = 0; - fVerbCnt = 0; - fPointCnt = 0; - this->makeSpace(minSize); - fVerbCnt = verbCount; - fPointCnt = pointCount; - fFreeSpace -= newSize; - } else { - fPointCnt = pointCount; - fVerbCnt = verbCount; - fFreeSpace = this->currSize() - minSize; - } - this->validate(); - } - - /** - * Increases the verb count by newVerbs and the point count be newPoints. New verbs and points - * are uninitialized. - */ - void grow(int newVerbs, int newPoints) { - this->validate(); - size_t space = newVerbs * sizeof(uint8_t) + newPoints * sizeof (SkPoint); - this->makeSpace(space); - fVerbCnt += newVerbs; - fPointCnt += newPoints; - fFreeSpace -= space; - this->validate(); - } - - /** - * Increases the verb count 1, records the new verb, and creates room for the requisite number - * of additional points. A pointer to the first point is returned. Any new points are - * uninitialized. - */ - SkPoint* growForVerb(SkPath::Verb verb) { - this->validate(); - int pCnt; - switch (verb) { - case SkPath::kMove_Verb: - pCnt = 1; - break; - case SkPath::kLine_Verb: - pCnt = 1; - break; - case SkPath::kQuad_Verb: - pCnt = 2; - break; - case SkPath::kCubic_Verb: - pCnt = 3; - break; - default: - pCnt = 0; - } - size_t space = sizeof(uint8_t) + pCnt * sizeof (SkPoint); - this->makeSpace(space); - this->fVerbs[~fVerbCnt] = verb; - SkPoint* ret = fPoints + fPointCnt; - fVerbCnt += 1; - fPointCnt += pCnt; - fFreeSpace -= space; - this->validate(); - return ret; - } - - /** - * Ensures that the free space available in the path ref is >= size. The verb and point counts - * are not changed. - */ - void makeSpace(size_t size) { - this->validate(); - ptrdiff_t growSize = size - fFreeSpace; - if (growSize <= 0) { - return; - } - size_t oldSize = this->currSize(); - // round to next multiple of 8 bytes - growSize = (growSize + 7) & ~static_cast(7); - // we always at least double the allocation - if (static_cast(growSize) < oldSize) { - growSize = oldSize; - } - if (growSize < kMinSize) { - growSize = kMinSize; - } - size_t newSize = oldSize + growSize; - // Note that realloc could memcpy more than we need. It seems to be a win anyway. TODO: - // encapsulate this. - fPoints = reinterpret_cast(sk_realloc_throw(fPoints, newSize)); - size_t oldVerbSize = fVerbCnt * sizeof(uint8_t); - void* newVerbsDst = reinterpret_cast( - reinterpret_cast(fPoints) + newSize - oldVerbSize); - void* oldVerbsSrc = reinterpret_cast( - reinterpret_cast(fPoints) + oldSize - oldVerbSize); - memmove(newVerbsDst, oldVerbsSrc, oldVerbSize); - fVerbs = reinterpret_cast(reinterpret_cast(fPoints) + newSize); - fFreeSpace += growSize; - this->validate(); - } - - /** - * Private, non-const-ptr version of the public function verbsMemBegin(). - */ - uint8_t* verbsMemWritable() { - this->validate(); - return fVerbs - fVerbCnt; - } - - /** - * Gets the total amount of space allocated for verbs, points, and reserve. - */ - size_t currSize() const { - return reinterpret_cast(fVerbs) - reinterpret_cast(fPoints); - } - - /** - * 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. Zero is reserved and means an ID has not yet been determined - * for the path ref. - */ - int32_t genID() const { - SkDEBUGCODE(SkASSERT(!fEditorsAttached)); - if (!fGenerationID) { - if (0 == fPointCnt && 0 == fVerbCnt) { - fGenerationID = kEmptyGenID; - } else { - static int32_t gPathRefGenerationID; - // do a loop in case our global wraps around, as we never want to return a 0 or the - // empty ID - do { - fGenerationID = sk_atomic_inc(&gPathRefGenerationID) + 1; - } while (fGenerationID <= kEmptyGenID); - } - } - return fGenerationID; - } - - void validate() const { - SkASSERT(static_cast(fFreeSpace) >= 0); - SkASSERT(reinterpret_cast(fVerbs) - reinterpret_cast(fPoints) >= 0); - SkASSERT((NULL == fPoints) == (NULL == fVerbs)); - SkASSERT(!(NULL == fPoints && 0 != fFreeSpace)); - SkASSERT(!(NULL == fPoints && 0 != fFreeSpace)); - SkASSERT(!(NULL == fPoints && fPointCnt)); - SkASSERT(!(NULL == fVerbs && fVerbCnt)); - SkASSERT(this->currSize() == - fFreeSpace + sizeof(SkPoint) * fPointCnt + sizeof(uint8_t) * fVerbCnt); - } - - enum { - kMinSize = 256, - }; - - SkPoint* fPoints; // points to begining of the allocation - uint8_t* fVerbs; // points just past the end of the allocation (verbs grow backwards) - int fVerbCnt; - int fPointCnt; - size_t fFreeSpace; // redundant but saves computation - enum { - kEmptyGenID = 1, // GenID reserved for path ref with zero points and zero verbs. - }; - mutable int32_t fGenerationID; - SkDEBUGCODE(int32_t fEditorsAttached;) // assert that only one editor in use at any time. - - typedef SkRefCnt INHERITED; -}; - -SK_DEFINE_INST_COUNT(SkPathRef); - -#endif -- cgit v1.2.3