[SVG] Nested elements rendering when they shouldn't
MewPurPur opened this issue · comments
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><rect x="2" y="2" width="6" height="4" fill="red"><circle cx="10" cy="10" r="3"/></rect></svg>
Every renderer I found ignores the circle inside the rect tag, but not ThorVG, which renders both shapes.
I didn't find this behavior stated explicitly anywhere in the SVG specification. This seems like it might be it, though: https://www.w3.org/TR/SVG2/struct.html#InterfaceSVGSVGElement
To find the non-container graphics elements within a given element element, the following steps are run:
Let result be an initially empty list.
If element is an ‘svg’ or ‘g’ element, then for each child element child of element, in document order:
- Let descendants be the result of finding the non-container graphics elements within child.
- Append to result all the elements of descendants.
Otherwise, if element is a graphics element then append element to result.
Return result.
But while at it, I found other related ones that we're doing wrong: https://www.w3.org/TR/SVG2/struct.html#UnknownElement
Here's an example SVG from the specification, trimmed down to only consider the elements we currently support:
<svg viewBox="0 0 700 200" xmlns="http://www.w3.org/2000/svg">
<mysteryElement>
<path d="M0 0h600v200h-600z" fill="#bdb76b"/>
</mysteryElement>
<hideElement xmlns="http://www.example.com/invisibleML">
<path d="M0 0h300v100h-300z" fill="#f5f5f5"/>
</hideElement>
<linearGradient>
<gradientExtension>
<path d="M300 0h100v200h-100z" fill="#f0f"/>
</gradientExtension>
</linearGradient>
</svg>
The rectangle inside the mysteryElement renders, which is correct.
The rectangle inside the hideElement shouldn't render because namespace was overridden with a non-SVG one, but it does render.
The rectangle inside gradientExtension shouldn't render because linearGradient isn't rendered, but it does. It actually does even if we put it directly under linearGradient.
@MewPurPur this first example should be (and will be :) ) fixed. basic shapes should be siblings within a container, not nested within each other.
Regarding the unknown elements - do you really need them, or are they more like a curiosity ?
Regarding the unknown elements - do you really need them, or are they more like a curiosity?
I'm making a code-focused SVG editor with the ThorVG rendering backend, so in theory, since it accepts any code, anything that doesn't render according to the specification counts as a bug in my app too.
In practice, only the issues with shapes rendering when inside other shapes or gradients will be encountered often, since you can create those from the GUI and drag-and-drop them around easily, while the other things are niche and can't be done via UI.
@MewPurPur, do you think we can close this one? The 'unknown elements support' issue can be opened separately.
hmm.. I wonder if 'unknown elements support' can be resolved.
I don't think we can distinguish between <mysteryElement>
and <hideElement xmlns="http://www.example.com/invisibleML">
in our current structure. Neither may be recognized, or both may be recognized as <g>
.
Graphics Element declared inside <linearGradient>
can be sent as a child of defs
.
I don't know if I should support this, I don't think it's common.
hmm.. I wonder if 'unknown elements support' can be resolved. I don't think we can distinguish between
<mysteryElement>
and<hideElement xmlns="http://www.example.com/invisibleML">
in our current structure. Neither may be recognized, or both may be recognized as<g>
. Graphics Element declared inside<linearGradient>
can be sent as a child ofdefs
. I don't know if I should support this, I don't think it's common.
Yes, I don't think anyone will ever use this, so I would suggest separating this task from here. If @MewPurPur thinks it's worthwhile to open such an issue, he will. I believe the original issue here has already been resolved.
Sure, we can close this. But I'll open for the "Shapes inside linearGradient element rendering" one, it's important to me.