diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index 46a2970c..46627be7 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -723,7 +723,7 @@ static float _parseLength(const char* str, SvgLengthType* type) } -static bool _parseStyleAttr(void* data, const char* key, const char* value); +static bool _parseStyleAttr(void* data, const char* key, const char* value, bool style); static bool _attrParseSvgNode(void* data, const char* key, const char* value) @@ -761,7 +761,7 @@ static bool _attrParseSvgNode(void* data, const char* key, const char* value) } #endif else { - return _parseStyleAttr(loader, key, value); + return _parseStyleAttr(loader, key, value, false); } return true; } @@ -912,33 +912,35 @@ static void _handleDisplayAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, typedef void (*styleMethod)(SvgLoaderData* loader, SvgNode* node, const char* value); -#define STYLE_DEF(Name, Name1) { #Name, sizeof(#Name), _handle##Name1##Attr } +#define STYLE_DEF(Name, Name1, Flag) { #Name, sizeof(#Name), _handle##Name1##Attr, Flag } + static constexpr struct { const char* tag; int sz; styleMethod tagHandler; + SvgStyleFlags flag; } styleTags[] = { - STYLE_DEF(color, Color), - STYLE_DEF(fill, Fill), - STYLE_DEF(fill-rule, FillRule), - STYLE_DEF(fill-opacity, FillOpacity), - STYLE_DEF(opacity, Opacity), - STYLE_DEF(stroke, Stroke), - STYLE_DEF(stroke-width, StrokeWidth), - STYLE_DEF(stroke-linejoin, StrokeLineJoin), - STYLE_DEF(stroke-linecap, StrokeLineCap), - STYLE_DEF(stroke-opacity, StrokeOpacity), - STYLE_DEF(stroke-dasharray, StrokeDashArray), - STYLE_DEF(transform, Transform), - STYLE_DEF(clip-path, ClipPath), - STYLE_DEF(mask, Mask), - STYLE_DEF(display, Display) + STYLE_DEF(color, Color, SvgStyleFlags::Color), + STYLE_DEF(fill, Fill, SvgStyleFlags::Fill), + STYLE_DEF(fill-rule, FillRule, SvgStyleFlags::FillRule), + STYLE_DEF(fill-opacity, FillOpacity, SvgStyleFlags::FillOpacity), + STYLE_DEF(opacity, Opacity, SvgStyleFlags::Opacity), + STYLE_DEF(stroke, Stroke, SvgStyleFlags::Stroke), + STYLE_DEF(stroke-width, StrokeWidth, SvgStyleFlags::StrokeWidth), + STYLE_DEF(stroke-linejoin, StrokeLineJoin, SvgStyleFlags::StrokeLineJoin), + STYLE_DEF(stroke-linecap, StrokeLineCap, SvgStyleFlags::StrokeLineCap), + STYLE_DEF(stroke-opacity, StrokeOpacity, SvgStyleFlags::StrokeOpacity), + STYLE_DEF(stroke-dasharray, StrokeDashArray, SvgStyleFlags::StrokeDashArray), + STYLE_DEF(transform, Transform, SvgStyleFlags::Transform), + STYLE_DEF(clip-path, ClipPath, SvgStyleFlags::ClipPath), + STYLE_DEF(mask, Mask, SvgStyleFlags::Mask), + STYLE_DEF(display, Display, SvgStyleFlags::Display) }; -static bool _parseStyleAttr(void* data, const char* key, const char* value) +static bool _parseStyleAttr(void* data, const char* key, const char* value, bool style) { SvgLoaderData* loader = (SvgLoaderData*)data; SvgNode* node = loader->svgParse->node; @@ -953,7 +955,12 @@ static bool _parseStyleAttr(void* data, const char* key, const char* value) sz = strlen(key); for (unsigned int i = 0; i < sizeof(styleTags) / sizeof(styleTags[0]); i++) { if (styleTags[i].sz - 1 == sz && !strncmp(styleTags[i].tag, key, sz)) { - styleTags[i].tagHandler(loader, node, value); + if (style) { + styleTags[i].tagHandler(loader, node, value); + node->style->flags = (SvgStyleFlags)((int)node->style->flags | (int)styleTags[i].flag); + } else if (!((int)node->style->flags && (int)styleTags[i].flag)) { + styleTags[i].tagHandler(loader, node, value); + } return true; } } @@ -980,7 +987,7 @@ static bool _attrParseGNode(void* data, const char* key, const char* value) } else if (!strcmp(key, "mask")) { _handleMaskAttr(loader, node, value); } else { - return _parseStyleAttr(loader, key, value); + return _parseStyleAttr(loader, key, value, false); } return true; } @@ -1001,7 +1008,7 @@ static bool _attrParseClipPathNode(void* data, const char* key, const char* valu } else if (!strcmp(key, "id")) { node->id = _copyId(value); } else { - return _parseStyleAttr(loader, key, value); + return _parseStyleAttr(loader, key, value, false); } return true; } @@ -1019,7 +1026,7 @@ static bool _attrParseMaskNode(void* data, const char* key, const char* value) } else if (!strcmp(key, "id")) { node->id = _copyId(value); } else { - return _parseStyleAttr(loader, key, value); + return _parseStyleAttr(loader, key, value, false); } return true; } @@ -1161,7 +1168,7 @@ static bool _attrParsePathNode(void* data, const char* key, const char* value) } else if (!strcmp(key, "id")) { node->id = _copyId(value); } else { - return _parseStyleAttr(loader, key, value); + return _parseStyleAttr(loader, key, value, false); } return true; } @@ -1220,7 +1227,7 @@ static bool _attrParseCircleNode(void* data, const char* key, const char* value) } else if (!strcmp(key, "id")) { node->id = _copyId(value); } else { - return _parseStyleAttr(loader, key, value); + return _parseStyleAttr(loader, key, value, false); } return true; } @@ -1279,7 +1286,7 @@ static bool _attrParseEllipseNode(void* data, const char* key, const char* value } else if (!strcmp(key, "mask")) { _handleMaskAttr(loader, node, value); } else { - return _parseStyleAttr(loader, key, value); + return _parseStyleAttr(loader, key, value, false); } return true; } @@ -1356,7 +1363,7 @@ static bool _attrParsePolygonNode(void* data, const char* key, const char* value } else if (!strcmp(key, "id")) { node->id = _copyId(value); } else { - return _parseStyleAttr(loader, key, value); + return _parseStyleAttr(loader, key, value, false); } return true; } @@ -1435,7 +1442,7 @@ static bool _attrParseRectNode(void* data, const char* key, const char* value) } else if (!strcmp(key, "mask")) { _handleMaskAttr(loader, node, value); } else { - ret = _parseStyleAttr(loader, key, value); + ret = _parseStyleAttr(loader, key, value, false); } return ret; @@ -1497,7 +1504,7 @@ static bool _attrParseLineNode(void* data, const char* key, const char* value) } else if (!strcmp(key, "mask")) { _handleMaskAttr(loader, node, value); } else { - return _parseStyleAttr(loader, key, value); + return _parseStyleAttr(loader, key, value, false); } return true; } @@ -1955,7 +1962,7 @@ static SvgStyleGradient* _createRadialGradient(SvgLoaderData* loader, const char } -static bool _attrParseStops(void* data, const char* key, const char* value) +static bool _attrParseStops(void* data, const char* key, const char* value, bool style) { SvgLoaderData* loader = (SvgLoaderData*)data; auto stop = loader->svgParse->gradStop; @@ -1976,6 +1983,12 @@ static bool _attrParseStops(void* data, const char* key, const char* value) } +static bool _attrParseStops(void* data, const char* key, const char* value) +{ + return _attrParseStops(data, key, value, false); +} + + static void _handleLinearX1Attr(SvgLoaderData* loader, SvgLinearGradient* linear, const char* value) { linear->x1 = _gradientToFloat(loader->svgParse, value, SvgParserLengthType::Horizontal); diff --git a/src/loaders/svg/tvgSvgLoaderCommon.h b/src/loaders/svg/tvgSvgLoaderCommon.h index 8c432935..027c02f5 100644 --- a/src/loaders/svg/tvgSvgLoaderCommon.h +++ b/src/loaders/svg/tvgSvgLoaderCommon.h @@ -91,6 +91,31 @@ enum class SvgGradientType Radial }; +enum class SvgStyleFlags +{ + Color = 0x01, + Fill = 0x02, + FillRule = 0x04, + FillOpacity = 0x08, + Opacity = 0x010, + Stroke = 0x20, + StrokeWidth = 0x40, + StrokeLineJoin = 0x80, + StrokeLineCap = 0x100, + StrokeOpacity = 0x200, + StrokeDashArray = 0x400, + Transform = 0x800, + ClipPath = 0x1000, + Mask = 0x2000, + Display = 0x4000 +}; + +enum class SvgFillRule +{ + Winding = 0, + OddEven = 1 +}; + //Length type to recalculate %, pt, pc, mm, cm etc enum class SvgParserLengthType { @@ -258,6 +283,7 @@ struct SvgStyleProperty int opacity; SvgColor color; bool curColorSet; + SvgStyleFlags flags; }; struct SvgNode diff --git a/src/loaders/svg/tvgXmlParser.cpp b/src/loaders/svg/tvgXmlParser.cpp index ed2a9b84..770a3279 100644 --- a/src/loaders/svg/tvgXmlParser.cpp +++ b/src/loaders/svg/tvgXmlParser.cpp @@ -463,7 +463,7 @@ bool simpleXmlParse(const char* buf, unsigned bufLength, bool strip, simpleXMLCb } -bool simpleXmlParseW3CAttribute(const char* buf, simpleXMLAttributeCb func, const void* data) +bool simpleXmlParseW3CAttribute(const char* buf, simpleXMLW3CAttributeCb func, const void* data) { const char* end; char* key; @@ -509,11 +509,11 @@ bool simpleXmlParseW3CAttribute(const char* buf, simpleXMLAttributeCb func, cons val[_simpleXmlUnskipWhiteSpace(val + strlen(val) , val) - val] = '\0'; #ifdef THORVG_LOG_ENABLED - if (!func((void*)data, key, val)) { + if (!func((void*)data, key, val, true)) { if (!_isIgnoreUnsupportedLogAttributes(key, val)) printf("SVG: Unsupported attributes used [Elements type: %s][Id : %s][Attribute: %s][Value: %s]\n", simpleXmlNodeTypeToString(((SvgLoaderData*)data)->svgParse->node->type).c_str(), ((SvgLoaderData*)data)->svgParse->node->id ? ((SvgLoaderData*)data)->svgParse->node->id->c_str() : "NO_ID", key, val ? val : "NONE"); } #else - func((void*)data, key, val); + func((void*)data, key, val, true); #endif } diff --git a/src/loaders/svg/tvgXmlParser.h b/src/loaders/svg/tvgXmlParser.h index f7758190..df2dcf72 100644 --- a/src/loaders/svg/tvgXmlParser.h +++ b/src/loaders/svg/tvgXmlParser.h @@ -46,10 +46,11 @@ enum class SimpleXMLType typedef bool (*simpleXMLCb)(void* data, SimpleXMLType type, const char* content, unsigned length); typedef bool (*simpleXMLAttributeCb)(void* data, const char* key, const char* value); +typedef bool (*simpleXMLW3CAttributeCb)(void* data, const char* key, const char* value, bool style); bool simpleXmlParseAttributes(const char* buf, unsigned buflen, simpleXMLAttributeCb func, const void* data); bool simpleXmlParse(const char* buf, unsigned buflen, bool strip, simpleXMLCb func, const void* data); -bool simpleXmlParseW3CAttribute(const char* buf, simpleXMLAttributeCb func, const void* data); +bool simpleXmlParseW3CAttribute(const char* buf, simpleXMLW3CAttributeCb func, const void* data); const char *simpleXmlFindAttributesTag(const char* buf, unsigned buflen); #ifdef THORVG_LOG_ENABLED