linebender / resvg

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

Split text layouting and text outlining into two separate steps #728

Closed LaurenzV closed 7 months ago

LaurenzV commented 8 months ago

I had to update one reference image, but it was only a one pixel difference. Probably due to some float rounding issue.

LaurenzV commented 8 months ago

The feature thing is probably not solved very nicely... I'm open for suggestions on how else to do it.

RazrFalcon commented 8 months ago

Looks good to me. I'm still confused why we need Path in TextFragment, but other than that it's fine.

The current limitation is that there is no way to get the original text/character position from the layout, which will be useful when generation a PDF with ToUnicode object.

LaurenzV commented 8 months ago

Looks good to me. I'm still confused why we need Path in TextFragment, but other than that it's fine.

I removed text fragment now. What do you think?

The current limitation is that there is no way to get the original text/character position from the layout, which will be useful when generation a PDF with ToUnicode object.

I think it should be okay because I will still load the requested font and then save the cmap into the PDF, which should be enough (at least that's what Typst does and it seems to work fine). But I guess I will find out soon.

RazrFalcon commented 8 months ago

You cannot really get a Unicode character from TrueType cmap. You're suppose to use ToUnicode. PS: I had a "pleasure" of working with PDF as well...

LaurenzV commented 8 months ago

Oh damn, yeah, you are right, I need to somehow store the corresponding string for the glyphs... Will see if I can figure out how.

LaurenzV commented 8 months ago

Actually, sorry, there is one more small thing I would like to implement, so it would be good if we could hold off merging for now. I'll write here once I think it's done.

LaurenzV commented 8 months ago

Okay well, I've managed to produce the same visual output for all test cases but embedded text instead, so from my side I have everything I need in that regard. I still want to get copy-pasting to work, so still want to try to figure out a way to map the glyphs to their respective character, but I guess this can happen in a separate PR in the next few days, if I find the time. I'm already pretty happy with what I have for now. :D

RazrFalcon commented 8 months ago

Sure, sounds good.

I'm still trying to understand how do you handle decorations. I'm not sure they should be part of layout::Span. Let's say we have "Hello world" where the second word has a different color, but the whole text has the same style otherwise and we have underline for the whole text. In this case we would have two spans but one underline. How do you handle it right now? Because the old implementation would join continuous decorations.

LaurenzV commented 8 months ago

So, I just checked with the following SVG:

<svg id="svg1" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"
     font-family="Noto Sans" font-size="64">
    <title>Simple case</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="32" y="100" text-decoration="underline">Te<tspan fill="green">x</tspan>t</text>

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

In this case, there will be 3 spans and each of them has a separate underline (but each underline only covers the range of the glyphs they contain, so they are not overlapping)... But I think it should be fine like that, right? I mean it can't be noticed that they are three different underlines, anyway. Or is that a problem?

RazrFalcon commented 7 months ago

Great, the current implementation also breaks underlines. I don't know how my own code works anymore... I wrote it like 4 years ago.

Either way, let's leave decoration as a part of a span. Not ideal, but not breaking either.

LaurenzV commented 7 months ago

Thanks!