diff options
author | 2017-06-07 10:57:22 -0400 | |
---|---|---|
committer | 2017-06-07 15:24:46 +0000 | |
commit | 89c8fecb62e664749211668dff2148bbc27090cc (patch) | |
tree | e829c083d4482705c99ed639a36bfdb4179ab84d /include/core | |
parent | fd7819c5d8779e7394277abb49e0a0b2b03d1045 (diff) |
move SkPathRef.h into private
Bug: skia:
Change-Id: I3370c594301ae833ec1fe3cb16ac544e5b2128e8
Reviewed-on: https://skia-review.googlesource.com/18982
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Diffstat (limited to 'include/core')
-rw-r--r-- | include/core/SkPath.h | 2 | ||||
-rw-r--r-- | include/core/SkPathRef.h | 548 |
2 files changed, 1 insertions, 549 deletions
diff --git a/include/core/SkPath.h b/include/core/SkPath.h index 60aa44ff86..b8c921f3ee 100644 --- a/include/core/SkPath.h +++ b/include/core/SkPath.h @@ -9,7 +9,7 @@ #define SkPath_DEFINED #include "SkMatrix.h" -#include "SkPathRef.h" +#include "../private/SkPathRef.h" class SkAutoPathBoundsUpdate; class SkRRect; diff --git a/include/core/SkPathRef.h b/include/core/SkPathRef.h deleted file mode 100644 index 5e6fda7d85..0000000000 --- a/include/core/SkPathRef.h +++ /dev/null @@ -1,548 +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 "../private/SkAtomics.h" -#include "../private/SkTDArray.h" -#include "SkMatrix.h" -#include "SkPoint.h" -#include "SkRRect.h" -#include "SkRect.h" -#include "SkRefCnt.h" -#include <stddef.h> // ptrdiff_t - -class SkRBuffer; -class SkWBuffer; - -/** - * 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). - */ - -class SK_API SkPathRef final : public SkNVRefCnt<SkPathRef> { -public: - class Editor { - public: - Editor(sk_sp<SkPathRef>* pathRef, - int incReserveVerbs = 0, - int incReservePoints = 0); - - ~Editor() { SkDEBUGCODE(sk_atomic_dec(&fPathRef->fEditorsAttached);) } - - /** - * Returns the array of points. - */ - SkPoint* points() { return fPathRef->getPoints(); } - const SkPoint* points() const { return fPathRef->points(); } - - /** - * Gets the ith point. Shortcut for this->points() + i - */ - SkPoint* atPoint(int i) { - SkASSERT((unsigned) i < (unsigned) fPathRef->fPointCnt); - return this->points() + i; - } - const SkPoint* atPoint(int i) const { - 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. - * 'weight' is only used if 'verb' is kConic_Verb - */ - SkPoint* growForVerb(int /*SkPath::Verb*/ verb, SkScalar weight = 0) { - SkDEBUGCODE(fPathRef->validate();) - return fPathRef->growForVerb(verb, weight); - } - - /** - * Allocates space for multiple instances of a particular verb and the - * requisite points & weights. - * The return pointer points at the first new point (indexed normally [<i>]). - * If 'verb' is kConic_Verb, 'weights' will return a pointer to the - * space for the conic weights (indexed normally). - */ - SkPoint* growForRepeatedVerb(int /*SkPath::Verb*/ verb, - int numVbs, - SkScalar** weights = NULL) { - return fPathRef->growForRepeatedVerb(verb, numVbs, weights); - } - - /** - * Resets the path ref to a new verb and point count. The new verbs and points are - * uninitialized. - */ - 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 setIsOval(bool isOval, bool isCCW, unsigned start) { - fPathRef->setIsOval(isOval, isCCW, start); - } - - void setIsRRect(bool isRRect, bool isCCW, unsigned start) { - fPathRef->setIsRRect(isRRect, isCCW, start); - } - - void setBounds(const SkRect& rect) { fPathRef->setBounds(rect); } - - private: - SkPathRef* fPathRef; - }; - - class SK_API Iter { - public: - Iter(); - Iter(const SkPathRef&); - - void setPathRef(const SkPathRef&); - - /** Return the next verb in this iteration of the path. When all - segments have been visited, return kDone_Verb. - - @param pts The points representing the current verb and/or segment - This must not be NULL. - @return The verb for the current segment - */ - uint8_t next(SkPoint pts[4]); - uint8_t peek() const; - - SkScalar conicWeight() const { return *fConicWeights; } - - private: - const SkPoint* fPts; - const uint8_t* fVerbs; - const uint8_t* fVerbStop; - const SkScalar* fConicWeights; - }; - -public: - /** - * Gets a path ref with no verbs or points. - */ - static SkPathRef* CreateEmpty(); - - /** - * Returns true if all of the points in this path are finite, meaning there - * are no infinities and no NaNs. - */ - bool isFinite() const { - if (fBoundsIsDirty) { - this->computeBounds(); - } - 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; } - - /** 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. - * @param isCCW is the oval CCW (or CW if false). - * @param start indicates where the contour starts on the oval (see - * SkPath::addOval for intepretation of the index). - * - * @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, bool* isCCW, unsigned* start) const { - if (fIsOval) { - if (rect) { - *rect = this->getBounds(); - } - if (isCCW) { - *isCCW = SkToBool(fRRectOrOvalIsCCW); - } - if (start) { - *start = fRRectOrOvalStartIdx; - } - } - - return SkToBool(fIsOval); - } - - bool isRRect(SkRRect* rrect, bool* isCCW, unsigned* start) const { - if (fIsRRect) { - if (rrect) { - *rrect = this->getRRect(); - } - if (isCCW) { - *isCCW = SkToBool(fRRectOrOvalIsCCW); - } - if (start) { - *start = fRRectOrOvalStartIdx; - } - } - return SkToBool(fIsRRect); - } - - - bool hasComputedBounds() const { - return !fBoundsIsDirty; - } - - /** 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. - */ - const SkRect& getBounds() const { - if (fBoundsIsDirty) { - this->computeBounds(); - } - return fBounds; - } - - SkRRect getRRect() const; - - /** - * Transforms a path ref by a matrix, allocating a new one only if necessary. - */ - static void CreateTransformedCopy(sk_sp<SkPathRef>* dst, - const SkPathRef& src, - const SkMatrix& matrix); - - static SkPathRef* CreateFromBuffer(SkRBuffer* buffer); - - /** - * 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(sk_sp<SkPathRef>* pathRef); - - ~SkPathRef(); - int countPoints() const { SkDEBUGCODE(this->validate();) return fPointCnt; } - int countVerbs() const { SkDEBUGCODE(this->validate();) return fVerbCnt; } - int countWeights() const { SkDEBUGCODE(this->validate();) return fConicWeights.count(); } - - /** - * Returns a pointer one beyond the first logical verb (last verb in memory order). - */ - const uint8_t* verbs() const { SkDEBUGCODE(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 { SkDEBUGCODE(this->validate();) return fPoints; } - - /** - * Shortcut for this->points() + this->countPoints() - */ - const SkPoint* pointsEnd() const { return this->points() + this->countPoints(); } - - const SkScalar* conicWeights() const { SkDEBUGCODE(this->validate();) return fConicWeights.begin(); } - const SkScalar* conicWeightsEnd() const { SkDEBUGCODE(this->validate();) return fConicWeights.end(); } - - /** - * Convenience methods for getting to a verb or point by index. - */ - uint8_t atVerb(int index) const { - 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; - - /** - * Writes the path points and verbs to a buffer. - */ - void writeToBuffer(SkWBuffer* buffer) const; - - /** - * Gets the number of bytes that would be written in writeBuffer() - */ - uint32_t writeSize() const; - - void interpolate(const SkPathRef& ending, SkScalar weight, SkPathRef* out) 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. - */ - uint32_t genID() const; - - struct GenIDChangeListener { - virtual ~GenIDChangeListener() {} - virtual void onChange() = 0; - }; - - void addGenIDChangeListener(GenIDChangeListener* listener); - - SkDEBUGCODE(void validate() const;) - -private: - enum SerializationOffsets { - kRRectOrOvalStartIdx_SerializationShift = 28, // requires 3 bits - kRRectOrOvalIsCCW_SerializationShift = 27, // requires 1 bit - kIsRRect_SerializationShift = 26, // requires 1 bit - kIsFinite_SerializationShift = 25, // requires 1 bit - kIsOval_SerializationShift = 24, // requires 1 bit - 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; - fSegmentMask = 0; - fIsOval = false; - fIsRRect = false; - // The next two values don't matter unless fIsOval or fIsRRect are true. - fRRectOrOvalIsCCW = false; - fRRectOrOvalStartIdx = 0xAC; - SkDEBUGCODE(fEditorsAttached = 0;) - SkDEBUGCODE(this->validate();) - } - - 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) { - return bounds->setBoundsCheck(ref.points(), ref.countPoints()); - } - - // called, if dirty, by getBounds() - void computeBounds() const { - SkDEBUGCODE(this->validate();) - // TODO(mtklein): remove fBoundsIsDirty and fIsFinite, - // using an inverted rect instead of fBoundsIsDirty and always recalculating fIsFinite. - SkASSERT(fBoundsIsDirty); - - fIsFinite = ComputePtBounds(&fBounds, *this); - fBoundsIsDirty = false; - } - - void setBounds(const SkRect& rect) { - SkASSERT(rect.fLeft <= rect.fRight && rect.fTop <= rect.fBottom); - fBounds = rect; - fBoundsIsDirty = false; - fIsFinite = fBounds.isFinite(); - } - - /** Makes additional room but does not change the counts or change the genID */ - void incReserve(int additionalVerbs, int additionalPoints) { - SkDEBUGCODE(this->validate();) - size_t space = additionalVerbs * sizeof(uint8_t) + additionalPoints * sizeof (SkPoint); - this->makeSpace(space); - SkDEBUGCODE(this->validate();) - } - - /** 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; - - fSegmentMask = 0; - fIsOval = false; - fIsRRect = false; - - 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<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 numVbs and point count by the required amount. - * The new points are uninitialized. All the new verbs are set to the specified - * verb. If 'verb' is kConic_Verb, 'weights' will return a pointer to the - * uninitialized conic weights. - */ - SkPoint* growForRepeatedVerb(int /*SkPath::Verb*/ verb, int numVbs, SkScalar** weights); - - /** - * 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, SkScalar weight); - - /** - * 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) { - SkDEBUGCODE(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<size_t>(7); - // we always at least double the allocation - if (static_cast<size_t>(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<SkPoint*>(sk_realloc_throw(fPoints, newSize)); - size_t oldVerbSize = fVerbCnt * sizeof(uint8_t); - void* newVerbsDst = reinterpret_cast<void*>( - reinterpret_cast<intptr_t>(fPoints) + newSize - oldVerbSize); - void* oldVerbsSrc = reinterpret_cast<void*>( - reinterpret_cast<intptr_t>(fPoints) + oldSize - oldVerbSize); - memmove(newVerbsDst, oldVerbsSrc, oldVerbSize); - fVerbs = reinterpret_cast<uint8_t*>(reinterpret_cast<intptr_t>(fPoints) + newSize); - fFreeSpace += growSize; - SkDEBUGCODE(this->validate();) - } - - /** - * Private, non-const-ptr version of the public function verbsMemBegin(). - */ - uint8_t* verbsMemWritable() { - SkDEBUGCODE(this->validate();) - return fVerbs - fVerbCnt; - } - - /** - * Gets the total amount of space allocated for verbs, points, and reserve. - */ - size_t currSize() const { - return reinterpret_cast<intptr_t>(fVerbs) - reinterpret_cast<intptr_t>(fPoints); - } - - /** - * Called the first time someone calls CreateEmpty to actually create the singleton. - */ - friend SkPathRef* sk_create_empty_pathref(); - - void setIsOval(bool isOval, bool isCCW, unsigned start) { - fIsOval = isOval; - fRRectOrOvalIsCCW = isCCW; - fRRectOrOvalStartIdx = start; - } - - void setIsRRect(bool isRRect, bool isCCW, unsigned start) { - fIsRRect = isRRect; - fRRectOrOvalIsCCW = isCCW; - fRRectOrOvalStartIdx = start; - } - - // called only by the editor. Note that this is not a const function. - SkPoint* getPoints() { - SkDEBUGCODE(this->validate();) - fIsOval = false; - fIsRRect = false; - return fPoints; - } - - const SkPoint* getPoints() const { - SkDEBUGCODE(this->validate();) - return fPoints; - } - - void callGenIDChangeListeners(); - - enum { - kMinSize = 256, - }; - - mutable SkRect fBounds; - - 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 - SkTDArray<SkScalar> fConicWeights; - - enum { - kEmptyGenID = 1, // GenID reserved for path ref with zero points and zero verbs. - }; - mutable uint32_t fGenerationID; - SkDEBUGCODE(int32_t fEditorsAttached;) // assert that only one editor in use at any time. - - SkTDArray<GenIDChangeListener*> fGenIDChangeListeners; // pointers are owned - - mutable uint8_t fBoundsIsDirty; - mutable SkBool8 fIsFinite; // only meaningful if bounds are valid - - SkBool8 fIsOval; - SkBool8 fIsRRect; - // Both the circle and rrect special cases have a notion of direction and starting point - // The next two variables store that information for either. - SkBool8 fRRectOrOvalIsCCW; - uint8_t fRRectOrOvalStartIdx; - uint8_t fSegmentMask; - - friend class PathRefTest_Private; - friend class ForceIsRRect_Private; // unit test isRRect -}; - -#endif |