[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:
parent
7712db9c24
commit
a0a5146ba9
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -61,6 +61,10 @@ private:
|
||||
Unit fUnit;
|
||||
};
|
||||
|
||||
struct SkSVGIRI {
|
||||
SkSVGStringType fIRI;
|
||||
};
|
||||
|
||||
class SkSVGPaint {
|
||||
public:
|
||||
enum class Type {
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 }},
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user