From: Michal Maciola <71131832+mmaciola@users.noreply.github.com> Date: Wed, 7 Jul 2021 06:34:15 +0000 (+0200) Subject: svg_loader: postpone cloneNode() X-Git-Tag: submit/tizen/20210712.055754~31 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c2de81daf966fdf9aee772e267d37b4879d8e7e5;p=platform%2Fcore%2Fgraphics%2Ftizenvg.git svg_loader: postpone cloneNode() Some svg export software puts element at the end of the file. If so, the element won't be found, when parsing . In such scenario, this patch postpone node cloning until the whole file is parsed. @issue: #568 --- diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index 5f58c83e..6bff1d42 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -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* 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 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); }; diff --git a/src/loaders/svg/tvgSvgLoaderCommon.h b/src/loaders/svg/tvgSvgLoaderCommon.h index 07b66e68..b9f02b80 100644 --- a/src/loaders/svg/tvgSvgLoaderCommon.h +++ b/src/loaders/svg/tvgSvgLoaderCommon.h @@ -333,6 +333,12 @@ struct SvgParser } gradient; }; +struct SvgNodeIdPair +{ + SvgNode* node; + string *id; +}; + struct SvgLoaderData { Array stack = {nullptr, 0, 0}; @@ -341,6 +347,7 @@ struct SvgLoaderData Array gradients; SvgStyleGradient* latestGradient = nullptr; //For stops SvgParser* svgParse = nullptr; + Array cloneNodes; int level = 0; bool result = false; };