Index: include/core/SkPathRef.h |
=================================================================== |
--- include/core/SkPathRef.h (revision 11888) |
+++ include/core/SkPathRef.h (working copy) |
@@ -23,7 +23,7 @@ |
* 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 |
+ * copy-on-write if the SkPathRef is shared by multiple 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. |
* |
@@ -71,21 +71,12 @@ |
SkPoint* growForConic(SkScalar w); |
/** |
- * 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 [~<i>]). pts points |
- * at the first new point (indexed normally [<i>]). |
+ * Allocates space for additional lines and returns a pointer to the new |
+ * points. The return pointer points at the first new point (indexed normally [<i>]). |
*/ |
- void grow(int newVerbs, int newPts, uint8_t** verbs, SkPoint** pts) { |
- SkASSERT(NULL != verbs); |
- SkASSERT(NULL != pts); |
+ SkPoint* growForLines(int numLines) { |
SkDEBUGCODE(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; |
- SkDEBUGCODE(fPathRef->validate();) |
+ return fPathRef->growForLines(numLines); |
} |
/** |
@@ -95,11 +86,23 @@ |
void resetToSize(int newVerbCnt, int newPointCnt, int newConicCount) { |
fPathRef->resetToSize(newVerbCnt, newPointCnt, newConicCount); |
} |
+ |
/** |
* Gets the path ref that is wrapped in the Editor. |
*/ |
SkPathRef* pathRef() { return fPathRef; } |
+ void setDirection(int /* SkPath::Direction */ dir) { fPathRef->setDirection(dir); } |
+ |
+ void setIsOval(bool isOval) { fPathRef->setIsOval(isOval); } |
+ |
+ void setConvexity(int /*SkPath::Convexity*/ convexity) { |
+ fPathRef->setConvexity(convexity); |
+ } |
+ |
+ // 'rect' needs to be sorted |
+ void setBounds(const SkRect& rect) { fPathRef->setBounds(rect); } |
+ |
private: |
SkPathRef* fPathRef; |
}; |
@@ -117,7 +120,51 @@ |
return SkRef(gEmptyPathRef); |
} |
+ uint8_t /*SkPath::Direction*/ getDirection() const { return fDirection; } |
+ |
/** |
+ * Tries to quickly compute the direction of the first non-degenerate |
+ * contour. If it can be computed, return true and set dir to that |
+ * direction. If it cannot be (quickly) determined, return false and ignore |
+ * the dir parameter. If the direction was determined, it is cached to make |
+ * subsequent calls return quickly. |
+ */ |
+ bool cheapComputeDirection(int* dir) const; |
+ |
+ /** |
+ * Return the path's convexity, as stored in the path. If it is currently unknown, |
+ * then this function will attempt to compute the convexity (and cache the result). |
+ */ |
+ int /*SkPath::Convexity*/ getConvexity() const; |
+ |
+ /** |
+ * Return the currently cached value for convexity, even if that is set to |
+ * kUnknown_Convexity. Note: getConvexity() will automatically call |
+ * ComputeConvexity and cache its return value if the current setting is |
+ * kUnknown. |
+ */ |
+ int /*SkPath::Convexity*/ getConvexityOrUnknown() const { |
+ return fConvexity; |
+ } |
+ |
+ /** Returns true if the path is an oval. |
+ * |
+ * @param rect returns the bounding rect of this oval. It's a circle |
+ * if the height and width are the same. |
+ * |
+ * @return 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. |
+ */ |
+ bool isOval(SkRect* rect) const { |
+ if (fIsOval && NULL != rect) { |
+ *rect = this->getBounds(); |
+ } |
+ return SkToBool(fIsOval); |
+ } |
+ |
+ /** |
* Returns true if all of the points in this path are finite, meaning there |
* are no infinities and no NaNs. |
*/ |
@@ -128,6 +175,13 @@ |
return SkToBool(fIsFinite); |
} |
+ /** |
+ * 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). |
+ */ |
+ uint32_t getSegmentMasks() const { return fSegmentMask; } |
+ |
bool hasComputedBounds() const { |
return !fBoundsIsDirty; |
} |
@@ -144,13 +198,6 @@ |
return fBounds; |
} |
- void setBounds(const SkRect& rect) { |
- SkASSERT(rect.fLeft <= rect.fRight && rect.fTop <= rect.fBottom); |
- fBounds = rect; |
- fBoundsIsDirty = false; |
- fIsFinite = fBounds.isFinite(); |
- } |
- |
/** |
* Transforms a path ref by a matrix, allocating a new one only if necessary. |
*/ |
@@ -213,7 +260,7 @@ |
/** |
* Convenience methods for getting to a verb or point by index. |
*/ |
- uint8_t atVerb(int index) { |
+ uint8_t atVerb(int index) const { |
SkASSERT((unsigned) index < (unsigned) fVerbCnt); |
return this->verbs()[~index]; |
} |
@@ -227,40 +274,58 @@ |
/** |
* Writes the path points and verbs to a buffer. |
*/ |
- void writeToBuffer(SkWBuffer* buffer); |
+ void writeToBuffer(SkWBuffer* buffer) const; |
/** |
* Gets the number of bytes that would be written in writeBuffer() |
*/ |
- uint32_t writeSize(); |
+ uint32_t writeSize() const; |
private: |
enum SerializationOffsets { |
+ kDirection_SerializationShift = 26, // requires 2 bits |
kIsFinite_SerializationShift = 25, // requires 1 bit |
+ kIsOval_SerializationShift = 24, // requires 1 bit |
+ kConvexity_SerializationShift = 16, // requires 8 bits |
+ // FillType (in SkPath) takes up 8 |
+ kSegmentMask_SerializationShift = 0 // requires 4 bits |
}; |
- SkPathRef() { |
- fBoundsIsDirty = true; // this also invalidates fIsFinite |
- fPointCnt = 0; |
- fVerbCnt = 0; |
- fVerbs = NULL; |
- fPoints = NULL; |
- fFreeSpace = 0; |
- fGenerationID = kEmptyGenID; |
- SkDEBUGCODE(fEditorsAttached = 0;) |
- SkDEBUGCODE(this->validate();) |
+ // flag to require a moveTo if we begin with something else, like lineTo etc. |
+ static const int kINITIAL_LASTMOVETOINDEX_VALUE = ~0; |
+ |
+ SkPathRef(); |
+ |
+ /** |
+ * Store a convexity setting in the path. There is no automatic check to |
+ * see if this value actually agrees with the return value that would be |
+ * computed by getConvexity(). |
+ * |
+ * Note: even if this is set to a "known" value, if the path is later |
+ * changed (e.g. lineTo(), addRect(), etc.) then the cached value will be |
+ * reset to kUnknown_Convexity. |
+ */ |
+ void setConvexity(int /*SkPath::Convexity*/ convexity) { |
+ fConvexity = convexity; |
} |
+ // 'rect' needs to be sorted |
+ void setBounds(const SkRect& rect) { |
+ SkASSERT(rect.fLeft <= rect.fRight && rect.fTop <= rect.fBottom); |
+ fBounds = rect; |
+ fBoundsIsDirty = false; |
+ fIsFinite = fBounds.isFinite(); |
+ } |
+ |
void copy(const SkPathRef& ref, int additionalReserveVerbs, int additionalReservePoints); |
// Return true if the computed bounds are finite. |
- static bool ComputePtBounds(SkRect* bounds, const SkPathRef& ref) { |
- int count = ref.countPoints(); |
+ static bool ComputePtBounds(SkRect* bounds, const SkPoint* points, int count) { |
if (count <= 1) { // we ignore just 1 point (moveto) |
bounds->setEmpty(); |
- return count ? ref.points()->isFinite() : true; |
+ return count ? points->isFinite() : true; |
} else { |
- return bounds->setBoundsCheck(ref.points(), count); |
+ return bounds->setBoundsCheck(points, count); |
} |
} |
@@ -269,7 +334,7 @@ |
SkDEBUGCODE(this->validate();) |
SkASSERT(fBoundsIsDirty); |
- fIsFinite = ComputePtBounds(&fBounds, *this); |
+ fIsFinite = ComputePtBounds(&fBounds, this->points(), this->countPoints()); |
fBoundsIsDirty = false; |
} |
@@ -284,58 +349,24 @@ |
/** Resets the path ref with verbCount verbs and pointCount points, all uninitialized. Also |
* allocates space for reserveVerb additional verbs and reservePoints additional points.*/ |
void resetToSize(int verbCount, int pointCount, int conicCount, |
- int reserveVerbs = 0, int reservePoints = 0) { |
- SkDEBUGCODE(this->validate();) |
- fBoundsIsDirty = true; // this also invalidates fIsFinite |
- fGenerationID = 0; |
+ int reserveVerbs = 0, int reservePoints = 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; |
+ // This method assumes space has already been allocated for the new |
+ // verb and point. |
+ void injectMove(); |
- ptrdiff_t sizeDelta = this->currSize() - minSize; |
- |
- if (sizeDelta < 0 || static_cast<size_t>(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; |
- } |
- fConicWeights.setCount(conicCount); |
- SkDEBUGCODE(this->validate();) |
- } |
- |
/** |
- * Increases the verb count by newVerbs and the point count be newPoints. New verbs and points |
- * are uninitialized. |
+ * Increases the verb and point count by numLines. The new points |
+ * are uninitialized. All the new verbs are set to kLine_SegmentMask. |
*/ |
- void grow(int newVerbs, int newPoints) { |
- SkDEBUGCODE(this->validate();) |
- size_t space = newVerbs * sizeof(uint8_t) + newPoints * sizeof (SkPoint); |
- this->makeSpace(space); |
- fVerbCnt += newVerbs; |
- fPointCnt += newPoints; |
- fFreeSpace -= space; |
- fBoundsIsDirty = true; // this also invalidates fIsFinite |
- SkDEBUGCODE(this->validate();) |
- } |
+ SkPoint* growForLines(int numLines); |
/** |
* 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(int /*SkPath::Verb*/ verb); |
+ SkPoint* growForVerb(int /* SkPath::Verb */ verb); |
/** |
* Ensures that the free space available in the path ref is >= size. The verb and point counts |
@@ -397,13 +428,24 @@ |
SkDEBUGCODE(void validate() const;) |
+ int internalGetConvexity() const; |
+ |
+ void setIsOval(bool isOval) { fIsOval = isOval; } |
+ void setDirection(int direction) { fDirection = direction; } |
+ |
enum { |
kMinSize = 256, |
}; |
mutable SkRect fBounds; |
+ int fLastMoveToIndex; |
+ |
+ uint8_t fSegmentMask; |
mutable uint8_t fBoundsIsDirty; |
+ mutable uint8_t fConvexity; |
+ mutable uint8_t fDirection; |
mutable SkBool8 fIsFinite; // only meaningful if bounds are valid |
+ mutable SkBool8 fIsOval; |
SkPoint* fPoints; // points to begining of the allocation |
uint8_t* fVerbs; // points just past the end of the allocation (verbs grow backwards) |