svg-native-viewer
svg-native-viewer copied to clipboard
Fill or stroke attributes on a `use` element
While I'm not exactly sure what the standard says on whether fill or stroke attributes on the use
element are taken into account or not, according to this, they are taken into account if the "referred" element didn't have any such attribute applied.
SNV doesn't seem to take it into account at all.
Look at the following document as an example. The first one is the rendering by SNV and the second one is by Librsvg.
Please, feel free to close this issue if this behavior isn't required by the standard.
@moazin It is complicated and the behaviour may differ even between web browsers.
First, the fill
property is an inherited property: https://www.w3.org/TR/SVG/painting.html#FillProperties
If the value is not set, it inherits the value from the ancestor.
2nd, the use element in SVG 1.1 behaves like a copy operation. The behaviour is as if the <use>
element gets replaced by a group and the referenced content copied into the use element.
With SVG2, the definition of <use>
changed and now acts as a shadow root of an non-isolated shadow tree. This has been implemented by Firefox but by no other browser.
SVG Native is based on SVG2. So svg-native-viewer should behave similar to Firefox.
I believe for the most simple case, the behaviour should not differ:
<rect width="100" height="100" id="rect"/>
<use fill="green" xlink:href="#rect" x="100"/>
should probably show a black rect with a green rect right next to it. (There might be a difference between presentation attribute and property definition that I would need to check again.)
Can you attach the source which produced the above images?
@litherum Oh, I thought I had attached the SVG document as well, but seems like I didn't.
I guess this is the one:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink= "http://www.w3.org/1999/xlink" xmlns:svg="http://www.w3.org/2000/svg" viewBox=" 0 0 1000 1000">
<rect x="500" y="500" width="100" height="100" id="myCircle"/>
<use xlink:href="#myCircle" x="200" fill="red"/>
<use xlink:href="#myCircle" y="200" fill="blue"/>
<use xlink:href="#myCircle" x="-200" fill="green"/>
<use xlink:href="#myCircle" y="-200" fill="yellow"/>
</svg>
So I analyzed the problem a little bit and here are my thoughts.
SNV iterates through the XML tree first, parsing attributes, maintaining stacks and ultimately populates an object tree. This mechanism is designed in such a way that each draw-able element of this object tree is more or less independent and self-sufficient. In other words, all attributes such as transforms, stroking information, gradient information, etc is embedded within that element. This is not true for the Reference
element though, which refers to another element that's to be rendered. This is simply done by calling TraverseTree
on the referred element. Any attributes such as fillStyle
or strokeStyle
on the Reference
object are simply ignored. graphicStyle
is taken into account though. Given this situation, I'm not quite sure how to go about this.
I would also like to point out that it's very important for this to be resolved. Almost every glyph of Trajan and a lot of glyphs of NotoColorEmoji have use
elements with styling attributes like fill
.
Any updates about this issue ?
I found even the sample from Microsoft's SVG open type can not render on the svg-native-viewer (I tested using CoreGraphics port)
https://learn.microsoft.com/en-us/typography/opentype/spec/svg#example-2-glyph-specified-directly-in-expected-position
<svg id="glyph7" version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 1000 1000 1000">
<defs>
<linearGradient id="grad" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="darkblue" stop-opacity="1" />
<stop offset="100%" stop-color="#00aab3" stop-opacity="1" />
</linearGradient>
</defs>
<rect x="100" y="570" width="200" height="430" fill="url(#grad)" />
<rect x="100" y="365" width="200" height="135" fill="darkblue" />
</svg>
I think this x1="0%" y1="0%" x2="0%" y2="100%"
should be treated as actually x1=100 y1=570 x2=300 y2=1000
, but not just x1=0 y1=0 x2=0 y2=1000