RazrFalcon / resvg

An SVG rendering library.
Mozilla Public License 2.0
2.74k stars 220 forks source link

Add support for color fonts #735

Closed LaurenzV closed 5 months ago

LaurenzV commented 5 months ago

Not polished code yet, but it should be enough to test it.

Oh, and top-to-bottom text also doesn't quite work yet. 😅

LaurenzV commented 5 months ago

So I just tried adding support for SVG and the positioning seems to work out-of-the-box (for horizontal writing), so the issue definitely seems limited to bitmap emojis...

RazrFalcon commented 5 months ago

Thanks, will take a look.

LaurenzV commented 5 months ago

COLRv0 works now, too!

<svg id="svg1" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"
      font-size="25">
    <title>Emojis</title>

    <path id="crosshair" d="M 20 100 L 180 100 M 100 20 L 100 180"
          stroke="gray" stroke-width="0.5"/>

    <text id="text1" x="0" y="50" font-family="Segoe UI Emoji">Hii😀 😁how </text>
    <text id="text1" x="0" y="90" font-family="Twitter Color Emoji">Hii😀😁how </text>
    <text id="text1" x="0" y="130" font-family="Apple Color Emoji">Hii😀😁how </text>
    <text id="text1" x="0" y="160" font-family="Noto Color Emoji">Hii😀😁how </text>

    <!-- image frame -->
    <rect id="frame" x="1" y="1" width="198" height="198" fill="none" stroke="black"/>
</svg>

Our output: test

Chrome:

image
LaurenzV commented 5 months ago

Here is a toy sbix font we can use to debug: https://github.com/simoncozens/test-fonts?tab=readme-ov-file#cff-and-sbixotf

If I install it locally and open the following SVG:

<svg id="svg1" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"
      font-size="25">
    <title>Emojis</title>

    <path id="crosshair" d="M 20 100 L 180 100 M 100 20 L 100 180"
          stroke="gray" stroke-width="0.5"/>

    <text id="text1" x="0" y="100" font-family="CFF Outlines and SBIX">AAA</text>

    <!-- image frame -->
    <rect id="frame" x="1" y="1" width="198" height="198" fill="none" stroke="black"/>
</svg>

I get the same behaviour on Firefox and Chrome. I'm trying to change different glyph metrics and recompile the font with fonttools, but none of them have an impact on the y offset. So if you feel like looking into it, this might help.

EDIT: I tried changing different glyph metrics, and apart from x and y offset, none of them have any effect on the positioning... But in the original font the y offset is already 0, so that can't be where it is coming from.

RazrFalcon commented 5 months ago

Thanks for looking into it.

LaurenzV commented 5 months ago

Looks like we are not the only ones troubled by this: https://github.com/harfbuzz/harfbuzz/issues/2679#issuecomment-1345595425

So can we ignore it for now?

RazrFalcon commented 5 months ago

We should at least try to use the same hack everyone else is using.

yisibl commented 5 months ago

COLRv0 works now, too!

So Cool! Thank you for all you have done for this.

LaurenzV commented 5 months ago

We should at least try to use the same hack everyone else is using.

Well, guess what:

Consider the following SVG with the font I mentioned above:

<svg id="svg1" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"
      font-size="64">
    <title>Emojis</title>

    <path id="crosshair" d="M 20 100 L 180 100 M 100 20 L 100 180"
          stroke="gray" stroke-width="0.5"/>

    <text id="text1" x="0" y="100" font-family="CFF Outlines and SBIX">AAA</text>

    <!-- image frame -->
    <rect id="frame" x="1" y="1" width="198" height="198" fill="none" stroke="black"/>
</svg>

Here is how it renders on MacOS in Chrome:

image

Here is how it renders on Windows 11 in Chrome, which is exactly the same we have right now in resvg:

image

So what I think is happening here is that Chrome, Firefox etc, use CoreText for rendering text in SVG, which is why on MacOS, they have the same behavior as all other Apple programs (like TextEdit, as mentioned in the issue linked above). However, on Windows they use something else, meaning that we don't have this same behaviour there...

So I still think it's safe if we just ignore this for now, right? The reason why I'm reluctant to add manual corrections here is that right now, layouting doesn't care at all about which type of glyph is used, but if we want to add manual corrections, then we might have to decide on the type of glyph that is used while layouting, which is not so nice in my opinion.

RazrFalcon commented 5 months ago

So I still think it's safe if we just ignore this for now, right?

Sounds good to me.

LaurenzV commented 5 months ago

I think it mostly works now, but there is still something wrong with ttb text that I need to investigate once I find the time to do so...

LaurenzV commented 5 months ago

Also I'm not sure if 14MB is too big for a font (Twitter Color Emoji), should I use the SVG font from Simon Cozen's test-font repository instead?

RazrFalcon commented 5 months ago

A smaller font is preferable. You could try subsetting the Twitter font with pyftsubset. Just not forget the license file and some readme explaining how you got this file.

Top-to-bottom text is kinda broken by design. There are basically no docs explaining how it should be implemented. The current implementation is just a guess work.

LaurenzV commented 5 months ago

Regarding subsetting, I think I tried that but iirc fonttools didn't support subsetting SVG tables. But I will try again.

So should I disregard TTB writing for now?

RazrFalcon commented 5 months ago

TTB writing

Writing to SVG? Or do you mean the layout? It's fine.

yisibl commented 5 months ago

Regarding subsetting, I think I tried that but iirc fonttools didn't support subsetting SVG tables. But I will try again.

I remember that fonttools already support subsetting OT-SVG fonts, see https://github.com/fonttools/fonttools/issues/534#issuecomment-970496354

Alternatively, you can use nanoemoji to convert SVG files into color fonts in a variety of formats, which will produce test fonts that are small enough to use.

LaurenzV commented 5 months ago

I remember that fonttools already support subsetting OT-SVG fonts, see https://github.com/fonttools/fonttools/issues/534#issuecomment-970496354

Huh okay, I'll try it again then, thanks!

LaurenzV commented 5 months ago

I think I'm getting close now. I'll try to investigate the tb writing mode issue again, then clean up and then it should be ready. Hopefully will be done within the next few days.

LaurenzV commented 5 months ago

There's still something off, but not sure I will be able to fix it for now, this would require me to make a deep dive into how writing-mode works exactly, which I might do at some point, but I don't think it's worth it to hold up emoji support for this... This is how it looks currently:

test

versus in other browsers:

image

For some reason there is more space in the vertical writing mode... But no idea why. I will add a test case regardless so we don't forget about it.

LaurenzV commented 5 months ago

I've added a few small TODOs where I wasn't sure what I should change it to. But otherwise it should be good, I hope.

RazrFalcon commented 5 months ago

Thanks! Looks good to me. I will think about how we can simplify abs_transform handling.

RazrFalcon commented 5 months ago

Ready to merge?

LaurenzV commented 5 months ago

I think so!