aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrShape.cpp
diff options
context:
space:
mode:
authorGravatar bsalomon <bsalomon@google.com>2016-06-10 08:05:14 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-06-10 08:05:14 -0700
commit7049396b65660907af5292d899053280430d929a (patch)
tree3a15e986397427c28acd312650035f9e32179728 /src/gpu/GrShape.cpp
parent013e0e6d482f61181b829bf5ebfcad912c0061b1 (diff)
Make GrShape capable of representing inverse filled rrects.
Diffstat (limited to 'src/gpu/GrShape.cpp')
-rw-r--r--src/gpu/GrShape.cpp38
1 files changed, 34 insertions, 4 deletions
diff --git a/src/gpu/GrShape.cpp b/src/gpu/GrShape.cpp
index 7605cbf1ff..d2bec72cbf 100644
--- a/src/gpu/GrShape.cpp
+++ b/src/gpu/GrShape.cpp
@@ -24,6 +24,7 @@ GrShape& GrShape::operator=(const GrShape& that) {
fRRect = that.fRRect;
fRRectDir = that.fRRectDir;
fRRectStart = that.fRRectStart;
+ fRRectIsInverted = that.fRRectIsInverted;
break;
case Type::kPath:
if (wasPath) {
@@ -71,13 +72,14 @@ int GrShape::unstyledKeySize() const {
case Type::kRRect:
SkASSERT(!fInheritedKey.count());
SkASSERT(0 == SkRRect::kSizeInMemory % sizeof(uint32_t));
- // + 1 for the direction + start index.
+ // + 1 for the direction, start index, and inverseness.
return SkRRect::kSizeInMemory / sizeof(uint32_t) + 1;
case Type::kPath:
if (fPath.get()->isVolatile()) {
return -1;
} else {
- return 1;
+ // The key is the path ID and fill type.
+ return 2;
}
}
SkFAIL("Should never get here.");
@@ -99,12 +101,16 @@ void GrShape::writeUnstyledKey(uint32_t* key) const {
fRRect.writeToMemory(key);
key += SkRRect::kSizeInMemory / sizeof(uint32_t);
*key = (fRRectDir == SkPath::kCCW_Direction) ? (1 << 31) : 0;
+ *key |= fRRectIsInverted ? (1 << 30) : 0;
*key++ |= fRRectStart;
SkASSERT(fRRectStart < 8);
break;
case Type::kPath:
SkASSERT(!fPath.get()->isVolatile());
*key++ = fPath.get()->getGenerationID();
+ // We could canonicalize the fill rule for paths that don't differentiate between
+ // even/odd or winding fill (e.g. convex).
+ *key++ = fPath.get()->getFillType();
break;
}
}
@@ -163,6 +169,9 @@ GrShape::GrShape(const GrShape& that) : fType(that.fType), fStyle(that.fStyle) {
return;
case Type::kRRect:
fRRect = that.fRRect;
+ fRRectDir = that.fRRectDir;
+ fRRectStart = that.fRRectStart;
+ fRRectIsInverted = that.fRRectIsInverted;
return;
case Type::kPath:
fPath.set(*that.fPath.get());
@@ -230,15 +239,16 @@ GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply, SkScalar scale) {
SkRRect rrect;
SkPath::Direction dir;
unsigned start;
+ bool inverted;
Type parentType = AttemptToReduceFromPathImpl(*fPath.get(), &rrect, &dir, &start,
- nullptr, strokeRec);
+ &inverted, nullptr, strokeRec);
switch (parentType) {
case Type::kEmpty:
tmpParent.init();
parentForKey = tmpParent.get();
break;
case Type::kRRect:
- tmpParent.init(rrect, dir, start, GrStyle(strokeRec, nullptr));
+ tmpParent.init(rrect, dir, start, inverted, GrStyle(strokeRec, nullptr));
parentForKey = tmpParent.get();
case Type::kPath:
break;
@@ -269,9 +279,25 @@ GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply, SkScalar scale) {
this->setInheritedKey(*parentForKey, apply, scale);
}
+static inline bool rrect_path_is_inverse_filled(const SkPath& path, const SkStrokeRec& strokeRec,
+ const SkPathEffect* pe) {
+ // Dashing doesn't use the path fill type. Dashing only works with stroking
+ if (pe && pe->asADash(nullptr)) {
+ pe = nullptr;
+ }
+
+ SkStrokeRec::Style style = strokeRec.getStyle();
+ if (!pe && (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style)) {
+ // stroking ignores the path fill rule.
+ return false;
+ }
+ return path.isInverseFillType();
+}
+
GrShape::Type GrShape::AttemptToReduceFromPathImpl(const SkPath& path, SkRRect* rrect,
SkPath::Direction* rrectDir,
unsigned* rrectStart,
+ bool* rrectIsInverted,
const SkPathEffect* pe,
const SkStrokeRec& strokeRec) {
if (path.isEmpty()) {
@@ -285,6 +311,7 @@ GrShape::Type GrShape::AttemptToReduceFromPathImpl(const SkPath& path, SkRRect*
if (!pe) {
*rrectStart = DefaultRRectDirAndStartIndex(*rrect, false, rrectDir);
}
+ *rrectIsInverted = rrect_path_is_inverse_filled(path, strokeRec, pe);
return Type::kRRect;
}
SkRect rect;
@@ -297,6 +324,7 @@ GrShape::Type GrShape::AttemptToReduceFromPathImpl(const SkPath& path, SkRRect*
// convert from oval indexing to rrect indexiing.
*rrectStart *= 2;
}
+ *rrectIsInverted = rrect_path_is_inverse_filled(path, strokeRec, pe);
return Type::kRRect;
}
// When there is a path effect we restrict rect detection to the narrower API that
@@ -310,6 +338,7 @@ GrShape::Type GrShape::AttemptToReduceFromPathImpl(const SkPath& path, SkRRect*
*rrectStart *= 2;
}
rrect->setRect(rect);
+ *rrectIsInverted = rrect_path_is_inverse_filled(path, strokeRec, pe);
return Type::kRRect;
}
if (!pe) {
@@ -320,6 +349,7 @@ GrShape::Type GrShape::AttemptToReduceFromPathImpl(const SkPath& path, SkRRect*
// Since there is no path effect the dir and start index is immaterial.
*rrectDir = kDefaultRRectDir;
*rrectStart = kDefaultRRectStart;
+ *rrectIsInverted = rrect_path_is_inverse_filled(path, strokeRec, pe);
return Type::kRRect;
}
}