linebender / resvg

An SVG rendering library.
Apache License 2.0
2.84k stars 229 forks source link

Fix handling of SVG table #776

Closed LaurenzV closed 5 months ago

LaurenzV commented 5 months ago

Alright, so while debugging something with Noto Color Emoji in typst, I realized that the new Noto Color Emoji fonts ship with an SVG table in addition to COLR. And I did not realize that an SVG record can actually contain multiple glyphs (see here: https://learn.microsoft.com/en-us/typography/opentype/spec/svg#glyph-identifiers). I have no idea who thought it was a good idea to stuff hundreds of glyphs in a single SVG file, but yeah, this is the fix I came up with. 😅

This might not be the 100% correct approach (could glyphs for example appear in nested groups? How would we deal with transforms? etc. etc...) But I tested it manually and it works with Noto Color Emoji (and the test for Twitter Color Emoji also still pass), so I hope this is okay... I'm open for suggestions, though.

khaledhosny commented 5 months ago

I have no idea who thought it was a good idea to stuff hundreds of glyphs in a single SVG file, but yeah, this is the fix I came up with. 😅

It allows for big file size saving by reusing paths across glyphs, since SVG table neither has glyf composite glyphs nor CFF subroutines.

LaurenzV commented 5 months ago

Fair enough, that makes sense. 😄 But unfortunately that means that we have to parse the whole SVG file just to render a single glyph, but I guess there is no way around that.

RazrFalcon commented 5 months ago

Got it.

No idea what the spec means by rendering a glyph as a use. Do they mean that in case of

<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
  <defs>...</defs>
  <g fill="green">
    <g id="glyph14">...</g>
  </g>
</svg>

we should ignore the green fill? In which case our implementation is wrong and I don't think there is an easy way to implement this behavior in resvg.

LaurenzV commented 5 months ago

Yeah I have no idea... But it's only a best-effort implementation after all.