Open Maximkaaa opened 7 months ago
@maxammann I know you did a lot of research about this for maplibre-rs
. Do you have any input on how to approach this?
I believe that some other projects like Bevy are looking at using cosmic-text
for this, per https://github.com/bevyengine/bevy/issues/7616
Yes, glyphon
also uses cosmic-text
for text shaping, but it also includes glyph texture atlases.
You can find some of my notes here: https://maplibre.org/maplibre-rs/book/development-documents/font-rendering.html
Text rendering can have varying challenges based on what you want achieve. MapLibre is able to place text in the "game world". So you can actually walk around text and have text "printed onto the map". If you want to have the same then the problem becomes very hard as you have to come up with a technique to achieve that (SDFs, Bezier rendering etc).
I think that goal is maybe too ambitious and not needed in 99% of the cases. If you want to render text in the screen space then you probably can get away with using something like glyphon.
Note though, if you want perfect text rendering for all languages you kind of still have to use harfbuzz and not rustybuzz :/
I've spent some time trying things out and researching and here is what I've come with: https://maximkaaa.github.io/galileo/blog/posts/text_rendering_design/
In case it's helpful, I'm definitely interested in adding transformations into glyphon. We just need to decide on the right approach to expose it. iced currently uses glyphon for regular text but uses the vector representation for transforms (e.g., https://github.com/iced-rs/iced/pull/2204) that doesn't go through the glyph cache, so it would be really cool to upstream something similar to glyphon itself.
So far I've decided to go to vector only approach first, as it is more general and covers all uses cases. So I don't use glyphon at the moment. But my experiments I already see less than ideal results in some cases due to lack of hinting. So I will definitely be looking into glyphon later.
That being said, even for vector representation of glyphs, caching tessellated glyphs would be very useful. I believe that swash does cache path commands for glyphs similar to how it caches rasterizations. But the most computationally heavy operation for these is tessellation, so if glyphon would take care of caching that, that would be great.
As for transformations themselves, in my case I would have to line up glyphs along a path, which means I would have to apply different set of rotations and translates to each glyph, not to the whole glyph run. This is something SVG can do, but I'm not sure if this is in scope of glyphon. If not, just convenience functions to rotate/translate vector glyphs would be helpful but not essential.
Yeah for sure, I'd like to cache tessellated glyphs if we went to vectors for transformations.
The path use case is interesting. I don't know how SVG renderers handle this but it seems like you'd need deep integration with shaping/layout to do per-character transformations (vs. projecting the entire run along the path somehow).
Great blog post!
So far I've decided to go to vector only approach first, as it is more general and covers all uses cases.
Do you go with the maplibre signed distance fields or plainly tessellating the curves in the font files?
If it is the latter then you likely will hit performance limitations.
Thanks for the link, @maxammann , it is very well written. And as follows from the article, using SDF has some issues also. So far in my tests I haven't faced any performance issues, but I didn't test for performance in any depth. Anyway, my main concern at the moment is to create a solution that will work correctly for all inputs and on all platforms, and MapLibre approach doesn't allow both of these (shaping problem and using server-side rasterizing are big no-no for me). After that is done, performance can be improved by caching, multithreading etc., but that should be done only after testing to see, which part of the code would be a bottleneck.
How long will it take for this to be released?
I don't have much time to work on Galileo at the moment, but hope to roll out first iteration of labels late next week. Implementing everything that is planned including optimizations for web, advanced rasterization and caching will take a while.
@Maximkaaa The following repository might be helpful for font rendering: https://github.com/mooman219/fontdue
To support labels on the map, we need a mechanism to render shaped text onto the map. This includes:
Rendering a text along a path would be desirable, but we can do it separately later.
At the first glance, https://github.com/grovesNL/glyphon library can cover all our needs.
iced
uses it for text shaping, so it must be mature enough to support our use cases.We would also need test cases for complex cases:
Must have options for initial implemenation: