diff options
author | bsalomon <bsalomon@google.com> | 2016-06-06 14:01:25 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-06-06 14:01:25 -0700 |
commit | ee295645bd91fcbe1714847c5fe5341759037cc5 (patch) | |
tree | cfa03cc1b5ce3831372218166ffa86a4e1e162f2 /src/gpu/GrShape.cpp | |
parent | 982eb7f377a0c771345276558072deb2fcea0d3e (diff) |
Make GrShape track the winding direction and starting point for rrect types.
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2042813002
Review-Url: https://codereview.chromium.org/2042813002
Diffstat (limited to 'src/gpu/GrShape.cpp')
-rw-r--r-- | src/gpu/GrShape.cpp | 74 |
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; +} |