Index: src/gpu/GrShape.cpp |
diff --git a/src/gpu/GrShape.cpp b/src/gpu/GrShape.cpp |
index 7be7e7ad041931a04316b5aeaa2a0d77986a4f4d..395089cf49bc8412aa63b6f9cbf3438c20092a65 100644 |
--- a/src/gpu/GrShape.cpp |
+++ b/src/gpu/GrShape.cpp |
@@ -227,36 +227,25 @@ GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply, SkScalar scale) { |
// 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. |
SkASSERT(scale == strokeRec.getResScale()); |
- if (GrStyle::Apply::kPathEffectAndStrokeRec == apply) { |
- if (strokeRec.needToApply()) { |
- // The intermediate shape may not be a general path. If we we're just applying |
- // the path effect then attemptToReduceFromPath would catch it. This means that |
- // when we subsequently applied the remaining strokeRec we would have a non-path |
- // parent shape that would be used to determine the the stroked path's key. |
- // 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. |
- SkRRect rrect; |
- SkPath::Direction dir; |
- unsigned start; |
- bool inverted; |
- Type parentType = AttemptToReduceFromPathImpl(*fPath.get(), &rrect, &dir, &start, |
- &inverted, nullptr, strokeRec); |
- switch (parentType) { |
- case Type::kEmpty: |
- tmpParent.init(); |
- parentForKey = tmpParent.get(); |
- break; |
- case Type::kRRect: |
- tmpParent.init(rrect, dir, start, inverted, GrStyle(strokeRec, nullptr)); |
- parentForKey = tmpParent.get(); |
- case Type::kPath: |
- break; |
- } |
- SkAssertResult(strokeRec.applyToPath(fPath.get(), *fPath.get())); |
- } else { |
- fStyle = GrStyle(strokeRec, nullptr); |
+ if (GrStyle::Apply::kPathEffectAndStrokeRec == apply && strokeRec.needToApply()) { |
+ // The intermediate shape may not be a general path. If we we're just applying |
+ // the path effect then attemptToReduceFromPath would catch it. This means that |
+ // when we subsequently applied the remaining strokeRec we would have a non-path |
+ // parent shape that would be used to determine the the stroked path's key. |
+ // 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.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, |
+ *tmpPath.get(), scale)); |
+ fStyle.resetToInitStyle(fillOrHairline); |
+ parentForKey = tmpParent.get(); |
} else { |
fStyle = GrStyle(strokeRec, nullptr); |
} |
@@ -275,84 +264,72 @@ GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply, SkScalar scale) { |
scale)); |
fStyle.resetToInitStyle(fillOrHairline); |
} |
- this->attemptToReduceFromPath(); |
+ this->attemptToSimplifyPath(); |
this->setInheritedKey(*parentForKey, apply, scale); |
} |
-static inline bool rrect_path_is_inverse_filled(const SkPath& path, const SkStrokeRec& strokeRec, |
- const SkPathEffect* pe) { |
- // This is currently imitating the questionable behavior of the sw-rasterizer. Inverseness is |
- // respected for stroking but not dashing + stroking. (We make no assumptions about arbitrary |
- // path effects and preserve the path's inverseness.) |
- // skbug.com/5421 |
- if (pe && pe->asADash(nullptr)) { |
- SkDEBUGCODE(SkStrokeRec::Style style = strokeRec.getStyle();) |
- SkASSERT(SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style); |
- 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()) { |
- return Type::kEmpty; |
- } |
- if (path.isRRect(rrect, rrectDir, rrectStart)) { |
+void GrShape::attemptToSimplifyPath() { |
+ SkASSERT(Type::kPath == fType); |
+ SkRect rect; |
+ if (fPath.get()->isEmpty()) { |
+ fType = Type::kEmpty; |
+ } else if (fPath.get()->isRRect(&fRRect, &fRRectDir, &fRRectStart)) { |
// 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); |
+ 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(); |
+ // convert from oval indexing to rrect indexiing. |
+ fRRectStart *= 2; |
+ fType = Type::kRRect; |
+ } else if (SkPathPriv::IsSimpleClosedRect(*fPath.get(), &rect, &fRRectDir, &fRRectStart)) { |
+ // 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(); |
+ // convert from rect indexing to rrect indexiing. |
+ fRRectStart *= 2; |
+ fType = Type::kRRect; |
+ } else if (!this->style().hasPathEffect()) { |
+ bool closed; |
+ if (fPath.get()->isRect(&rect, &closed, nullptr)) { |
+ if (closed || this->style().isSimpleFill()) { |
+ fRRect.setRect(rect); |
+ // Since there is no path effect the dir and start index is immaterial. |
+ fRRectDir = kDefaultRRectDir; |
+ fRRectStart = kDefaultRRectStart; |
+ // There isn't dashing so we will have to preserver inverseness. |
+ fRRectIsInverted = fPath.get()->isInverseFillType(); |
+ fType = Type::kRRect; |
+ } |
} |
- *rrectIsInverted = rrect_path_is_inverse_filled(path, strokeRec, pe); |
- 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; |
+ if (Type::kPath != fType) { |
+ fPath.reset(); |
+ fInheritedKey.reset(0); |
+ if (Type::kRRect == fType) { |
+ this->attemptToSimplifyRRect(); |
} |
- *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 |
- // 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); |
- *rrectIsInverted = rrect_path_is_inverse_filled(path, strokeRec, pe); |
- return Type::kRRect; |
+} |
+ |
+void GrShape::attemptToSimplifyRRect() { |
+ SkASSERT(Type::kRRect == fType); |
+ SkASSERT(!fInheritedKey.count()); |
+ if (fRRect.isEmpty()) { |
+ fType = Type::kEmpty; |
+ return; |
} |
- 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; |
- *rrectIsInverted = rrect_path_is_inverse_filled(path, strokeRec, pe); |
- return Type::kRRect; |
- } |
- } |
+ if (!this->style().hasPathEffect()) { |
+ fRRectDir = kDefaultRRectDir; |
+ fRRectStart = kDefaultRRectStart; |
+ } else if (fStyle.isDashed()) { |
+ // Dashing ignores the inverseness (currently). skbug.com/5421 |
+ fRRectIsInverted = false; |
} |
- return Type::kPath; |
} |