aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental/svg/model
diff options
context:
space:
mode:
Diffstat (limited to 'experimental/svg/model')
-rw-r--r--experimental/svg/model/SkSVGAttribute.cpp1
-rw-r--r--experimental/svg/model/SkSVGAttribute.h2
-rw-r--r--experimental/svg/model/SkSVGAttributeParser.cpp23
-rw-r--r--experimental/svg/model/SkSVGAttributeParser.h1
-rw-r--r--experimental/svg/model/SkSVGCircle.cpp2
-rw-r--r--experimental/svg/model/SkSVGCircle.h3
-rw-r--r--experimental/svg/model/SkSVGDOM.cpp13
-rw-r--r--experimental/svg/model/SkSVGEllipse.cpp2
-rw-r--r--experimental/svg/model/SkSVGEllipse.h3
-rw-r--r--experimental/svg/model/SkSVGLine.cpp2
-rw-r--r--experimental/svg/model/SkSVGLine.h3
-rw-r--r--experimental/svg/model/SkSVGNode.cpp9
-rw-r--r--experimental/svg/model/SkSVGNode.h1
-rw-r--r--experimental/svg/model/SkSVGPath.cpp5
-rw-r--r--experimental/svg/model/SkSVGPath.h5
-rw-r--r--experimental/svg/model/SkSVGPoly.cpp6
-rw-r--r--experimental/svg/model/SkSVGPoly.h5
-rw-r--r--experimental/svg/model/SkSVGRect.cpp2
-rw-r--r--experimental/svg/model/SkSVGRect.h3
-rw-r--r--experimental/svg/model/SkSVGRenderContext.cpp9
-rw-r--r--experimental/svg/model/SkSVGRenderContext.h2
-rw-r--r--experimental/svg/model/SkSVGShape.cpp19
-rw-r--r--experimental/svg/model/SkSVGShape.h6
-rw-r--r--experimental/svg/model/SkSVGTypes.h23
-rw-r--r--experimental/svg/model/SkSVGValue.h2
25 files changed, 135 insertions, 17 deletions
diff --git a/experimental/svg/model/SkSVGAttribute.cpp b/experimental/svg/model/SkSVGAttribute.cpp
index 9d6b193e04..4935d6afcf 100644
--- a/experimental/svg/model/SkSVGAttribute.cpp
+++ b/experimental/svg/model/SkSVGAttribute.cpp
@@ -12,6 +12,7 @@ SkSVGPresentationAttributes SkSVGPresentationAttributes::MakeInitial() {
result.fFill.set(SkSVGPaint(SkSVGColorType(SK_ColorBLACK)));
result.fFillOpacity.set(SkSVGNumberType(1));
+ result.fFillRule.set(SkSVGFillRule(SkSVGFillRule::Type::kNonZero));
result.fStroke.set(SkSVGPaint(SkSVGPaint::Type::kNone));
result.fStrokeLineCap.set(SkSVGLineCap(SkSVGLineCap::Type::kButt));
diff --git a/experimental/svg/model/SkSVGAttribute.h b/experimental/svg/model/SkSVGAttribute.h
index 478a26b261..93c5f99153 100644
--- a/experimental/svg/model/SkSVGAttribute.h
+++ b/experimental/svg/model/SkSVGAttribute.h
@@ -19,6 +19,7 @@ enum class SkSVGAttribute {
kD,
kFill,
kFillOpacity,
+ kFillRule,
kGradientTransform,
kHeight,
kHref,
@@ -56,6 +57,7 @@ struct SkSVGPresentationAttributes {
SkTLazy<SkSVGPaint> fFill;
SkTLazy<SkSVGNumberType> fFillOpacity;
+ SkTLazy<SkSVGFillRule> fFillRule;
SkTLazy<SkSVGPaint> fStroke;
SkTLazy<SkSVGLineCap> fStrokeLineCap;
diff --git a/experimental/svg/model/SkSVGAttributeParser.cpp b/experimental/svg/model/SkSVGAttributeParser.cpp
index 04b050828a..5ca317ccc3 100644
--- a/experimental/svg/model/SkSVGAttributeParser.cpp
+++ b/experimental/svg/model/SkSVGAttributeParser.cpp
@@ -551,3 +551,26 @@ bool SkSVGAttributeParser::parsePoints(SkSVGPointsType* points) {
return false;
}
+
+// https://www.w3.org/TR/SVG/painting.html#FillRuleProperty
+bool SkSVGAttributeParser::parseFillRule(SkSVGFillRule* fillRule) {
+ static const struct {
+ SkSVGFillRule::Type fType;
+ const char* fName;
+ } gFillRuleInfo[] = {
+ { SkSVGFillRule::Type::kNonZero, "nonzero" },
+ { SkSVGFillRule::Type::kEvenOdd, "evenodd" },
+ { SkSVGFillRule::Type::kInherit, "inherit" },
+ };
+
+ bool parsedValue = false;
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gFillRuleInfo); ++i) {
+ if (this->parseExpectedStringToken(gFillRuleInfo[i].fName)) {
+ *fillRule = SkSVGFillRule(gFillRuleInfo[i].fType);
+ parsedValue = true;
+ break;
+ }
+ }
+
+ return parsedValue && this->parseEOSToken();
+}
diff --git a/experimental/svg/model/SkSVGAttributeParser.h b/experimental/svg/model/SkSVGAttributeParser.h
index 9d6939b2e2..2ffa79f543 100644
--- a/experimental/svg/model/SkSVGAttributeParser.h
+++ b/experimental/svg/model/SkSVGAttributeParser.h
@@ -15,6 +15,7 @@ public:
SkSVGAttributeParser(const char[]);
bool parseColor(SkSVGColorType*);
+ bool parseFillRule(SkSVGFillRule*);
bool parseNumber(SkSVGNumberType*);
bool parseLength(SkSVGLength*);
bool parseViewBox(SkSVGViewBoxType*);
diff --git a/experimental/svg/model/SkSVGCircle.cpp b/experimental/svg/model/SkSVGCircle.cpp
index 692cd9ff54..9d8117379a 100644
--- a/experimental/svg/model/SkSVGCircle.cpp
+++ b/experimental/svg/model/SkSVGCircle.cpp
@@ -47,7 +47,7 @@ void SkSVGCircle::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
}
void SkSVGCircle::onDraw(SkCanvas* canvas, const SkSVGLengthContext& lctx,
- const SkPaint& paint) const {
+ const SkPaint& paint, SkPath::FillType) const {
const auto cx = lctx.resolve(fCx, SkSVGLengthContext::LengthType::kHorizontal);
const auto cy = lctx.resolve(fCy, SkSVGLengthContext::LengthType::kVertical);
const auto r = lctx.resolve(fR , SkSVGLengthContext::LengthType::kOther);
diff --git a/experimental/svg/model/SkSVGCircle.h b/experimental/svg/model/SkSVGCircle.h
index ef1bd2aadb..02aaad4891 100644
--- a/experimental/svg/model/SkSVGCircle.h
+++ b/experimental/svg/model/SkSVGCircle.h
@@ -23,7 +23,8 @@ public:
protected:
void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
- void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&) const override;
+ void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&,
+ SkPath::FillType) const override;
private:
SkSVGCircle();
diff --git a/experimental/svg/model/SkSVGDOM.cpp b/experimental/svg/model/SkSVGDOM.cpp
index c9745f1730..2120f80e36 100644
--- a/experimental/svg/model/SkSVGDOM.cpp
+++ b/experimental/svg/model/SkSVGDOM.cpp
@@ -173,6 +173,18 @@ bool SetPointsAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
return true;
}
+bool SetFillRuleAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
+ const char* stringValue) {
+ SkSVGFillRule fillRule;
+ SkSVGAttributeParser parser(stringValue);
+ if (!parser.parseFillRule(&fillRule)) {
+ return false;
+ }
+
+ node->setAttribute(attr, SkSVGFillRuleValue(fillRule));
+ return true;
+}
+
SkString TrimmedString(const char* first, const char* last) {
SkASSERT(first);
SkASSERT(last);
@@ -256,6 +268,7 @@ SortedDictionaryEntry<AttrParseInfo> gAttributeParseInfo[] = {
{ "d" , { SkSVGAttribute::kD , SetPathDataAttribute }},
{ "fill" , { SkSVGAttribute::kFill , SetPaintAttribute }},
{ "fill-opacity" , { SkSVGAttribute::kFillOpacity , SetNumberAttribute }},
+ { "fill-rule" , { SkSVGAttribute::kFillRule , SetFillRuleAttribute }},
{ "gradientTransform", { SkSVGAttribute::kGradientTransform, SetTransformAttribute }},
{ "height" , { SkSVGAttribute::kHeight , SetLengthAttribute }},
{ "offset" , { SkSVGAttribute::kOffset , SetLengthAttribute }},
diff --git a/experimental/svg/model/SkSVGEllipse.cpp b/experimental/svg/model/SkSVGEllipse.cpp
index f7461b8cd7..481af5c3ab 100644
--- a/experimental/svg/model/SkSVGEllipse.cpp
+++ b/experimental/svg/model/SkSVGEllipse.cpp
@@ -56,7 +56,7 @@ void SkSVGEllipse::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
}
void SkSVGEllipse::onDraw(SkCanvas* canvas, const SkSVGLengthContext& lctx,
- const SkPaint& paint) const {
+ const SkPaint& paint, SkPath::FillType) const {
const auto cx = lctx.resolve(fCx, SkSVGLengthContext::LengthType::kHorizontal);
const auto cy = lctx.resolve(fCy, SkSVGLengthContext::LengthType::kVertical);
const auto rx = lctx.resolve(fRx, SkSVGLengthContext::LengthType::kHorizontal);
diff --git a/experimental/svg/model/SkSVGEllipse.h b/experimental/svg/model/SkSVGEllipse.h
index 640d7f6f26..0042b3364e 100644
--- a/experimental/svg/model/SkSVGEllipse.h
+++ b/experimental/svg/model/SkSVGEllipse.h
@@ -24,7 +24,8 @@ public:
protected:
void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
- void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&) const override;
+ void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&,
+ SkPath::FillType) const override;
private:
SkSVGEllipse();
diff --git a/experimental/svg/model/SkSVGLine.cpp b/experimental/svg/model/SkSVGLine.cpp
index 030aad8db4..27cdd469d2 100644
--- a/experimental/svg/model/SkSVGLine.cpp
+++ b/experimental/svg/model/SkSVGLine.cpp
@@ -56,7 +56,7 @@ void SkSVGLine::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
}
void SkSVGLine::onDraw(SkCanvas* canvas, const SkSVGLengthContext& lctx,
- const SkPaint& paint) const {
+ const SkPaint& paint, SkPath::FillType) const {
const auto x1 = lctx.resolve(fX1, SkSVGLengthContext::LengthType::kHorizontal);
const auto y1 = lctx.resolve(fY1, SkSVGLengthContext::LengthType::kVertical);
const auto x2 = lctx.resolve(fX2, SkSVGLengthContext::LengthType::kHorizontal);
diff --git a/experimental/svg/model/SkSVGLine.h b/experimental/svg/model/SkSVGLine.h
index c2716e00e2..524fc2ac0e 100644
--- a/experimental/svg/model/SkSVGLine.h
+++ b/experimental/svg/model/SkSVGLine.h
@@ -24,7 +24,8 @@ public:
protected:
void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
- void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&) const override;
+ void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&,
+ SkPath::FillType) const override;
private:
SkSVGLine();
diff --git a/experimental/svg/model/SkSVGNode.cpp b/experimental/svg/model/SkSVGNode.cpp
index f40ee5dadb..a5c8147554 100644
--- a/experimental/svg/model/SkSVGNode.cpp
+++ b/experimental/svg/model/SkSVGNode.cpp
@@ -49,6 +49,10 @@ void SkSVGNode::setFillOpacity(const SkSVGNumberType& opacity) {
SkSVGNumberType(SkTPin<SkScalar>(opacity.value(), 0, 1)));
}
+void SkSVGNode::setFillRule(const SkSVGFillRule& fillRule) {
+ fPresentationAttributes.fFillRule.set(fillRule);
+}
+
void SkSVGNode::setOpacity(const SkSVGNumberType& opacity) {
fPresentationAttributes.fOpacity.set(
SkSVGNumberType(SkTPin<SkScalar>(opacity.value(), 0, 1)));
@@ -79,6 +83,11 @@ void SkSVGNode::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
this->setFillOpacity(*opacity);
}
break;
+ case SkSVGAttribute::kFillRule:
+ if (const SkSVGFillRuleValue* fillRule = v.as<SkSVGFillRuleValue>()) {
+ this->setFillRule(*fillRule);
+ }
+ break;
case SkSVGAttribute::kOpacity:
if (const SkSVGNumberValue* opacity = v.as<SkSVGNumberValue>()) {
this->setOpacity(*opacity);
diff --git a/experimental/svg/model/SkSVGNode.h b/experimental/svg/model/SkSVGNode.h
index 2a7c836413..1e092a4d87 100644
--- a/experimental/svg/model/SkSVGNode.h
+++ b/experimental/svg/model/SkSVGNode.h
@@ -47,6 +47,7 @@ public:
void setFill(const SkSVGPaint&);
void setFillOpacity(const SkSVGNumberType&);
+ void setFillRule(const SkSVGFillRule&);
void setOpacity(const SkSVGNumberType&);
void setStroke(const SkSVGPaint&);
void setStrokeOpacity(const SkSVGNumberType&);
diff --git a/experimental/svg/model/SkSVGPath.cpp b/experimental/svg/model/SkSVGPath.cpp
index 07e0a3e545..dd248237f1 100644
--- a/experimental/svg/model/SkSVGPath.cpp
+++ b/experimental/svg/model/SkSVGPath.cpp
@@ -25,6 +25,9 @@ void SkSVGPath::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
}
}
-void SkSVGPath::onDraw(SkCanvas* canvas, const SkSVGLengthContext&, const SkPaint& paint) const {
+void SkSVGPath::onDraw(SkCanvas* canvas, const SkSVGLengthContext&, const SkPaint& paint,
+ SkPath::FillType fillType) const {
+ // the passed fillType follows inheritance rules and needs to be applied at draw time.
+ fPath.setFillType(fillType);
canvas->drawPath(fPath, paint);
}
diff --git a/experimental/svg/model/SkSVGPath.h b/experimental/svg/model/SkSVGPath.h
index e72f0d137e..8297a8d557 100644
--- a/experimental/svg/model/SkSVGPath.h
+++ b/experimental/svg/model/SkSVGPath.h
@@ -21,12 +21,13 @@ public:
protected:
void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
- void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&) const override;
+ void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&,
+ SkPath::FillType) const override;
private:
SkSVGPath();
- SkPath fPath;
+ mutable SkPath fPath; // mutated in onDraw(), to apply inherited fill types.
typedef SkSVGShape INHERITED;
};
diff --git a/experimental/svg/model/SkSVGPoly.cpp b/experimental/svg/model/SkSVGPoly.cpp
index bcc716f362..826ca2457e 100644
--- a/experimental/svg/model/SkSVGPoly.cpp
+++ b/experimental/svg/model/SkSVGPoly.cpp
@@ -6,6 +6,7 @@
*/
#include "SkCanvas.h"
+#include "SkTLazy.h"
#include "SkSVGRenderContext.h"
#include "SkSVGPoly.h"
#include "SkSVGValue.h"
@@ -31,6 +32,9 @@ void SkSVGPoly::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
}
}
-void SkSVGPoly::onDraw(SkCanvas* canvas, const SkSVGLengthContext&, const SkPaint& paint) const {
+void SkSVGPoly::onDraw(SkCanvas* canvas, const SkSVGLengthContext&, const SkPaint& paint,
+ SkPath::FillType fillType) const {
+ // the passed fillType follows inheritance rules and needs to be applied at draw time.
+ fPath.setFillType(fillType);
canvas->drawPath(fPath, paint);
}
diff --git a/experimental/svg/model/SkSVGPoly.h b/experimental/svg/model/SkSVGPoly.h
index 3ae8dc6f02..f75d3626cc 100644
--- a/experimental/svg/model/SkSVGPoly.h
+++ b/experimental/svg/model/SkSVGPoly.h
@@ -29,12 +29,13 @@ public:
protected:
void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
- void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&) const override;
+ void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&,
+ SkPath::FillType) const override;
private:
SkSVGPoly(SkSVGTag);
- SkPath fPath;
+ mutable SkPath fPath; // mutated in onDraw(), to apply inherited fill types.
typedef SkSVGShape INHERITED;
};
diff --git a/experimental/svg/model/SkSVGRect.cpp b/experimental/svg/model/SkSVGRect.cpp
index cbb18306a5..1afd9957c6 100644
--- a/experimental/svg/model/SkSVGRect.cpp
+++ b/experimental/svg/model/SkSVGRect.cpp
@@ -75,7 +75,7 @@ void SkSVGRect::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
}
void SkSVGRect::onDraw(SkCanvas* canvas, const SkSVGLengthContext& lctx,
- const SkPaint& paint) const {
+ const SkPaint& paint, SkPath::FillType) const {
const SkRect rect = lctx.resolveRect(fX, fY, fWidth, fHeight);
const SkScalar rx = lctx.resolve(fRx, SkSVGLengthContext::LengthType::kHorizontal);
const SkScalar ry = lctx.resolve(fRy, SkSVGLengthContext::LengthType::kVertical);
diff --git a/experimental/svg/model/SkSVGRect.h b/experimental/svg/model/SkSVGRect.h
index 0da248c4eb..affa65f610 100644
--- a/experimental/svg/model/SkSVGRect.h
+++ b/experimental/svg/model/SkSVGRect.h
@@ -26,7 +26,8 @@ public:
protected:
void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
- void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&) const override;
+ void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&,
+ SkPath::FillType) const override;
private:
SkSVGRect();
diff --git a/experimental/svg/model/SkSVGRenderContext.cpp b/experimental/svg/model/SkSVGRenderContext.cpp
index 147d64edb3..fd0262319a 100644
--- a/experimental/svg/model/SkSVGRenderContext.cpp
+++ b/experimental/svg/model/SkSVGRenderContext.cpp
@@ -6,6 +6,7 @@
*/
#include "SkCanvas.h"
+#include "SkPath.h"
#include "SkSVGAttribute.h"
#include "SkSVGNode.h"
#include "SkSVGRenderContext.h"
@@ -188,6 +189,13 @@ void commitToPaint<SkSVGAttribute::kStrokeWidth>(const SkSVGPresentationAttribut
pctx->fStrokePaint.setStrokeWidth(strokeWidth);
}
+template <>
+void commitToPaint<SkSVGAttribute::kFillRule>(const SkSVGPresentationAttributes&,
+ const SkSVGRenderContext&,
+ SkSVGPresentationContext*) {
+ // Not part of the SkPaint state; applied to the path at render time.
+}
+
} // anonymous ns
SkSVGPresentationContext::SkSVGPresentationContext()
@@ -258,6 +266,7 @@ void SkSVGRenderContext::applyPresentationAttributes(const SkSVGPresentationAttr
ApplyLazyInheritedAttribute(Fill);
ApplyLazyInheritedAttribute(FillOpacity);
+ ApplyLazyInheritedAttribute(FillRule);
ApplyLazyInheritedAttribute(Stroke);
ApplyLazyInheritedAttribute(StrokeLineCap);
ApplyLazyInheritedAttribute(StrokeLineJoin);
diff --git a/experimental/svg/model/SkSVGRenderContext.h b/experimental/svg/model/SkSVGRenderContext.h
index 393c2849eb..9d2fb3a621 100644
--- a/experimental/svg/model/SkSVGRenderContext.h
+++ b/experimental/svg/model/SkSVGRenderContext.h
@@ -65,6 +65,8 @@ public:
const SkSVGLengthContext& lengthContext() const { return *fLengthContext; }
SkSVGLengthContext* writableLengthContext() { return fLengthContext.writable(); }
+ const SkSVGPresentationContext& presentationContext() const { return *fPresentationContext; }
+
SkCanvas* canvas() const { return fCanvas; }
enum ApplyFlags {
diff --git a/experimental/svg/model/SkSVGShape.cpp b/experimental/svg/model/SkSVGShape.cpp
index 38af4c9303..9351a2f096 100644
--- a/experimental/svg/model/SkSVGShape.cpp
+++ b/experimental/svg/model/SkSVGShape.cpp
@@ -11,16 +11,31 @@
SkSVGShape::SkSVGShape(SkSVGTag t) : INHERITED(t) {}
void SkSVGShape::onRender(const SkSVGRenderContext& ctx) const {
+ const SkPath::FillType fillType =
+ FillRuleToFillType(*ctx.presentationContext().fInherited.fFillRule.get());
+
// TODO: this approach forces duplicate geometry resolution in onDraw(); refactor to avoid.
if (const SkPaint* fillPaint = ctx.fillPaint()) {
- this->onDraw(ctx.canvas(), ctx.lengthContext(), *fillPaint);
+ this->onDraw(ctx.canvas(), ctx.lengthContext(), *fillPaint, fillType);
}
if (const SkPaint* strokePaint = ctx.strokePaint()) {
- this->onDraw(ctx.canvas(), ctx.lengthContext(), *strokePaint);
+ this->onDraw(ctx.canvas(), ctx.lengthContext(), *strokePaint, fillType);
}
}
void SkSVGShape::appendChild(sk_sp<SkSVGNode>) {
SkDebugf("cannot append child nodes to an SVG shape.\n");
}
+
+SkPath::FillType SkSVGShape::FillRuleToFillType(const SkSVGFillRule& fillRule) {
+ switch (fillRule.type()) {
+ case SkSVGFillRule::Type::kNonZero:
+ return SkPath::kWinding_FillType;
+ case SkSVGFillRule::Type::kEvenOdd:
+ return SkPath::kEvenOdd_FillType;
+ default:
+ SkASSERT(false);
+ return SkPath::kWinding_FillType;
+ }
+}
diff --git a/experimental/svg/model/SkSVGShape.h b/experimental/svg/model/SkSVGShape.h
index 1f3c4555c3..48b2ead0c1 100644
--- a/experimental/svg/model/SkSVGShape.h
+++ b/experimental/svg/model/SkSVGShape.h
@@ -8,6 +8,7 @@
#ifndef SkSVGShape_DEFINED
#define SkSVGShape_DEFINED
+#include "SkPath.h"
#include "SkSVGTransformableNode.h"
class SkSVGLengthContext;
@@ -24,7 +25,10 @@ protected:
void onRender(const SkSVGRenderContext&) const final;
- virtual void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&) const = 0;
+ virtual void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&,
+ SkPath::FillType) const = 0;
+
+ static SkPath::FillType FillRuleToFillType(const SkSVGFillRule&);
private:
typedef SkSVGTransformableNode INHERITED;
diff --git a/experimental/svg/model/SkSVGTypes.h b/experimental/svg/model/SkSVGTypes.h
index b07f9a2c8c..d5d2b7146f 100644
--- a/experimental/svg/model/SkSVGTypes.h
+++ b/experimental/svg/model/SkSVGTypes.h
@@ -191,4 +191,27 @@ private:
Type fType;
};
+class SkSVGFillRule {
+public:
+ enum class Type {
+ kNonZero,
+ kEvenOdd,
+ kInherit,
+ };
+
+ constexpr SkSVGFillRule() : fType(Type::kInherit) {}
+ constexpr explicit SkSVGFillRule(Type t) : fType(t) {}
+
+ SkSVGFillRule(const SkSVGFillRule&) = default;
+ SkSVGFillRule& operator=(const SkSVGFillRule&) = default;
+
+ bool operator==(const SkSVGFillRule& other) const { return fType == other.fType; }
+ bool operator!=(const SkSVGFillRule& other) const { return !(*this == other); }
+
+ Type type() const { return fType; }
+
+private:
+ Type fType;
+};
+
#endif // SkSVGTypes_DEFINED
diff --git a/experimental/svg/model/SkSVGValue.h b/experimental/svg/model/SkSVGValue.h
index 0160af0371..9f3095c918 100644
--- a/experimental/svg/model/SkSVGValue.h
+++ b/experimental/svg/model/SkSVGValue.h
@@ -18,6 +18,7 @@ class SkSVGValue : public SkNoncopyable {
public:
enum class Type {
kColor,
+ kFillRule,
kLength,
kLineCap,
kLineJoin,
@@ -70,6 +71,7 @@ private:
};
using SkSVGColorValue = SkSVGWrapperValue<SkSVGColorType , SkSVGValue::Type::kColor >;
+using SkSVGFillRuleValue = SkSVGWrapperValue<SkSVGFillRule , SkSVGValue::Type::kFillRule >;
using SkSVGLengthValue = SkSVGWrapperValue<SkSVGLength , SkSVGValue::Type::kLength >;
using SkSVGPathValue = SkSVGWrapperValue<SkPath , SkSVGValue::Type::kPath >;
using SkSVGTransformValue = SkSVGWrapperValue<SkSVGTransformType, SkSVGValue::Type::kTransform>;