mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-09 06:04:03 +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
|
static constexpr struct
|
||||||
{
|
{
|
||||||
const char* tag;
|
const char* tag;
|
||||||
|
@ -1959,8 +1972,12 @@ static bool _attrParseUseNode(void* data, const char* key, const char* value)
|
||||||
defs = _getDefsNode(node);
|
defs = _getDefsNode(node);
|
||||||
nodeFrom = _findNodeById(defs, id);
|
nodeFrom = _findNodeById(defs, id);
|
||||||
if (nodeFrom) {
|
if (nodeFrom) {
|
||||||
_cloneNode(nodeFrom, node, 0);
|
if (!_findParentById(node, id, loader->doc)) {
|
||||||
if (nodeFrom->type == SvgNodeType::Symbol) use->symbol = nodeFrom;
|
_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);
|
free(id);
|
||||||
} else {
|
} else {
|
||||||
//some svg export software include <defs> element at the end of the file
|
//some svg export software include <defs> element at the end of the file
|
||||||
|
@ -3024,9 +3041,13 @@ static void _clonePostponedNodes(Array<SvgNodeIdPair>* cloneNodes, SvgNode* doc)
|
||||||
auto defs = _getDefsNode(nodeIdPair.node);
|
auto defs = _getDefsNode(nodeIdPair.node);
|
||||||
auto nodeFrom = _findNodeById(defs, nodeIdPair.id);
|
auto nodeFrom = _findNodeById(defs, nodeIdPair.id);
|
||||||
if (!nodeFrom) nodeFrom = _findNodeById(doc, nodeIdPair.id);
|
if (!nodeFrom) nodeFrom = _findNodeById(doc, nodeIdPair.id);
|
||||||
_cloneNode(nodeFrom, nodeIdPair.node, 0);
|
if (!_findParentById(nodeIdPair.node, nodeIdPair.id, doc)) {
|
||||||
if (nodeFrom && nodeFrom->type == SvgNodeType::Symbol && nodeIdPair.node->type == SvgNodeType::Use) {
|
_cloneNode(nodeFrom, nodeIdPair.node, 0);
|
||||||
nodeIdPair.node->node.use.symbol = nodeFrom;
|
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);
|
free(nodeIdPair.id);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue