mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-14 12:04:29 +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)
|
||||
{
|
||||
SvgLoaderData* loader = (SvgLoaderData*)data;
|
||||
|
@ -1725,8 +1744,15 @@ static bool _attrParseUseNode(void* data, const char* key, const char* value)
|
|||
id = _idFromHref(value);
|
||||
defs = _getDefsNode(node);
|
||||
nodeFrom = _findChildById(defs, id->c_str());
|
||||
_cloneNode(nodeFrom, node);
|
||||
delete id;
|
||||
if (nodeFrom) {
|
||||
_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")) {
|
||||
_handleClipPathAttr(loader, node, value);
|
||||
} else if (!strcmp(key, "mask")) {
|
||||
|
@ -2682,6 +2708,8 @@ void SvgLoader::run(unsigned tid)
|
|||
|
||||
_updateComposite(loaderData.doc, loaderData.doc);
|
||||
if (defs) _updateComposite(loaderData.doc, defs);
|
||||
|
||||
if (loaderData.cloneNodes.count > 0) _clonePostponedNodes(&loaderData.cloneNodes);
|
||||
}
|
||||
root = svgSceneBuild(loaderData.doc, vx, vy, vw, vh);
|
||||
};
|
||||
|
|
|
@ -333,6 +333,12 @@ struct SvgParser
|
|||
} gradient;
|
||||
};
|
||||
|
||||
struct SvgNodeIdPair
|
||||
{
|
||||
SvgNode* node;
|
||||
string *id;
|
||||
};
|
||||
|
||||
struct SvgLoaderData
|
||||
{
|
||||
Array<SvgNode *> stack = {nullptr, 0, 0};
|
||||
|
@ -341,6 +347,7 @@ struct SvgLoaderData
|
|||
Array<SvgStyleGradient*> gradients;
|
||||
SvgStyleGradient* latestGradient = nullptr; //For stops
|
||||
SvgParser* svgParse = nullptr;
|
||||
Array<SvgNodeIdPair> cloneNodes;
|
||||
int level = 0;
|
||||
bool result = false;
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue