[svg] Use new parsing for gradient classes

- Added new SVG_OPTIONAL_ATTR macro for lazy properties
- Added SkSVGIRI type -- we need explicit types now to be able to
  dispatch via the templated parse function
- Converted several attribute parse functions to templated version

Change-Id: I270d35983083f368e36afd96a62c768161d49942
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/333518
Commit-Queue: Tyler Denniston <tdenniston@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
This commit is contained in:
Tyler Denniston 2020-11-10 13:13:28 -05:00 committed by Skia Commit-Bot
parent 7712db9c24
commit a0a5146ba9
12 changed files with 145 additions and 264 deletions

View File

@ -20,14 +20,9 @@ public:
bool parseFilter(SkSVGFilterType*);
bool parseNumber(SkSVGNumberType*);
bool parseInteger(SkSVGIntegerType*);
bool parseLength(SkSVGLength*);
bool parseViewBox(SkSVGViewBoxType*);
bool parseTransform(SkSVGTransformType*);
bool parsePoints(SkSVGPointsType*);
bool parseIRI(SkSVGStringType*);
bool parseSpreadMethod(SkSVGSpreadMethod*);
bool parseStopColor(SkSVGStopColor*);
bool parseObjectBoundingBoxUnits(SkSVGObjectBoundingBoxUnits*);
bool parsePreserveAspectRatio(SkSVGPreserveAspectRatio*);
// TODO: Migrate all parse*() functions to this style (and delete the old version)
@ -37,22 +32,27 @@ public:
template <typename T> using ParseResult = SkTLazy<T>;
template <typename T> static ParseResult<T> parse(const char* value) {
ParseResult<T> result;
T parsedValue;
if (SkSVGAttributeParser(value).parse(&parsedValue)) {
result.set(std::move(parsedValue));
}
return result;
}
template <typename T>
static ParseResult<T> parse(const char* expectedName,
const char* name,
const char* value) {
ParseResult<T> result;
if (!strcmp(name, expectedName)) {
T parsedValue;
if (SkSVGAttributeParser(value).parse(&parsedValue)) {
result.set(std::move(parsedValue));
}
return parse<T>(value);
}
return result;
return ParseResult<T>();
}
private:
// Stack-only
void* operator new(size_t) = delete;

View File

@ -20,15 +20,17 @@ class SkSVGGradient : public SkSVGHiddenContainer {
public:
~SkSVGGradient() override = default;
void setHref(const SkSVGStringType&);
void setGradientTransform(const SkSVGTransformType&);
void setSpreadMethod(const SkSVGSpreadMethod&);
void setGradientUnits(const SkSVGObjectBoundingBoxUnits&);
SVG_ATTR(Href, SkSVGIRI, SkSVGIRI())
SVG_ATTR(GradientTransform, SkSVGTransformType, SkSVGTransformType(SkMatrix::I()))
SVG_ATTR(SpreadMethod, SkSVGSpreadMethod, SkSVGSpreadMethod(SkSVGSpreadMethod::Type::kPad))
SVG_ATTR(GradientUnits,
SkSVGObjectBoundingBoxUnits,
SkSVGObjectBoundingBoxUnits(SkSVGObjectBoundingBoxUnits::Type::kObjectBoundingBox))
protected:
explicit SkSVGGradient(SkSVGTag t) : INHERITED(t) {}
void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
bool parseAndSetAttribute(const char*, const char*) override;
bool onAsPaint(const SkSVGRenderContext&, SkPaint*) const final;
@ -36,19 +38,12 @@ protected:
const SkColor*, const SkScalar*, int count,
SkTileMode, const SkMatrix& localMatrix) const = 0;
SkSVGObjectBoundingBoxUnits fGradientUnits =
SkSVGObjectBoundingBoxUnits(SkSVGObjectBoundingBoxUnits::Type::kObjectBoundingBox);
private:
using StopPositionArray = SkSTArray<2, SkScalar, true>;
using StopColorArray = SkSTArray<2, SkColor, true>;
void collectColorStops(const SkSVGRenderContext&, StopPositionArray*, StopColorArray*) const;
SkColor resolveStopColor(const SkSVGRenderContext&, const SkSVGStop&) const;
SkSVGStringType fHref;
SkSVGTransformType fGradientTransform = SkSVGTransformType(SkMatrix::I());
SkSVGSpreadMethod fSpreadMethod = SkSVGSpreadMethod(SkSVGSpreadMethod::Type::kPad);
using INHERITED = SkSVGHiddenContainer;
};

