Index: src/core/SkPath.cpp |
=================================================================== |
--- src/core/SkPath.cpp (revision 11466) |
+++ src/core/SkPath.cpp (working copy) |
@@ -77,12 +77,12 @@ |
(usually a new contour, but not required). |
It captures some state about the path up front (i.e. if it already has a |
- cached bounds), and the if it can, it updates the cache bounds explicitly, |
+ cached bounds), and then if it can, it updates the cache bounds explicitly, |
avoiding the need to revisit all of the points in getBounds(). |
It also notes if the path was originally degenerate, and if so, sets |
isConvex to true. Thus it can only be used if the contour being added is |
- convex. |
+ convex (which is always true since we only allow the addition of rects). |
*/ |
class SkAutoPathBoundsUpdate { |
public: |
@@ -98,48 +98,33 @@ |
~SkAutoPathBoundsUpdate() { |
fPath->setIsConvex(fDegenerate); |
- if (fEmpty) { |
- fPath->fBounds = fRect; |
- fPath->fBoundsIsDirty = false; |
- fPath->fIsFinite = fPath->fBounds.isFinite(); |
- } else if (!fDirty) { |
- joinNoEmptyChecks(&fPath->fBounds, fRect); |
- fPath->fBoundsIsDirty = false; |
- fPath->fIsFinite = fPath->fBounds.isFinite(); |
+ if (fEmpty || fHasValidBounds) { |
+ fPath->setBounds(fRect); |
} |
} |
private: |
SkPath* fPath; |
SkRect fRect; |
- bool fDirty; |
+ bool fHasValidBounds; |
bool fDegenerate; |
bool fEmpty; |
- // returns true if we should proceed |
void init(SkPath* path) { |
+ // Cannot use fRect for our bounds unless we know it is sorted |
+ fRect.sort(); |
fPath = path; |
// Mark the path's bounds as dirty if (1) they are, or (2) the path |
// is non-finite, and therefore its bounds are not meaningful |
- fDirty = SkToBool(path->fBoundsIsDirty) || !path->fIsFinite; |
- fDegenerate = is_degenerate(*path); |
+ fHasValidBounds = path->hasComputedBounds() && path->isFinite(); |
fEmpty = path->isEmpty(); |
- // Cannot use fRect for our bounds unless we know it is sorted |
- fRect.sort(); |
+ if (fHasValidBounds && !fEmpty) { |
+ joinNoEmptyChecks(&fRect, fPath->getBounds()); |
+ } |
+ fDegenerate = is_degenerate(*path); |
} |
}; |
-// Return true if the computed bounds are finite. |
-static bool compute_pt_bounds(SkRect* bounds, const SkPathRef& ref) { |
- int count = ref.countPoints(); |
- if (count <= 1) { // we ignore just 1 point (moveto) |
- bounds->setEmpty(); |
- return count ? ref.points()->isFinite() : true; |
- } else { |
- return bounds->setBoundsCheck(ref.points(), count); |
- } |
-} |
- |
//////////////////////////////////////////////////////////////////////////// |
/* |
@@ -173,10 +158,8 @@ |
fLastMoveToIndex = INITIAL_LASTMOVETOINDEX_VALUE; |
fFillType = kWinding_FillType; |
fSegmentMask = 0; |
- fBoundsIsDirty = true; |
fConvexity = kUnknown_Convexity; |
fDirection = kUnknown_Direction; |
- fIsFinite = false; |
fIsOval = false; |
#ifdef SK_BUILD_FOR_ANDROID |
GEN_ID_INC; |
@@ -216,14 +199,11 @@ |
void SkPath::copyFields(const SkPath& that) { |
//fPathRef is assumed to have been set by the caller. |
- fBounds = that.fBounds; |
fLastMoveToIndex = that.fLastMoveToIndex; |
fFillType = that.fFillType; |
fSegmentMask = that.fSegmentMask; |
- fBoundsIsDirty = that.fBoundsIsDirty; |
fConvexity = that.fConvexity; |
fDirection = that.fDirection; |
- fIsFinite = that.fIsFinite; |
fIsOval = that.fIsOval; |
} |
@@ -245,14 +225,11 @@ |
if (this != &that) { |
fPathRef.swap(&that.fPathRef); |
- SkTSwap<SkRect>(fBounds, that.fBounds); |
SkTSwap<int>(fLastMoveToIndex, that.fLastMoveToIndex); |
SkTSwap<uint8_t>(fFillType, that.fFillType); |
SkTSwap<uint8_t>(fSegmentMask, that.fSegmentMask); |
- SkTSwap<uint8_t>(fBoundsIsDirty, that.fBoundsIsDirty); |
SkTSwap<uint8_t>(fConvexity, that.fConvexity); |
SkTSwap<uint8_t>(fDirection, that.fDirection); |
- SkTSwap<SkBool8>(fIsFinite, that.fIsFinite); |
SkTSwap<SkBool8>(fIsOval, that.fIsOval); |
#ifdef SK_BUILD_FOR_ANDROID |
// It doesn't really make sense to swap the generation IDs here, because they might go |
@@ -379,11 +356,6 @@ |
this->resetFields(); |
} |
-bool SkPath::isEmpty() const { |
- SkDEBUGCODE(this->validate();) |
- return 0 == fPathRef->countVerbs(); |
-} |
- |
bool SkPath::isLine(SkPoint line[2]) const { |
int verbCount = fPathRef->countVerbs(); |
@@ -665,14 +637,6 @@ |
} |
} |
-void SkPath::computeBounds() const { |
- SkDEBUGCODE(this->validate();) |
- SkASSERT(fBoundsIsDirty); |
- |
- fIsFinite = compute_pt_bounds(&fBounds, *fPathRef.get()); |
- fBoundsIsDirty = false; |
-} |
- |
void SkPath::setConvexity(Convexity c) { |
if (fConvexity != c) { |
fConvexity = c; |
@@ -685,17 +649,11 @@ |
#define DIRTY_AFTER_EDIT \ |
do { \ |
- fBoundsIsDirty = true; \ |
fConvexity = kUnknown_Convexity; \ |
fDirection = kUnknown_Direction; \ |
fIsOval = false; \ |
} while (0) |
-#define DIRTY_AFTER_EDIT_NO_CONVEXITY_OR_DIRECTION_CHANGE \ |
- do { \ |
- fBoundsIsDirty = true; \ |
- } while (0) |
- |
void SkPath::incReserve(U16CPU inc) { |
SkDEBUGCODE(this->validate();) |
SkPathRef::Editor(&fPathRef, inc, inc); |
@@ -713,7 +671,6 @@ |
ed.growForVerb(kMove_Verb)->set(x, y); |
GEN_ID_INC; |
- DIRTY_AFTER_EDIT_NO_CONVEXITY_OR_DIRECTION_CHANGE; |
} |
void SkPath::rMoveTo(SkScalar x, SkScalar y) { |
@@ -1682,35 +1639,6 @@ |
matrix.mapPoints(ed.points(), ed.pathRef()->countPoints()); |
dst->fDirection = kUnknown_Direction; |
} else { |
- /* |
- * If we're not in perspective, we can transform all of the points at |
- * once. |
- * |
- * Here we also want to optimize bounds, by noting if the bounds are |
- * already known, and if so, we just transform those as well and mark |
- * them as "known", rather than force the transformed path to have to |
- * recompute them. |
- * |
- * Special gotchas if the path is effectively empty (<= 1 point) or |
- * if it is non-finite. In those cases bounds need to stay empty, |
- * regardless of the matrix. |
- */ |
- if (!fBoundsIsDirty && matrix.rectStaysRect() && fPathRef->countPoints() > 1) { |
- dst->fBoundsIsDirty = false; |
- if (fIsFinite) { |
- matrix.mapRect(&dst->fBounds, fBounds); |
- if (!(dst->fIsFinite = dst->fBounds.isFinite())) { |
- dst->fBounds.setEmpty(); |
- } |
- } else { |
- dst->fIsFinite = false; |
- dst->fBounds.setEmpty(); |
- } |
- } else { |
- GEN_ID_PTR_INC(dst); |
- dst->fBoundsIsDirty = true; |
- } |
- |
SkPathRef::CreateTransformedCopy(&dst->fPathRef, *fPathRef.get(), matrix); |
if (this != dst) { |
@@ -1720,7 +1648,7 @@ |
} |
#ifdef SK_BUILD_FOR_ANDROID |
- if (!matrix.isIdentity()) { |
+ if (!matrix.isIdentity() && !dst->hasComputedBounds()) { |
GEN_ID_PTR_INC(dst); |
} |
#endif |
@@ -2089,32 +2017,25 @@ |
SkDEBUGCODE(this->validate();) |
if (NULL == storage) { |
- const int byteCount = sizeof(int32_t) |
- + fPathRef->writeSize() |
- + sizeof(SkRect); |
+ const int byteCount = sizeof(int32_t) + fPathRef->writeSize(); |
return SkAlign4(byteCount); |
} |
SkWBuffer buffer(storage); |
- // Call getBounds() to ensure (as a side-effect) that fBounds |
- // and fIsFinite are computed. |
- const SkRect& bounds = this->getBounds(); |
- SkASSERT(!fBoundsIsDirty); |
- |
- int32_t packed = ((fIsFinite & 1) << kIsFinite_SerializationShift) | |
- ((fIsOval & 1) << kIsOval_SerializationShift) | |
+ int32_t packed = ((fIsOval & 1) << kIsOval_SerializationShift) | |
(fConvexity << kConvexity_SerializationShift) | |
(fFillType << kFillType_SerializationShift) | |
(fSegmentMask << kSegmentMask_SerializationShift) | |
- (fDirection << kDirection_SerializationShift); |
+ (fDirection << kDirection_SerializationShift) |
+#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V14_AND_ALL_OTHER_INSTANCES_TOO |
+ | (0x1 << kNewFormat_SerializationShift); |
+#endif |
buffer.write32(packed); |
fPathRef->writeToBuffer(&buffer); |
- buffer.write(&bounds, sizeof(bounds)); |
- |
buffer.padToAlign4(); |
return SkToU32(buffer.pos()); |
} |
@@ -2123,18 +2044,21 @@ |
SkRBuffer buffer(storage); |
uint32_t packed = buffer.readS32(); |
- fIsFinite = (packed >> kIsFinite_SerializationShift) & 1; |
fIsOval = (packed >> kIsOval_SerializationShift) & 1; |
fConvexity = (packed >> kConvexity_SerializationShift) & 0xFF; |
fFillType = (packed >> kFillType_SerializationShift) & 0xFF; |
fSegmentMask = (packed >> kSegmentMask_SerializationShift) & 0xF; |
fDirection = (packed >> kDirection_SerializationShift) & 0x3; |
+#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V14_AND_ALL_OTHER_INSTANCES_TOO |
+ bool newFormat = (packed >> kNewFormat_SerializationShift) & 1; |
+#endif |
- fPathRef.reset(SkPathRef::CreateFromBuffer(&buffer)); |
+ fPathRef.reset(SkPathRef::CreateFromBuffer(&buffer |
+#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V14_AND_ALL_OTHER_INSTANCES_TOO |
+ , newFormat, packed) |
+#endif |
+ ); |
- buffer.read(&fBounds, sizeof(fBounds)); |
- fBoundsIsDirty = false; |
- |
buffer.skipToAlign4(); |
GEN_ID_INC; |