Closed paxbun closed 1 year ago
This is a known issue. #486 should help eventually.
Also, there are no such thing as a correct font fallback. Its behavior is unspecified. A library can do whatever it wants. So resvg isn't wrong here - just different from Chrome. Could it be improved - yes. Is it easy to do - no.
A proper SVG document must not rely on font fallback. It's up to the author to make sure that provided fonts have the required glyphs.
It seems like
usvg_text_layout::shape_text[_with_font]
converts the entire<text>
with a single font even if it contains multiple<tspan>
s with different fonts and copies glyphs to a correct position later with span_contains, could you please share any reason for this logic?
You will be surprised, but this is the correct behavior. In SVG text layout, shaping is done across text chunks, not text spans.
In your case, resvg
has to shape the whole text
element (which contains a single text chunk in this case) twice. Once with Helvetica
and once with Times
. And then use glyphs according to spans. So resvg does work as expected. It's just the font fallback algorithm fallbacks to a different font compared to Chrome. Mainly because how dumb the current implementation is.
Duplicate of #486
I'm new to the SVG and the CSS standard, so please let me know if I'm wrong.
In 15.2.2 Font family: the 'font-family' property of the CSS 2 standard, which SVG 1.1 is based on:
This property specifies a prioritized list of font family names ... that are tried in sequence to see if they contain a glyph for a certain character. ...
In 15.5 Font matching algorithm of CSS 2:
2. At a given element and for each character in that element, the UA assembles ...
though descriptors seem to be different from properties.
In addition, in 5. Font Matching Algorithm of CSS Fonts Module Level 4:
... For each character in the run a font family is chosen and a particular font face is selected containing a glyph for that character.
All standard publications I've read say that the font fallback logic should be done character-wise with a specific priority. From this point of view, shouldn't resvg render texts as Chrome does in my case?
This is a very abstract overview of the font fallback algorithm. There are much more nuances. For example, librsvg and QtSvg would fail to render this file as well. But in a different way. Writing reproducible SVGs is extremely hard. Even Safari would render this file wrong. It would use correct fonts, but would add needless whitespaces in cases 4 and 5.
I'm not sure what is the exact issue with this file. I would have to investigate it. Maybe this is not font fallback at all.
usvg-text-layout
0.29 uses wrong fonts for<text>
with multiple<tspan>
s, where each<tspan>
uses different fonts and some<tspan>
contains texts that are not supported by the designated font.For example, for the following SVG file,
resvg renders the file as the following:
while Chrome renders the file as the following.
As you can see in cases 1 and 5, resvg used a sans-serif font for the "Text" parts, though
font-family
is set to"Times"
for those<tspan>
s. This happens only when another<tspan>
in the same<text>
contains glyphs unsupported by its font.It seems like
usvg_text_layout::shape_text[_with_font]
converts the entire<text>
with a single font even if it contains multiple<tspan>
s with different fonts and copies glyphs to a correct position later withspan_contains
, could you please share any reason for this logic?Thanks for reading!