Skip to content

Commit

Permalink
Merge pull request #93378 from akien-mga/thorvg-0.13.8
Browse files Browse the repository at this point in the history
thorvg: Update to 0.13.8
  • Loading branch information
akien-mga committed Jun 21, 2024
2 parents b749ff5 + e94df6f commit 1f134f3
Show file tree
Hide file tree
Showing 14 changed files with 310 additions and 130 deletions.
2 changes: 1 addition & 1 deletion thirdparty/thorvg/inc/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@
// For internal debugging:
//#define THORVG_LOG_ENABLED

#define THORVG_VERSION_STRING "0.13.7"
#define THORVG_VERSION_STRING "0.13.8"
#endif
13 changes: 0 additions & 13 deletions thirdparty/thorvg/patches/pr2338-float_t.patch

This file was deleted.

2 changes: 2 additions & 0 deletions thirdparty/thorvg/src/common/tvgLock.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@

#ifdef THORVG_THREAD_SUPPORT

#define _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR

#include <mutex>

namespace tvg {
Expand Down
161 changes: 122 additions & 39 deletions thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,14 +175,14 @@ static float _toFloat(const SvgParser* svgParse, const char* str, SvgParserLengt
else if (strstr(str, "pc")) parsedValue *= PX_PER_PC;
else if (strstr(str, "in")) parsedValue *= PX_PER_IN;
else if (strstr(str, "%")) {
if (type == SvgParserLengthType::Vertical) parsedValue = (parsedValue / 100.0) * svgParse->global.h;
else if (type == SvgParserLengthType::Horizontal) parsedValue = (parsedValue / 100.0) * svgParse->global.w;
else //if other then it's radius
if (type == SvgParserLengthType::Vertical) parsedValue = (parsedValue / 100.0f) * svgParse->global.h;
else if (type == SvgParserLengthType::Horizontal) parsedValue = (parsedValue / 100.0f) * svgParse->global.w;
else //if other than it's radius
{
float max = svgParse->global.w;
if (max < svgParse->global.h)
max = svgParse->global.h;
parsedValue = (parsedValue / 100.0) * max;
parsedValue = (parsedValue / 100.0f) * max;
}
}
//TODO: Implement 'em', 'ex' attributes
Expand Down Expand Up @@ -580,20 +580,20 @@ static constexpr struct
};


static bool _hslToRgb(float hue, float satuation, float brightness, uint8_t* red, uint8_t* green, uint8_t* blue)
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;

if (mathZero(satuation)) _red = _green = _blue = brightness;
if (mathZero(saturation)) _red = _green = _blue = brightness;
else {
if (mathEqual(hue, 360.0)) hue = 0.0f;
hue /= 60.0f;

v = (brightness <= 0.5f) ? (brightness * (1.0f + satuation)) : (brightness + satuation - (brightness * satuation));
v = (brightness <= 0.5f) ? (brightness * (1.0f + saturation)) : (brightness + saturation - (brightness * saturation));
p = brightness + brightness - v;

if (!mathZero(v)) sv = (v - p) / v;
Expand Down Expand Up @@ -662,7 +662,7 @@ static bool _toColor(const char* str, uint8_t* r, uint8_t* g, uint8_t* b, char**
unsigned char tr, tg, tb;

if (len == 4 && str[0] == '#') {
//Case for "#456" should be interprete as "#445566"
//Case for "#456" should be interpreted as "#445566"
if (isxdigit(str[1]) && isxdigit(str[2]) && isxdigit(str[3])) {
char tmp[3] = { '\0', '\0', '\0' };
tmp[0] = str[1];
Expand Down Expand Up @@ -710,20 +710,20 @@ static bool _toColor(const char* str, uint8_t* r, uint8_t* g, uint8_t* b, char**
return true;
} else if (len >= 10 && (str[0] == 'h' || str[0] == 'H') && (str[1] == 's' || str[1] == 'S') && (str[2] == 'l' || str[2] == 'L') && str[3] == '(' && str[len - 1] == ')') {
float th, ts, tb;
const char *content, *hue, *satuation, *brightness;
const char *content, *hue, *saturation, *brightness;
content = str + 4;
content = _skipSpace(content, nullptr);
if (_parseNumber(&content, &hue, &th) && hue) {
th = float(uint32_t(th) % 360);
hue = _skipSpace(hue, nullptr);
hue = (char*)_skipComma(hue);
hue = _skipSpace(hue, nullptr);
if (_parseNumber(&hue, &satuation, &ts) && satuation && *satuation == '%') {
if (_parseNumber(&hue, &saturation, &ts) && saturation && *saturation == '%') {
ts /= 100.0f;
satuation = _skipSpace(satuation + 1, nullptr);
satuation = (char*)_skipComma(satuation);
satuation = _skipSpace(satuation, nullptr);
if (_parseNumber(&satuation, &brightness, &tb) && brightness && *brightness == '%') {
saturation = _skipSpace(saturation + 1, nullptr);
saturation = (char*)_skipComma(saturation);
saturation = _skipSpace(saturation, nullptr);
if (_parseNumber(&saturation, &brightness, &tb) && brightness && *brightness == '%') {
tb /= 100.0f;
brightness = _skipSpace(brightness + 1, nullptr);
if (brightness && brightness[0] == ')' && brightness[1] == '\0') {
Expand Down Expand Up @@ -2119,7 +2119,72 @@ static SvgNode* _createUseNode(SvgLoaderData* loader, SvgNode* parent, const cha
}


//TODO: Implement 'text' primitive
static constexpr struct
{
const char* tag;
SvgParserLengthType type;
int sz;
size_t offset;
} textTags[] = {
{"x", SvgParserLengthType::Horizontal, sizeof("x"), offsetof(SvgTextNode, x)},
{"y", SvgParserLengthType::Vertical, sizeof("y"), offsetof(SvgTextNode, y)},
{"font-size", SvgParserLengthType::Vertical, sizeof("font-size"), offsetof(SvgTextNode, fontSize)}
};


static bool _attrParseTextNode(void* data, const char* key, const char* value)
{
SvgLoaderData* loader = (SvgLoaderData*)data;
SvgNode* node = loader->svgParse->node;
SvgTextNode* text = &(node->node.text);

unsigned char* array;
int sz = strlen(key);

array = (unsigned char*)text;
for (unsigned int i = 0; i < sizeof(textTags) / sizeof(textTags[0]); i++) {
if (textTags[i].sz - 1 == sz && !strncmp(textTags[i].tag, key, sz)) {
*((float*)(array + textTags[i].offset)) = _toFloat(loader->svgParse, value, textTags[i].type);
return true;
}
}

if (!strcmp(key, "font-family")) {
if (text->fontFamily && value) free(text->fontFamily);
text->fontFamily = strdup(value);
} else if (!strcmp(key, "style")) {
return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader);
} else if (!strcmp(key, "clip-path")) {
_handleClipPathAttr(loader, node, value);
} else if (!strcmp(key, "mask")) {
_handleMaskAttr(loader, node, value);
} else if (!strcmp(key, "id")) {
if (node->id && value) free(node->id);
node->id = _copyId(value);
} else if (!strcmp(key, "class")) {
_handleCssClassAttr(loader, node, value);
} else {
return _parseStyleAttr(loader, key, value, false);
}
return true;
}


static SvgNode* _createTextNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{
loader->svgParse->node = _createNode(parent, SvgNodeType::Text);
if (!loader->svgParse->node) return nullptr;

//TODO: support the def font and size as used in a system?
loader->svgParse->node->node.text.fontSize = 10.0f;
loader->svgParse->node->node.text.fontFamily = nullptr;

func(buf, bufLength, _attrParseTextNode, loader);

return loader->svgParse->node;
}


static constexpr struct
{
const char* tag;
Expand All @@ -2134,7 +2199,8 @@ static constexpr struct
{"rect", sizeof("rect"), _createRectNode},
{"polyline", sizeof("polyline"), _createPolylineNode},
{"line", sizeof("line"), _createLineNode},
{"image", sizeof("image"), _createImageNode}
{"image", sizeof("image"), _createImageNode},
{"text", sizeof("text"), _createTextNode}
};


Expand Down Expand Up @@ -3122,6 +3188,20 @@ static void _copyAttr(SvgNode* to, const SvgNode* from)
to->node.use.symbol = from->node.use.symbol;
break;
}
case SvgNodeType::Text: {
to->node.text.x = from->node.text.x;
to->node.text.y = from->node.text.y;
to->node.text.fontSize = from->node.text.fontSize;
if (from->node.text.text) {
if (to->node.text.text) free(to->node.text.text);
to->node.text.text = strdup(from->node.text.text);
}
if (from->node.text.fontFamily) {
if (to->node.text.fontFamily) free(to->node.text.fontFamily);
to->node.text.fontFamily = strdup(from->node.text.fontFamily);
}
break;
}
default: {
break;
}
Expand Down Expand Up @@ -3174,27 +3254,12 @@ static void _clonePostponedNodes(Array<SvgNodeIdPair>* cloneNodes, SvgNode* doc)
}


static constexpr struct
{
const char* tag;
size_t sz;
} popArray[] = {
{"g", sizeof("g")},
{"svg", sizeof("svg")},
{"defs", sizeof("defs")},
{"mask", sizeof("mask")},
{"clipPath", sizeof("clipPath")},
{"style", sizeof("style")},
{"symbol", sizeof("symbol")}
};


static void _svgLoaderParserXmlClose(SvgLoaderData* loader, const char* content)
{
content = _skipSpace(content, nullptr);

for (unsigned int i = 0; i < sizeof(popArray) / sizeof(popArray[0]); i++) {
if (!strncmp(content, popArray[i].tag, popArray[i].sz - 1)) {
for (unsigned int i = 0; i < sizeof(groupTags) / sizeof(groupTags[0]); i++) {
if (!strncmp(content, groupTags[i].tag, groupTags[i].sz - 1)) {
loader->stack.pop();
break;
}
Expand Down Expand Up @@ -3259,7 +3324,7 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content,
node = method(loader, nullptr, attrs, attrsLength, simpleXmlParseAttributes);
loader->cssStyle = node;
loader->doc->node.doc.style = node;
loader->style = true;
loader->openedTag = OpenedTagType::Style;
}
} else {
node = method(loader, parent, attrs, attrsLength, simpleXmlParseAttributes);
Expand All @@ -3275,9 +3340,12 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content,
else parent = loader->doc;
node = method(loader, parent, attrs, attrsLength, simpleXmlParseAttributes);
if (node && !empty) {
auto defs = _createDefsNode(loader, nullptr, nullptr, 0, nullptr);
loader->stack.push(defs);
loader->currentGraphicsNode = node;
if (!strcmp(tagName, "text")) loader->openedTag = OpenedTagType::Text;
else {
auto defs = _createDefsNode(loader, nullptr, nullptr, 0, nullptr);
loader->stack.push(defs);
loader->currentGraphicsNode = node;
}
}
} else if ((gradientMethod = _findGradientFactory(tagName))) {
SvgStyleGradient* gradient;
Expand Down Expand Up @@ -3310,6 +3378,15 @@ 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;
if (text->text) free(text->text);
text->text = strDuplicate(content, length);
loader->openedTag = OpenedTagType::Other;
}


static void _svgLoaderParserXmlCssStyle(SvgLoaderData* loader, const char* content, unsigned int length)
{
char* tag;
Expand Down Expand Up @@ -3342,7 +3419,7 @@ static void _svgLoaderParserXmlCssStyle(SvgLoaderData* loader, const char* conte
free(tag);
free(name);
}
loader->style = false;
loader->openedTag = OpenedTagType::Other;
}


Expand All @@ -3365,7 +3442,8 @@ static bool _svgLoaderParser(void* data, SimpleXMLType type, const char* content
}
case SimpleXMLType::Data:
case SimpleXMLType::CData: {
if (loader->style) _svgLoaderParserXmlCssStyle(loader, content, length);
if (loader->openedTag == OpenedTagType::Style) _svgLoaderParserXmlCssStyle(loader, content, length);
else if (loader->openedTag == OpenedTagType::Text) _svgLoaderParserText(loader, content, length);
break;
}
case SimpleXMLType::DoctypeChild: {
Expand Down Expand Up @@ -3587,6 +3665,11 @@ static void _freeNode(SvgNode* node)
free(node->node.image.href);
break;
}
case SvgNodeType::Text: {
free(node->node.text.text);
free(node->node.text.fontFamily);
break;
}
default: {
break;
}
Expand Down
20 changes: 18 additions & 2 deletions thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,14 @@ struct SvgCssStyleNode
{
};

struct SvgTextNode
{
char* text;
char* fontFamily;
float x, y;
float fontSize;
};

struct SvgLinearGradient
{
float x1;
Expand Down Expand Up @@ -518,6 +526,7 @@ struct SvgNode
SvgClipNode clip;
SvgCssStyleNode cssStyle;
SvgSymbolNode symbol;
SvgTextNode text;
} node;
~SvgNode();
};
Expand Down Expand Up @@ -545,11 +554,18 @@ struct SvgNodeIdPair
char *id;
};

enum class OpenedTagType : uint8_t
{
Other = 0,
Style,
Text
};

struct SvgLoaderData
{
Array<SvgNode*> stack;
SvgNode* doc = nullptr;
SvgNode* def = nullptr;
SvgNode* def = nullptr; //also used to store nested graphic nodes
SvgNode* cssStyle = nullptr;
Array<SvgStyleGradient*> gradients;
SvgStyleGradient* latestGradient = nullptr; //For stops
Expand All @@ -559,7 +575,7 @@ struct SvgLoaderData
Array<char*> images; //embedded images
int level = 0;
bool result = false;
bool style = false;
OpenedTagType openedTag = OpenedTagType::Other;
SvgNode* currentGraphicsNode = nullptr;
};

Expand Down
Loading

0 comments on commit 1f134f3

Please sign in to comment.