char* str = (char*)value;
char* end = str + strlen(str);
+ if (!matrix) return nullptr;
*matrix = { 1, 0, 0, 0, 1, 0, 0, 0, 1 };
while (str < end) {
if (isspace(*str) || (*str == ',')) {
{
SvgNode* node = (SvgNode*)calloc(1, sizeof(SvgNode));
+ if (!node) return nullptr;
+
//Default fill property
node->style = (SvgStyleProperty*)calloc(1, sizeof(SvgStyleProperty));
+ if (!node->style) {
+ free(node);
+ return nullptr;
+ }
+
//Update the default value of stroke and fill
//https://www.w3.org/TR/SVGTiny12/painting.html#SpecifyingPaint
node->style->fill.paint.none = false;
static SvgNode* _createDefsNode(TVG_UNUSED SvgLoaderData* loader, TVG_UNUSED SvgNode* parent, const char* buf, unsigned bufLength)
{
SvgNode* node = _createNode(nullptr, SvgNodeType::Defs);
+ if (!node) return nullptr;
simpleXmlParseAttributes(buf, bufLength, nullptr, node);
return node;
}
static SvgNode* _createGNode(TVG_UNUSED SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength)
{
loader->svgParse->node = _createNode(parent, SvgNodeType::G);
+ if (!loader->svgParse->node) return nullptr;
simpleXmlParseAttributes(buf, bufLength, _attrParseGNode, loader);
return loader->svgParse->node;
static SvgNode* _createSvgNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength)
{
loader->svgParse->node = _createNode(parent, SvgNodeType::Doc);
+ if (!loader->svgParse->node) return nullptr;
SvgDocNode* doc = &(loader->svgParse->node->node.doc);
doc->preserveAspect = true;
static SvgNode* _createMaskNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength)
{
loader->svgParse->node = _createNode(parent, SvgNodeType::Unknown);
+ if (!loader->svgParse->node) return nullptr;
loader->svgParse->node->display = false;
#ifdef THORVG_LOG_ENABLED
{
loader->svgParse->node = _createNode(parent, SvgNodeType::ClipPath);
+ if (!loader->svgParse->node) return nullptr;
+
loader->svgParse->node->display = false;
simpleXmlParseAttributes(buf, bufLength, _attrParseClipPathNode, loader);
{
loader->svgParse->node = _createNode(parent, SvgNodeType::Path);
+ if (!loader->svgParse->node) return nullptr;
+
simpleXmlParseAttributes(buf, bufLength, _attrParsePathNode, loader);
return loader->svgParse->node;
{
loader->svgParse->node = _createNode(parent, SvgNodeType::Circle);
+ if (!loader->svgParse->node) return nullptr;
+
simpleXmlParseAttributes(buf, bufLength, _attrParseCircleNode, loader);
return loader->svgParse->node;
}
{
loader->svgParse->node = _createNode(parent, SvgNodeType::Ellipse);
+ if (!loader->svgParse->node) return nullptr;
+
simpleXmlParseAttributes(buf, bufLength, _attrParseEllipseNode, loader);
return loader->svgParse->node;
}
{
loader->svgParse->node = _createNode(parent, SvgNodeType::Polygon);
+ if (!loader->svgParse->node) return nullptr;
+
simpleXmlParseAttributes(buf, bufLength, _attrParsePolygonNode, loader);
return loader->svgParse->node;
}
{
loader->svgParse->node = _createNode(parent, SvgNodeType::Polyline);
+ if (!loader->svgParse->node) return nullptr;
+
simpleXmlParseAttributes(buf, bufLength, _attrParsePolygonNode, loader);
return loader->svgParse->node;
}
static SvgNode* _createRectNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength)
{
loader->svgParse->node = _createNode(parent, SvgNodeType::Rect);
- if (loader->svgParse->node) {
- loader->svgParse->node->node.rect.hasRx = loader->svgParse->node->node.rect.hasRy = false;
- }
+
+ if (!loader->svgParse->node) return nullptr;
+
+ loader->svgParse->node->node.rect.hasRx = loader->svgParse->node->node.rect.hasRy = false;
simpleXmlParseAttributes(buf, bufLength, _attrParseRectNode, loader);
return loader->svgParse->node;
{
loader->svgParse->node = _createNode(parent, SvgNodeType::Line);
+ if (!loader->svgParse->node) return nullptr;
+
simpleXmlParseAttributes(buf, bufLength, _attrParseLineNode, loader);
return loader->svgParse->node;
}
if (!from) return nullptr;
grad = (SvgStyleGradient*)calloc(1, sizeof(SvgStyleGradient));
+ if (!grad) return nullptr;
grad->type = from->type;
grad->id = from->id ? _copyId(from->id->c_str()) : nullptr;
grad->ref = from->ref ? _copyId(from->ref->c_str()) : nullptr;
grad->userSpace = from->userSpace;
if (from->transform) {
grad->transform = (Matrix*)calloc(1, sizeof(Matrix));
- memcpy(grad->transform, from->transform, sizeof(Matrix));
+ if (grad->transform) memcpy(grad->transform, from->transform, sizeof(Matrix));
}
if (grad->type == SvgGradientType::Linear) {
grad->linear = (SvgLinearGradient*)calloc(1, sizeof(SvgLinearGradient));
+ if (!grad->linear) goto error_grad_alloc;
memcpy(grad->linear, from->linear, sizeof(SvgLinearGradient));
} else if (grad->type == SvgGradientType::Radial) {
grad->radial = (SvgRadialGradient*)calloc(1, sizeof(SvgRadialGradient));
+ if (!grad->radial) goto error_grad_alloc;
memcpy(grad->radial, from->radial, sizeof(SvgRadialGradient));
}
_cloneGradStops(&grad->stops, &from->stops);
return grad;
+error_grad_alloc:
+ //LOG: allocation failed. out of memory
+ if (grad) free(grad);
+ return nullptr;
}
//Copy matrix attribute
if (from->transform) {
to->transform = (Matrix*)calloc(1, sizeof(Matrix));
- memcpy(to->transform, from->transform, sizeof(Matrix));
+ if (to->transform) memcpy(to->transform, from->transform, sizeof(Matrix));
}
//Copy style attribute;
memcpy(to->style, from->style, sizeof(SvgStyleProperty));
if (!from || !parent) return;
newNode = _createNode(parent, from->type);
+
+ if (!newNode) return;
+
_copyAttr(newNode, from);
auto child = from->child.data;
{
loader->svgParse->node = _createNode(parent, SvgNodeType::G);
+ if (!loader->svgParse->node) return nullptr;
+
simpleXmlParseAttributes(buf, bufLength, _attrParseUseNode, loader);
return loader->svgParse->node;
}
{
unsigned int i = 0;
SvgStyleGradient* grad = (SvgStyleGradient*)calloc(1, sizeof(SvgStyleGradient));
+ if (!grad) return nullptr;
loader->svgParse->styleGrad = grad;
grad->type = SvgGradientType::Radial;
grad->userSpace = false;
grad->radial = (SvgRadialGradient*)calloc(1, sizeof(SvgRadialGradient));
+ if (!grad->radial) {
+ free(grad);
+ return nullptr;
+ }
/**
* Default values of gradient
*/
static SvgStyleGradient* _createLinearGradient(SvgLoaderData* loader, const char* buf, unsigned bufLength)
{
SvgStyleGradient* grad = (SvgStyleGradient*)calloc(1, sizeof(SvgStyleGradient));
+ if (!grad) return nullptr;
loader->svgParse->styleGrad = grad;
unsigned int i;
grad->type = SvgGradientType::Linear;
grad->userSpace = false;
grad->linear = (SvgLinearGradient*)calloc(1, sizeof(SvgLinearGradient));
+ if (!grad->linear) {
+ free(grad);
+ return nullptr;
+ }
/**
* Default value of x2 is 100%
*/
loader->latestGradient = gradient;
} else if (!strcmp(tagName, "stop")) {
auto stop = static_cast<Fill::ColorStop*>(calloc(1, sizeof(Fill::ColorStop)));
+ if (!stop) return;
loader->svgParse->gradStop = stop;
/* default value for opacity */
stop->a = 255;