svg_loader: set the higher priority of style attributes

issue #515
This commit is contained in:
Mira Grudzinska 2021-06-29 14:30:56 +02:00 committed by Mira Grudzinska
parent ca86907739
commit fff5bfee83
4 changed files with 74 additions and 34 deletions

View file

@ -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);

View file

@ -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

View file

@ -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
}

View file

@ -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