mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-15 12:34:30 +00:00
svg_loader: postpone cloneNode()
Some svg export software puts <defs> element at the end of the file. If so, the <defs> element won't be found, when parsing <use>. In such scenario, this patch postpone node cloning until the whole file is parsed. @issue: #568
This commit is contained in:
parent
90a8c9d197
commit
bb19bcf64f
2 changed files with 37 additions and 2 deletions
|
@ -1715,6 +1715,25 @@ static void _cloneNode(SvgNode* from, SvgNode* parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void _postponeCloneNode(SvgLoaderData* loader, SvgNode *node, string* id) {
|
||||||
|
SvgNodeIdPair nodeIdPair;
|
||||||
|
nodeIdPair.node = node;
|
||||||
|
nodeIdPair.id = id;
|
||||||
|
loader->cloneNodes.push(nodeIdPair);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void _clonePostponedNodes(Array<SvgNodeIdPair>* cloneNodes) {
|
||||||
|
for (uint32_t i = 0; i < cloneNodes->count; ++i) {
|
||||||
|
SvgNodeIdPair nodeIdPair = cloneNodes->data[i];
|
||||||
|
SvgNode *defs = _getDefsNode(nodeIdPair.node);
|
||||||
|
SvgNode *nodeFrom = _findChildById(defs, nodeIdPair.id->c_str());
|
||||||
|
_cloneNode(nodeFrom, nodeIdPair.node);
|
||||||
|
delete nodeIdPair.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool _attrParseUseNode(void* data, const char* key, const char* value)
|
static bool _attrParseUseNode(void* data, const char* key, const char* value)
|
||||||
{
|
{
|
||||||
SvgLoaderData* loader = (SvgLoaderData*)data;
|
SvgLoaderData* loader = (SvgLoaderData*)data;
|
||||||
|
@ -1725,8 +1744,15 @@ static bool _attrParseUseNode(void* data, const char* key, const char* value)
|
||||||
id = _idFromHref(value);
|
id = _idFromHref(value);
|
||||||
defs = _getDefsNode(node);
|
defs = _getDefsNode(node);
|
||||||
nodeFrom = _findChildById(defs, id->c_str());
|
nodeFrom = _findChildById(defs, id->c_str());
|
||||||
_cloneNode(nodeFrom, node);
|
if (nodeFrom) {
|
||||||
delete id;
|
_cloneNode(nodeFrom, node);
|
||||||
|
delete id;
|
||||||
|
} else {
|
||||||
|
//some svg export software include <defs> element at the end of the file
|
||||||
|
//if so the 'from' element won't be found now and we have to repeat finding
|
||||||
|
//after the whole file is parsed
|
||||||
|
_postponeCloneNode(loader, node, id);
|
||||||
|
}
|
||||||
} else if (!strcmp(key, "clip-path")) {
|
} else if (!strcmp(key, "clip-path")) {
|
||||||
_handleClipPathAttr(loader, node, value);
|
_handleClipPathAttr(loader, node, value);
|
||||||
} else if (!strcmp(key, "mask")) {
|
} else if (!strcmp(key, "mask")) {
|
||||||
|
@ -2682,6 +2708,8 @@ void SvgLoader::run(unsigned tid)
|
||||||
|
|
||||||
_updateComposite(loaderData.doc, loaderData.doc);
|
_updateComposite(loaderData.doc, loaderData.doc);
|
||||||
if (defs) _updateComposite(loaderData.doc, defs);
|
if (defs) _updateComposite(loaderData.doc, defs);
|
||||||
|
|
||||||
|
if (loaderData.cloneNodes.count > 0) _clonePostponedNodes(&loaderData.cloneNodes);
|
||||||
}
|
}
|
||||||
root = svgSceneBuild(loaderData.doc, vx, vy, vw, vh);
|
root = svgSceneBuild(loaderData.doc, vx, vy, vw, vh);
|
||||||
};
|
};
|
||||||
|
|
|
@ -333,6 +333,12 @@ struct SvgParser
|
||||||
} gradient;
|
} gradient;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SvgNodeIdPair
|
||||||
|
{
|
||||||
|
SvgNode* node;
|
||||||
|
string *id;
|
||||||
|
};
|
||||||
|
|
||||||
struct SvgLoaderData
|
struct SvgLoaderData
|
||||||
{
|
{
|
||||||
Array<SvgNode *> stack = {nullptr, 0, 0};
|
Array<SvgNode *> stack = {nullptr, 0, 0};
|
||||||
|
@ -341,6 +347,7 @@ struct SvgLoaderData
|
||||||
Array<SvgStyleGradient*> gradients;
|
Array<SvgStyleGradient*> gradients;
|
||||||
SvgStyleGradient* latestGradient = nullptr; //For stops
|
SvgStyleGradient* latestGradient = nullptr; //For stops
|
||||||
SvgParser* svgParse = nullptr;
|
SvgParser* svgParse = nullptr;
|
||||||
|
Array<SvgNodeIdPair> cloneNodes;
|
||||||
int level = 0;
|
int level = 0;
|
||||||
bool result = false;
|
bool result = false;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue