Index: src/gpu/GrShape.h |
diff --git a/src/gpu/GrShape.h b/src/gpu/GrShape.h |
index 4ba56061e5158dbd5524deff65a61b6a455c3b00..3efb66fd6b8522e396a7b3173adcd40d2e058504 100644 |
--- a/src/gpu/GrShape.h |
+++ b/src/gpu/GrShape.h |
@@ -44,14 +44,16 @@ public: |
explicit GrShape(const SkRRect& rrect) |
: fType(Type::kRRect) |
- , fRRect(rrect) { |
+ , fRRect(rrect) |
+ , fRRectIsInverted(false) { |
fRRectStart = DefaultRRectDirAndStartIndex(rrect, false, &fRRectDir); |
this->attemptToReduceFromRRect(); |
} |
explicit GrShape(const SkRect& rect) |
: fType(Type::kRRect) |
- , fRRect(SkRRect::MakeRect(rect)) { |
+ , fRRect(SkRRect::MakeRect(rect)) |
+ , fRRectIsInverted(false) { |
fRRectStart = DefaultRectDirAndStartIndex(rect, false, &fRRectDir); |
this->attemptToReduceFromRRect(); |
} |
@@ -66,18 +68,26 @@ public: |
GrShape(const SkRRect& rrect, const GrStyle& style) |
: fType(Type::kRRect) |
, fRRect(rrect) |
+ , fRRectIsInverted(false) |
, fStyle(style) { |
fRRectStart = DefaultRRectDirAndStartIndex(rrect, style.hasPathEffect(), &fRRectDir); |
this->attemptToReduceFromRRect(); |
} |
- GrShape(const SkRRect& rrect, SkPath::Direction dir, unsigned start, const GrStyle& style) |
+ GrShape(const SkRRect& rrect, SkPath::Direction dir, unsigned start, bool inverted, |
+ const GrStyle& style) |
: fType(Type::kRRect) |
, fRRect(rrect) |
+ , fRRectIsInverted(inverted) |
, fStyle(style) { |
if (style.pathEffect()) { |
fRRectDir = dir; |
fRRectStart = start; |
+ if (fRRect.getType() == SkRRect::kRect_Type) { |
+ fRRectStart = (fRRectStart + 1) & 0b110; |
+ } else if (fRRect.getType() == SkRRect::kOval_Type) { |
+ fRRectStart &= 0b110; |
+ } |
} else { |
fRRectStart = DefaultRRectDirAndStartIndex(rrect, false, &fRRectDir); |
} |
@@ -87,6 +97,7 @@ public: |
GrShape(const SkRect& rect, const GrStyle& style) |
: fType(Type::kRRect) |
, fRRect(SkRRect::MakeRect(rect)) |
+ , fRRectIsInverted(false) |
, fStyle(style) { |
fRRectStart = DefaultRectDirAndStartIndex(rect, style.hasPathEffect(), &fRRectDir); |
this->attemptToReduceFromRRect(); |
@@ -102,6 +113,7 @@ public: |
GrShape(const SkRRect& rrect, const SkPaint& paint) |
: fType(Type::kRRect) |
, fRRect(rrect) |
+ , fRRectIsInverted(false) |
, fStyle(paint) { |
fRRectStart = DefaultRRectDirAndStartIndex(rrect, fStyle.hasPathEffect(), &fRRectDir); |
this->attemptToReduceFromRRect(); |
@@ -110,6 +122,7 @@ public: |
GrShape(const SkRect& rect, const SkPaint& paint) |
: fType(Type::kRRect) |
, fRRect(SkRRect::MakeRect(rect)) |
+ , fRRectIsInverted(false) |
, fStyle(paint) { |
fRRectStart = DefaultRectDirAndStartIndex(rect, fStyle.hasPathEffect(), &fRRectDir); |
this->attemptToReduceFromRRect(); |
@@ -136,7 +149,7 @@ public: |
} |
/** Returns the unstyled geometry as a rrect if possible. */ |
- bool asRRect(SkRRect* rrect, SkPath::Direction* dir, unsigned* start) const { |
+ bool asRRect(SkRRect* rrect, SkPath::Direction* dir, unsigned* start, bool* inverted) const { |
if (Type::kRRect != fType) { |
return false; |
} |
@@ -149,6 +162,9 @@ public: |
if (start) { |
*start = fRRectStart; |
} |
+ if (inverted) { |
+ *inverted = fRRectIsInverted; |
+ } |
return true; |
} |
@@ -161,6 +177,9 @@ public: |
case Type::kRRect: |
out->reset(); |
out->addRRect(fRRect, fRRectDir, fRRectStart); |
+ if (fRRectIsInverted) { |
+ out->setFillType(SkPath::kInverseWinding_FillType); |
+ } |
break; |
case Type::kPath: |
*out = *fPath.get(); |
@@ -174,10 +193,16 @@ public: |
*/ |
bool isEmpty() const { return Type::kEmpty == fType; } |
- /** Gets the bounds of the geometry without reflecting the shape's styling. */ |
+ /** |
+ * Gets the bounds of the geometry without reflecting the shape's styling. This ignores |
+ * the inverse fill nature of the geometry. |
+ */ |
const SkRect& bounds() const; |
- /** Gets the bounds of the geometry reflecting the shape's styling. */ |
+ /** |
+ * Gets the bounds of the geometry reflecting the shape's styling (ignoring inverse fill |
+ * status). |
+ */ |
void styledBounds(SkRect* bounds) const; |
/** |
@@ -245,7 +270,8 @@ private: |
void attemptToReduceFromPath() { |
SkASSERT(Type::kPath == fType); |
fType = AttemptToReduceFromPathImpl(*fPath.get(), &fRRect, &fRRectDir, &fRRectStart, |
- fStyle.pathEffect(), fStyle.strokeRec()); |
+ &fRRectIsInverted, fStyle.pathEffect(), |
+ fStyle.strokeRec()); |
if (Type::kPath != fType) { |
fPath.reset(); |
fInheritedKey.reset(0); |
@@ -255,14 +281,24 @@ private: |
void attemptToReduceFromRRect() { |
SkASSERT(Type::kRRect == fType); |
SkASSERT(!fInheritedKey.count()); |
- if (fRRect.isEmpty()) { |
+ if (fRRectIsInverted) { |
+ if (!fStyle.hasNonDashPathEffect()) { |
+ SkStrokeRec::Style recStyle = fStyle.strokeRec().getStyle(); |
+ if (SkStrokeRec::kStroke_Style == recStyle || |
+ SkStrokeRec::kHairline_Style == recStyle) { |
+ // stroking ignores the path fill rule. |
+ fRRectIsInverted = false; |
+ } |
+ } |
+ } else if (fRRect.isEmpty()) { |
fType = Type::kEmpty; |
} |
} |
static Type AttemptToReduceFromPathImpl(const SkPath& path, SkRRect* rrect, |
SkPath::Direction* rrectDir, unsigned* rrectStart, |
- const SkPathEffect* pe, const SkStrokeRec& strokeRec); |
+ bool* rrectIsInverted, const SkPathEffect* pe, |
+ const SkStrokeRec& strokeRec); |
static constexpr SkPath::Direction kDefaultRRectDir = SkPath::kCW_Direction; |
static constexpr unsigned kDefaultRRectStart = 0; |
@@ -313,6 +349,7 @@ private: |
SkRRect fRRect; |
SkPath::Direction fRRectDir; |
unsigned fRRectStart; |
+ bool fRRectIsInverted; |
SkTLazy<SkPath> fPath; |
GrStyle fStyle; |
SkAutoSTArray<8, uint32_t> fInheritedKey; |