aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrShape.cpp
diff options
context:
space:
mode:
authorGravatar bsalomon <bsalomon@google.com>2016-06-06 14:01:25 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-06-06 14:01:25 -0700
commitee295645bd91fcbe1714847c5fe5341759037cc5 (patch)
treecfa03cc1b5ce3831372218166ffa86a4e1e162f2 /src/gpu/GrShape.cpp
parent982eb7f377a0c771345276558072deb2fcea0d3e (diff)
Make GrShape track the winding direction and starting point for rrect types.
Diffstat (limited to 'src/gpu/GrShape.cpp')
-rw-r--r--src/gpu/GrShape.cpp74
1 files changed, 70 insertions, 4 deletions
diff --git a/src/gpu/GrShape.cpp b/src/gpu/GrShape.cpp
index e0ddc55e02..9fcc6ee911 100644
--- a/src/gpu/GrShape.cpp
+++ b/src/gpu/GrShape.cpp
@@ -22,6 +22,8 @@ GrShape& GrShape::operator=(const GrShape& that) {
fPath.reset();
}
fRRect = that.fRRect;
+ fRRectDir = that.fRRectDir;
+ fRRectStart = that.fRRectStart;
break;
case Type::kPath:
if (wasPath) {
@@ -69,7 +71,8 @@ int GrShape::unstyledKeySize() const {
case Type::kRRect:
SkASSERT(!fInheritedKey.count());
SkASSERT(0 == SkRRect::kSizeInMemory % sizeof(uint32_t));
- return SkRRect::kSizeInMemory / sizeof(uint32_t);
+ // + 1 for the direction + start index.
+ return SkRRect::kSizeInMemory / sizeof(uint32_t) + 1;
case Type::kPath:
if (fPath.get()->isVolatile()) {
return -1;
@@ -95,6 +98,9 @@ void GrShape::writeUnstyledKey(uint32_t* key) const {
case Type::kRRect:
fRRect.writeToMemory(key);
key += SkRRect::kSizeInMemory / sizeof(uint32_t);
+ *key = (fRRectDir == SkPath::kCCW_Direction) ? (1 << 31) : 0;
+ *key++ |= fRRectStart;
+ SkASSERT(fRRectStart < 8);
break;
case Type::kPath:
SkASSERT(!fPath.get()->isVolatile());
@@ -217,15 +223,17 @@ GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply, SkScalar scale) {
// the simpler shape so that applying both path effect and the strokerec all at
// once produces the same key.
SkRRect rrect;
- Type parentType = AttemptToReduceFromPathImpl(*fPath.get(), &rrect, nullptr,
- strokeRec);
+ SkPath::Direction dir;
+ unsigned start;
+ Type parentType = AttemptToReduceFromPathImpl(*fPath.get(), &rrect, &dir, &start,
+ nullptr, strokeRec);
switch (parentType) {
case Type::kEmpty:
tmpParent.init();
parentForKey = tmpParent.get();
break;
case Type::kRRect:
- tmpParent.init(rrect, GrStyle(strokeRec, nullptr));
+ tmpParent.init(rrect, dir, start, GrStyle(strokeRec, nullptr));
parentForKey = tmpParent.get();
case Type::kPath:
break;
@@ -255,3 +263,61 @@ GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply, SkScalar scale) {
this->attemptToReduceFromPath();
this->setInheritedKey(*parentForKey, apply, scale);
}
+
+GrShape::Type GrShape::AttemptToReduceFromPathImpl(const SkPath& path, SkRRect* rrect,
+ SkPath::Direction* rrectDir,
+ unsigned* rrectStart,
+ const SkPathEffect* pe,
+ const SkStrokeRec& strokeRec) {
+ if (path.isEmpty()) {
+ return Type::kEmpty;
+ }
+ if (path.isRRect(rrect, rrectDir, rrectStart)) {
+ // Currently SkPath does not acknowledge that empty, rect, or oval subtypes as rrects.
+ SkASSERT(!rrect->isEmpty());
+ SkASSERT(rrect->getType() != SkRRect::kRect_Type);
+ SkASSERT(rrect->getType() != SkRRect::kOval_Type);
+ if (!pe) {
+ *rrectStart = DefaultRRectDirAndStartIndex(*rrect, false, rrectDir);
+ }
+ return Type::kRRect;
+ }
+ SkRect rect;
+ if (path.isOval(&rect, rrectDir, rrectStart)) {
+ rrect->setOval(rect);
+ if (!pe) {
+ *rrectDir = kDefaultRRectDir;
+ *rrectStart = kDefaultRRectStart;
+ } else {
+ // convert from oval indexing to rrect indexiing.
+ *rrectStart *= 2;
+ }
+ return Type::kRRect;
+ }
+ // When there is a path effect we restrict rect detection to the narrower API that
+ // gives us the starting position. Otherwise, we will retry with the more aggressive isRect().
+ if (SkPathPriv::IsSimpleClosedRect(path, &rect, rrectDir, rrectStart)) {
+ if (!pe) {
+ *rrectDir = kDefaultRRectDir;
+ *rrectStart = kDefaultRRectStart;
+ } else {
+ // convert from rect indexing to rrect indexiing.
+ *rrectStart *= 2;
+ }
+ rrect->setRect(rect);
+ return Type::kRRect;
+ }
+ if (!pe) {
+ bool closed;
+ if (path.isRect(&rect, &closed, nullptr)) {
+ if (closed || strokeRec.isFillStyle()) {
+ rrect->setRect(rect);
+ // Since there is no path effect the dir and start index is immaterial.
+ *rrectDir = kDefaultRRectDir;
+ *rrectStart = kDefaultRRectStart;
+ return Type::kRRect;
+ }
+ }
+ }
+ return Type::kPath;
+}