aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar bsalomon <bsalomon@google.com>2016-06-20 12:28:17 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-06-20 12:28:17 -0700
commit1b28c1adc1e156831d5332546e942b63fd29075b (patch)
tree35371fb05ace084a934a607c8518ce344079a8d7 /src
parentd7ec12e41cce090ec0b2e68e995ea511d33c9967 (diff)
Some simplifications of GrShape reductions/canonicalizations
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrShape.cpp175
-rw-r--r--src/gpu/GrShape.h49
2 files changed, 88 insertions, 136 deletions
diff --git a/src/gpu/GrShape.cpp b/src/gpu/GrShape.cpp
index 7be7e7ad04..395089cf49 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;
}
diff --git a/src/gpu/GrShape.h b/src/gpu/GrShape.h
index 6da1a41acb..6086537a99 100644
--- a/src/gpu/GrShape.h
+++ b/src/gpu/GrShape.h
@@ -39,7 +39,7 @@ public:
explicit GrShape(const SkPath& path)
: fType(Type::kPath)
, fPath(&path) {
- this->attemptToReduceFromPath();
+ this->attemptToSimplifyPath();
}
explicit GrShape(const SkRRect& rrect)
@@ -47,7 +47,7 @@ public:
, fRRect(rrect)
, fRRectIsInverted(false) {
fRRectStart = DefaultRRectDirAndStartIndex(rrect, false, &fRRectDir);
- this->attemptToReduceFromRRect();
+ this->attemptToSimplifyRRect();
}
explicit GrShape(const SkRect& rect)
@@ -55,14 +55,14 @@ public:
, fRRect(SkRRect::MakeRect(rect))
, fRRectIsInverted(false) {
fRRectStart = DefaultRectDirAndStartIndex(rect, false, &fRRectDir);
- this->attemptToReduceFromRRect();
+ this->attemptToSimplifyRRect();
}
GrShape(const SkPath& path, const GrStyle& style)
: fType(Type::kPath)
, fPath(&path)
, fStyle(style) {
- this->attemptToReduceFromPath();
+ this->attemptToSimplifyPath();
}
GrShape(const SkRRect& rrect, const GrStyle& style)
@@ -71,7 +71,7 @@ public:
, fRRectIsInverted(false)
, fStyle(style) {
fRRectStart = DefaultRRectDirAndStartIndex(rrect, style.hasPathEffect(), &fRRectDir);
- this->attemptToReduceFromRRect();
+ this->attemptToSimplifyRRect();
}
GrShape(const SkRRect& rrect, SkPath::Direction dir, unsigned start, bool inverted,
@@ -91,7 +91,7 @@ public:
} else {
fRRectStart = DefaultRRectDirAndStartIndex(rrect, false, &fRRectDir);
}
- this->attemptToReduceFromRRect();
+ this->attemptToSimplifyRRect();
}
GrShape(const SkRect& rect, const GrStyle& style)
@@ -100,14 +100,14 @@ public:
, fRRectIsInverted(false)
, fStyle(style) {
fRRectStart = DefaultRectDirAndStartIndex(rect, style.hasPathEffect(), &fRRectDir);
- this->attemptToReduceFromRRect();
+ this->attemptToSimplifyRRect();
}
GrShape(const SkPath& path, const SkPaint& paint)
: fType(Type::kPath)
, fPath(&path)
, fStyle(paint) {
- this->attemptToReduceFromPath();
+ this->attemptToSimplifyPath();
}
GrShape(const SkRRect& rrect, const SkPaint& paint)
@@ -116,7 +116,7 @@ public:
, fRRectIsInverted(false)
, fStyle(paint) {
fRRectStart = DefaultRRectDirAndStartIndex(rrect, fStyle.hasPathEffect(), &fRRectDir);
- this->attemptToReduceFromRRect();
+ this->attemptToSimplifyRRect();
}
GrShape(const SkRect& rect, const SkPaint& paint)
@@ -125,7 +125,7 @@ public:
, fRRectIsInverted(false)
, fStyle(paint) {
fRRectStart = DefaultRectDirAndStartIndex(rect, fStyle.hasPathEffect(), &fRRectDir);
- this->attemptToReduceFromRRect();
+ this->attemptToSimplifyRRect();
}
GrShape(const GrShape&);
@@ -278,34 +278,9 @@ private:
*/
void setInheritedKey(const GrShape& parentShape, GrStyle::Apply, SkScalar scale);
- void attemptToReduceFromPath() {
- SkASSERT(Type::kPath == fType);
- fType = AttemptToReduceFromPathImpl(*fPath.get(), &fRRect, &fRRectDir, &fRRectStart,
- &fRRectIsInverted, fStyle.pathEffect(),
- fStyle.strokeRec());
- if (Type::kPath != fType) {
- fPath.reset();
- fInheritedKey.reset(0);
- }
- }
-
- void attemptToReduceFromRRect() {
- SkASSERT(Type::kRRect == fType);
- SkASSERT(!fInheritedKey.count());
- if (fRRectIsInverted) {
- if (fStyle.isDashed()) {
- // Dashing ignores the inverseness (currently). skbug.com/5421
- fRRectIsInverted = false;
- }
- } else if (fRRect.isEmpty()) {
- fType = Type::kEmpty;
- }
- }
+ void attemptToSimplifyPath();
- static Type AttemptToReduceFromPathImpl(const SkPath& path, SkRRect* rrect,
- SkPath::Direction* rrectDir, unsigned* rrectStart,
- bool* rrectIsInverted, const SkPathEffect* pe,
- const SkStrokeRec& strokeRec);
+ void attemptToSimplifyRRect();
static constexpr SkPath::Direction kDefaultRRectDir = SkPath::kCW_Direction;
static constexpr unsigned kDefaultRRectStart = 0;