mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-14 12:04:29 +00:00
svg_loader: fix vector memory leaks.
vector is designed for c++ syntaxes, it works properly when c++ memory allocator is applied, Here svg_loader uses c style structures which allocated using malloc()/calloc(). That brings the memory broken of stl vectors. So, we replaced it with our customized SvgVector to easily fix it.
This commit is contained in:
parent
6bd56e26c7
commit
6f962151b4
3 changed files with 107 additions and 67 deletions
|
@ -944,7 +944,7 @@ static SvgNode* _createNode(SvgNode* parent, SvgNodeType type)
|
||||||
node->parent = parent;
|
node->parent = parent;
|
||||||
node->type = type;
|
node->type = type;
|
||||||
|
|
||||||
if (parent) parent->child.push_back(node);
|
if (parent) parent->child.push(node);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1334,22 +1334,22 @@ static SvgNode* _getDefsNode(SvgNode* node)
|
||||||
|
|
||||||
static SvgNode* _findChildById(SvgNode* node, const char* id)
|
static SvgNode* _findChildById(SvgNode* node, const char* id)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!node) return nullptr;
|
if (!node) return nullptr;
|
||||||
|
|
||||||
for (vector<SvgNode*>::iterator itrChild = node->child.begin(); itrChild != node->child.end(); itrChild++) {
|
auto child = node->child.list;
|
||||||
if (((*itrChild)->id != nullptr) && !strcmp((*itrChild)->id->c_str(), id)) return *itrChild;
|
for (uint32_t i = 0; i < node->child.cnt; ++i, ++child) {
|
||||||
|
if (((*child)->id != nullptr) && !strcmp((*child)->id->c_str(), id)) return (*child);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void _cloneGradStops(vector<Fill::ColorStop*> *dst, vector<Fill::ColorStop*> src)
|
static void _cloneGradStops(SvgVector<Fill::ColorStop*>* dst, SvgVector<Fill::ColorStop*>* src)
|
||||||
{
|
{
|
||||||
for (auto colorStop : src) {
|
for (uint32_t i = 0; i < src->cnt; ++i) {
|
||||||
auto stop = static_cast<Fill::ColorStop *>(malloc(sizeof(Fill::ColorStop)));
|
auto stop = static_cast<Fill::ColorStop *>(malloc(sizeof(Fill::ColorStop)));
|
||||||
*stop = *colorStop;
|
*stop = *src->list[i];
|
||||||
dst->push_back(stop);
|
dst->push(stop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1379,7 +1379,7 @@ static SvgStyleGradient* _cloneGradient(SvgStyleGradient* from)
|
||||||
memcpy(grad->radial, from->radial, sizeof(SvgRadialGradient));
|
memcpy(grad->radial, from->radial, sizeof(SvgRadialGradient));
|
||||||
}
|
}
|
||||||
|
|
||||||
_cloneGradStops(&(grad->stops), from->stops);
|
_cloneGradStops(&grad->stops, &from->stops);
|
||||||
return grad;
|
return grad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1454,8 +1454,9 @@ static void _cloneNode(SvgNode* from, SvgNode* parent)
|
||||||
newNode = _createNode(parent, from->type);
|
newNode = _createNode(parent, from->type);
|
||||||
_copyAttr(newNode, from);
|
_copyAttr(newNode, from);
|
||||||
|
|
||||||
for (auto child : from->child) {
|
auto child = from->child.list;
|
||||||
_cloneNode(child, newNode);
|
for (uint32_t i = 0; i < from->child.cnt; ++i, ++child) {
|
||||||
|
_cloneNode(*child, newNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
_freeNode(newNode);
|
_freeNode(newNode);
|
||||||
|
@ -1907,7 +1908,7 @@ static void _svgLoaderParerXmlClose(SvgLoaderData* loader, const char* content)
|
||||||
|
|
||||||
for (i = 0; i < sizeof(popArray) / sizeof(popArray[0]); i++) {
|
for (i = 0; i < sizeof(popArray) / sizeof(popArray[0]); i++) {
|
||||||
if (!strncmp(content, popArray[i].tag, popArray[i].sz - 1)) {
|
if (!strncmp(content, popArray[i].tag, popArray[i].sz - 1)) {
|
||||||
loader->stack.pop_back();
|
loader->stack.pop();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1951,17 +1952,17 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content,
|
||||||
loader->doc = node;
|
loader->doc = node;
|
||||||
} else {
|
} else {
|
||||||
if (!strcmp(tagName, "svg")) return; //Already loadded <svg>(SvgNodeType::Doc) tag
|
if (!strcmp(tagName, "svg")) return; //Already loadded <svg>(SvgNodeType::Doc) tag
|
||||||
if (loader->stack.size() > 0) parent = loader->stack.at(loader->stack.size() - 1);
|
if (loader->stack.cnt > 0) parent = loader->stack.list[loader->stack.cnt - 1];
|
||||||
node = method(loader, parent, attrs, attrsLength);
|
node = method(loader, parent, attrs, attrsLength);
|
||||||
}
|
}
|
||||||
loader->stack.push_back(node);
|
loader->stack.push(node);
|
||||||
|
|
||||||
if (node->type == SvgNodeType::Defs) {
|
if (node->type == SvgNodeType::Defs) {
|
||||||
loader->doc->node.doc.defs = node;
|
loader->doc->node.doc.defs = node;
|
||||||
loader->def = node;
|
loader->def = node;
|
||||||
}
|
}
|
||||||
} else if ((method = _findGraphicsFactory(tagName))) {
|
} else if ((method = _findGraphicsFactory(tagName))) {
|
||||||
parent = loader->stack.at(loader->stack.size() - 1);
|
parent = loader->stack.list[loader->stack.cnt - 1];
|
||||||
node = method(loader, parent, attrs, attrsLength);
|
node = method(loader, parent, attrs, attrsLength);
|
||||||
} else if ((gradientMethod = _findGradientFactory(tagName))) {
|
} else if ((gradientMethod = _findGradientFactory(tagName))) {
|
||||||
SvgStyleGradient* gradient;
|
SvgStyleGradient* gradient;
|
||||||
|
@ -1973,9 +1974,9 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content,
|
||||||
// This is only to support this when multiple gradients are declared, even if no defs are declared.
|
// This is only to support this when multiple gradients are declared, even if no defs are declared.
|
||||||
// refer to: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/defs
|
// refer to: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/defs
|
||||||
if (loader->doc->node.doc.defs) {
|
if (loader->doc->node.doc.defs) {
|
||||||
loader->def->node.defs.gradients.push_back(gradient);
|
loader->def->node.defs.gradients.push(gradient);
|
||||||
} else {
|
} else {
|
||||||
loader->gradients.push_back(gradient);
|
loader->gradients.push(gradient);
|
||||||
}
|
}
|
||||||
loader->latestGradient = gradient;
|
loader->latestGradient = gradient;
|
||||||
} else if (!strcmp(tagName, "stop")) {
|
} else if (!strcmp(tagName, "stop")) {
|
||||||
|
@ -1985,7 +1986,7 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content,
|
||||||
stop->a = 255;
|
stop->a = 255;
|
||||||
simpleXmlParseAttributes(attrs, attrsLength, _attrParseStops, loader);
|
simpleXmlParseAttributes(attrs, attrsLength, _attrParseStops, loader);
|
||||||
if (loader->latestGradient) {
|
if (loader->latestGradient) {
|
||||||
loader->latestGradient->stops.push_back(stop);
|
loader->latestGradient->stops.push(stop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2074,32 +2075,38 @@ static void _updateStyle(SvgNode* node, SvgStyleProperty* parentStyle)
|
||||||
{
|
{
|
||||||
_styleInherit(node->style, parentStyle);
|
_styleInherit(node->style, parentStyle);
|
||||||
|
|
||||||
for (vector<SvgNode*>::iterator itrChild = node->child.begin(); itrChild != node->child.end(); itrChild++) {
|
auto child = node->child.list;
|
||||||
_updateStyle(*itrChild, node->style);
|
for (uint32_t i = 0; i < node->child.cnt; ++i, ++child) {
|
||||||
|
_updateStyle(*child, node->style);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static SvgStyleGradient* _gradientDup(vector<SvgStyleGradient*> gradList, string* id)
|
static SvgStyleGradient* _gradientDup(SvgVector<SvgStyleGradient*>* gradients, string* id)
|
||||||
{
|
{
|
||||||
SvgStyleGradient* result = nullptr;
|
SvgStyleGradient* result = nullptr;
|
||||||
|
|
||||||
for (vector<SvgStyleGradient*>::iterator itrGrad = gradList.begin(); itrGrad != gradList.end(); itrGrad++) {
|
auto gradList = gradients->list;
|
||||||
if (!((*itrGrad)->id->compare(*id))) {
|
|
||||||
result = _cloneGradient(*itrGrad);
|
for (uint32_t i = 0; i < gradients->cnt; ++i) {
|
||||||
|
if (!((*gradList)->id->compare(*id))) {
|
||||||
|
result = _cloneGradient(*gradList);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
++gradList;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result && result->ref) {
|
if (result && result->ref) {
|
||||||
for (vector<SvgStyleGradient*>::iterator itrGrad = gradList.begin(); itrGrad != gradList.end(); itrGrad++) {
|
gradList = gradients->list;
|
||||||
if (!((*itrGrad)->id->compare(*result->ref))) {
|
for (uint32_t i = 0; i < gradients->cnt; ++i) {
|
||||||
if (!result->stops.empty()) {
|
if (!((*gradList)->id->compare(*result->ref))) {
|
||||||
_cloneGradStops(&(result->stops), (*itrGrad)->stops);
|
if (result->stops.cnt > 0) {
|
||||||
|
_cloneGradStops(&result->stops, &(*gradList)->stops);
|
||||||
}
|
}
|
||||||
//TODO: Properly inherit other property
|
//TODO: Properly inherit other property
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
++gradList;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2107,15 +2114,16 @@ static SvgStyleGradient* _gradientDup(vector<SvgStyleGradient*> gradList, string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void _updateGradient(SvgNode* node, vector<SvgStyleGradient*> gradList)
|
static void _updateGradient(SvgNode* node, SvgVector<SvgStyleGradient*>* gradidents)
|
||||||
{
|
{
|
||||||
if (!node->child.empty()) {
|
if (node->child.cnt > 0) {
|
||||||
for (vector<SvgNode*>::iterator itrChild = node->child.begin(); itrChild != node->child.end(); itrChild++) {
|
auto child = node->child.list;
|
||||||
_updateGradient(*itrChild, gradList);
|
for (uint32_t i = 0; i < node->child.cnt; ++i, ++child) {
|
||||||
|
_updateGradient(*child, gradidents);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (node->style->fill.paint.url) {
|
if (node->style->fill.paint.url) {
|
||||||
node->style->fill.paint.gradient = _gradientDup(gradList, node->style->fill.paint.url);
|
node->style->fill.paint.gradient = _gradientDup(gradidents, node->style->fill.paint.url);
|
||||||
} else if (node->style->stroke.paint.url) {
|
} else if (node->style->stroke.paint.url) {
|
||||||
//node->style->stroke.paint.gradient = _gradientDup(gradList, node->style->stroke.paint.url);
|
//node->style->stroke.paint.gradient = _gradientDup(gradList, node->style->stroke.paint.url);
|
||||||
}
|
}
|
||||||
|
@ -2132,8 +2140,11 @@ static void _freeGradientStyle(SvgStyleGradient* grad)
|
||||||
free(grad->linear);
|
free(grad->linear);
|
||||||
if (grad->transform) free(grad->transform);
|
if (grad->transform) free(grad->transform);
|
||||||
|
|
||||||
for (auto colorStop : grad->stops) free(colorStop);
|
for (uint32_t i = 0; i < grad->stops.cnt; ++i) {
|
||||||
|
auto colorStop = grad->stops.list[i];
|
||||||
|
free(colorStop);
|
||||||
|
}
|
||||||
|
grad->stops.clear();
|
||||||
free(grad);
|
free(grad);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2152,8 +2163,9 @@ static void _freeNode(SvgNode* node)
|
||||||
{
|
{
|
||||||
if (!node) return;
|
if (!node) return;
|
||||||
|
|
||||||
for(auto child : node->child) {
|
auto child = node->child.list;
|
||||||
_freeNode(child);
|
for (uint32_t i = 0; i < node->child.cnt; ++i, ++child) {
|
||||||
|
_freeNode(*child);
|
||||||
}
|
}
|
||||||
node->child.clear();
|
node->child.clear();
|
||||||
|
|
||||||
|
@ -2178,9 +2190,12 @@ static void _freeNode(SvgNode* node)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SvgNodeType::Defs: {
|
case SvgNodeType::Defs: {
|
||||||
for(vector<SvgStyleGradient*>::iterator itrGrad = node->node.defs.gradients.begin(); itrGrad != node->node.defs.gradients.end(); itrGrad++) {
|
auto gradients = node->node.defs.gradients.list;
|
||||||
_freeGradientStyle(*itrGrad);
|
for (size_t i = 0; i < node->node.defs.gradients.cnt; ++i) {
|
||||||
|
_freeGradientStyle(*gradients);
|
||||||
|
++gradients;
|
||||||
}
|
}
|
||||||
|
node->node.defs.gradients.clear();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
@ -2221,7 +2236,7 @@ static bool _svgLoaderParserForValidCheckXmlOpen(SvgLoaderData* loader, const ch
|
||||||
if (strcmp(tagName, "svg")) return true; //Not a valid svg document
|
if (strcmp(tagName, "svg")) return true; //Not a valid svg document
|
||||||
node = method(loader, nullptr, attrs, attrsLength);
|
node = method(loader, nullptr, attrs, attrsLength);
|
||||||
loader->doc = node;
|
loader->doc = node;
|
||||||
loader->stack.push_back(node);
|
loader->stack.push(node);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2257,15 +2272,10 @@ void SvgTask::run()
|
||||||
if (loader->loaderData.doc) {
|
if (loader->loaderData.doc) {
|
||||||
_updateStyle(loader->loaderData.doc, nullptr);
|
_updateStyle(loader->loaderData.doc, nullptr);
|
||||||
auto defs = loader->loaderData.doc->node.doc.defs;
|
auto defs = loader->loaderData.doc->node.doc.defs;
|
||||||
if (defs) _updateGradient(loader->loaderData.doc, defs->node.defs.gradients);
|
if (defs) _updateGradient(loader->loaderData.doc, &defs->node.defs.gradients);
|
||||||
else {
|
else {
|
||||||
if (!loader->loaderData.gradients.empty()) {
|
if (loader->loaderData.gradients.cnt > 0) {
|
||||||
vector<SvgStyleGradient*> gradientList;
|
_updateGradient(loader->loaderData.doc, &loader->loaderData.gradients);
|
||||||
for (auto gradient : loader->loaderData.gradients) {
|
|
||||||
gradientList.push_back(gradient);
|
|
||||||
}
|
|
||||||
_updateGradient(loader->loaderData.doc, gradientList);
|
|
||||||
gradientList.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2368,6 +2378,7 @@ bool SvgLoader::close()
|
||||||
}
|
}
|
||||||
_freeNode(loaderData.doc);
|
_freeNode(loaderData.doc);
|
||||||
loaderData.doc = nullptr;
|
loaderData.doc = nullptr;
|
||||||
|
loaderData.stack.clear();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,6 +119,35 @@ enum class SvgParserLengthType
|
||||||
struct SvgNode;
|
struct SvgNode;
|
||||||
struct SvgStyleGradient;
|
struct SvgStyleGradient;
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
struct SvgVector
|
||||||
|
{
|
||||||
|
T* list;
|
||||||
|
uint32_t cnt;
|
||||||
|
uint32_t reserved;
|
||||||
|
|
||||||
|
void push(T element)
|
||||||
|
{
|
||||||
|
if (cnt + 1 > reserved) {
|
||||||
|
reserved = (cnt + 1) * 2;
|
||||||
|
list = static_cast<T*>(realloc(list, sizeof(T) * reserved));
|
||||||
|
}
|
||||||
|
list[cnt++] = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop()
|
||||||
|
{
|
||||||
|
if (cnt > 0) --cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
if (list) free(list);
|
||||||
|
list = nullptr;
|
||||||
|
cnt = reserved = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct SvgDocNode
|
struct SvgDocNode
|
||||||
{
|
{
|
||||||
float w;
|
float w;
|
||||||
|
@ -137,7 +166,7 @@ struct SvgGNode
|
||||||
|
|
||||||
struct SvgDefsNode
|
struct SvgDefsNode
|
||||||
{
|
{
|
||||||
vector<SvgStyleGradient *> gradients;
|
SvgVector<SvgStyleGradient*> gradients;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SvgArcNode
|
struct SvgArcNode
|
||||||
|
@ -240,7 +269,7 @@ struct SvgStyleGradient
|
||||||
SvgRadialGradient* radial;
|
SvgRadialGradient* radial;
|
||||||
SvgLinearGradient* linear;
|
SvgLinearGradient* linear;
|
||||||
Matrix* transform;
|
Matrix* transform;
|
||||||
vector<Fill::ColorStop *> stops;
|
SvgVector<Fill::ColorStop *> stops;
|
||||||
bool userSpace;
|
bool userSpace;
|
||||||
bool usePercentage;
|
bool usePercentage;
|
||||||
};
|
};
|
||||||
|
@ -281,7 +310,7 @@ struct SvgNode
|
||||||
{
|
{
|
||||||
SvgNodeType type;
|
SvgNodeType type;
|
||||||
SvgNode* parent;
|
SvgNode* parent;
|
||||||
vector<SvgNode*> child;
|
SvgVector<SvgNode*> child;
|
||||||
string *id;
|
string *id;
|
||||||
SvgStyleProperty *style;
|
SvgStyleProperty *style;
|
||||||
Matrix* transform;
|
Matrix* transform;
|
||||||
|
@ -320,10 +349,10 @@ struct SvgParser
|
||||||
|
|
||||||
struct SvgLoaderData
|
struct SvgLoaderData
|
||||||
{
|
{
|
||||||
vector<SvgNode *> stack;
|
SvgVector<SvgNode *> stack = {nullptr, 0, 0};
|
||||||
SvgNode* doc = nullptr;
|
SvgNode* doc = nullptr;
|
||||||
SvgNode* def = nullptr;
|
SvgNode* def = nullptr;
|
||||||
vector<SvgStyleGradient*> gradients;
|
SvgVector<SvgStyleGradient*> gradients;
|
||||||
SvgStyleGradient* latestGradient = nullptr; //For stops
|
SvgStyleGradient* latestGradient = nullptr; //For stops
|
||||||
SvgParser* svgParse = nullptr;
|
SvgParser* svgParse = nullptr;
|
||||||
int level = 0;
|
int level = 0;
|
||||||
|
|
|
@ -93,13 +93,13 @@ unique_ptr<LinearGradient> _applyLinearGradientProperty(SvgStyleGradient* g, Sha
|
||||||
fillGrad->spread(g->spread);
|
fillGrad->spread(g->spread);
|
||||||
|
|
||||||
//Update the stops
|
//Update the stops
|
||||||
stopCount = g->stops.size();
|
stopCount = g->stops.cnt;
|
||||||
if (stopCount > 0) {
|
if (stopCount > 0) {
|
||||||
float opacity;
|
float opacity;
|
||||||
float fopacity = fillOpacity / 255.0f; //fill opacity if any exists.
|
float fopacity = fillOpacity / 255.0f; //fill opacity if any exists.
|
||||||
int i = 0;
|
|
||||||
stops = (Fill::ColorStop*)calloc(stopCount, sizeof(Fill::ColorStop));
|
stops = (Fill::ColorStop*)calloc(stopCount, sizeof(Fill::ColorStop));
|
||||||
for (auto colorStop : g->stops) {
|
for (uint32_t i = 0; i < g->stops.cnt; ++i) {
|
||||||
|
auto colorStop = g->stops.list[i];
|
||||||
//Use premultiplied color
|
//Use premultiplied color
|
||||||
opacity = ((float)colorStop->a / 255.0f) * fopacity;
|
opacity = ((float)colorStop->a / 255.0f) * fopacity;
|
||||||
stops[i].r = colorStop->r * opacity;
|
stops[i].r = colorStop->r * opacity;
|
||||||
|
@ -107,7 +107,6 @@ unique_ptr<LinearGradient> _applyLinearGradientProperty(SvgStyleGradient* g, Sha
|
||||||
stops[i].b = colorStop->b * opacity;
|
stops[i].b = colorStop->b * opacity;
|
||||||
stops[i].a = colorStop->a * fopacity;
|
stops[i].a = colorStop->a * fopacity;
|
||||||
stops[i].offset = colorStop->offset;
|
stops[i].offset = colorStop->offset;
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
fillGrad->colorStops(stops, stopCount);
|
fillGrad->colorStops(stops, stopCount);
|
||||||
free(stops);
|
free(stops);
|
||||||
|
@ -179,13 +178,13 @@ unique_ptr<RadialGradient> _applyRadialGradientProperty(SvgStyleGradient* g, Sha
|
||||||
fillGrad->spread(g->spread);
|
fillGrad->spread(g->spread);
|
||||||
|
|
||||||
//Update the stops
|
//Update the stops
|
||||||
stopCount = g->stops.size();
|
stopCount = g->stops.cnt;
|
||||||
if (stopCount > 0) {
|
if (stopCount > 0) {
|
||||||
float opacity;
|
float opacity;
|
||||||
float fopacity = fillOpacity / 255.0f; //fill opacity if any exists.
|
float fopacity = fillOpacity / 255.0f; //fill opacity if any exists.
|
||||||
int i = 0;
|
|
||||||
stops = (Fill::ColorStop*)calloc(stopCount, sizeof(Fill::ColorStop));
|
stops = (Fill::ColorStop*)calloc(stopCount, sizeof(Fill::ColorStop));
|
||||||
for (auto colorStop : g->stops) {
|
for (uint32_t i = 0; i < g->stops.cnt; ++i) {
|
||||||
|
auto colorStop = g->stops.list[i];
|
||||||
//Use premultiplied color
|
//Use premultiplied color
|
||||||
opacity = ((float)colorStop->a / 255.0f) * fopacity;
|
opacity = ((float)colorStop->a / 255.0f) * fopacity;
|
||||||
stops[i].r = colorStop->r * opacity;
|
stops[i].r = colorStop->r * opacity;
|
||||||
|
@ -193,7 +192,6 @@ unique_ptr<RadialGradient> _applyRadialGradientProperty(SvgStyleGradient* g, Sha
|
||||||
stops[i].b = colorStop->b * opacity;
|
stops[i].b = colorStop->b * opacity;
|
||||||
stops[i].a = colorStop->a * fopacity;
|
stops[i].a = colorStop->a * fopacity;
|
||||||
stops[i].offset = colorStop->offset;
|
stops[i].offset = colorStop->offset;
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
fillGrad->colorStops(stops, stopCount);
|
fillGrad->colorStops(stops, stopCount);
|
||||||
free(stops);
|
free(stops);
|
||||||
|
@ -335,11 +333,13 @@ unique_ptr<Scene> _sceneBuildHelper(SvgNode* node, float vx, float vy, float vw,
|
||||||
if (node->transform) scene->transform(*node->transform);
|
if (node->transform) scene->transform(*node->transform);
|
||||||
node->style->opacity = (node->style->opacity * parentOpacity) / 255.0f;
|
node->style->opacity = (node->style->opacity * parentOpacity) / 255.0f;
|
||||||
if (node->display) {
|
if (node->display) {
|
||||||
for (auto child : node->child) {
|
auto child = node->child.list;
|
||||||
if (child->type == SvgNodeType::Doc || child->type == SvgNodeType::G) scene->push(_sceneBuildHelper(child, vx, vy, vw, vh, node->style->opacity));
|
for (uint32_t i = 0; i < node->child.cnt; ++i, ++child) {
|
||||||
else {
|
if ((*child)->type == SvgNodeType::Doc || (*child)->type == SvgNodeType::G) {
|
||||||
child->style->opacity = (child->style->opacity * node->style->opacity) / 255.0f;
|
scene->push(_sceneBuildHelper(*child, vx, vy, vw, vh, node->style->opacity));
|
||||||
scene->push(_shapeBuildHelper(child, vx, vy, vw, vh));
|
} else {
|
||||||
|
(*child)->style->opacity = ((*child)->style->opacity * node->style->opacity) / 255.0f;
|
||||||
|
scene->push(_shapeBuildHelper(*child, vx, vy, vw, vh));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue