[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>
This commit is contained in:
parent
7416571f4e
commit
04e03bc181
@ -43,8 +43,6 @@ enum class SkSVGAttribute {
|
||||
kRx, // <ellipse>,<rect>: horizontal (corner) radius
|
||||
kRy, // <ellipse>,<rect>: vertical (corner) radius
|
||||
kSpreadMethod,
|
||||
kStopColor,
|
||||
kStopOpacity,
|
||||
kStroke,
|
||||
kStrokeDashArray,
|
||||
kStrokeDashOffset,
|
||||
@ -98,12 +96,12 @@ struct SkSVGPresentationAttributes {
|
||||
SkSVGProperty<SkSVGFontWeight, true> fFontWeight;
|
||||
SkSVGProperty<SkSVGTextAnchor, true> fTextAnchor;
|
||||
|
||||
// TODO(tdenniston): add SkSVGStopColor
|
||||
|
||||
// uninherited
|
||||
SkSVGProperty<SkSVGNumberType, false> fOpacity;
|
||||
SkSVGProperty<SkSVGClip , false> fClipPath;
|
||||
SkSVGProperty<SkSVGFilterType, false> fFilter;
|
||||
SkSVGProperty<SkSVGColor , false> fStopColor;
|
||||
SkSVGProperty<SkSVGNumberType, false> fStopOpacity;
|
||||
};
|
||||
|
||||
#endif // SkSVGAttribute_DEFINED
|
||||
|
@ -19,7 +19,6 @@ public:
|
||||
bool parseInteger(SkSVGIntegerType*);
|
||||
bool parseViewBox(SkSVGViewBoxType*);
|
||||
bool parsePoints(SkSVGPointsType*);
|
||||
bool parseStopColor(SkSVGStopColor*);
|
||||
bool parsePreserveAspectRatio(SkSVGPreserveAspectRatio*);
|
||||
|
||||
// TODO: Migrate all parse*() functions to this style (and delete the old version)
|
||||
|
@ -121,6 +121,8 @@ public:
|
||||
SVG_PRES_ATTR(ClipPath , SkSVGClip , false)
|
||||
SVG_PRES_ATTR(Filter , SkSVGFilterType, false)
|
||||
SVG_PRES_ATTR(Opacity , SkSVGNumberType, false)
|
||||
SVG_PRES_ATTR(StopColor , SkSVGColor , false)
|
||||
SVG_PRES_ATTR(StopOpacity , SkSVGNumberType, false)
|
||||
|
||||
protected:
|
||||
SkSVGNode(SkSVGTag);
|
||||
|
@ -21,12 +21,8 @@ public:
|
||||
}
|
||||
|
||||
const SkSVGLength& offset() const { return fOffset; }
|
||||
const SkSVGStopColor& stopColor() const { return fStopColor; }
|
||||
const SkSVGNumberType& stopOpacity() const { return fStopOpacity; }
|
||||
|
||||
void setOffset(const SkSVGLength&);
|
||||
void setStopColor(const SkSVGStopColor&);
|
||||
void setStopOpacity(const SkSVGNumberType&);
|
||||
|
||||
protected:
|
||||
void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
|
||||
@ -34,9 +30,7 @@ protected:
|
||||
private:
|
||||
SkSVGStop();
|
||||
|
||||
SkSVGLength fOffset = SkSVGLength(0 , SkSVGLength::Unit::kPercentage);
|
||||
SkSVGStopColor fStopColor = SkSVGStopColor(SK_ColorBLACK);
|
||||
SkSVGNumberType fStopOpacity = SkSVGNumberType(1);
|
||||
SkSVGLength fOffset = SkSVGLength(0, SkSVGLength::Unit::kPercentage);
|
||||
|
||||
using INHERITED = SkSVGHiddenContainer;
|
||||
};
|
||||
|
@ -34,5 +34,8 @@ SkSVGPresentationAttributes SkSVGPresentationAttributes::MakeInitial() {
|
||||
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;
|
||||
}
|
||||
|
@ -604,23 +604,6 @@ bool SkSVGAttributeParser::parse(SkSVGLineJoin* join) {
|
||||
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) {
|
||||
|
@ -93,17 +93,6 @@ bool SetLengthAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
|
||||
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 @@ bool SetViewBoxAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
|
||||
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 @@ SortedDictionaryEntry<AttrParseInfo> gAttributeParseInfo[] = {
|
||||
{ "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 }},
|
||||
|
@ -53,25 +53,28 @@ void SkSVGGradient::collectColorStops(const SkSVGRenderContext& ctx,
|
||||
|
||||
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 {
|
||||
|
@ -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 @@ bool SkSVGNode::parseAndSetAttribute(const char* n, const char* v) {
|
||||
|| 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)
|
||||
|
@ -455,6 +455,12 @@ void SkSVGRenderContext::applyPresentationAttributes(const SkSVGPresentationAttr
|
||||
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) {
|
||||
|
@ -16,14 +16,6 @@ void SkSVGStop::setOffset(const SkSVGLength& offset) {
|
||||
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 @@ void SkSVGStop::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
|
||||
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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user