mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 13:43:43 +00:00
loader/svg: Check whether href id of use is parent or not
When finding the 'nodeFrom' referenced by `<use>`, if it is the parent, it is not referenced. https://www.w3.org/TR/SVG2/struct.html#UseElement Specification: If the referenced element is a (shadow-including) ancestor of the ‘use’ element, then this is an invalid circular reference and the ‘use’ element is in error. related issue: https://github.com/thorvg/thorvg/issues/2078 SVG_FILE_65171.svg SVG_FILE_65172.svg
This commit is contained in:
parent
46448a1520
commit
fdebb15dcb
1 changed files with 26 additions and 5 deletions
|
@ -1919,6 +1919,19 @@ static SvgNode* _findNodeById(SvgNode *node, const char* id)
|
|||
}
|
||||
|
||||
|
||||
static SvgNode* _findParentById(SvgNode* node, char* id, SvgNode* doc)
|
||||
{
|
||||
SvgNode *parent = node->parent;
|
||||
while (parent != nullptr && parent != doc) {
|
||||
if (parent->id && !strcmp(parent->id, id)) {
|
||||
return parent;
|
||||
}
|
||||
parent = parent->parent;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
static constexpr struct
|
||||
{
|
||||
const char* tag;
|
||||
|
@ -1959,8 +1972,12 @@ static bool _attrParseUseNode(void* data, const char* key, const char* value)
|
|||
defs = _getDefsNode(node);
|
||||
nodeFrom = _findNodeById(defs, id);
|
||||
if (nodeFrom) {
|
||||
if (!_findParentById(node, id, loader->doc)) {
|
||||
_cloneNode(nodeFrom, node, 0);
|
||||
if (nodeFrom->type == SvgNodeType::Symbol) use->symbol = nodeFrom;
|
||||
} else {
|
||||
TVGLOG("SVG", "%s is ancestor element. This reference is invalid.", id);
|
||||
}
|
||||
free(id);
|
||||
} else {
|
||||
//some svg export software include <defs> element at the end of the file
|
||||
|
@ -3024,10 +3041,14 @@ static void _clonePostponedNodes(Array<SvgNodeIdPair>* cloneNodes, SvgNode* doc)
|
|||
auto defs = _getDefsNode(nodeIdPair.node);
|
||||
auto nodeFrom = _findNodeById(defs, nodeIdPair.id);
|
||||
if (!nodeFrom) nodeFrom = _findNodeById(doc, nodeIdPair.id);
|
||||
if (!_findParentById(nodeIdPair.node, nodeIdPair.id, doc)) {
|
||||
_cloneNode(nodeFrom, nodeIdPair.node, 0);
|
||||
if (nodeFrom && nodeFrom->type == SvgNodeType::Symbol && nodeIdPair.node->type == SvgNodeType::Use) {
|
||||
nodeIdPair.node->node.use.symbol = nodeFrom;
|
||||
}
|
||||
} else {
|
||||
TVGLOG("SVG", "%s is ancestor element. This reference is invalid.", nodeIdPair.id);
|
||||
}
|
||||
free(nodeIdPair.id);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue