Index: src/gpu/GrShape.cpp |
diff --git a/src/gpu/GrShape.cpp b/src/gpu/GrShape.cpp |
index b40d696b824efb027df65d3c7944fc5dbed3097c..45ddb777789214c95714a2e75cd7fc20d329b519 100644 |
--- a/src/gpu/GrShape.cpp |
+++ b/src/gpu/GrShape.cpp |
@@ -8,31 +8,19 @@ |
#include "GrShape.h" |
GrShape& GrShape::operator=(const GrShape& that) { |
- bool wasPath = Type::kPath == fType; |
fStyle = that.fStyle; |
- fType = that.fType; |
+ this->changeType(that.fType, Type::kPath == that.fType ? &that.path() : nullptr); |
switch (fType) { |
case Type::kEmpty: |
- if (wasPath) { |
- fPath.reset(); |
- } |
break; |
case Type::kRRect: |
- if (wasPath) { |
- fPath.reset(); |
- } |
- fRRect = that.fRRect; |
- fRRectDir = that.fRRectDir; |
- fRRectStart = that.fRRectStart; |
- fRRectIsInverted = that.fRRectIsInverted; |
+ fRRectData.fRRect = that.fRRectData.fRRect; |
+ fRRectData.fDir = that.fRRectData.fDir; |
+ fRRectData.fStart = that.fRRectData.fStart; |
+ fRRectData.fInverted = that.fRRectData.fInverted; |
break; |
case Type::kPath: |
- if (wasPath) { |
- *fPath.get() = *that.fPath.get(); |
- } else { |
- fPath.set(*that.fPath.get()); |
- } |
- fPathGenID = that.fPathGenID; |
+ fPathData.fGenID = that.fPathData.fGenID; |
break; |
} |
fInheritedKey.reset(that.fInheritedKey.count()); |
@@ -47,9 +35,9 @@ const SkRect& GrShape::bounds() const { |
case Type::kEmpty: |
return kEmpty; |
case Type::kRRect: |
- return fRRect.getBounds(); |
+ return fRRectData.fRRect.getBounds(); |
case Type::kPath: |
- return fPath.get()->getBounds(); |
+ return this->path().getBounds(); |
} |
SkFAIL("Unknown shape type"); |
return kEmpty; |
@@ -76,7 +64,7 @@ int GrShape::unstyledKeySize() const { |
// + 1 for the direction, start index, and inverseness. |
return SkRRect::kSizeInMemory / sizeof(uint32_t) + 1; |
case Type::kPath: |
- if (0 == fPathGenID) { |
+ if (0 == fPathData.fGenID) { |
return -1; |
} else { |
// The key is the path ID and fill type. |
@@ -99,19 +87,19 @@ void GrShape::writeUnstyledKey(uint32_t* key) const { |
*key++ = 1; |
break; |
case Type::kRRect: |
- fRRect.writeToMemory(key); |
+ fRRectData.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); |
+ *key = (fRRectData.fDir == SkPath::kCCW_Direction) ? (1 << 31) : 0; |
+ *key |= fRRectData.fInverted ? (1 << 30) : 0; |
+ *key++ |= fRRectData.fStart; |
+ SkASSERT(fRRectData.fStart < 8); |
break; |
case Type::kPath: |
- SkASSERT(fPathGenID); |
- *key++ = fPathGenID; |
+ SkASSERT(fPathData.fGenID); |
+ *key++ = fPathData.fGenID; |
// 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(); |
+ *key++ = this->path().getFillType(); |
break; |
} |
} |
@@ -134,7 +122,7 @@ void GrShape::setInheritedKey(const GrShape &parent, GrStyle::Apply apply, SkSca |
parentCnt = parent.unstyledKeySize(); |
if (parentCnt < 0) { |
// The parent's geometry has no key so we will have no key. |
- fPathGenID = 0; |
+ fPathData.fGenID = 0; |
return; |
} |
} |
@@ -146,7 +134,7 @@ void GrShape::setInheritedKey(const GrShape &parent, GrStyle::Apply apply, SkSca |
if (styleCnt < 0) { |
// The style doesn't allow a key, set the path gen ID to 0 so that we fail when |
// we try to get a key for the shape. |
- fPathGenID = 0; |
+ fPathData.fGenID = 0; |
return; |
} |
fInheritedKey.reset(parentCnt + styleCnt); |
@@ -164,19 +152,20 @@ void GrShape::setInheritedKey(const GrShape &parent, GrStyle::Apply apply, SkSca |
} |
} |
-GrShape::GrShape(const GrShape& that) : fType(that.fType), fStyle(that.fStyle) { |
+GrShape::GrShape(const GrShape& that) : fStyle(that.fStyle) { |
+ const SkPath* thatPath = Type::kPath == that.fType ? &that.fPathData.fPath : nullptr; |
+ this->initType(that.fType, thatPath); |
switch (fType) { |
case Type::kEmpty: |
break; |
case Type::kRRect: |
- fRRect = that.fRRect; |
- fRRectDir = that.fRRectDir; |
- fRRectStart = that.fRRectStart; |
- fRRectIsInverted = that.fRRectIsInverted; |
+ fRRectData.fRRect = that.fRRectData.fRRect; |
+ fRRectData.fDir = that.fRRectData.fDir; |
+ fRRectData.fStart = that.fRRectData.fStart; |
+ fRRectData.fInverted = that.fRRectData.fInverted; |
break; |
case Type::kPath: |
- fPath.set(*that.fPath.get()); |
- fPathGenID = that.fPathGenID; |
+ fPathData.fGenID = that.fPathData.fGenID; |
break; |
} |
fInheritedKey.reset(that.fInheritedKey.count()); |
@@ -191,7 +180,7 @@ GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply, SkScalar scale) { |
// stroke of a rect). |
if (!parent.style().applies() || |
(GrStyle::Apply::kPathEffectOnly == apply && !parent.style().pathEffect())) { |
- fType = Type::kEmpty; |
+ this->initType(Type::kEmpty); |
*this = parent; |
return; |
} |
@@ -200,12 +189,12 @@ GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply, SkScalar scale) { |
SkTLazy<SkPath> tmpPath; |
const GrShape* parentForKey = &parent; |
SkTLazy<GrShape> tmpParent; |
- fType = Type::kPath; |
- fPath.init(); |
+ this->initType(Type::kPath); |
+ fPathData.fGenID = 0; |
if (pe) { |
- SkPath* srcForPathEffect; |
+ const SkPath* srcForPathEffect; |
if (parent.fType == Type::kPath) { |
- srcForPathEffect = parent.fPath.get(); |
+ srcForPathEffect = &parent.path(); |
} else { |
srcForPathEffect = tmpPath.init(); |
parent.asPath(tmpPath.get()); |
@@ -213,18 +202,19 @@ GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply, SkScalar scale) { |
// Should we consider bounds? Would have to include in key, but it'd be nice to know |
// if the bounds actually modified anything before including in key. |
SkStrokeRec strokeRec = parent.fStyle.strokeRec(); |
- if (!parent.fStyle.applyPathEffectToPath(fPath.get(), &strokeRec, *srcForPathEffect, |
+ if (!parent.fStyle.applyPathEffectToPath(&this->path(), &strokeRec, *srcForPathEffect, |
scale)) { |
// If the path effect fails then we continue as though there was no path effect. |
// If the original was a rrect that we couldn't canonicalize because of the path |
// effect, then do so now. |
- if (parent.fType == Type::kRRect && (parent.fRRectDir != kDefaultRRectDir || |
- parent.fRRectStart != kDefaultRRectStart)) { |
+ if (parent.fType == Type::kRRect && (parent.fRRectData.fDir != kDefaultRRectDir || |
+ parent.fRRectData.fStart != kDefaultRRectStart)) { |
SkASSERT(srcForPathEffect == tmpPath.get()); |
tmpPath.get()->reset(); |
- tmpPath.get()->addRRect(parent.fRRect, kDefaultRRectDir, kDefaultRRectDir); |
+ tmpPath.get()->addRRect(parent.fRRectData.fRRect, kDefaultRRectDir, |
+ kDefaultRRectDir); |
} |
- *fPath.get() = *srcForPathEffect; |
+ this->path() = *srcForPathEffect; |
} |
// A path effect has access to change the res scale but we aren't expecting it to and it |
// would mess up our key computation. |
@@ -237,14 +227,14 @@ GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply, SkScalar scale) { |
// We detect that case here and change parentForKey to a temporary that represents |
// the simpler shape so that applying both path effect and the strokerec all at |
// once produces the same key. |
- tmpParent.init(*fPath.get(), GrStyle(strokeRec, nullptr)); |
+ tmpParent.init(this->path(), GrStyle(strokeRec, nullptr)); |
tmpParent.get()->setInheritedKey(parent, GrStyle::Apply::kPathEffectOnly, scale); |
if (!tmpPath.isValid()) { |
tmpPath.init(); |
} |
tmpParent.get()->asPath(tmpPath.get()); |
SkStrokeRec::InitStyle fillOrHairline; |
- SkAssertResult(tmpParent.get()->style().applyToPath(fPath.get(), &fillOrHairline, |
+ SkAssertResult(tmpParent.get()->style().applyToPath(&this->path(), &fillOrHairline, |
*tmpPath.get(), scale)); |
fStyle.resetToInitStyle(fillOrHairline); |
parentForKey = tmpParent.get(); |
@@ -254,7 +244,7 @@ GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply, SkScalar scale) { |
} else { |
const SkPath* srcForParentStyle; |
if (parent.fType == Type::kPath) { |
- srcForParentStyle = parent.fPath.get(); |
+ srcForParentStyle = &parent.path(); |
} else { |
srcForParentStyle = tmpPath.init(); |
parent.asPath(tmpPath.get()); |
@@ -262,7 +252,7 @@ GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply, SkScalar scale) { |
SkStrokeRec::InitStyle fillOrHairline; |
SkASSERT(parent.fStyle.applies()); |
SkASSERT(!parent.fStyle.pathEffect()); |
- SkAssertResult(parent.fStyle.applyToPath(fPath.get(), &fillOrHairline, *srcForParentStyle, |
+ SkAssertResult(parent.fStyle.applyToPath(&this->path(), &fillOrHairline, *srcForParentStyle, |
scale)); |
fStyle.resetToInitStyle(fillOrHairline); |
} |
@@ -271,65 +261,72 @@ GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply, SkScalar scale) { |
} |
void GrShape::attemptToSimplifyPath() { |
- SkASSERT(Type::kPath == fType); |
SkRect rect; |
- if (fPath.get()->isEmpty()) { |
- fType = Type::kEmpty; |
- } else if (fPath.get()->isRRect(&fRRect, &fRRectDir, &fRRectStart)) { |
+ SkRRect rrect; |
+ SkPath::Direction rrectDir; |
+ unsigned rrectStart; |
+ bool inverted = this->path().isInverseFillType(); |
+ if (this->path().isEmpty()) { |
+ this->changeType(Type::kEmpty); |
+ } else if (this->path().isRRect(&rrect, &rrectDir, &rrectStart)) { |
+ this->changeType(Type::kRRect); |
+ fRRectData.fRRect = rrect; |
+ fRRectData.fDir = rrectDir; |
+ fRRectData.fStart = rrectStart; |
+ fRRectData.fInverted = inverted; |
// Currently SkPath does not acknowledge that empty, rect, or oval subtypes as rrects. |
- SkASSERT(!fRRect.isEmpty()); |
- SkASSERT(fRRect.getType() != SkRRect::kRect_Type); |
- SkASSERT(fRRect.getType() != SkRRect::kOval_Type); |
- fRRectIsInverted = fPath.get()->isInverseFillType(); |
- fType = Type::kRRect; |
- } else if (fPath.get()->isOval(&rect, &fRRectDir, &fRRectStart)) { |
- fRRect.setOval(rect); |
- fRRectIsInverted = fPath.get()->isInverseFillType(); |
+ SkASSERT(!fRRectData.fRRect.isEmpty()); |
+ SkASSERT(fRRectData.fRRect.getType() != SkRRect::kRect_Type); |
+ SkASSERT(fRRectData.fRRect.getType() != SkRRect::kOval_Type); |
+ } else if (this->path().isOval(&rect, &rrectDir, &rrectStart)) { |
+ this->changeType(Type::kRRect); |
+ fRRectData.fRRect.setOval(rect); |
+ fRRectData.fDir = rrectDir; |
+ fRRectData.fInverted = inverted; |
// convert from oval indexing to rrect indexiing. |
- fRRectStart *= 2; |
- fType = Type::kRRect; |
- } else if (SkPathPriv::IsSimpleClosedRect(*fPath.get(), &rect, &fRRectDir, &fRRectStart)) { |
+ fRRectData.fStart = 2 * rrectStart; |
+ } else if (SkPathPriv::IsSimpleClosedRect(this->path(), &rect, &rrectDir, &rrectStart)) { |
+ this->changeType(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(). |
- fRRect.setRect(rect); |
- fRRectIsInverted = fPath.get()->isInverseFillType(); |
+ fRRectData.fRRect.setRect(rect); |
+ fRRectData.fInverted = inverted; |
+ fRRectData.fDir = rrectDir; |
// convert from rect indexing to rrect indexiing. |
- fRRectStart *= 2; |
- fType = Type::kRRect; |
+ fRRectData.fStart = 2 * rrectStart; |
} else if (!this->style().hasPathEffect()) { |
bool closed; |
- if (fPath.get()->isRect(&rect, &closed, nullptr)) { |
+ if (this->path().isRect(&rect, &closed, nullptr)) { |
if (closed || this->style().isSimpleFill()) { |
- fRRect.setRect(rect); |
+ this->changeType(Type::kRRect); |
+ fRRectData.fRRect.setRect(rect); |
// Since there is no path effect the dir and start index is immaterial. |
- fRRectDir = kDefaultRRectDir; |
- fRRectStart = kDefaultRRectStart; |
+ fRRectData.fDir = kDefaultRRectDir; |
+ fRRectData.fStart = kDefaultRRectStart; |
// There isn't dashing so we will have to preserver inverseness. |
- fRRectIsInverted = fPath.get()->isInverseFillType(); |
- fType = Type::kRRect; |
+ fRRectData.fInverted = inverted; |
} |
} |
} |
if (Type::kPath != fType) { |
- fPath.reset(); |
fInheritedKey.reset(0); |
if (Type::kRRect == fType) { |
this->attemptToSimplifyRRect(); |
} |
} else { |
- if (fInheritedKey.count() || fPath.get()->isVolatile()) { |
- fPathGenID = 0; |
+ if (fInheritedKey.count() || this->path().isVolatile()) { |
+ fPathData.fGenID = 0; |
} else { |
- fPathGenID = fPath.get()->getGenerationID(); |
+ fPathData.fGenID = this->path().getGenerationID(); |
} |
if (this->style().isSimpleFill()) { |
// Filled paths are treated as though all their contours were closed. |
// Since SkPath doesn't track individual contours, this will only close the last. :( |
// There is no point in closing lines, though, since they loose their line-ness. |
- if (!fPath.get()->isLine(nullptr)) { |
- fPath.get()->close(); |
- fPath.get()->setIsVolatile(true); |
+ if (!this->path().isLine(nullptr)) { |
+ this->path().close(); |
+ this->path().setIsVolatile(true); |
} |
} |
if (!this->style().hasNonDashPathEffect()) { |
@@ -337,19 +334,19 @@ void GrShape::attemptToSimplifyPath() { |
this->style().strokeRec().getStyle() == SkStrokeRec::kHairline_Style) { |
// Stroke styles don't differentiate between winding and even/odd. |
// Moreover, dashing ignores inverseness (skbug.com/5421) |
- bool inverse = !this->style().isDashed() && fPath.get()->isInverseFillType(); |
+ bool inverse = !this->style().isDashed() && this->path().isInverseFillType(); |
if (inverse) { |
- fPath.get()->setFillType(kDefaultPathInverseFillType); |
+ this->path().setFillType(kDefaultPathInverseFillType); |
} else { |
- fPath.get()->setFillType(kDefaultPathFillType); |
+ this->path().setFillType(kDefaultPathFillType); |
} |
- } else if (fPath.get()->isConvex()) { |
+ } else if (this->path().isConvex()) { |
// There is no distinction between even/odd and non-zero winding count for convex |
// paths. |
- if (fPath.get()->isInverseFillType()) { |
- fPath.get()->setFillType(kDefaultPathInverseFillType); |
+ if (this->path().isInverseFillType()) { |
+ this->path().setFillType(kDefaultPathInverseFillType); |
} else { |
- fPath.get()->setFillType(kDefaultPathFillType); |
+ this->path().setFillType(kDefaultPathFillType); |
} |
} |
} |
@@ -359,15 +356,15 @@ void GrShape::attemptToSimplifyPath() { |
void GrShape::attemptToSimplifyRRect() { |
SkASSERT(Type::kRRect == fType); |
SkASSERT(!fInheritedKey.count()); |
- if (fRRect.isEmpty()) { |
+ if (fRRectData.fRRect.isEmpty()) { |
fType = Type::kEmpty; |
return; |
} |
if (!this->style().hasPathEffect()) { |
- fRRectDir = kDefaultRRectDir; |
- fRRectStart = kDefaultRRectStart; |
+ fRRectData.fDir = kDefaultRRectDir; |
+ fRRectData.fStart = kDefaultRRectStart; |
} else if (fStyle.isDashed()) { |
// Dashing ignores the inverseness (currently). skbug.com/5421 |
- fRRectIsInverted = false; |
+ fRRectData.fInverted = false; |
} |
} |