Chromium Code Reviews| Index: src/gpu/GrShape.cpp |
| diff --git a/src/gpu/GrShape.cpp b/src/gpu/GrShape.cpp |
| index e0ddc55e028e2a1b1ce24be5bd831dc9ea4d0620..0ab438c75c815cf797c3bb7642f9d9b7e3c835c7 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,8 @@ 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; |
|
egdaniel
2016/06/06 18:34:36
So obviously fRRectStart will be less than 2^31, b
bsalomon
2016/06/06 19:41:29
Added SkASSERT(fRRectStart < 8)
|
| break; |
| case Type::kPath: |
| SkASSERT(!fPath.get()->isVolatile()); |
| @@ -217,15 +222,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 +262,66 @@ 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)) { |
| + SkASSERT(!rrect->isEmpty()); |
| + if (!pe) { |
| + *rrectStart = DefaultRRectDirAndStartIndex(*rrect, false, rrectDir); |
| + } else { |
| + // For oval and rect subtypes of rrects pairs of start indices collapse to the same |
| + // point. Here ,we canonicalize which of the start points we use. |
| + if (rrect->getType() == SkRRect::kOval_Type) { |
| + *rrectStart |= ~0b1; |
| + } else if (rrect->getType() == SkRRect::kRect_Type) { |
| + *rrectStart = ((*rrectStart + 1) & 0b110); |
| + } |
| + } |
| + 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; |
| +} |