}
+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;
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")) {
_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);
};