View File

@ -18,13 +18,13 @@ public:
return sk_sp<SkSVGLinearGradient>(new SkSVGLinearGradient());
}
void setX1(const SkSVGLength&);
void setY1(const SkSVGLength&);
void setX2(const SkSVGLength&);
void setY2(const SkSVGLength&);
SVG_ATTR(X1, SkSVGLength, SkSVGLength(0 , SkSVGLength::Unit::kPercentage))
SVG_ATTR(Y1, SkSVGLength, SkSVGLength(0 , SkSVGLength::Unit::kPercentage))
SVG_ATTR(X2, SkSVGLength, SkSVGLength(100, SkSVGLength::Unit::kPercentage))
SVG_ATTR(Y2, SkSVGLength, SkSVGLength(0 , SkSVGLength::Unit::kPercentage))
protected:
void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
bool parseAndSetAttribute(const char*, const char*) override;
sk_sp<SkShader> onMakeShader(const SkSVGRenderContext&,
const SkColor*, const SkScalar*, int count,
@ -32,11 +32,6 @@ protected:
private:
SkSVGLinearGradient();
SkSVGLength fX1 = SkSVGLength(0 , SkSVGLength::Unit::kPercentage);
SkSVGLength fY1 = SkSVGLength(0 , SkSVGLength::Unit::kPercentage);
SkSVGLength fX2 = SkSVGLength(100, SkSVGLength::Unit::kPercentage);
SkSVGLength fY2 = SkSVGLength(0 , SkSVGLength::Unit::kPercentage);
using INHERITED = SkSVGGradient;
};

View File

@ -155,22 +155,40 @@ private:
#undef SVG_PRES_ATTR // presentation attributes are only defined for the base class
#define _SVG_ATTR_SETTERS(attr_name, attr_type, attr_default, set_cp, set_mv) \
private: \
bool set##attr_name( \
const SkSVGAttributeParser::ParseResult<attr_type>& pr) { \
if (pr.isValid()) { this->set##attr_name(*pr); } \
return pr.isValid(); \
} \
bool set##attr_name( \
SkSVGAttributeParser::ParseResult<attr_type>&& pr) { \
if (pr.isValid()) { this->set##attr_name(std::move(*pr)); } \
return pr.isValid(); \
} \
public: \
void set##attr_name(const attr_type& a) { set_cp(a); } \
void set##attr_name(attr_type&& a) { set_mv(std::move(a)); }
#define SVG_ATTR(attr_name, attr_type, attr_default) \
private: \
attr_type f##attr_name = attr_default; \
bool set##attr_name( \
const SkSVGAttributeParser::ParseResult<attr_type>& pr) { \
if (pr.isValid()) { this->set##attr_name(*pr); } \
return pr.isValid(); \
} \
bool set##attr_name( \
SkSVGAttributeParser::ParseResult<attr_type>&& pr) { \
if (pr.isValid()) { this->set##attr_name(std::move(*pr)); } \
return pr.isValid(); \
} \
public: \
const attr_type& get##attr_name() const { return f##attr_name; } \
void set##attr_name(const attr_type& a) { f##attr_name = a; } \
void set##attr_name(attr_type&& a) { f##attr_name = std::move(a); }
_SVG_ATTR_SETTERS( \
attr_name, attr_type, attr_default, \
[this](const attr_type& a) { this->f##attr_name = a; }, \
[this](attr_type&& a) { this->f##attr_name = std::move(a); })
#define SVG_OPTIONAL_ATTR(attr_name, attr_type) \
private: \
SkTLazy<attr_type> f##attr_name; \
public: \
const SkTLazy<attr_type>& get##attr_name() const { return f##attr_name; } \
_SVG_ATTR_SETTERS( \
attr_name, attr_type, attr_default, \
[this](const attr_type& a) { this->f##attr_name.set(a); }, \
[this](attr_type&& a) { this->f##attr_name.set(std::move(a)); })
#endif // SkSVGNode_DEFINED

View File

@ -18,14 +18,14 @@ public:
return sk_sp<SkSVGRadialGradient>(new SkSVGRadialGradient());
}
void setCx(const SkSVGLength&);
void setCy(const SkSVGLength&);
void setR(const SkSVGLength&);
void setFx(const SkSVGLength&);
void setFy(const SkSVGLength&);
SVG_ATTR(Cx, SkSVGLength, SkSVGLength(50, SkSVGLength::Unit::kPercentage))
SVG_ATTR(Cy, SkSVGLength, SkSVGLength(50, SkSVGLength::Unit::kPercentage))
SVG_ATTR(R, SkSVGLength, SkSVGLength(50, SkSVGLength::Unit::kPercentage))
SVG_OPTIONAL_ATTR(Fx, SkSVGLength)
SVG_OPTIONAL_ATTR(Fy, SkSVGLength)
protected:
void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
bool parseAndSetAttribute(const char*, const char*) override;
sk_sp<SkShader> onMakeShader(const SkSVGRenderContext&,
const SkColor*, const SkScalar*, int count,
@ -33,14 +33,7 @@ protected:
private:
SkSVGRadialGradient();
SkSVGLength fCx = SkSVGLength(50, SkSVGLength::Unit::kPercentage);
SkSVGLength fCy = SkSVGLength(50, SkSVGLength::Unit::kPercentage);
SkSVGLength fR = SkSVGLength(50, SkSVGLength::Unit::kPercentage);
SkTLazy<SkSVGLength> fFx;
SkTLazy<SkSVGLength> fFy;
using INHERITED = SkSVGGradient;
using INHERITED = SkSVGGradient;
};
#endif // SkSVGRadialGradient_DEFINED

View File

@ -61,6 +61,10 @@ private:
Unit fUnit;
};
struct SkSVGIRI {
SkSVGStringType fIRI;
};
class SkSVGPaint {
public:
enum class Type {

View File

@ -26,7 +26,6 @@ public:
kPath,
kPoints,
kPreserveAspectRatio,
kSpreadMethod,
kStopColor,
kString,
kTransform,
@ -80,8 +79,6 @@ using SkSVGViewBoxValue = SkSVGWrapperValue<SkSVGViewBoxType , SkSVGValue:
using SkSVGNumberValue = SkSVGWrapperValue<SkSVGNumberType , SkSVGValue::Type::kNumber >;
using SkSVGPointsValue = SkSVGWrapperValue<SkSVGPointsType , SkSVGValue::Type::kPoints >;
using SkSVGStringValue = SkSVGWrapperValue<SkSVGStringType , SkSVGValue::Type::kString >;
using SkSVGSpreadMethodValue = SkSVGWrapperValue<SkSVGSpreadMethod ,
SkSVGValue::Type::kSpreadMethod>;
using SkSVGStopColorValue = SkSVGWrapperValue<SkSVGStopColor , SkSVGValue::Type::kStopColor >;
using SkSVGPreserveAspectRatioValue = SkSVGWrapperValue<SkSVGPreserveAspectRatio,

View File

@ -245,7 +245,8 @@ bool SkSVGAttributeParser::parseColor(SkSVGColorType* color) {
}
// https://www.w3.org/TR/SVG11/linking.html#IRIReference
bool SkSVGAttributeParser::parseIRI(SkSVGStringType* iri) {
template <>
bool SkSVGAttributeParser::parse(SkSVGIRI* iri) {
// consume preceding whitespace
this->parseWSToken();
@ -258,14 +259,19 @@ bool SkSVGAttributeParser::parseIRI(SkSVGStringType* iri) {
if (start == fCurPos) {
return false;
}
*iri = SkString(start, fCurPos - start);
*iri = {SkString(start, fCurPos - start)};
return true;
}
// https://www.w3.org/TR/SVG11/types.html#DataTypeFuncIRI
bool SkSVGAttributeParser::parseFuncIRI(SkSVGStringType* iri) {
return this->parseParenthesized("url", [this](SkSVGStringType* iri) -> bool {
return this->parseIRI(iri);
return this->parseParenthesized("url", [this](SkSVGStringType* iriString) -> bool {
SkSVGIRI iri;
if (this->parse(&iri)) {
*iriString = iri.fIRI;
return true;
}
return false;
}, iri);
}
@ -315,7 +321,8 @@ bool SkSVGAttributeParser::parseInteger(SkSVGIntegerType* number) {
}
// https://www.w3.org/TR/SVG11/types.html#DataTypeLength
bool SkSVGAttributeParser::parseLength(SkSVGLength* length) {
template <>
bool SkSVGAttributeParser::parse(SkSVGLength* length) {
SkScalar s;
SkSVGLength::Unit u = SkSVGLength::Unit::kNumber;
@ -461,7 +468,8 @@ bool SkSVGAttributeParser::parseSkewYToken(SkMatrix* matrix) {
}
// https://www.w3.org/TR/SVG11/coords.html#TransformAttribute
bool SkSVGAttributeParser::parseTransform(SkSVGTransformType* t) {
template <>
bool SkSVGAttributeParser::parse(SkSVGTransformType* t) {
SkMatrix matrix = SkMatrix::I();
bool parsed = false;
@ -587,29 +595,6 @@ bool SkSVGAttributeParser::parse(SkSVGLineJoin* join) {
return parsedValue && this->parseEOSToken();
}
// https://www.w3.org/TR/SVG11/pservers.html#LinearGradientElementSpreadMethodAttribute
bool SkSVGAttributeParser::parseSpreadMethod(SkSVGSpreadMethod* spread) {
static const struct {
SkSVGSpreadMethod::Type fType;
const char* fName;
} gSpreadInfo[] = {
{ SkSVGSpreadMethod::Type::kPad , "pad" },
{ SkSVGSpreadMethod::Type::kReflect, "reflect" },
{ SkSVGSpreadMethod::Type::kRepeat , "repeat" },
};
bool parsedValue = false;
for (size_t i = 0; i < SK_ARRAY_COUNT(gSpreadInfo); ++i) {
if (this->parseExpectedStringToken(gSpreadInfo[i].fName)) {
*spread = SkSVGSpreadMethod(gSpreadInfo[i].fType);
parsedValue = true;
break;
}
}
return parsedValue && this->parseEOSToken();
}
// https://www.w3.org/TR/SVG11/pservers.html#StopElement
bool SkSVGAttributeParser::parseStopColor(SkSVGStopColor* stopColor) {
SkSVGColorType c;
@ -628,8 +613,8 @@ bool SkSVGAttributeParser::parseStopColor(SkSVGStopColor* stopColor) {
}
// https://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBoxUnits
bool SkSVGAttributeParser::parseObjectBoundingBoxUnits(
SkSVGObjectBoundingBoxUnits* objectBoundingBoxUnits) {
template <>
bool SkSVGAttributeParser::parse(SkSVGObjectBoundingBoxUnits* objectBoundingBoxUnits) {
bool parsedValue = false;
if (this->parseExpectedStringToken("userSpaceOnUse")) {
*objectBoundingBoxUnits =
@ -774,7 +759,7 @@ bool SkSVGAttributeParser::parse(SkSVGDashArray* dashArray) {
for (;;) {
SkSVGLength dash;
// parseLength() also consumes trailing separators.
if (!this->parseLength(&dash)) {
if (!this->parse(&dash)) {
break;
}
@ -820,7 +805,7 @@ bool SkSVGAttributeParser::parse(SkSVGFontSize* size) {
parsedValue = true;
} else {
SkSVGLength length;
if (this->parseLength(&length)) {
if (this->parse(&length)) {
*size = SkSVGFontSize(length);
parsedValue = true;
}

View File

@ -54,13 +54,12 @@ bool SetColorAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
bool SetIRIAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
const char* stringValue) {
SkSVGStringType iri;
SkSVGAttributeParser parser(stringValue);
if (!parser.parseIRI(&iri)) {
auto parseResult = SkSVGAttributeParser::parse<SkSVGIRI>(stringValue);
if (!parseResult.isValid()) {
return false;
}
node->setAttribute(attr, SkSVGStringValue(iri));
node->setAttribute(attr, SkSVGStringValue(parseResult->fIRI));
return true;
}
@ -85,25 +84,23 @@ bool SetStringAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
bool SetTransformAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
const char* stringValue) {
SkSVGTransformType transform;
SkSVGAttributeParser parser(stringValue);
if (!parser.parseTransform(&transform)) {
auto parseResult = SkSVGAttributeParser::parse<SkSVGTransformType>(stringValue);
if (!parseResult.isValid()) {
return false;
}
node->setAttribute(attr, SkSVGTransformValue(transform));
node->setAttribute(attr, SkSVGTransformValue(*parseResult));
return true;
}
bool SetLengthAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
const char* stringValue) {
SkSVGLength length;
SkSVGAttributeParser parser(stringValue);
if (!parser.parseLength(&length)) {
auto parseResult = SkSVGAttributeParser::parse<SkSVGLength>(stringValue);
if (!parseResult.isValid()) {
return false;
}
node->setAttribute(attr, SkSVGLengthValue(length));
node->setAttribute(attr, SkSVGLengthValue(*parseResult));
return true;
}
@ -131,18 +128,6 @@ bool SetViewBoxAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
return true;
}
bool SetSpreadMethodAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
const char* stringValue) {
SkSVGSpreadMethod spread;
SkSVGAttributeParser parser(stringValue);
if (!parser.parseSpreadMethod(&spread)) {
return false;
}
node->setAttribute(attr, SkSVGSpreadMethodValue(spread));
return true;
}
bool SetStopColorAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
const char* stringValue) {
SkSVGStopColor stopColor;
@ -158,13 +143,12 @@ bool SetStopColorAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
bool SetObjectBoundingBoxUnitsAttribute(const sk_sp<SkSVGNode>& node,
SkSVGAttribute attr,
const char* stringValue) {
SkSVGObjectBoundingBoxUnits objectBoundingBoxUnits;
SkSVGAttributeParser parser(stringValue);
if (!parser.parseObjectBoundingBoxUnits(&objectBoundingBoxUnits)) {
auto parseResult = SkSVGAttributeParser::parse<SkSVGObjectBoundingBoxUnits>(stringValue);
if (!parseResult.isValid()) {
return false;
}
node->setAttribute(attr, SkSVGObjectBoundingBoxUnitsValue(objectBoundingBoxUnits));
node->setAttribute(attr, SkSVGObjectBoundingBoxUnitsValue(*parseResult));
return true;
}
@ -293,9 +277,6 @@ SortedDictionaryEntry<AttrParseInfo> gAttributeParseInfo[] = {
// focal point x & y
{ "fx" , { SkSVGAttribute::kFx , SetLengthAttribute }},
{ "fy" , { SkSVGAttribute::kFy , SetLengthAttribute }},
{ "gradientTransform" , { SkSVGAttribute::kGradientTransform, SetTransformAttribute }},
{ "gradientUnits" , { SkSVGAttribute::kGradientUnits ,
SetObjectBoundingBoxUnitsAttribute }},
{ "height" , { SkSVGAttribute::kHeight , SetLengthAttribute }},
{ "offset" , { SkSVGAttribute::kOffset , SetLengthAttribute }},
{ "opacity" , { SkSVGAttribute::kOpacity , SetNumberAttribute }},
@ -306,7 +287,6 @@ SortedDictionaryEntry<AttrParseInfo> gAttributeParseInfo[] = {
{ "r" , { SkSVGAttribute::kR , SetLengthAttribute }},
{ "rx" , { SkSVGAttribute::kRx , SetLengthAttribute }},
{ "ry" , { SkSVGAttribute::kRy , SetLengthAttribute }},
{ "spreadMethod" , { SkSVGAttribute::kSpreadMethod , SetSpreadMethodAttribute }},
{ "stop-color" , { SkSVGAttribute::kStopColor , SetStopColorAttribute }},
{ "stop-opacity" , { SkSVGAttribute::kStopOpacity , SetNumberAttribute }},
{ "stroke-dashoffset" , { SkSVGAttribute::kStrokeDashOffset , SetLengthAttribute }},

View File

@ -11,47 +11,15 @@
#include "modules/svg/include/SkSVGStop.h"
#include "modules/svg/include/SkSVGValue.h"
void SkSVGGradient::setHref(const SkSVGStringType& href) {
fHref = std::move(href);
}
void SkSVGGradient::setGradientTransform(const SkSVGTransformType& t) {
fGradientTransform = t;
}
void SkSVGGradient::setSpreadMethod(const SkSVGSpreadMethod& spread) {
fSpreadMethod = spread;
}
void SkSVGGradient::setGradientUnits(const SkSVGObjectBoundingBoxUnits& gradientUnits) {
fGradientUnits = gradientUnits;
}
void SkSVGGradient::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
switch (attr) {
case SkSVGAttribute::kGradientTransform:
if (const auto* t = v.as<SkSVGTransformValue>()) {
this->setGradientTransform(*t);
}
break;
case SkSVGAttribute::kHref:
if (const auto* href = v.as<SkSVGStringValue>()) {
this->setHref(*href);
}
break;
case SkSVGAttribute::kSpreadMethod:
if (const auto* spread = v.as<SkSVGSpreadMethodValue>()) {
this->setSpreadMethod(*spread);
}
break;
case SkSVGAttribute::kGradientUnits:
if (const auto* gradientUnits = v.as<SkSVGObjectBoundingBoxUnitsValue>()) {
this->setGradientUnits(*gradientUnits);
}
break;
default:
this->INHERITED::onSetAttribute(attr, v);
}
bool SkSVGGradient::parseAndSetAttribute(const char* name, const char* value) {
return INHERITED::parseAndSetAttribute(name, value) ||
this->setGradientTransform(SkSVGAttributeParser::parse<SkSVGTransformType>(
"gradientTransform", name, value)) ||
this->setHref(SkSVGAttributeParser::parse<SkSVGIRI>("xlink:href", name, value)) ||
this->setSpreadMethod(
SkSVGAttributeParser::parse<SkSVGSpreadMethod>("spreadMethod", name, value)) ||
this->setGradientUnits(SkSVGAttributeParser::parse<SkSVGObjectBoundingBoxUnits>(
"gradientUnits", name, value));
}
// https://www.w3.org/TR/SVG11/pservers.html#LinearGradientElementHrefAttribute
@ -74,8 +42,8 @@ void SkSVGGradient::collectColorStops(const SkSVGRenderContext& ctx,
SkASSERT(colors->count() == pos->count());
if (pos->empty() && !fHref.isEmpty()) {
const auto ref = ctx.findNodeById(fHref);
if (pos->empty() && !fHref.fIRI.isEmpty()) {
const auto ref = ctx.findNodeById(fHref.fIRI);
if (ref && (ref->tag() == SkSVGTag::kLinearGradient ||
ref->tag() == SkSVGTag::kRadialGradient)) {
static_cast<const SkSVGGradient*>(ref.get())->collectColorStops(ctx, pos, colors);
@ -139,3 +107,27 @@ bool SkSVGGradient::onAsPaint(const SkSVGRenderContext& ctx, SkPaint* paint) con
localMatrix));
return true;
}
// https://www.w3.org/TR/SVG11/pservers.html#LinearGradientElementSpreadMethodAttribute
template <>
bool SkSVGAttributeParser::parse(SkSVGSpreadMethod* spread) {
static const struct {
SkSVGSpreadMethod::Type fType;
const char* fName;
} gSpreadInfo[] = {
{ SkSVGSpreadMethod::Type::kPad , "pad" },
{ SkSVGSpreadMethod::Type::kReflect, "reflect" },
{ SkSVGSpreadMethod::Type::kRepeat , "repeat" },
};
bool parsedValue = false;
for (size_t i = 0; i < SK_ARRAY_COUNT(gSpreadInfo); ++i) {
if (this->parseExpectedStringToken(gSpreadInfo[i].fName)) {
*spread = SkSVGSpreadMethod(gSpreadInfo[i].fType);
parsedValue = true;
break;
}
}
return parsedValue && this->parseEOSToken();
}

View File

@ -12,47 +12,12 @@
SkSVGLinearGradient::SkSVGLinearGradient() : INHERITED(SkSVGTag::kLinearGradient) {}
void SkSVGLinearGradient::setX1(const SkSVGLength& x1) {
fX1 = x1;
}
void SkSVGLinearGradient::setY1(const SkSVGLength& y1) {
fY1 = y1;
}
void SkSVGLinearGradient::setX2(const SkSVGLength& x2) {
fX2 = x2;
}
void SkSVGLinearGradient::setY2(const SkSVGLength& y2) {
fY2 = y2;
}
void SkSVGLinearGradient::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
switch (attr) {
case SkSVGAttribute::kX1:
if (const auto* x1 = v.as<SkSVGLengthValue>()) {
this->setX1(*x1);
}
break;
case SkSVGAttribute::kY1:
if (const auto* y1 = v.as<SkSVGLengthValue>()) {
this->setY1(*y1);
}
break;
case SkSVGAttribute::kX2:
if (const auto* x2 = v.as<SkSVGLengthValue>()) {
this->setX2(*x2);
}
break;
case SkSVGAttribute::kY2:
if (const auto* y2 = v.as<SkSVGLengthValue>()) {
this->setY2(*y2);
}
break;
default:
this->INHERITED::onSetAttribute(attr, v);
}
bool SkSVGLinearGradient::parseAndSetAttribute(const char* name, const char* value) {
return INHERITED::parseAndSetAttribute(name, value) ||
this->setX1(SkSVGAttributeParser::parse<SkSVGLength>("x1", name, value)) ||
this->setY1(SkSVGAttributeParser::parse<SkSVGLength>("y1", name, value)) ||
this->setX2(SkSVGAttributeParser::parse<SkSVGLength>("x2", name, value)) ||
this->setY2(SkSVGAttributeParser::parse<SkSVGLength>("y2", name, value));
}
sk_sp<SkShader> SkSVGLinearGradient::onMakeShader(const SkSVGRenderContext& ctx,
@ -60,7 +25,7 @@ sk_sp<SkShader> SkSVGLinearGradient::onMakeShader(const SkSVGRenderContext& ctx,
int count, SkTileMode tm,
const SkMatrix& localMatrix) const {
const SkSVGLengthContext lctx =
fGradientUnits.type() == SkSVGObjectBoundingBoxUnits::Type::kObjectBoundingBox
this->getGradientUnits().type() == SkSVGObjectBoundingBoxUnits::Type::kObjectBoundingBox
? SkSVGLengthContext({1, 1})
: ctx.lengthContext();

View File

@ -12,56 +12,13 @@
SkSVGRadialGradient::SkSVGRadialGradient() : INHERITED(SkSVGTag::kRadialGradient) {}
void SkSVGRadialGradient::setCx(const SkSVGLength& cx) {
fCx = cx;
}
void SkSVGRadialGradient::setCy(const SkSVGLength& cy) {
fCy = cy;
}
void SkSVGRadialGradient::setR(const SkSVGLength& r) {
fR = r;
}
void SkSVGRadialGradient::setFx(const SkSVGLength& fx) {
fFx.set(fx);
}
void SkSVGRadialGradient::setFy(const SkSVGLength& fy) {
fFy.set(fy);
}
void SkSVGRadialGradient::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
switch (attr) {
case SkSVGAttribute::kCx:
if (const auto* cx = v.as<SkSVGLengthValue>()) {
this->setCx(*cx);
}
break;
case SkSVGAttribute::kCy:
if (const auto* cy = v.as<SkSVGLengthValue>()) {
this->setCy(*cy);
}
break;
case SkSVGAttribute::kR:
if (const auto* r = v.as<SkSVGLengthValue>()) {
this->setR(*r);
}
break;
case SkSVGAttribute::kFx:
if (const auto* fx = v.as<SkSVGLengthValue>()) {
this->setFx(*fx);
}
break;
case SkSVGAttribute::kFy:
if (const auto* fy = v.as<SkSVGLengthValue>()) {
this->setFy(*fy);
}
break;
default:
this->INHERITED::onSetAttribute(attr, v);
}
bool SkSVGRadialGradient::parseAndSetAttribute(const char* name, const char* value) {
return INHERITED::parseAndSetAttribute(name, value) ||
this->setCx(SkSVGAttributeParser::parse<SkSVGLength>("cx", name, value)) ||
this->setCy(SkSVGAttributeParser::parse<SkSVGLength>("cy", name, value)) ||
this->setR(SkSVGAttributeParser::parse<SkSVGLength>("r", name, value)) ||
this->setFx(SkSVGAttributeParser::parse<SkSVGLength>("fx", name, value)) ||
this->setFy(SkSVGAttributeParser::parse<SkSVGLength>("fy", name, value));
}
sk_sp<SkShader> SkSVGRadialGradient::onMakeShader(const SkSVGRenderContext& ctx,
@ -69,7 +26,7 @@ sk_sp<SkShader> SkSVGRadialGradient::onMakeShader(const SkSVGRenderContext& ctx,
int count, SkTileMode tm,
const SkMatrix& m) const {
const SkSVGLengthContext lctx =
fGradientUnits.type() == SkSVGObjectBoundingBoxUnits::Type::kObjectBoundingBox
this->getGradientUnits().type() == SkSVGObjectBoundingBoxUnits::Type::kObjectBoundingBox
? SkSVGLengthContext({1, 1})
: ctx.lengthContext();