diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index 1d8c5508..d1594e47 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -45,9 +45,12 @@ #define STR_AS(A, B) !strcmp((A), (B)) -typedef bool (*parseAttributes)(const char* buf, unsigned bufLength, simpleXMLAttributeCb func, const void* data); +typedef bool (*parseAttributes)(const char* buf, unsigned bufLength, xmlAttributeCb func, const void* data); typedef SvgNode* (*FactoryMethod)(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func); typedef SvgStyleGradient* (*GradientFactoryMethod)(SvgLoaderData* loader, const char* buf, unsigned bufLength); +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 char* _skipSpace(const char* str, const char* end) { @@ -62,7 +65,6 @@ static char* _copyId(const char* str) { if (!str) return nullptr; if (strlen(str) == 0) return nullptr; - return duplicate(str); } @@ -77,7 +79,7 @@ static const char* _skipComma(const char* content) static bool _parseNumber(const char** content, const char** end, float* number) { - const char* _end = end ? *end : nullptr; + auto _end = end ? *end : nullptr; *number = toFloat(*content, (char**)&_end); //If the start of string is not number @@ -166,7 +168,7 @@ static float _gradientToFloat(const SvgParser* svgParse, const char* str, bool& { char* end = nullptr; - float parsedValue = toFloat(str, &end); + auto parsedValue = toFloat(str, &end); isPercentage = false; if (strstr(str, "%")) { @@ -189,7 +191,7 @@ static float _toOffset(const char* str) char* end = nullptr; auto strEnd = str + strlen(str); - float parsedValue = toFloat(str, &end); + auto parsedValue = toFloat(str, &end); end = _skipSpace(end, nullptr); auto ptr = strstr(str, "%"); @@ -206,7 +208,7 @@ static float _toOffset(const char* str) static int _toOpacity(const char* str) { char* end = nullptr; - float opacity = toFloat(str, &end); + auto opacity = toFloat(str, &end); if (end) { if (end[0] == '%' && end[1] == '\0') return lrint(opacity * 2.55f); @@ -228,9 +230,9 @@ static SvgMaskType _toMaskType(const char* str) //If any is omitted, will be rendered in its default order after the specified ones. static bool _toPaintOrder(const char* str) { - uint8_t position = 1; - uint8_t strokePosition = 0; - uint8_t fillPosition = 0; + auto position = 1; + auto strokePosition = 0; + auto fillPosition = 0; while (*str != '\0') { str = _skipSpace(str, nullptr); @@ -334,7 +336,7 @@ static void _parseDashArray(SvgLoaderData* loader, const char *str, SvgDash* das while (*str) { str = _skipComma(str); - float parsedValue = toFloat(str, &end); + auto parsedValue = toFloat(str, &end); if (str == end) break; if (parsedValue <= 0.0f) break; if (*end == '%') { @@ -398,9 +400,7 @@ static size_t _srcFromUrl(const char* url, char*& src) static unsigned char _parseColor(const char* value, char** end) { - float r; - - r = toFloat(value, end); + auto r = toFloat(value, end); *end = _skipSpace(*end, nullptr); if (**end == '%') { r = 255 * r / 100; @@ -574,79 +574,77 @@ static constexpr struct static bool _hslToRgb(float hue, float saturation, float brightness, uint8_t* red, uint8_t* green, uint8_t* blue) { - if (!red || !green || !blue) return false; - - float sv, vsf, f, p, q, t, v; - float _red = 0, _green = 0, _blue = 0; - uint32_t i = 0; + auto r = 0.0f, g = 0.0f, b = 0.0f; + auto i = 0; while (hue < 0) hue += 360.0f; hue = fmod(hue, 360.0f); saturation = saturation > 0 ? std::min(saturation, 1.0f) : 0.0f; brightness = brightness > 0 ? std::min(brightness, 1.0f) : 0.0f; - if (tvg::zero(saturation)) _red = _green = _blue = brightness; + if (tvg::zero(saturation)) r = g = b = brightness; else { if (tvg::equal(hue, 360.0)) hue = 0.0f; hue /= 60.0f; - v = (brightness <= 0.5f) ? (brightness * (1.0f + saturation)) : (brightness + saturation - (brightness * saturation)); - p = brightness + brightness - v; + auto v = (brightness <= 0.5f) ? (brightness * (1.0f + saturation)) : (brightness + saturation - (brightness * saturation)); + auto p = brightness + brightness - v; + float sv; if (!tvg::zero(v)) sv = (v - p) / v; - else sv = 0; + else sv = 0.0f; i = static_cast(hue); - f = hue - i; + auto f = hue - i; - vsf = v * sv * f; + auto vsf = v * sv * f; - t = p + vsf; - q = v - vsf; + auto t = p + vsf; + auto q = v - vsf; switch (i) { case 0: { - _red = v; - _green = t; - _blue = p; + r = v; + g = t; + b = p; break; } case 1: { - _red = q; - _green = v; - _blue = p; + r = q; + g = v; + b = p; break; } case 2: { - _red = p; - _green = v; - _blue = t; + r = p; + g = v; + b = t; break; } case 3: { - _red = p; - _green = q; - _blue = v; + r = p; + g = q; + b = v; break; } case 4: { - _red = t; - _green = p; - _blue = v; + r = t; + g = p; + b = v; break; } case 5: { - _red = v; - _green = p; - _blue = q; + r = v; + g = p; + b = q; break; } } } - *red = (uint8_t)nearbyint(_red * 255.0f); - *green = (uint8_t)nearbyint(_green * 255.0f); - *blue = (uint8_t)nearbyint(_blue * 255.0f); + *red = (uint8_t)nearbyint(r * 255.0f); + *green = (uint8_t)nearbyint(g * 255.0f); + *blue = (uint8_t)nearbyint(b * 255.0f); return true; } @@ -654,9 +652,7 @@ static bool _hslToRgb(float hue, float saturation, float brightness, uint8_t* re static bool _toColor(const char* str, uint8_t* r, uint8_t* g, uint8_t* b, char** ref) { - unsigned int len = strlen(str); - char *red, *green, *blue; - unsigned char tr, tg, tb; + auto len = strlen(str); if (len == 4 && str[0] == '#') { //Case for "#456" should be interpreted as "#445566" @@ -688,11 +684,12 @@ static bool _toColor(const char* str, uint8_t* r, uint8_t* g, uint8_t* b, char** } return true; } else if (len >= 10 && (str[0] == 'r' || str[0] == 'R') && (str[1] == 'g' || str[1] == 'G') && (str[2] == 'b' || str[2] == 'B') && str[3] == '(' && str[len - 1] == ')') { - tr = _parseColor(str + 4, &red); + char *red, *green, *blue; + auto tr = _parseColor(str + 4, &red); if (red && *red == ',') { - tg = _parseColor(red + 1, &green); + auto tg = _parseColor(red + 1, &green); if (green && *green == ',') { - tb = _parseColor(green + 1, &blue); + auto tb = _parseColor(green + 1, &blue); if (blue && blue[0] == ')' && blue[1] == '\0') { *r = tr; *g = tg; @@ -747,10 +744,10 @@ static bool _toColor(const char* str, uint8_t* r, uint8_t* g, uint8_t* b, char** static char* _parseNumbersArray(char* str, float* points, int* ptCount, int len) { int count = 0; - char* end = nullptr; str = _skipSpace(str, nullptr); while ((count < len) && (isdigit(*str) || *str == '-' || *str == '+' || *str == '.')) { + char* end = nullptr; points[count++] = toFloat(str, &end); str = end; str = _skipSpace(str, nullptr); @@ -807,8 +804,8 @@ static Matrix* _parseTransformationMatrix(const char* value) float points[POINT_CNT]; int ptCount = 0; - char* str = (char*)value; - char* end = str + strlen(str); + auto str = (char*)value; + auto end = str + strlen(str); while (str < end) { auto state = MatrixState::Unknown; @@ -902,10 +899,6 @@ static void _postpone(Array& nodes, SvgNode *node, char* id) } -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) { SvgLoaderData* loader = (SvgLoaderData*)data; @@ -951,7 +944,7 @@ static bool _attrParseSvgNode(void* data, const char* key, const char* value) } else if (STR_AS(key, "preserveAspectRatio")) { _parseAspectRatio(&value, &doc->align, &doc->meetOrSlice); } else if (STR_AS(key, "style")) { - return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); + return xmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); #ifdef THORVG_LOG_ENABLED } else if ((STR_AS(key, "x") || STR_AS(key, "y")) && fabsf(toFloat(value, nullptr)) > FLOAT_EPSILON) { TVGLOG("SVG", "Unsupported attributes used [Elements type: Svg][Attribute: %s][Value: %s]", key, value); @@ -1051,8 +1044,7 @@ static void _handleStrokeMiterlimitAttr(SvgLoaderData* loader, SvgNode* node, co // https://www.w3.org/TR/SVG2/painting.html#LineJoin // - A negative value for stroke-miterlimit must be treated as an illegal value. if (miterlimit < 0.0f) { - TVGERR("SVG", "A stroke-miterlimit change (%f <- %f) with a negative value is omitted.", - node->style->stroke.miterlimit, miterlimit); + TVGERR("SVG", "A stroke-miterlimit change (%f <- %f) with a negative value is omitted.", node->style->stroke.miterlimit, miterlimit); return; } @@ -1261,7 +1253,7 @@ static bool _attrParseGNode(void* data, const char* key, const char* value) SvgNode* node = loader->svgParse->node; if (STR_AS(key, "style")) { - return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); + return xmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); } else if (STR_AS(key, "transform")) { node->transform = _parseTransformationMatrix(value); } else if (STR_AS(key, "id")) { @@ -1292,7 +1284,7 @@ static bool _attrParseClipPathNode(void* data, const char* key, const char* valu SvgClipNode* clip = &(node->node.clip); if (STR_AS(key, "style")) { - return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); + return xmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); } else if (STR_AS(key, "transform")) { node->transform = _parseTransformationMatrix(value); } else if (STR_AS(key, "id")) { @@ -1311,12 +1303,12 @@ static bool _attrParseClipPathNode(void* data, const char* key, const char* valu static bool _attrParseMaskNode(void* data, const char* key, const char* value) { - SvgLoaderData* loader = (SvgLoaderData*)data; - SvgNode* node = loader->svgParse->node; - SvgMaskNode* mask = &(node->node.mask); + auto loader = (SvgLoaderData*)data; + auto node = loader->svgParse->node; + auto mask = &(node->node.mask); if (STR_AS(key, "style")) { - return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); + return xmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); } else if (STR_AS(key, "transform")) { node->transform = _parseTransformationMatrix(value); } else if (STR_AS(key, "id")) { @@ -1337,8 +1329,8 @@ static bool _attrParseMaskNode(void* data, const char* key, const char* value) static bool _attrParseCssStyleNode(void* data, const char* key, const char* value) { - SvgLoaderData* loader = (SvgLoaderData*)data; - SvgNode* node = loader->svgParse->node; + auto loader = (SvgLoaderData*)data; + auto node = loader->svgParse->node; if (STR_AS(key, "id")) { if (value) tvg::free(node->id); @@ -1373,7 +1365,6 @@ static bool _attrParseSymbolNode(void* data, const char* key, const char* value) } else { return _attrParseGNode(data, key, value); } - return true; } @@ -1433,7 +1424,6 @@ static bool _attrParseFilterNode(void* data, const char* key, const char* value) } else if (STR_AS(key, "filterUnits")) { if (STR_AS(value, "userSpaceOnUse")) filter->filterUserSpace = true; } - return true; } @@ -1484,22 +1474,13 @@ static SvgNode* _createNode(SvgNode* parent, SvgNodeType type) { SvgNode* node = tvg::calloc(1, sizeof(SvgNode)); - if (!node) return nullptr; - //Default fill property node->style = tvg::calloc(1, sizeof(SvgStyleProperty)); - if (!node->style) { - tvg::free(node); - return nullptr; - } - //Set the default values other than 0/false: https://www.w3.org/TR/SVGTiny12/painting.html#SpecifyingPaint node->style->opacity = 255; - node->style->fill.opacity = 255; node->style->fill.fillRule = FillRule::NonZero; - node->style->stroke.paint.none = true; node->style->stroke.opacity = 255; node->style->stroke.width = 1; @@ -1507,11 +1488,8 @@ static SvgNode* _createNode(SvgNode* parent, SvgNodeType type) node->style->stroke.join = StrokeJoin::Miter; node->style->stroke.miterlimit = 4.0f; node->style->stroke.scale = 1.0; - node->style->paintOrder = _toPaintOrder("fill stroke"); - node->style->display = true; - node->parent = parent; node->type = type; @@ -1523,19 +1501,14 @@ static SvgNode* _createNode(SvgNode* parent, SvgNodeType type) static SvgNode* _createDefsNode(TVG_UNUSED SvgLoaderData* loader, TVG_UNUSED SvgNode* parent, const char* buf, unsigned bufLength, TVG_UNUSED parseAttributes func) { if (loader->def && loader->doc->node.doc.defs) return loader->def; - SvgNode* node = _createNode(nullptr, SvgNodeType::Defs); - - loader->def = node; - loader->doc->node.doc.defs = node; - return node; + loader->def = loader->doc->node.doc.defs = _createNode(nullptr, SvgNodeType::Defs); + return loader->def; } static SvgNode* _createGNode(TVG_UNUSED SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func) { loader->svgParse->node = _createNode(parent, SvgNodeType::G); - if (!loader->svgParse->node) return nullptr; - func(buf, bufLength, _attrParseGNode, loader); return loader->svgParse->node; } @@ -1544,8 +1517,7 @@ static SvgNode* _createGNode(TVG_UNUSED SvgLoaderData* loader, SvgNode* parent, static SvgNode* _createSvgNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func) { loader->svgParse->node = _createNode(parent, SvgNodeType::Doc); - if (!loader->svgParse->node) return nullptr; - SvgDocNode* doc = &(loader->svgParse->node->node.doc); + auto doc = &(loader->svgParse->node->node.doc); loader->svgParse->global.w = 1.0f; loader->svgParse->global.h = 1.0f; @@ -1663,7 +1635,7 @@ static bool _attrParsePathNode(void* data, const char* key, const char* value) //Temporary: need to copy path->path = _copyId(value); } else if (STR_AS(key, "style")) { - return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); + return xmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); } else if (STR_AS(key, "clip-path")) { _handleClipPathAttr(loader, node, value); } else if (STR_AS(key, "mask")) { @@ -1727,7 +1699,7 @@ static bool _attrParseCircleNode(void* data, const char* key, const char* value) } if (STR_AS(key, "style")) { - return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); + return xmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); } else if (STR_AS(key, "clip-path")) { _handleClipPathAttr(loader, node, value); } else if (STR_AS(key, "mask")) { @@ -1796,7 +1768,7 @@ static bool _attrParseEllipseNode(void* data, const char* key, const char* value } else if (STR_AS(key, "class")) { _handleCssClassAttr(loader, node, value); } else if (STR_AS(key, "style")) { - return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); + return xmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); } else if (STR_AS(key, "clip-path")) { _handleClipPathAttr(loader, node, value); } else if (STR_AS(key, "mask")) { @@ -1847,7 +1819,7 @@ static bool _attrParsePolygonNode(void* data, const char* key, const char* value if (STR_AS(key, "points")) { return _attrParsePolygonPoints(value, polygon); } else if (STR_AS(key, "style")) { - return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); + return xmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); } else if (STR_AS(key, "clip-path")) { _handleClipPathAttr(loader, node, value); } else if (STR_AS(key, "mask")) { @@ -1936,7 +1908,7 @@ static bool _attrParseRectNode(void* data, const char* key, const char* value) } else if (STR_AS(key, "class")) { _handleCssClassAttr(loader, node, value); } else if (STR_AS(key, "style")) { - ret = simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); + ret = xmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); } else if (STR_AS(key, "clip-path")) { _handleClipPathAttr(loader, node, value); } else if (STR_AS(key, "mask")) { @@ -2001,7 +1973,7 @@ static bool _attrParseLineNode(void* data, const char* key, const char* value) } else if (STR_AS(key, "class")) { _handleCssClassAttr(loader, node, value); } else if (STR_AS(key, "style")) { - return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); + return xmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); } else if (STR_AS(key, "clip-path")) { _handleClipPathAttr(loader, node, value); } else if (STR_AS(key, "mask")) { @@ -2076,7 +2048,7 @@ static bool _attrParseImageNode(void* data, const char* key, const char* value) } else if (STR_AS(key, "class")) { _handleCssClassAttr(loader, node, value); } else if (STR_AS(key, "style")) { - return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); + return xmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); } else if (STR_AS(key, "clip-path")) { _handleClipPathAttr(loader, node, value); } else if (STR_AS(key, "mask")) { @@ -2143,7 +2115,7 @@ static SvgNode* _getDefsNode(SvgNode* node) { if (!node) return nullptr; - while (node->parent != nullptr) { + while (node->parent) { node = node->parent; } @@ -2158,16 +2130,14 @@ static SvgNode* _findNodeById(SvgNode *node, const char* id) { if (!node) return nullptr; - SvgNode* result = nullptr; if (node->id && STR_AS(node->id, id)) return node; if (node->child.count > 0) { ARRAY_FOREACH(p, node->child) { - result = _findNodeById(*p, id); - if (result) break; + if (auto result = _findNodeById(*p, id)) return result; } } - return result; + return nullptr; } @@ -2291,7 +2261,7 @@ static bool _attrParseTextNode(void* data, const char* key, const char* value) text->fontFamily = duplicate(value); } } else if (STR_AS(key, "style")) { - return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); + return xmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader); } else if (STR_AS(key, "clip-path")) { _handleClipPathAttr(loader, node, value); } else if (STR_AS(key, "mask")) { @@ -2677,7 +2647,7 @@ static SvgStyleGradient* _createRadialGradient(SvgLoaderData* loader, const char loader->svgParse->gradient.parsedFx = false; loader->svgParse->gradient.parsedFy = false; - simpleXmlParseAttributes(buf, bufLength, + xmlParseAttributes(buf, bufLength, _attrParseRadialGradientNode, loader); for (unsigned int i = 0; i < sizeof(radialTags) / sizeof(radialTags[0]); i++) { @@ -2748,7 +2718,7 @@ static bool _attrParseStops(void* data, const char* key, const char* value) _toColor(value, &stop->r, &stop->g, &stop->b, nullptr); } } else if (STR_AS(key, "style")) { - simpleXmlParseW3CAttribute(value, strlen(value), _attrParseStopsStyle, data); + xmlParseW3CAttribute(value, strlen(value), _attrParseStopsStyle, data); } else { return false; } @@ -2957,7 +2927,7 @@ static SvgStyleGradient* _createLinearGradient(SvgLoaderData* loader, const char grad->linear->x2 = 1.0f; grad->linear->isX2Percentage = true; - simpleXmlParseAttributes(buf, bufLength, _attrParseLinearGradientNode, loader); + xmlParseAttributes(buf, bufLength, _attrParseLinearGradientNode, loader); for (unsigned int i = 0; i < sizeof(linear_tags) / sizeof(linear_tags[0]); i++) { linear_tags[i].tagRecalc(loader, grad->linear, grad->userSpace); @@ -3454,7 +3424,7 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content, GradientFactoryMethod gradientMethod; SvgNode *node = nullptr, *parent = nullptr; loader->level++; - attrs = simpleXmlFindAttributesTag(content, length); + attrs = xmlFindAttributesTag(content, length); if (!attrs) { //Parse the empty tag @@ -3478,7 +3448,7 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content, if (empty) return; if (!loader->doc) { if (!STR_AS(tagName, "svg")) return; //Not a valid svg document - node = method(loader, nullptr, attrs, attrsLength, simpleXmlParseAttributes); + node = method(loader, nullptr, attrs, attrsLength, xmlParseAttributes); loader->doc = node; } else { if (STR_AS(tagName, "svg")) return; //Already loaded (SvgNodeType::Doc) tag @@ -3488,13 +3458,13 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content, // TODO: For now only the first style node is saved. After the css id selector // is introduced this if condition shouldn't be necessary any more if (!loader->cssStyle) { - node = method(loader, nullptr, attrs, attrsLength, simpleXmlParseAttributes); + node = method(loader, nullptr, attrs, attrsLength, xmlParseAttributes); loader->cssStyle = node; loader->doc->node.doc.style = node; loader->openedTag = OpenedTagType::Style; } } else { - node = method(loader, parent, attrs, attrsLength, simpleXmlParseAttributes); + node = method(loader, parent, attrs, attrsLength, xmlParseAttributes); } } @@ -3506,7 +3476,7 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content, } else if ((method = _findGraphicsFactory(tagName))) { if (loader->stack.count > 0) parent = loader->stack.last(); else parent = loader->doc; - node = method(loader, parent, attrs, attrsLength, simpleXmlParseAttributes); + node = method(loader, parent, attrs, attrsLength, xmlParseAttributes); if (node && !empty) { if (STR_AS(tagName, "text")) loader->openedTag = OpenedTagType::Text; auto defs = _createDefsNode(loader, nullptr, nullptr, 0, nullptr); @@ -3537,7 +3507,7 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content, /* default value for opacity */ loader->svgParse->gradStop = {0.0f, 0, 0, 0, 255}; loader->svgParse->flags = SvgStopStyleFlags::StopDefault; - simpleXmlParseAttributes(attrs, attrsLength, _attrParseStops, loader); + xmlParseAttributes(attrs, attrsLength, _attrParseStops, loader); loader->latestGradient->stops.push(loader->svgParse->gradStop); } else { loader->latestGradient = nullptr; @@ -3548,8 +3518,8 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content, static void _svgLoaderParserText(SvgLoaderData* loader, const char* content, unsigned int length) { - auto text = &loader->svgParse->node->node.text; - text->text = append(text->text, content, length); + auto& text = loader->svgParse->node->node.text; + text.text = append(text.text, content, length); } @@ -3564,19 +3534,19 @@ static void _svgLoaderParserXmlCssStyle(SvgLoaderData* loader, const char* conte GradientFactoryMethod gradientMethod; SvgNode *node = nullptr; - while (auto next = simpleXmlParseCSSAttribute(content, length, &tag, &name, &attrs, &attrsLength)) { + while (auto next = xmlParseCSSAttribute(content, length, &tag, &name, &attrs, &attrsLength)) { if ((method = _findGroupFactory(tag))) { - if ((node = method(loader, loader->cssStyle, attrs, attrsLength, simpleXmlParseW3CAttribute))) node->id = _copyId(name); + if ((node = method(loader, loader->cssStyle, attrs, attrsLength, xmlParseW3CAttribute))) node->id = _copyId(name); } else if ((method = _findGraphicsFactory(tag))) { - if ((node = method(loader, loader->cssStyle, attrs, attrsLength, simpleXmlParseW3CAttribute))) node->id = _copyId(name); + if ((node = method(loader, loader->cssStyle, attrs, attrsLength, xmlParseW3CAttribute))) node->id = _copyId(name); } else if ((gradientMethod = _findGradientFactory(tag))) { TVGLOG("SVG", "Unsupported elements used in the internal CSS style sheets [Elements: %s]", tag); } else if (STR_AS(tag, "stop")) { TVGLOG("SVG", "Unsupported elements used in the internal CSS style sheets [Elements: %s]", tag); } else if (STR_AS(tag, "all")) { - if ((node = _createCssStyleNode(loader, loader->cssStyle, attrs, attrsLength, simpleXmlParseW3CAttribute))) node->id = _copyId(name); + if ((node = _createCssStyleNode(loader, loader->cssStyle, attrs, attrsLength, xmlParseW3CAttribute))) node->id = _copyId(name); } else if (STR_AS(tag, "@font-face")) { //css at-rule specifying font - _createFontFace(loader, attrs, attrsLength, simpleXmlParseW3CAttribute); + _createFontFace(loader, attrs, attrsLength, xmlParseW3CAttribute); } else if (!isIgnoreUnsupportedLogElements(tag)) { TVGLOG("SVG", "Unsupported elements used in the internal CSS style sheets [Elements: %s]", tag); } @@ -3591,35 +3561,35 @@ static void _svgLoaderParserXmlCssStyle(SvgLoaderData* loader, const char* conte } -static bool _svgLoaderParser(void* data, SimpleXMLType type, const char* content, unsigned int length) +static bool _svgLoaderParser(void* data, XMLType type, const char* content, unsigned int length) { SvgLoaderData* loader = (SvgLoaderData*)data; switch (type) { - case SimpleXMLType::Open: { + case XMLType::Open: { _svgLoaderParserXmlOpen(loader, content, length, false); break; } - case SimpleXMLType::OpenEmpty: { + case XMLType::OpenEmpty: { _svgLoaderParserXmlOpen(loader, content, length, true); break; } - case SimpleXMLType::Close: { + case XMLType::Close: { _svgLoaderParserXmlClose(loader, content, length); break; } - case SimpleXMLType::Data: - case SimpleXMLType::CData: { + case XMLType::Data: + case XMLType::CData: { if (loader->openedTag == OpenedTagType::Style) _svgLoaderParserXmlCssStyle(loader, content, length); else if (loader->openedTag == OpenedTagType::Text) _svgLoaderParserText(loader, content, length); break; } - case SimpleXMLType::DoctypeChild: { + case XMLType::DoctypeChild: { break; } - case SimpleXMLType::Ignored: - case SimpleXMLType::Comment: - case SimpleXMLType::Doctype: { + case XMLType::Ignored: + case XMLType::Comment: + case XMLType::Doctype: { break; } default: { @@ -3631,91 +3601,44 @@ static bool _svgLoaderParser(void* data, SimpleXMLType type, const char* content } -static void _inefficientNodeCheck(TVG_UNUSED SvgNode* node) -{ -#ifdef THORVG_LOG_ENABLED - auto type = simpleXmlNodeTypeToString(node->type); - - if (!node->style->display && node->type != SvgNodeType::ClipPath) TVGLOG("SVG", "Inefficient elements used [Display is none][Node Type : %s]", type); - if (node->style->opacity == 0) TVGLOG("SVG", "Inefficient elements used [Opacity is zero][Node Type : %s]", type); - if (node->style->fill.opacity == 0 && node->style->stroke.opacity == 0) TVGLOG("SVG", "Inefficient elements used [Fill opacity and stroke opacity are zero][Node Type : %s]", type); - - switch (node->type) { - case SvgNodeType::Path: { - if (!node->node.path.path) TVGLOG("SVG", "Inefficient elements used [Empty path][Node Type : %s]", type); - break; - } - case SvgNodeType::Ellipse: { - if (node->node.ellipse.rx == 0 && node->node.ellipse.ry == 0) TVGLOG("SVG", "Inefficient elements used [Size is zero][Node Type : %s]", type); - break; - } - case SvgNodeType::Polygon: - case SvgNodeType::Polyline: { - if (node->node.polygon.pts.count < 2) TVGLOG("SVG", "Inefficient elements used [Invalid Polygon][Node Type : %s]", type); - break; - } - case SvgNodeType::Circle: { - if (node->node.circle.r == 0) TVGLOG("SVG", "Inefficient elements used [Size is zero][Node Type : %s]", type); - break; - } - case SvgNodeType::Rect: { - if (node->node.rect.w == 0 && node->node.rect.h) TVGLOG("SVG", "Inefficient elements used [Size is zero][Node Type : %s]", type); - break; - } - case SvgNodeType::Line: { - if (node->node.line.x1 == node->node.line.x2 && node->node.line.y1 == node->node.line.y2) TVGLOG("SVG", "Inefficient elements used [Size is zero][Node Type : %s]", type); - break; - } - default: break; - } -#endif -} - - static void _updateStyle(SvgNode* node, SvgStyleProperty* parentStyle) { _styleInherit(node->style, parentStyle); - _inefficientNodeCheck(node); - ARRAY_FOREACH(p, node->child) { _updateStyle(*p, node->style); } } -static SvgStyleGradient* _gradientDup(SvgLoaderData* loader, Array* gradients, const char* id) +static void _updateGradient(SvgLoaderData* loader, SvgNode* node, Array* gradients) { - SvgStyleGradient* result = nullptr; + auto duplicate = [&](SvgLoaderData* loader, Array* gradients, const char* id) -> SvgStyleGradient* { + SvgStyleGradient* result = nullptr; - ARRAY_FOREACH(p, *gradients) { - if ((*p)->id && STR_AS((*p)->id, id)) { - result = _cloneGradient(*p); - break; - } - } - - if (result && result->ref) { ARRAY_FOREACH(p, *gradients) { - if ((*p)->id && STR_AS((*p)->id, result->ref)) { - _inheritGradient(loader, result, *p); + if ((*p)->id && STR_AS((*p)->id, id)) { + result = _cloneGradient(*p); break; } } - } + if (result && result->ref) { + ARRAY_FOREACH(p, *gradients) { + if ((*p)->id && STR_AS((*p)->id, result->ref)) { + _inheritGradient(loader, result, *p); + break; + } + } + } + return result; + }; - return result; -} - - -static void _updateGradient(SvgLoaderData* loader, SvgNode* node, Array* gradients) -{ if (node->child.count > 0) { ARRAY_FOREACH(p, node->child) { _updateGradient(loader, *p, gradients); } } else { if (node->style->fill.paint.url) { - auto newGrad = _gradientDup(loader, gradients, node->style->fill.paint.url); + auto newGrad = duplicate(loader, gradients, node->style->fill.paint.url); if (newGrad) { if (node->style->fill.paint.gradient) { node->style->fill.paint.gradient->clear(); @@ -3725,7 +3648,7 @@ static void _updateGradient(SvgLoaderData* loader, SvgNode* node, Arraystyle->stroke.paint.url) { - auto newGrad = _gradientDup(loader, gradients, node->style->stroke.paint.url); + auto newGrad = duplicate(loader, gradients, node->style->stroke.paint.url); if (newGrad) { if (node->style->stroke.paint.gradient) { node->style->stroke.paint.gradient->clear(); @@ -3759,14 +3682,10 @@ static void _updateComposite(SvgNode* node, SvgNode* root) static void _updateFilter(SvgNode* node, SvgNode* root) { if (node->style->filter.url && !node->style->filter.node) { - SvgNode* findResult = _findNodeById(root, node->style->filter.url); - if (findResult) node->style->filter.node = findResult; + node->style->filter.node = _findNodeById(root, node->style->filter.url); } - if (node->child.count > 0) { - auto child = node->child.data; - for (uint32_t i = 0; i < node->child.count; ++i, ++child) { - _updateFilter(*child, root); - } + ARRAY_FOREACH(child, node->child) { + _updateFilter(*child, root); } } @@ -3858,7 +3777,7 @@ static bool _svgLoaderParserForValidCheckXmlOpen(SvgLoaderData* loader, const ch SvgNode *node = nullptr; int attrsLength = 0; loader->level++; - attrs = simpleXmlFindAttributesTag(content, length); + attrs = xmlFindAttributesTag(content, length); if (!attrs) { //Parse the empty tag @@ -3878,7 +3797,7 @@ static bool _svgLoaderParserForValidCheckXmlOpen(SvgLoaderData* loader, const ch if ((method = _findGroupFactory(tagName))) { if (!loader->doc) { if (!STR_AS(tagName, "svg")) return true; //Not a valid svg document - node = method(loader, nullptr, attrs, attrsLength, simpleXmlParseAttributes); + node = method(loader, nullptr, attrs, attrsLength, xmlParseAttributes); loader->doc = node; loader->stack.push(node); return false; @@ -3888,24 +3807,16 @@ static bool _svgLoaderParserForValidCheckXmlOpen(SvgLoaderData* loader, const ch } -static bool _svgLoaderParserForValidCheck(void* data, SimpleXMLType type, const char* content, unsigned int length) +static bool _svgLoaderParserForValidCheck(void* data, XMLType type, const char* content, unsigned int length) { - SvgLoaderData* loader = (SvgLoaderData*)data; - bool res = true;; - switch (type) { - case SimpleXMLType::Open: - case SimpleXMLType::OpenEmpty: { + case XMLType::Open: + case XMLType::OpenEmpty: { //If 'res' is false, it means tag is found. - res = _svgLoaderParserForValidCheckXmlOpen(loader, content, length); - break; - } - default: { - break; + return _svgLoaderParserForValidCheckXmlOpen(static_cast(data), content, length); } + default: return true; } - - return res; } @@ -3973,7 +3884,7 @@ void SvgLoader::run(unsigned tid) return; } - if (!simpleXmlParse(content, size, true, _svgLoaderParser, &(loaderData))) return; + if (!xmlParse(content, size, true, _svgLoaderParser, &(loaderData))) return; if (loaderData.doc) { auto defs = loaderData.doc->node.doc.defs; @@ -3994,16 +3905,17 @@ void SvgLoader::run(unsigned tid) if (loaderData.gradients.count > 0) _updateGradient(&loaderData, loaderData.doc, &loaderData.gradients); if (defs) _updateGradient(&loaderData, loaderData.doc, &defs->node.defs.gradients); - } - root = svgSceneBuild(loaderData, vbox, w, h, align, meetOrSlice, svgPath, viewFlag); - //In case no viewbox and width/height data is provided the completion of loading - //has to be forced, in order to establish this data based on the whole picture. - if (!(viewFlag & SvgViewFlag::Viewbox)) { - //Override viewbox & size again after svg loading. - vbox = loaderData.doc->node.doc.vbox; - w = loaderData.doc->node.doc.w; - h = loaderData.doc->node.doc.h; + root = svgSceneBuild(loaderData, vbox, w, h, align, meetOrSlice, svgPath, viewFlag); + + //In case no viewbox and width/height data is provided the completion of loading + //has to be forced, in order to establish this data based on the whole picture. + if (!(viewFlag & SvgViewFlag::Viewbox)) { + //Override viewbox & size again after svg loading. + vbox = loaderData.doc->node.doc.vbox; + w = loaderData.doc->node.doc.w; + h = loaderData.doc->node.doc.h; + } } clear(false); @@ -4016,70 +3928,67 @@ bool SvgLoader::header() //If the tag is found, the loaded file is valid and stores viewbox information. //After that, the remaining content data is parsed in order with async. loaderData.svgParse = tvg::malloc(sizeof(SvgParser)); - if (!loaderData.svgParse) return false; - loaderData.svgParse->flags = SvgStopStyleFlags::StopDefault; viewFlag = SvgViewFlag::None; - simpleXmlParse(content, size, true, _svgLoaderParserForValidCheck, &(loaderData)); + xmlParse(content, size, true, _svgLoaderParserForValidCheck, &(loaderData)); - if (loaderData.doc && loaderData.doc->type == SvgNodeType::Doc) { - viewFlag = loaderData.doc->node.doc.viewFlag; - align = loaderData.doc->node.doc.align; - meetOrSlice = loaderData.doc->node.doc.meetOrSlice; - - if (viewFlag & SvgViewFlag::Viewbox) { - vbox = loaderData.doc->node.doc.vbox; - - if (viewFlag & SvgViewFlag::Width) w = loaderData.doc->node.doc.w; - else { - w = loaderData.doc->node.doc.vbox.w; - if (viewFlag & SvgViewFlag::WidthInPercent) { - w *= loaderData.doc->node.doc.w; - viewFlag = (viewFlag ^ SvgViewFlag::WidthInPercent); - } - viewFlag = (viewFlag | SvgViewFlag::Width); - } - if (viewFlag & SvgViewFlag::Height) h = loaderData.doc->node.doc.h; - else { - h = loaderData.doc->node.doc.vbox.h; - if (viewFlag & SvgViewFlag::HeightInPercent) { - h *= loaderData.doc->node.doc.h; - viewFlag = (viewFlag ^ SvgViewFlag::HeightInPercent); - } - viewFlag = (viewFlag | SvgViewFlag::Height); - } - //In case no viewbox and width/height data is provided the completion of loading - //has to be forced, in order to establish this data based on the whole picture. - } else { - //Before loading, set default viewbox & size if they are empty - vbox.x = vbox.y = 0.0f; - if (viewFlag & SvgViewFlag::Width) { - vbox.w = w = loaderData.doc->node.doc.w; - } else { - vbox.w = 1.0f; - if (viewFlag & SvgViewFlag::WidthInPercent) { - w = loaderData.doc->node.doc.w; - } else w = 1.0f; - } - - if (viewFlag & SvgViewFlag::Height) { - vbox.h = h = loaderData.doc->node.doc.h; - } else { - vbox.h = 1.0f; - if (viewFlag & SvgViewFlag::HeightInPercent) { - h = loaderData.doc->node.doc.h; - } else h = 1.0f; - } - - run(0); - } - - return true; + if (!loaderData.doc || loaderData.doc->type != SvgNodeType::Doc) { + TVGLOG("SVG", "No SVG File. There is no "); + return false; } - TVGLOG("SVG", "No SVG File. There is no "); - return false; + viewFlag = loaderData.doc->node.doc.viewFlag; + align = loaderData.doc->node.doc.align; + meetOrSlice = loaderData.doc->node.doc.meetOrSlice; + + if (viewFlag & SvgViewFlag::Viewbox) { + vbox = loaderData.doc->node.doc.vbox; + + if (viewFlag & SvgViewFlag::Width) w = loaderData.doc->node.doc.w; + else { + w = loaderData.doc->node.doc.vbox.w; + if (viewFlag & SvgViewFlag::WidthInPercent) { + w *= loaderData.doc->node.doc.w; + viewFlag = (viewFlag ^ SvgViewFlag::WidthInPercent); + } + viewFlag = (viewFlag | SvgViewFlag::Width); + } + if (viewFlag & SvgViewFlag::Height) h = loaderData.doc->node.doc.h; + else { + h = loaderData.doc->node.doc.vbox.h; + if (viewFlag & SvgViewFlag::HeightInPercent) { + h *= loaderData.doc->node.doc.h; + viewFlag = (viewFlag ^ SvgViewFlag::HeightInPercent); + } + viewFlag = (viewFlag | SvgViewFlag::Height); + } + //In case no viewbox and width/height data is provided the completion of loading + //has to be forced, in order to establish this data based on the whole picture. + } else { + //Before loading, set default viewbox & size if they are empty + vbox.x = vbox.y = 0.0f; + if (viewFlag & SvgViewFlag::Width) { + vbox.w = w = loaderData.doc->node.doc.w; + } else { + vbox.w = 1.0f; + if (viewFlag & SvgViewFlag::WidthInPercent) { + w = loaderData.doc->node.doc.w; + } else w = 1.0f; + } + + if (viewFlag & SvgViewFlag::Height) { + vbox.h = h = loaderData.doc->node.doc.h; + } else { + vbox.h = 1.0f; + if (viewFlag & SvgViewFlag::HeightInPercent) { + h = loaderData.doc->node.doc.h; + } else h = 1.0f; + } + + run(0); + } + return true; } diff --git a/src/loaders/svg/tvgXmlParser.cpp b/src/loaders/svg/tvgXmlParser.cpp index ce9902bf..1da761d0 100644 --- a/src/loaders/svg/tvgXmlParser.cpp +++ b/src/loaders/svg/tvgXmlParser.cpp @@ -29,7 +29,7 @@ /* Internal Class Implementation */ /************************************************************************/ -bool _isIgnoreUnsupportedLogAttributes(TVG_UNUSED const char* tagAttribute, TVG_UNUSED const char* tagValue) +bool _unsupported(TVG_UNUSED const char* tagAttribute, TVG_UNUSED const char* tagValue) { #ifdef THORVG_LOG_ENABLED const auto attributesNum = 6; @@ -48,22 +48,18 @@ bool _isIgnoreUnsupportedLogAttributes(TVG_UNUSED const char* tagAttribute, TVG_ }; for (unsigned int i = 0; i < attributesNum; ++i) { - if (!strncmp(tagAttribute, attributes[i].tag, attributes[i].tagWildcard ? strlen(attributes[i].tag) : strlen(tagAttribute))) { - if (attributes[i].value && tagValue) { - if (!strncmp(tagValue, attributes[i].value, strlen(tagValue))) { - return true; - } else continue; - } - return true; + if (tvg::equal(tagAttribute, attributes[i].tag)) { + if (!attributes[i].value) return false; + if (tvg::equal(tagValue, attributes[i].value)) return false; } } - return false; -#endif return true; +#endif + return false; } -static const char* _simpleXmlFindWhiteSpace(const char* itr, const char* itrEnd) +static const char* _xmlFindWhiteSpace(const char* itr, const char* itrEnd) { for (; itr < itrEnd; itr++) { if (isspace((unsigned char)*itr)) break; @@ -72,7 +68,7 @@ static const char* _simpleXmlFindWhiteSpace(const char* itr, const char* itrEnd) } -static const char* _simpleXmlSkipWhiteSpace(const char* itr, const char* itrEnd) +static const char* _xmlSkipWhiteSpace(const char* itr, const char* itrEnd) { for (; itr < itrEnd; itr++) { if (!isspace((unsigned char)*itr)) break; @@ -81,7 +77,7 @@ static const char* _simpleXmlSkipWhiteSpace(const char* itr, const char* itrEnd) } -static const char* _simpleXmlUnskipWhiteSpace(const char* itr, const char* itrStart) +static const char* _xmlUnskipWhiteSpace(const char* itr, const char* itrStart) { for (itr--; itr > itrStart; itr--) { if (!isspace((unsigned char)*itr)) break; @@ -90,7 +86,7 @@ static const char* _simpleXmlUnskipWhiteSpace(const char* itr, const char* itrSt } -static const char* _simpleXmlSkipXmlEntities(const char* itr, const char* itrEnd) +static const char* _xmlSkipXmlEntities(const char* itr, const char* itrEnd) { auto p = itr; while (itr < itrEnd && *itr == '&') { @@ -107,7 +103,7 @@ static const char* _simpleXmlSkipXmlEntities(const char* itr, const char* itrEnd } -static const char* _simpleXmlUnskipXmlEntities(const char* itr, const char* itrStart) +static const char* _xmlUnskipXmlEntities(const char* itr, const char* itrStart) { auto p = itr; while (itr > itrStart && *(itr - 1) == ';') { @@ -127,12 +123,12 @@ static const char* _simpleXmlUnskipXmlEntities(const char* itr, const char* itrS static const char* _skipWhiteSpacesAndXmlEntities(const char* itr, const char* itrEnd) { - itr = _simpleXmlSkipWhiteSpace(itr, itrEnd); + itr = _xmlSkipWhiteSpace(itr, itrEnd); auto p = itr; while (true) { - if (p != (itr = _simpleXmlSkipXmlEntities(itr, itrEnd))) p = itr; + if (p != (itr = _xmlSkipXmlEntities(itr, itrEnd))) p = itr; else break; - if (p != (itr = _simpleXmlSkipWhiteSpace(itr, itrEnd))) p = itr; + if (p != (itr = _xmlSkipWhiteSpace(itr, itrEnd))) p = itr; else break; } return itr; @@ -141,25 +137,25 @@ static const char* _skipWhiteSpacesAndXmlEntities(const char* itr, const char* i static const char* _unskipWhiteSpacesAndXmlEntities(const char* itr, const char* itrStart) { - itr = _simpleXmlUnskipWhiteSpace(itr, itrStart); + itr = _xmlUnskipWhiteSpace(itr, itrStart); auto p = itr; while (true) { - if (p != (itr = _simpleXmlUnskipXmlEntities(itr, itrStart))) p = itr; + if (p != (itr = _xmlUnskipXmlEntities(itr, itrStart))) p = itr; else break; - if (p != (itr = _simpleXmlUnskipWhiteSpace(itr, itrStart))) p = itr; + if (p != (itr = _xmlUnskipWhiteSpace(itr, itrStart))) p = itr; else break; } return itr; } -static const char* _simpleXmlFindStartTag(const char* itr, const char* itrEnd) +static const char* _xmlFindStartTag(const char* itr, const char* itrEnd) { return (const char*)memchr(itr, '<', itrEnd - itr); } -static const char* _simpleXmlFindEndTag(const char* itr, const char* itrEnd) +static const char* _xmlFindEndTag(const char* itr, const char* itrEnd) { bool insideQuote[2] = {false, false}; // 0: ", 1: ' for (; itr < itrEnd; itr++) { @@ -174,7 +170,7 @@ static const char* _simpleXmlFindEndTag(const char* itr, const char* itrEnd) } -static const char* _simpleXmlFindEndCommentTag(const char* itr, const char* itrEnd) +static const char* _xmlFindEndCommentTag(const char* itr, const char* itrEnd) { for (; itr < itrEnd; itr++) { if ((*itr == '-') && ((itr + 1 < itrEnd) && (*(itr + 1) == '-')) && ((itr + 2 < itrEnd) && (*(itr + 2) == '>'))) return itr + 2; @@ -183,7 +179,7 @@ static const char* _simpleXmlFindEndCommentTag(const char* itr, const char* itrE } -static const char* _simpleXmlFindEndCdataTag(const char* itr, const char* itrEnd) +static const char* _xmlFindEndCdataTag(const char* itr, const char* itrEnd) { for (; itr < itrEnd; itr++) { if ((*itr == ']') && ((itr + 1 < itrEnd) && (*(itr + 1) == ']')) && ((itr + 2 < itrEnd) && (*(itr + 2) == '>'))) return itr + 2; @@ -192,7 +188,7 @@ static const char* _simpleXmlFindEndCdataTag(const char* itr, const char* itrEnd } -static const char* _simpleXmlFindDoctypeChildEndTag(const char* itr, const char* itrEnd) +static const char* _xmlFindDoctypeChildEndTag(const char* itr, const char* itrEnd) { for (; itr < itrEnd; itr++) { if (*itr == '>') return itr; @@ -201,32 +197,32 @@ static const char* _simpleXmlFindDoctypeChildEndTag(const char* itr, const char* } -static SimpleXMLType _getXMLType(const char* itr, const char* itrEnd, size_t &toff) +static XMLType _getXMLType(const char* itr, const char* itrEnd, size_t &toff) { toff = 0; if (itr[1] == '/') { toff = 1; - return SimpleXMLType::Close; + return XMLType::Close; } else if (itr[1] == '?') { toff = 1; - return SimpleXMLType::Processing; + return XMLType::Processing; } else if (itr[1] == '!') { if ((itr + sizeof("") - 1 < itrEnd) && (!memcmp(itr + 2, "DOCTYPE", sizeof("DOCTYPE") - 1)) && ((itr[2 + sizeof("DOCTYPE") - 1] == '>') || (isspace((unsigned char)itr[2 + sizeof("DOCTYPE") - 1])))) { toff = sizeof("!DOCTYPE") - 1; - return SimpleXMLType::Doctype; + return XMLType::Doctype; } else if ((itr + sizeof("") - 1 < itrEnd) && (!memcmp(itr + 2, "[CDATA[", sizeof("[CDATA[") - 1))) { toff = sizeof("![CDATA[") - 1; - return SimpleXMLType::CData; + return XMLType::CData; } else if ((itr + sizeof("") - 1 < itrEnd) && (!memcmp(itr + 2, "--", sizeof("--") - 1))) { toff = sizeof("!--") - 1; - return SimpleXMLType::Comment; + return XMLType::Comment; } else if (itr + sizeof("") - 1 < itrEnd) { toff = sizeof("!") - 1; - return SimpleXMLType::DoctypeChild; + return XMLType::DoctypeChild; } - return SimpleXMLType::Open; + return XMLType::Open; } - return SimpleXMLType::Open; + return XMLType::Open; } @@ -234,7 +230,7 @@ static SimpleXMLType _getXMLType(const char* itr, const char* itrEnd, size_t &to /* External Class Implementation */ /************************************************************************/ -const char* simpleXmlNodeTypeToString(TVG_UNUSED SvgNodeType type) +const char* xmlNodeTypeToString(TVG_UNUSED SvgNodeType type) { #ifdef THORVG_LOG_ENABLED static const char* TYPE_NAMES[] = { @@ -285,7 +281,7 @@ bool isIgnoreUnsupportedLogElements(TVG_UNUSED const char* tagName) } -bool simpleXmlParseAttributes(const char* buf, unsigned bufLength, simpleXMLAttributeCb func, const void* data) +bool xmlParseAttributes(const char* buf, unsigned bufLength, xmlAttributeCb func, const void* data) { const char *itr = buf, *itrEnd = buf + bufLength; char* tmpBuf = tvg::malloc(bufLength + 1); @@ -315,7 +311,7 @@ bool simpleXmlParseAttributes(const char* buf, unsigned bufLength, simpleXMLAttr if (!value) goto error; value++; } - keyEnd = _simpleXmlUnskipXmlEntities(keyEnd, key); + keyEnd = _xmlUnskipXmlEntities(keyEnd, key); value = _skipWhiteSpacesAndXmlEntities(value, itrEnd); if (value == itrEnd) goto error; @@ -325,7 +321,7 @@ bool simpleXmlParseAttributes(const char* buf, unsigned bufLength, simpleXMLAttr if (!valueEnd) goto error; value++; } else { - valueEnd = _simpleXmlFindWhiteSpace(value, itrEnd); + valueEnd = _xmlFindWhiteSpace(value, itrEnd); } itr = valueEnd + 1; @@ -339,15 +335,15 @@ bool simpleXmlParseAttributes(const char* buf, unsigned bufLength, simpleXMLAttr tval = tmpBuf + (keyEnd - key) + 1; int i = 0; while (value < valueEnd) { - value = _simpleXmlSkipXmlEntities(value, valueEnd); + value = _xmlSkipXmlEntities(value, valueEnd); tval[i++] = *value; value++; } tval[i] = '\0'; if (!func((void*)data, tmpBuf, tval)) { - if (!_isIgnoreUnsupportedLogAttributes(tmpBuf, tval)) { - TVGLOG("SVG", "Unsupported attributes used [Elements type: %s][Id : %s][Attribute: %s][Value: %s]", simpleXmlNodeTypeToString(((SvgLoaderData*)data)->svgParse->node->type), ((SvgLoaderData*)data)->svgParse->node->id ? ((SvgLoaderData*)data)->svgParse->node->id : "NO_ID", tmpBuf, tval ? tval : "NONE"); + if (_unsupported(tmpBuf, tval)) { + TVGLOG("SVG", "Unsupported attributes used [Elements type: %s][Id : %s][Attribute: %s][Value: %s]", xmlNodeTypeToString(((SvgLoaderData*)data)->svgParse->node->type), ((SvgLoaderData*)data)->svgParse->node->id ? ((SvgLoaderData*)data)->svgParse->node->id : "NO_ID", tmpBuf, tval ? tval : "NONE"); } } } @@ -362,51 +358,49 @@ error: } -bool simpleXmlParse(const char* buf, unsigned bufLength, bool strip, simpleXMLCb func, const void* data) +bool xmlParse(const char* buf, unsigned bufLength, bool strip, xmlCb func, const void* data) { const char *itr = buf, *itrEnd = buf + bufLength; - if (!buf || !func) return false; - while (itr < itrEnd) { if (itr[0] == '<') { //Invalid case if (itr + 1 >= itrEnd) return false; size_t toff = 0; - SimpleXMLType type = _getXMLType(itr, itrEnd, toff); + XMLType type = _getXMLType(itr, itrEnd, toff); const char* p; - if (type == SimpleXMLType::CData) p = _simpleXmlFindEndCdataTag(itr + 1 + toff, itrEnd); - else if (type == SimpleXMLType::DoctypeChild) p = _simpleXmlFindDoctypeChildEndTag(itr + 1 + toff, itrEnd); - else if (type == SimpleXMLType::Comment) p = _simpleXmlFindEndCommentTag(itr + 1 + toff, itrEnd); - else p = _simpleXmlFindEndTag(itr + 1 + toff, itrEnd); + if (type == XMLType::CData) p = _xmlFindEndCdataTag(itr + 1 + toff, itrEnd); + else if (type == XMLType::DoctypeChild) p = _xmlFindDoctypeChildEndTag(itr + 1 + toff, itrEnd); + else if (type == XMLType::Comment) p = _xmlFindEndCommentTag(itr + 1 + toff, itrEnd); + else p = _xmlFindEndTag(itr + 1 + toff, itrEnd); if (p) { //Invalid case: '<' nested - if (*p == '<' && type != SimpleXMLType::Doctype) return false; + if (*p == '<' && type != XMLType::Doctype) return false; const char *start, *end; start = itr + 1 + toff; end = p; switch (type) { - case SimpleXMLType::Open: { + case XMLType::Open: { if (p[-1] == '/') { - type = SimpleXMLType::OpenEmpty; + type = XMLType::OpenEmpty; end--; } break; } - case SimpleXMLType::CData: { + case XMLType::CData: { if (!memcmp(p - 2, "]]", 2)) end -= 2; break; } - case SimpleXMLType::Processing: { + case XMLType::Processing: { if (p[-1] == '?') end--; break; } - case SimpleXMLType::Comment: { + case XMLType::Comment: { if (!memcmp(p - 2, "--", 2)) end -= 2; break; } @@ -415,7 +409,7 @@ bool simpleXmlParse(const char* buf, unsigned bufLength, bool strip, simpleXMLCb } } - if (strip && (type != SimpleXMLType::CData)) { + if (strip && (type != XMLType::CData)) { start = _skipWhiteSpacesAndXmlEntities(start, end); end = _unskipWhiteSpacesAndXmlEntities(end, start); } @@ -433,20 +427,20 @@ bool simpleXmlParse(const char* buf, unsigned bufLength, bool strip, simpleXMLCb p = itr; p = _skipWhiteSpacesAndXmlEntities(p, itrEnd); if (p) { - if (!func((void*)data, SimpleXMLType::Ignored, itr, (unsigned int)(p - itr))) return false; + if (!func((void*)data, XMLType::Ignored, itr, (unsigned int)(p - itr))) return false; itr = p; } } - p = _simpleXmlFindStartTag(itr, itrEnd); + p = _xmlFindStartTag(itr, itrEnd); if (!p) p = itrEnd; end = p; if (strip) end = _unskipWhiteSpacesAndXmlEntities(end, itr); - if (itr != end && !func((void*)data, SimpleXMLType::Data, itr, (unsigned int)(end - itr))) return false; + if (itr != end && !func((void*)data, XMLType::Data, itr, (unsigned int)(end - itr))) return false; - if (strip && (end < p) && !func((void*)data, SimpleXMLType::Ignored, end, (unsigned int)(p - end))) return false; + if (strip && (end < p) && !func((void*)data, XMLType::Ignored, end, (unsigned int)(p - end))) return false; itr = p; } @@ -455,7 +449,7 @@ bool simpleXmlParse(const char* buf, unsigned bufLength, bool strip, simpleXMLCb } -bool simpleXmlParseW3CAttribute(const char* buf, unsigned bufLength, simpleXMLAttributeCb func, const void* data) +bool xmlParseW3CAttribute(const char* buf, unsigned bufLength, xmlAttributeCb func, const void* data) { const char* end; char* key; @@ -508,14 +502,14 @@ bool simpleXmlParseW3CAttribute(const char* buf, unsigned bufLength, simpleXMLAt } if (key[0]) { - key = const_cast(_simpleXmlSkipWhiteSpace(key, key + strlen(key))); - key[_simpleXmlUnskipWhiteSpace(key + strlen(key) , key) - key] = '\0'; - val = const_cast(_simpleXmlSkipWhiteSpace(val, val + strlen(val))); - val[_simpleXmlUnskipWhiteSpace(val + strlen(val) , val) - val] = '\0'; + key = const_cast(_xmlSkipWhiteSpace(key, key + strlen(key))); + key[_xmlUnskipWhiteSpace(key + strlen(key) , key) - key] = '\0'; + val = const_cast(_xmlSkipWhiteSpace(val, val + strlen(val))); + val[_xmlUnskipWhiteSpace(val + strlen(val) , val) - val] = '\0'; if (!func((void*)data, key, val)) { - if (!_isIgnoreUnsupportedLogAttributes(key, val)) { - TVGLOG("SVG", "Unsupported attributes used [Elements type: %s][Id : %s][Attribute: %s][Value: %s]", simpleXmlNodeTypeToString(((SvgLoaderData*)data)->svgParse->node->type), ((SvgLoaderData*)data)->svgParse->node->id ? ((SvgLoaderData*)data)->svgParse->node->id : "NO_ID", key, val ? val : "NONE"); + if (!_unsupported(key, val)) { + TVGLOG("SVG", "Unsupported attributes used [Elements type: %s][Id : %s][Attribute: %s][Value: %s]", xmlNodeTypeToString(((SvgLoaderData*)data)->svgParse->node->type), ((SvgLoaderData*)data)->svgParse->node->id ? ((SvgLoaderData*)data)->svgParse->node->id : "NO_ID", key, val ? val : "NONE"); } } } @@ -532,14 +526,14 @@ bool simpleXmlParseW3CAttribute(const char* buf, unsigned bufLength, simpleXMLAt * Supported formats: * tag {}, .name {}, tag.name{} */ -const char* simpleXmlParseCSSAttribute(const char* buf, unsigned bufLength, char** tag, char** name, const char** attrs, unsigned* attrsLength) +const char* xmlParseCSSAttribute(const char* buf, unsigned bufLength, char** tag, char** name, const char** attrs, unsigned* attrsLength) { if (!buf) return nullptr; *tag = *name = nullptr; *attrsLength = 0; - auto itr = _simpleXmlSkipWhiteSpace(buf, buf + bufLength); + auto itr = _xmlSkipWhiteSpace(buf, buf + bufLength); auto itrEnd = (const char*)memchr(buf, '{', bufLength); if (!itrEnd || itr == itrEnd) return nullptr; @@ -552,7 +546,7 @@ const char* simpleXmlParseCSSAttribute(const char* buf, unsigned bufLength, char const char *p; - itrEnd = _simpleXmlUnskipWhiteSpace(itrEnd, itr); + itrEnd = _xmlUnskipWhiteSpace(itrEnd, itr); if (*(itrEnd - 1) == '.') return nullptr; for (p = itr; p < itrEnd; p++) { @@ -569,7 +563,7 @@ const char* simpleXmlParseCSSAttribute(const char* buf, unsigned bufLength, char } -const char* simpleXmlFindAttributesTag(const char* buf, unsigned bufLength) +const char* xmlFindAttributesTag(const char* buf, unsigned bufLength) { const char *itr = buf, *itrEnd = buf + bufLength; @@ -578,7 +572,7 @@ const char* simpleXmlFindAttributesTag(const char* buf, unsigned bufLength) //User skip tagname and already gave it the attributes. if (*itr == '=') return buf; } else { - itr = _simpleXmlUnskipXmlEntities(itr, buf); + itr = _xmlUnskipXmlEntities(itr, buf); if (itr == itrEnd) return nullptr; return itr; } diff --git a/src/loaders/svg/tvgXmlParser.h b/src/loaders/svg/tvgXmlParser.h index 0bbaeedb..e0e199f7 100644 --- a/src/loaders/svg/tvgXmlParser.h +++ b/src/loaders/svg/tvgXmlParser.h @@ -20,8 +20,8 @@ * SOFTWARE. */ -#ifndef _TVG_SIMPLE_XML_PARSER_H_ -#define _TVG_SIMPLE_XML_PARSER_H_ +#ifndef _TVG_XML_PARSER_H_ +#define _TVG_XML_PARSER_H_ #include "tvgSvgLoaderCommon.h" @@ -29,7 +29,7 @@ const char* const xmlEntity[] = {" ", """, " ", "'", "&", "<", ">", "#", "'"}; const int xmlEntityLength[] = {5, 6, 6, 6, 5, 4, 4, 6, 6}; -enum class SimpleXMLType +enum class XMLType { Open = 0, //!< \ OpenEmpty, //!< \ @@ -44,15 +44,15 @@ enum class SimpleXMLType DoctypeChild //!< \