Expand GrStyle's interface.
Adds some basic getters on GrStyle as well as static const instances for fill and hairline.
Adds the ability to apply a GrStyle to a SkPath to produce an output SkPath.
Moves style key functions from GrShape to GrStyle.
Also fixes some issues with SkPath creation when applying style to GrShapes.
Adds tests that GrShape produces the correct SkPath when its GrStyle is applied.
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1951613002
Review-Url: https://codereview.chromium.org/1951613002
diff --git a/src/gpu/GrStyle.h b/src/gpu/GrStyle.h
index 4eef252..3ed4448 100644
--- a/src/gpu/GrStyle.h
+++ b/src/gpu/GrStyle.h
@@ -25,18 +25,56 @@
*/
class GrStyle {
public:
- GrStyle() : fStrokeRec(SkStrokeRec::kFill_InitStyle) {
- fDashInfo.fType = SkPathEffect::kNone_DashType;
+ /**
+ * A style object that represents a fill with no path effect.
+ * TODO: constexpr with C++14
+ */
+ static const GrStyle& SimpleFill() {
+ static const GrStyle kFill(SkStrokeRec::kFill_InitStyle);
+ return kFill;
+ }
+
+ /**
+ * A style object that represents a hairline stroke with no path effect.
+ * TODO: constexpr with C++14
+ */
+ static const GrStyle& SimpleHairline() {
+ static const GrStyle kHairline(SkStrokeRec::kHairline_InitStyle);
+ return kHairline;
}
+ enum class Apply {
+ kPathEffectOnly,
+ kPathEffectAndStrokeRec
+ };
+
+ /**
+ * Computes the key length for a GrStyle. The return will be negative if it cannot be turned
+ * into a key. This occurs when there is a path effect that is not a dash. The key can
+ * either reflect just the path effect (if one) or the path effect and the strokerec. Note
+ * that a simple fill has a zero sized key.
+ */
+ static int KeySize(const GrStyle& , Apply);
+
+ /**
+ * Writes a unique key for the style into the provided buffer. This function assumes the buffer
+ * has room for at least KeySize() values. It assumes that KeySize() returns a non-negative
+ * value for the style and Apply param. This is written so that the key for just dash
+ * application followed by the key for the remaining SkStrokeRec is the same as the key for
+ * applying dashing and SkStrokeRec all at once.
+ */
+ static void WriteKey(uint32_t*, const GrStyle&, Apply);
+
+ GrStyle() : GrStyle(SkStrokeRec::kFill_InitStyle) {}
+
+ explicit GrStyle(SkStrokeRec::InitStyle initStyle) : fStrokeRec(initStyle) {}
+
GrStyle(const SkStrokeRec& strokeRec, SkPathEffect* pe) : fStrokeRec(strokeRec) {
SkASSERT(SkStrokeRec::kStrokeAndFill_Style != strokeRec.getStyle());
this->initPathEffect(pe);
}
- GrStyle(const GrStyle& that) : fStrokeRec(SkStrokeRec::kFill_InitStyle) {
- *this = that;
- }
+ GrStyle(const GrStyle& that) : fStrokeRec(SkStrokeRec::kFill_InitStyle) { *this = that; }
explicit GrStyle(const SkPaint& paint) : fStrokeRec(paint) {
SkASSERT(SkStrokeRec::kStrokeAndFill_Style != fStrokeRec.getStyle());
@@ -49,8 +87,27 @@
fStrokeRec = that.fStrokeRec;
return *this;
}
+
+ void resetToInitStyle(SkStrokeRec::InitStyle fillOrHairline) {
+ fDashInfo.reset();
+ fPathEffect.reset(nullptr);
+ if (SkStrokeRec::kFill_InitStyle == fillOrHairline) {
+ fStrokeRec.setFillStyle();
+ } else {
+ fStrokeRec.setHairlineStyle();
+ }
+ }
+
+ /** Is this style a fill with no path effect? */
+ bool isSimpleFill() const { return fStrokeRec.isFillStyle() && !fPathEffect; }
+
+ /** Is this style a hairline with no path effect? */
+ bool isSimpleHairline() const { return fStrokeRec.isHairlineStyle() && !fPathEffect; }
+
SkPathEffect* pathEffect() const { return fPathEffect.get(); }
+ bool hasNonDashPathEffect() const { return fPathEffect.get() && !this->isDashed(); }
+
bool isDashed() const { return SkPathEffect::kDash_DashType == fDashInfo.fType; }
SkScalar dashPhase() const {
SkASSERT(this->isDashed());
@@ -67,10 +124,37 @@
const SkStrokeRec& strokeRec() const { return fStrokeRec; }
+ /** Hairline or fill styles without path effects make no alterations to a geometry. */
+ bool applies() const {
+ return this->pathEffect() || (!fStrokeRec.isFillStyle() && !fStrokeRec.isHairlineStyle());
+ }
+
+ /**
+ * Applies just the path effect and returns remaining stroke information. This will fail if
+ * there is no path effect.
+ */
+ bool applyPathEffectToPath(SkPath* dst, SkStrokeRec* remainingStoke, const SkPath& src) const;
+
+ /** If this succeeds then the result path should be filled or hairlined as indicated by the
+ returned SkStrokeRec::InitStyle value. Will fail if there is no path effect and the
+ strokerec doesn't change the geometry. */
+ bool applyToPath(SkPath* dst, SkStrokeRec::InitStyle* fillOrHairline, const SkPath& src) const;
+
+ /** Given bounds of a path compute the bounds of path with the style applied. */
+ void adjustBounds(SkRect* dst, const SkRect& src) const {
+ if (this->pathEffect()) {
+ this->pathEffect()->computeFastBounds(dst, src);
+ } else {
+ SkScalar radius = fStrokeRec.getInflationRadius();
+ *dst = src.makeOutset(radius, radius);
+ }
+ }
+
private:
void initPathEffect(SkPathEffect* pe);
struct DashInfo {
+ DashInfo() : fType(SkPathEffect::kNone_DashType) {}
DashInfo& operator=(const DashInfo& that) {
fType = that.fType;
fPhase = that.fPhase;
@@ -79,6 +163,10 @@
sizeof(SkScalar) * that.fIntervals.count());
return *this;
}
+ void reset() {
+ fType = SkPathEffect::kNone_DashType;
+ fIntervals.reset(0);
+ }
SkPathEffect::DashType fType;
SkScalar fPhase;
SkAutoSTArray<4, SkScalar> fIntervals;