mirror of
https://github.com/thorvg/thorvg.git
synced 2025-07-28 09:05:52 +00:00
svg_loader: fix gradient memory leak.
@Issue: https://github.com/Samsung/thorvg/issues/548
This commit is contained in:
parent
3997aedcd5
commit
af140a1fe5
2 changed files with 45 additions and 42 deletions
|
@ -1588,22 +1588,23 @@ static void _cloneGradStops(Array<Fill::ColorStop>& dst, const Array<Fill::Color
|
||||||
|
|
||||||
static SvgStyleGradient* _cloneGradient(SvgStyleGradient* from)
|
static SvgStyleGradient* _cloneGradient(SvgStyleGradient* from)
|
||||||
{
|
{
|
||||||
SvgStyleGradient* grad;
|
|
||||||
|
|
||||||
if (!from) return nullptr;
|
if (!from) return nullptr;
|
||||||
|
|
||||||
grad = (SvgStyleGradient*)calloc(1, sizeof(SvgStyleGradient));
|
auto grad = new SvgStyleGradient;
|
||||||
if (!grad) return nullptr;
|
if (!grad) return nullptr;
|
||||||
|
|
||||||
grad->type = from->type;
|
grad->type = from->type;
|
||||||
grad->id = from->id ? _copyId(from->id->c_str()) : nullptr;
|
grad->id = from->id ? _copyId(from->id->c_str()) : nullptr;
|
||||||
grad->ref = from->ref ? _copyId(from->ref->c_str()) : nullptr;
|
grad->ref = from->ref ? _copyId(from->ref->c_str()) : nullptr;
|
||||||
grad->spread = from->spread;
|
grad->spread = from->spread;
|
||||||
grad->usePercentage = from->usePercentage;
|
grad->usePercentage = from->usePercentage;
|
||||||
grad->userSpace = from->userSpace;
|
grad->userSpace = from->userSpace;
|
||||||
|
|
||||||
if (from->transform) {
|
if (from->transform) {
|
||||||
grad->transform = (Matrix*)calloc(1, sizeof(Matrix));
|
grad->transform = (Matrix*)calloc(1, sizeof(Matrix));
|
||||||
if (grad->transform) memcpy(grad->transform, from->transform, sizeof(Matrix));
|
if (grad->transform) memcpy(grad->transform, from->transform, sizeof(Matrix));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (grad->type == SvgGradientType::Linear) {
|
if (grad->type == SvgGradientType::Linear) {
|
||||||
grad->linear = (SvgLinearGradient*)calloc(1, sizeof(SvgLinearGradient));
|
grad->linear = (SvgLinearGradient*)calloc(1, sizeof(SvgLinearGradient));
|
||||||
if (!grad->linear) goto error_grad_alloc;
|
if (!grad->linear) goto error_grad_alloc;
|
||||||
|
@ -1615,13 +1616,11 @@ static SvgStyleGradient* _cloneGradient(SvgStyleGradient* from)
|
||||||
}
|
}
|
||||||
|
|
||||||
_cloneGradStops(grad->stops, from->stops);
|
_cloneGradStops(grad->stops, from->stops);
|
||||||
|
|
||||||
return grad;
|
return grad;
|
||||||
|
|
||||||
error_grad_alloc:
|
error_grad_alloc:
|
||||||
//LOG: allocation failed. out of memory
|
if (grad) delete(grad);
|
||||||
if (grad->transform) free(grad->transform);
|
|
||||||
if (grad->ref) delete grad->ref;
|
|
||||||
if (grad->id) delete grad->id;
|
|
||||||
if (grad) free(grad);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1960,15 +1959,16 @@ static bool _attrParseRadialGradientNode(void* data, const char* key, const char
|
||||||
|
|
||||||
static SvgStyleGradient* _createRadialGradient(SvgLoaderData* loader, const char* buf, unsigned bufLength)
|
static SvgStyleGradient* _createRadialGradient(SvgLoaderData* loader, const char* buf, unsigned bufLength)
|
||||||
{
|
{
|
||||||
SvgStyleGradient* grad = (SvgStyleGradient*)calloc(1, sizeof(SvgStyleGradient));
|
auto grad = new SvgStyleGradient;
|
||||||
if (!grad) return nullptr;
|
if (!grad) return nullptr;
|
||||||
|
|
||||||
loader->svgParse->styleGrad = grad;
|
loader->svgParse->styleGrad = grad;
|
||||||
|
|
||||||
grad->type = SvgGradientType::Radial;
|
grad->type = SvgGradientType::Radial;
|
||||||
grad->userSpace = false;
|
grad->userSpace = false;
|
||||||
grad->radial = (SvgRadialGradient*)calloc(1, sizeof(SvgRadialGradient));
|
grad->radial = (SvgRadialGradient*)calloc(1, sizeof(SvgRadialGradient));
|
||||||
if (!grad->radial) {
|
if (!grad->radial) {
|
||||||
free(grad);
|
delete(grad);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -2145,15 +2145,16 @@ static bool _attrParseLinearGradientNode(void* data, const char* key, const char
|
||||||
|
|
||||||
static SvgStyleGradient* _createLinearGradient(SvgLoaderData* loader, const char* buf, unsigned bufLength)
|
static SvgStyleGradient* _createLinearGradient(SvgLoaderData* loader, const char* buf, unsigned bufLength)
|
||||||
{
|
{
|
||||||
SvgStyleGradient* grad = (SvgStyleGradient*)calloc(1, sizeof(SvgStyleGradient));
|
auto grad = new SvgStyleGradient;
|
||||||
if (!grad) return nullptr;
|
if (!grad) return nullptr;
|
||||||
|
|
||||||
loader->svgParse->styleGrad = grad;
|
loader->svgParse->styleGrad = grad;
|
||||||
|
|
||||||
grad->type = SvgGradientType::Linear;
|
grad->type = SvgGradientType::Linear;
|
||||||
grad->userSpace = false;
|
grad->userSpace = false;
|
||||||
grad->linear = (SvgLinearGradient*)calloc(1, sizeof(SvgLinearGradient));
|
grad->linear = (SvgLinearGradient*)calloc(1, sizeof(SvgLinearGradient));
|
||||||
if (!grad->linear) {
|
if (!grad->linear) {
|
||||||
free(grad);
|
delete(grad);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -2504,14 +2505,17 @@ static void _updateGradient(SvgNode* node, Array<SvgStyleGradient*>* gradients)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (node->style->fill.paint.url) {
|
if (node->style->fill.paint.url) {
|
||||||
|
if (node->style->fill.paint.gradient) delete(node->style->fill.paint.gradient);
|
||||||
node->style->fill.paint.gradient = _gradientDup(gradients, node->style->fill.paint.url);
|
node->style->fill.paint.gradient = _gradientDup(gradients, node->style->fill.paint.url);
|
||||||
}
|
}
|
||||||
if (node->style->stroke.paint.url) {
|
if (node->style->stroke.paint.url) {
|
||||||
|
if (node->style->stroke.paint.gradient) delete(node->style->stroke.paint.gradient);
|
||||||
node->style->stroke.paint.gradient = _gradientDup(gradients, node->style->stroke.paint.url);
|
node->style->stroke.paint.gradient = _gradientDup(gradients, node->style->stroke.paint.url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void _updateComposite(SvgNode* node, SvgNode* root)
|
static void _updateComposite(SvgNode* node, SvgNode* root)
|
||||||
{
|
{
|
||||||
if (node->style->comp.url && !node->style->comp.node) {
|
if (node->style->comp.url && !node->style->comp.node) {
|
||||||
|
@ -2526,34 +2530,23 @@ static void _updateComposite(SvgNode* node, SvgNode* root)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _freeGradientStyle(SvgStyleGradient* grad)
|
|
||||||
{
|
|
||||||
if (!grad) return;
|
|
||||||
|
|
||||||
delete grad->id;
|
|
||||||
delete grad->ref;
|
|
||||||
free(grad->radial);
|
|
||||||
free(grad->linear);
|
|
||||||
if (grad->transform) free(grad->transform);
|
|
||||||
grad->stops.reset();
|
|
||||||
free(grad);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _freeNodeStyle(SvgStyleProperty* style)
|
static void _freeNodeStyle(SvgStyleProperty* style)
|
||||||
{
|
{
|
||||||
if (!style) return;
|
if (!style) return;
|
||||||
|
|
||||||
//style->comp.node has only the addresses of node. Therefore, style->comp.node is released from _freeNode.
|
//style->comp.node has only the addresses of node. Therefore, style->comp.node is released from _freeNode.
|
||||||
delete style->comp.url;
|
delete(style->comp.url);
|
||||||
|
|
||||||
_freeGradientStyle(style->fill.paint.gradient);
|
if (style->fill.paint.gradient) delete(style->fill.paint.gradient);
|
||||||
delete style->fill.paint.url;
|
if (style->stroke.paint.gradient) delete(style->stroke.paint.gradient);
|
||||||
_freeGradientStyle(style->stroke.paint.gradient);
|
delete(style->fill.paint.url);
|
||||||
if (style->stroke.dash.array.count > 0) style->stroke.dash.array.reset();
|
delete(style->stroke.paint.url);
|
||||||
delete style->stroke.paint.url;
|
style->stroke.dash.array.reset();
|
||||||
free(style);
|
free(style);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void _freeNode(SvgNode* node)
|
static void _freeNode(SvgNode* node)
|
||||||
{
|
{
|
||||||
if (!node) return;
|
if (!node) return;
|
||||||
|
@ -2587,7 +2580,7 @@ static void _freeNode(SvgNode* node)
|
||||||
case SvgNodeType::Defs: {
|
case SvgNodeType::Defs: {
|
||||||
auto gradients = node->node.defs.gradients.data;
|
auto gradients = node->node.defs.gradients.data;
|
||||||
for (size_t i = 0; i < node->node.defs.gradients.count; ++i) {
|
for (size_t i = 0; i < node->node.defs.gradients.count; ++i) {
|
||||||
_freeGradientStyle(*gradients);
|
delete(*gradients);
|
||||||
++gradients;
|
++gradients;
|
||||||
}
|
}
|
||||||
node->node.defs.gradients.reset();
|
node->node.defs.gradients.reset();
|
||||||
|
@ -2800,7 +2793,7 @@ bool SvgLoader::close()
|
||||||
}
|
}
|
||||||
auto gradients = loaderData.gradients.data;
|
auto gradients = loaderData.gradients.data;
|
||||||
for (size_t i = 0; i < loaderData.gradients.count; ++i) {
|
for (size_t i = 0; i < loaderData.gradients.count; ++i) {
|
||||||
_freeGradientStyle(*gradients);
|
delete(*gradients);
|
||||||
++gradients;
|
++gradients;
|
||||||
}
|
}
|
||||||
loaderData.gradients.reset();
|
loaderData.gradients.reset();
|
||||||
|
|
|
@ -247,16 +247,26 @@ struct SvgDash
|
||||||
|
|
||||||
struct SvgStyleGradient
|
struct SvgStyleGradient
|
||||||
{
|
{
|
||||||
SvgGradientType type;
|
SvgGradientType type = SvgGradientType::Linear;
|
||||||
string *id;
|
string *id = nullptr;
|
||||||
string *ref;
|
string *ref = nullptr;
|
||||||
FillSpread spread;
|
FillSpread spread = FillSpread::Pad;
|
||||||
SvgRadialGradient* radial;
|
SvgRadialGradient* radial = nullptr;
|
||||||
SvgLinearGradient* linear;
|
SvgLinearGradient* linear = nullptr;
|
||||||
Matrix* transform;
|
Matrix* transform = nullptr;
|
||||||
Array<Fill::ColorStop> stops;
|
Array<Fill::ColorStop> stops;
|
||||||
bool userSpace;
|
bool userSpace = false;
|
||||||
bool usePercentage;
|
bool usePercentage = false;
|
||||||
|
|
||||||
|
~SvgStyleGradient()
|
||||||
|
{
|
||||||
|
stops.reset();
|
||||||
|
free(transform);
|
||||||
|
free(radial);
|
||||||
|
free(linear);
|
||||||
|
delete(ref);
|
||||||
|
delete(id);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SvgStyleFill
|
struct SvgStyleFill
|
||||||
|
@ -319,7 +329,7 @@ struct SvgParser
|
||||||
{
|
{
|
||||||
SvgNode* node;
|
SvgNode* node;
|
||||||
SvgStyleGradient* styleGrad;
|
SvgStyleGradient* styleGrad;
|
||||||
Fill::ColorStop gradStop;
|
Fill::ColorStop gradStop;
|
||||||
SvgStopStyleFlags flags;
|
SvgStopStyleFlags flags;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue