[svg] Convert stop-color and stop-opacity to presentation attrs
These are somewhat the first presentation attributes of their kind,
in that they are non-inherited but also not applied via canvas layers.
Implementation-wise the main difference is that these attributes are
not propagated through the fInherited field of the render context's
presentation attribute list.
Change-Id: I0909507b0ecbd21732b3f80c46a343f5a0a9bf7a
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/340661
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Tyler Denniston <tdenniston@google.com>
diff --git a/modules/svg/src/SkSVGAttribute.cpp b/modules/svg/src/SkSVGAttribute.cpp
index 6a9129d..d07aa91 100644
--- a/modules/svg/src/SkSVGAttribute.cpp
+++ b/modules/svg/src/SkSVGAttribute.cpp
@@ -34,5 +34,8 @@
result.fFontWeight.init(SkSVGFontWeight::Type::kNormal);
result.fTextAnchor.init(SkSVGTextAnchor::Type::kStart);
+ result.fStopColor.set(SkSVGColor(SK_ColorBLACK));
+ result.fStopOpacity.set(SkSVGNumberType(1));
+
return result;
}
diff --git a/modules/svg/src/SkSVGAttributeParser.cpp b/modules/svg/src/SkSVGAttributeParser.cpp
index d34f153..5bfea3b 100644
--- a/modules/svg/src/SkSVGAttributeParser.cpp
+++ b/modules/svg/src/SkSVGAttributeParser.cpp
@@ -604,23 +604,6 @@
return parsedValue && this->parseEOSToken();
}
-// https://www.w3.org/TR/SVG11/pservers.html#StopElement
-bool SkSVGAttributeParser::parseStopColor(SkSVGStopColor* stopColor) {
- SkSVGColorType c;
- bool parsedValue = false;
- if (this->parse(&c)) {
- *stopColor = SkSVGStopColor(c);
- parsedValue = true;
- } else if (this->parseExpectedStringToken("currentColor")) {
- *stopColor = SkSVGStopColor(SkSVGStopColor::Type::kCurrentColor);
- parsedValue = true;
- } else if (this->parseExpectedStringToken("inherit")) {
- *stopColor = SkSVGStopColor(SkSVGStopColor::Type::kInherit);
- parsedValue = true;
- }
- return parsedValue && this->parseEOSToken();
-}
-
// https://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBoxUnits
template <>
bool SkSVGAttributeParser::parse(SkSVGObjectBoundingBoxUnits* objectBoundingBoxUnits) {
diff --git a/modules/svg/src/SkSVGDOM.cpp b/modules/svg/src/SkSVGDOM.cpp
index 356de27..643230e 100644
--- a/modules/svg/src/SkSVGDOM.cpp
+++ b/modules/svg/src/SkSVGDOM.cpp
@@ -93,17 +93,6 @@
return true;
}
-bool SetNumberAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
- const char* stringValue) {
- auto parseResult = SkSVGAttributeParser::parse<SkSVGNumberType>(stringValue);
- if (!parseResult.isValid()) {
- return false;
- }
-
- node->setAttribute(attr, SkSVGNumberValue(*parseResult));
- return true;
-}
-
bool SetViewBoxAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
const char* stringValue) {
SkSVGViewBoxType viewBox;
@@ -116,18 +105,6 @@
return true;
}
-bool SetStopColorAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
- const char* stringValue) {
- SkSVGStopColor stopColor;
- SkSVGAttributeParser parser(stringValue);
- if (!parser.parseStopColor(&stopColor)) {
- return false;
- }
-
- node->setAttribute(attr, SkSVGStopColorValue(stopColor));
- return true;
-}
-
bool SetObjectBoundingBoxUnitsAttribute(const sk_sp<SkSVGNode>& node,
SkSVGAttribute attr,
const char* stringValue) {
@@ -259,8 +236,6 @@
{ "r" , { SkSVGAttribute::kR , SetLengthAttribute }},
{ "rx" , { SkSVGAttribute::kRx , SetLengthAttribute }},
{ "ry" , { SkSVGAttribute::kRy , SetLengthAttribute }},
- { "stop-color" , { SkSVGAttribute::kStopColor , SetStopColorAttribute }},
- { "stop-opacity" , { SkSVGAttribute::kStopOpacity , SetNumberAttribute }},
{ "style" , { SkSVGAttribute::kUnknown , SetStyleAttributes }},
{ "text" , { SkSVGAttribute::kText , SetStringAttribute }},
{ "transform" , { SkSVGAttribute::kTransform , SetTransformAttribute }},
diff --git a/modules/svg/src/SkSVGGradient.cpp b/modules/svg/src/SkSVGGradient.cpp
index 2448d5b..cc5b297 100644
--- a/modules/svg/src/SkSVGGradient.cpp
+++ b/modules/svg/src/SkSVGGradient.cpp
@@ -53,25 +53,28 @@
SkColor SkSVGGradient::resolveStopColor(const SkSVGRenderContext& ctx,
const SkSVGStop& stop) const {
- const SkSVGStopColor& stopColor = stop.stopColor();
+ const auto& stopColor = stop.getStopColor();
+ const auto& stopOpacity = stop.getStopOpacity();
+ // Uninherited presentation attrs should have a concrete value at this point.
+ if (!stopColor.isValue() || !stopOpacity.isValue()) {
+ SkDebugf("unhandled: stop-color or stop-opacity has no value\n");
+ return SK_ColorBLACK;
+ }
+
SkColor color;
- switch (stopColor.type()) {
- case SkSVGStopColor::Type::kColor:
- color = stopColor.color();
+ switch (stopColor->type()) {
+ case SkSVGColor::Type::kColor:
+ color = stopColor->color();
break;
- case SkSVGStopColor::Type::kCurrentColor:
+ case SkSVGColor::Type::kCurrentColor:
color = *ctx.presentationContext().fInherited.fColor;
break;
- case SkSVGStopColor::Type::kICCColor:
+ case SkSVGColor::Type::kICCColor:
SkDebugf("unimplemented 'icccolor' stop-color type\n");
color = SK_ColorBLACK;
break;
- case SkSVGStopColor::Type::kInherit:
- SkDebugf("unimplemented 'inherit' stop-color type\n");
- color = SK_ColorBLACK;
- break;
}
- return SkColorSetA(color, SkScalarRoundToInt(stop.stopOpacity() * 255));
+ return SkColorSetA(color, SkScalarRoundToInt(*stopOpacity * 255));
}
bool SkSVGGradient::onAsPaint(const SkSVGRenderContext& ctx, SkPaint* paint) const {
diff --git a/modules/svg/src/SkSVGNode.cpp b/modules/svg/src/SkSVGNode.cpp
index a8f39ad..acf8f8f 100644
--- a/modules/svg/src/SkSVGNode.cpp
+++ b/modules/svg/src/SkSVGNode.cpp
@@ -14,7 +14,11 @@
#include "modules/svg/include/SkSVGValue.h"
#include "src/core/SkTLazy.h"
-SkSVGNode::SkSVGNode(SkSVGTag t) : fTag(t) { }
+SkSVGNode::SkSVGNode(SkSVGTag t) : fTag(t) {
+ // Uninherited presentation attributes need a non-null default value.
+ fPresentationAttributes.fStopColor.set(SkSVGColor(SK_ColorBLACK));
+ fPresentationAttributes.fStopOpacity.set(SkSVGNumberType(1.0f));
+}
SkSVGNode::~SkSVGNode() { }
@@ -94,6 +98,8 @@
|| PARSE_AND_SET("font-style" , FontStyle)
|| PARSE_AND_SET("font-weight" , FontWeight)
|| PARSE_AND_SET("opacity" , Opacity)
+ || PARSE_AND_SET("stop-color" , StopColor)
+ || PARSE_AND_SET("stop-opacity" , StopOpacity)
|| PARSE_AND_SET("stroke" , Stroke)
|| PARSE_AND_SET("stroke-dasharray" , StrokeDashArray)
|| PARSE_AND_SET("stroke-dashoffset", StrokeDashOffset)
diff --git a/modules/svg/src/SkSVGRenderContext.cpp b/modules/svg/src/SkSVGRenderContext.cpp
index 7f7be49..6925a4d 100644
--- a/modules/svg/src/SkSVGRenderContext.cpp
+++ b/modules/svg/src/SkSVGRenderContext.cpp
@@ -455,6 +455,12 @@
if (attrs.fFilter.isValue()) {
this->applyFilter(*attrs.fFilter);
}
+
+ // Remaining uninherited presentation attributes are accessed as SkSVGNode fields, not via
+ // the render context.
+ // TODO: resolve these in a pre-render styling pass and assert here that they are values.
+ // - stop-color
+ // - stop-opacity
}
void SkSVGRenderContext::applyOpacity(SkScalar opacity, uint32_t flags) {
diff --git a/modules/svg/src/SkSVGStop.cpp b/modules/svg/src/SkSVGStop.cpp
index edf39bc..03b80cc 100644
--- a/modules/svg/src/SkSVGStop.cpp
+++ b/modules/svg/src/SkSVGStop.cpp
@@ -16,14 +16,6 @@
fOffset = offset;
}
-void SkSVGStop::setStopColor(const SkSVGStopColor& color) {
- fStopColor = color;
-}
-
-void SkSVGStop::setStopOpacity(const SkSVGNumberType& opacity) {
- fStopOpacity = SkTPin<SkScalar>(opacity, 0, 1);
-}
-
void SkSVGStop::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
switch (attr) {
case SkSVGAttribute::kOffset:
@@ -31,16 +23,6 @@
this->setOffset(*offset);
}
break;
- case SkSVGAttribute::kStopColor:
- if (const auto* color = v.as<SkSVGStopColorValue>()) {
- this->setStopColor(*color);
- }
- break;
- case SkSVGAttribute::kStopOpacity:
- if (const auto* opacity = v.as<SkSVGNumberValue>()) {
- this->setStopOpacity(*opacity);
- }
- break;
default:
this->INHERITED::onSetAttribute(attr, v);
}