aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/core
diff options
context:
space:
mode:
authorGravatar caryclark <caryclark@google.com>2015-11-19 14:47:43 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-11-19 14:47:44 -0800
commitda707bf5635c70d4c3c284a0b05d92489b76788e (patch)
tree837638f90905b75992ef030664b62e49952dbdf3 /include/core
parentedb36445dbedff473a06a00de0813dc2e6e6845c (diff)
add SkPath::isRRect
Add helper to track when a round rect was added to a path, and then return the SkRRect specification that describes it. Move the implementation for SkPath::RawIter to SkPathRef so it can be used there as well. R=reed@google.com,robertphillips@google.com Review URL: https://codereview.chromium.org/1461763004
Diffstat (limited to 'include/core')
-rw-r--r--include/core/SkPath.h36
-rw-r--r--include/core/SkPathRef.h65
2 files changed, 86 insertions, 15 deletions
diff --git a/include/core/SkPath.h b/include/core/SkPath.h
index 3ff0af15a2..3c68ff7d84 100644
--- a/include/core/SkPath.h
+++ b/include/core/SkPath.h
@@ -154,6 +154,17 @@ public:
*/
bool isOval(SkRect* rect) const { return fPathRef->isOval(rect); }
+ /** Returns true if the path is a round rect.
+ *
+ * @param rrect Returns the bounding rect and radii of this round rect.
+ *
+ * @return true if this path is a round rect.
+ * Tracking whether a path is a round rect is considered an
+ * optimization for performance and so some paths that are in
+ * fact round rects can report false.
+ */
+ bool isRRect(SkRRect* rrect) const { return fPathRef->isRRect(rrect); }
+
/** Clear any lines and curves from the path, making it empty. This frees up
internal storage associated with those segments.
On Android, does not change fSourcePath.
@@ -918,10 +929,14 @@ public:
*/
class SK_API RawIter {
public:
- RawIter();
- RawIter(const SkPath&);
+ RawIter() {}
+ RawIter(const SkPath& path) {
+ setPath(path);
+ }
- void setPath(const SkPath&);
+ void setPath(const SkPath& path) {
+ fRawIter.setPathRef(*path.fPathRef.get());
+ }
/** Return the next verb in this iteration of the path. When all
segments have been visited, return kDone_Verb.
@@ -930,15 +945,17 @@ public:
This must not be NULL.
@return The verb for the current segment
*/
- Verb next(SkPoint pts[4]);
+ Verb next(SkPoint pts[4]) {
+ return (Verb) fRawIter.next(pts);
+ }
- SkScalar conicWeight() const { return *fConicWeights; }
+ SkScalar conicWeight() const {
+ return fRawIter.conicWeight();
+ }
private:
- const SkPoint* fPts;
- const uint8_t* fVerbs;
- const uint8_t* fVerbStop;
- const SkScalar* fConicWeights;
+ SkPathRef::Iter fRawIter;
+ friend class SkPath;
};
/**
@@ -1066,6 +1083,7 @@ private:
friend class SkAutoDisableDirectionCheck;
friend class SkBench_AddPathTest; // perf test reversePathTo
friend class PathTest_Private; // unit test reversePathTo
+ friend class ForceIsRRect_Private; // unit test isRRect
};
#endif
diff --git a/include/core/SkPathRef.h b/include/core/SkPathRef.h
index c09f6e87e4..86f55c9bca 100644
--- a/include/core/SkPathRef.h
+++ b/include/core/SkPathRef.h
@@ -11,6 +11,7 @@
#include "SkMatrix.h"
#include "SkPoint.h"
+#include "SkRRect.h"
#include "SkRect.h"
#include "SkRefCnt.h"
#include "SkTDArray.h"
@@ -100,12 +101,39 @@ public:
void setIsOval(bool isOval) { fPathRef->setIsOval(isOval); }
+ void setIsRRect(bool isRRect) { fPathRef->setIsRRect(isRRect); }
+
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]);
+
+ 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.
@@ -142,12 +170,20 @@ public:
*/
bool isOval(SkRect* rect) const {
if (fIsOval && rect) {
- *rect = getBounds();
+ *rect = this->getBounds();
}
return SkToBool(fIsOval);
}
+ bool isRRect(SkRRect* rrect) const {
+ if (fIsRRect && rrect) {
+ *rrect = this->getRRect();
+ }
+ return SkToBool(fIsRRect);
+ }
+
+
bool hasComputedBounds() const {
return !fBoundsIsDirty;
}
@@ -164,6 +200,8 @@ public:
return fBounds;
}
+ SkRRect getRRect() const;
+
/**
* Transforms a path ref by a matrix, allocating a new one only if necessary.
*/
@@ -250,6 +288,7 @@ public:
private:
enum SerializationOffsets {
+ kIsRRect_SerializationShift = 26, // requires 1 bit
kIsFinite_SerializationShift = 25, // requires 1 bit
kIsOval_SerializationShift = 24, // requires 1 bit
kSegmentMask_SerializationShift = 0 // requires 4 bits
@@ -265,6 +304,7 @@ private:
fGenerationID = kEmptyGenID;
fSegmentMask = 0;
fIsOval = false;
+ fIsRRect = false;
SkDEBUGCODE(fEditorsAttached = 0;)
SkDEBUGCODE(this->validate();)
}
@@ -312,6 +352,7 @@ private:
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;
@@ -411,9 +452,18 @@ private:
void setIsOval(bool isOval) { fIsOval = isOval; }
+ void setIsRRect(bool isRRect) { fIsRRect = isRRect; }
+
+ // 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;
}
@@ -424,11 +474,6 @@ private:
};
mutable SkRect fBounds;
- mutable uint8_t fBoundsIsDirty;
- mutable SkBool8 fIsFinite; // only meaningful if bounds are valid
-
- SkBool8 fIsOval;
- uint8_t fSegmentMask;
SkPoint* fPoints; // points to begining of the allocation
uint8_t* fVerbs; // points just past the end of the allocation (verbs grow backwards)
@@ -445,7 +490,15 @@ private:
SkTDArray<GenIDChangeListener*> fGenIDChangeListeners; // pointers are owned
+ mutable uint8_t fBoundsIsDirty;
+ mutable SkBool8 fIsFinite; // only meaningful if bounds are valid
+
+ SkBool8 fIsOval;
+ SkBool8 fIsRRect;
+ uint8_t fSegmentMask;
+
friend class PathRefTest_Private;
+ friend class ForceIsRRect_Private; // unit test isRRect
typedef SkRefCnt INHERITED;
};