| Index: src/gpu/GrShape.cpp
|
| diff --git a/src/gpu/GrShape.cpp b/src/gpu/GrShape.cpp
|
| index e0ddc55e028e2a1b1ce24be5bd831dc9ea4d0620..9fcc6ee91158aca88bcea7366a9fadbf31936b3f 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;
|
| +}
|
|
|