mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
svg: clean & neat code++
no logical changes
This commit is contained in:
parent
468a1db1fa
commit
ad888019e9
3 changed files with 275 additions and 372 deletions
|
@ -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<uint8_t>(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<SvgNodeIdPair>& 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<SvgNode*>(1, sizeof(SvgNode));
|
||||
|
||||
if (!node) return nullptr;
|
||||
|
||||
//Default fill property
|
||||
node->style = tvg::calloc<SvgStyleProperty*>(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 <svg>(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,60 +3601,18 @@ 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<SvgStyleGradient*>* gradients, const char* id)
|
||||
static void _updateGradient(SvgLoaderData* loader, SvgNode* node, Array<SvgStyleGradient*>* gradients)
|
||||
{
|
||||
auto duplicate = [&](SvgLoaderData* loader, Array<SvgStyleGradient*>* gradients, const char* id) -> SvgStyleGradient* {
|
||||
SvgStyleGradient* result = nullptr;
|
||||
|
||||
ARRAY_FOREACH(p, *gradients) {
|
||||
|
@ -3693,7 +3621,6 @@ static SvgStyleGradient* _gradientDup(SvgLoaderData* loader, Array<SvgStyleGradi
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result && result->ref) {
|
||||
ARRAY_FOREACH(p, *gradients) {
|
||||
if ((*p)->id && STR_AS((*p)->id, result->ref)) {
|
||||
|
@ -3702,20 +3629,16 @@ static SvgStyleGradient* _gradientDup(SvgLoaderData* loader, Array<SvgStyleGradi
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static void _updateGradient(SvgLoaderData* loader, SvgNode* node, Array<SvgStyleGradient*>* 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, Array<SvgStyle
|
|||
}
|
||||
}
|
||||
if (node->style->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,15 +3682,11 @@ 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) {
|
||||
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 <svg> tag is found.
|
||||
res = _svgLoaderParserForValidCheckXmlOpen(loader, content, length);
|
||||
break;
|
||||
return _svgLoaderParserForValidCheckXmlOpen(static_cast<SvgLoaderData*>(data), content, length);
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
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,7 +3905,7 @@ 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
|
||||
|
@ -4005,6 +3916,7 @@ void SvgLoader::run(unsigned tid)
|
|||
w = loaderData.doc->node.doc.w;
|
||||
h = loaderData.doc->node.doc.h;
|
||||
}
|
||||
}
|
||||
|
||||
clear(false);
|
||||
}
|
||||
|
@ -4016,14 +3928,16 @@ bool SvgLoader::header()
|
|||
//If the <svg> 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<SvgParser*>(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) {
|
||||
TVGLOG("SVG", "No SVG File. There is no <svg/>");
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -4074,12 +3988,7 @@ bool SvgLoader::header()
|
|||
|
||||
run(0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TVGLOG("SVG", "No SVG File. There is no <svg/>");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
if (tvg::equal(tagAttribute, attributes[i].tag)) {
|
||||
if (!attributes[i].value) return false;
|
||||
if (tvg::equal(tagValue, attributes[i].value)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
return true;
|
||||
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("<!DOCTYPE>") - 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("<![CDATA[]]>") - 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<char*>(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<char*>(_simpleXmlSkipWhiteSpace(key, key + strlen(key)));
|
||||
key[_simpleXmlUnskipWhiteSpace(key + strlen(key) , key) - key] = '\0';
|
||||
val = const_cast<char*>(_simpleXmlSkipWhiteSpace(val, val + strlen(val)));
|
||||
val[_simpleXmlUnskipWhiteSpace(val + strlen(val) , val) - val] = '\0';
|
||||
key = const_cast<char*>(_xmlSkipWhiteSpace(key, key + strlen(key)));
|
||||
key[_xmlUnskipWhiteSpace(key + strlen(key) , key) - key] = '\0';
|
||||
val = const_cast<char*>(_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;
|
||||
}
|
||||
|
|
|
@ -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, //!< \<tag attribute="value"\>
|
||||
OpenEmpty, //!< \<tag attribute="value" /\>
|
||||
|
@ -44,15 +44,15 @@ enum class SimpleXMLType
|
|||
DoctypeChild //!< \<!doctype_child
|
||||
};
|
||||
|
||||
typedef bool (*simpleXMLCb)(void* data, SimpleXMLType type, const char* content, unsigned int length);
|
||||
typedef bool (*simpleXMLAttributeCb)(void* data, const char* key, const char* value);
|
||||
typedef bool (*xmlCb)(void* data, XMLType type, const char* content, unsigned int length);
|
||||
typedef bool (*xmlAttributeCb)(void* data, const char* key, const char* value);
|
||||
|
||||
bool simpleXmlParseAttributes(const char* buf, unsigned bufLength, simpleXMLAttributeCb func, const void* data);
|
||||
bool simpleXmlParse(const char* buf, unsigned bufLength, bool strip, simpleXMLCb func, const void* data);
|
||||
bool simpleXmlParseW3CAttribute(const char* buf, unsigned bufLength, simpleXMLAttributeCb func, const void* data);
|
||||
const char* simpleXmlParseCSSAttribute(const char* buf, unsigned bufLength, char** tag, char** name, const char** attrs, unsigned* attrsLength);
|
||||
const char* simpleXmlFindAttributesTag(const char* buf, unsigned bufLength);
|
||||
bool xmlParseAttributes(const char* buf, unsigned bufLength, xmlAttributeCb func, const void* data);
|
||||
bool xmlParse(const char* buf, unsigned bufLength, bool strip, xmlCb func, const void* data);
|
||||
bool xmlParseW3CAttribute(const char* buf, unsigned bufLength, xmlAttributeCb func, const void* data);
|
||||
const char* xmlParseCSSAttribute(const char* buf, unsigned bufLength, char** tag, char** name, const char** attrs, unsigned* attrsLength);
|
||||
const char* xmlFindAttributesTag(const char* buf, unsigned bufLength);
|
||||
bool isIgnoreUnsupportedLogElements(const char* tagName);
|
||||
const char* simpleXmlNodeTypeToString(SvgNodeType type);
|
||||
const char* xmlNodeTypeToString(SvgNodeType type);
|
||||
|
||||
#endif //_TVG_SIMPLE_XML_PARSER_H_
|
||||
#endif //_TVG_XML_PARSER_H_
|
||||
|
|
Loading…
Add table
Reference in a new issue