Replies: 24 comments 55 replies
-
If only I knew which part of the code base was responsible for text rendering... |
Beta Was this translation helpful? Give feedback.
-
GrabMap Khmer Render solution.pdf |
Beta Was this translation helpful? Give feedback.
-
Here’s my personal advice on this. (Disclaimer: While I’ve spent quite many years working on maps, internationalization, fonts, and text rendering, I’m a complete newbie to MapLibre. Please apologize for anything that doesn’t make sense in the MapLibre context). Generally, GrabMap’s approach for Khmer goes in the right direction, but it’s incomplete, and you don’t need a separate hack for each language. Instead, once you’ve implemented text rendering correctly, a single code path can display all text in any language. This will also improve the display of Latin/English text in terms of kerning, ligatures, typographic features, and a big chunk of what’s needed for Emoji. Unfortunately, getting this right is fairly non-trivial, and also not exactly well documented. However, there’s several open-source implementations that might serve as inspiration. Personally, I’d mainly recommend looking at the source code of Chromium and Firefox; they both have state-of-the-art text rendering stacks. Another source of inspiration might be the Pango library used by GNOME/GTK and Qt, although with some reservations. Here’s how modern text rendering works from a high level:
Language tags: For good text rendering, you’ll actually need to know the language of each label being rendered, and pass it down the rendering stack (into HarfBuzz) as an IETF BCP-47 language tag. This is the same language code that’s also used for language tagging in HTML, XML, and other data formats; modern browsers use it to tweak text rendering. Knowing the language mainly matters for East Asia, where certain glyphs should look slightly differently depending on the language (and region/country, which is part of IETF language tags). For example, this picture illustrates how the same Unicode codepoint Color and variable fonts: Supporting color (and variable) fonts is a little complicated. But certainly doable, and I think both color and variations could have very nice applications for cartography. But it’s clearly less important than making text readable in the first place. Web fonts: According to their slides, GrabMap seems to load Noto Sans Khmer over the web. However, on most modern devices, this wouldn’t actually be necessary; both Apple and Google bundle most of Noto with their operating systems. Although Apple hides the presence of Noto from its user interfaces, apps can still access the glyphs. Likewise, Microsoft Windows bundles a lot of international fonts. Said that, it certainly would make sense for MapLibre to support web fonts, both for custom styling and as a fallback when device fonts don’t cover the Unicode range needed for display. My recommendation would be to re-implement MapLibre’s text stack so it supports web fonts in the same way as Chromium and Firefox. However, this would likely be a sizeable chunk of work. Font formats: Maybe I’m missing something here, but to me personally, the Mapbox font API seems a little weird. Again, my recommendation would be to make MapLibre behave like a modern web browser, support the same (standard) web font formats, and perform the conversion from Bézier curves to GPU-renderable Signed Distance Fields on the client device. Styles: To define the style of map labels, my suggestion would be to implement Text and Fonts of CSS3, just like a modern web browser. This would be quite a bit of work, though. |
Beta Was this translation helpful? Give feedback.
-
Worth reading: Text layout is a loose hierarchy of segmentation. There’s been several attempts to bundle text layout into a single library, such as Raqm, Minikin, ICU Paragraph Layout, or Cobbletext. Personally, I’d recommend looking at them for inspiration, although I’m not sure if they really fit MapLibre. Another source to consider might be lib/ui/text in Flutter: this is a fork of Chrome’s text handling, and less entangled than Chrome, but it’s deeply integrated with Flutter so not directly usable for MapLibre. On the other hand, if you just want to fix rendering quickly with little work, and if you don’t care about line breaking, hyphenation, and rendering text on GPUs, Raqm might be a good solution. Minikin implements line breaking, but being part of Android, it would need to be ported to other platforms. |
Beta Was this translation helpful? Give feedback.
-
Thanks for the great summary, I'll check it out later in more detail! A thing I was wondering regarding the Glyph rendering aspect: Does maplibre really need resolution independent glyph rendering? In Maplibre the glyphs "exist" within the 3D world. That means glyphs need to be resized depending on the zoom. Wouldn't it be enought for the major usecases to render glyphs with a static resolution as an overlay? |
Beta Was this translation helpful? Give feedback.
-
Personally I’d find it a nice feature if text were able to grow and shrink with the rest of the map. Zooming would feel smoother that way, especially on deep zoom levels. But admittedly that’s pretty far off; the current user experience doesn’t seem to need this. Also, you can always rasterize glyphs on the CPU (by calling FreeType) to any desired resolution; it just won’t feel as smooth as when doing it on GPU. |
Beta Was this translation helpful? Give feedback.
-
That is also my feeling. Yeah it would be cool to have resolution independant glphy rendering. But at the same time I'm wondering if we really need it. I honestly don't know right now why MapBox when that way originally. There must be some reason why it's neccassary. |
Beta Was this translation helpful? Give feedback.
-
I just want to add one more library for consideration w.r.t client side text breaking - https://github.com/unicode-org/icu4x This one is written especially for cases like maplibre. Edit: |
Beta Was this translation helpful? Give feedback.
-
@brawer feel free to add this point to the discussion at nyurik/future-mvt#1 |
Beta Was this translation helpful? Give feedback.
-
We are not the first ones to think about supporting more writing systems. Here are some Mapbox issues: |
Beta Was this translation helpful? Give feedback.
-
Almost 10 years ago, in the third issue created in the Mapbox GL JS repo, people talked about HarfBuzz mapbox/mapbox-gl-js#3. |
Beta Was this translation helpful? Give feedback.
-
Uuuh doesn't that issue suggest that they already used freetype/ICU lib? |
Beta Was this translation helpful? Give feedback.
-
Also lots of discussion in mapbox/DEPRECATED-mapbox-gl#4. |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
@ramSeraph Thanks for that collection. Do you mind if I include that in https://maplibre.org/maplibre-rs/book/development-documents/font-rendering.html? |
Beta Was this translation helpful? Give feedback.
-
@maxammann you can definitely include them. I wasn't sure if I should put effort into maplibre-rs or here. I wasn't sure how far from production maplibre-rs was and I don't know rust( that can be remedied though :) ) I have to say, it was heartwarming to see the top priority of this issue at maplibre-rs - maplibre/maplibre-rs#36 (comment) Is there a place where I can add more of the rust text util research? ( I can see that you already have looked at a few things I have ) |
Beta Was this translation helpful? Give feedback.
-
I wonder if this should be part of the maplibre style spec or MVT specification. Also, please consider dropping the glyph api from the maplibre style spec if possible. The alternative mentioned in this issue tracker seems like a good idea. |
Beta Was this translation helpful? Give feedback.
-
Thanks @alanchenboy for the nice presentation! Here are some links from the chat:
|
Beta Was this translation helpful? Give feedback.
-
@alanchenboy thanks for the nice presentation. I wonder: Can we remove the language encoding from the GrabMaps solution and decide which font file to used based on the Unicode range? |
Beta Was this translation helpful? Give feedback.
-
Thanks @ChrisLoer for pointing out a completely different approach than SDFs to scale-indelendent text rendering: vector font rendering. Gets used at Figma https://medium.com/@evanwallace/easy-scalable-text-rendering-on-the-gpu-c3f4d782c5ac |
Beta Was this translation helpful? Give feedback.
-
https://github.com/wipfli/maplibre-canvas-labels Played around with rendering text labels in a Demo: |
Beta Was this translation helpful? Give feedback.
-
@ramSeraph and @alanchenboy what should be our next step? Bring Grab's solution to a proof-of-concept in MapLibre GL Native? |
Beta Was this translation helpful? Give feedback.
-
I would personally suggest putting in more thought into the style spec before adding any more hacks into the maplibre-gl-js or native codebases. I understand that would mean a loss of momentum here. But, given that the last 10 year old mistake is still haunting us.. this would be the wise path. I also think @brawer and @1ec5 are more knowledgable people for designing such a spec( I am passing on the hot potato here :) ) |
Beta Was this translation helpful? Give feedback.
-
A full solution for complex text rendering would need to address line-placed labels, curving text along a curved line: mapbox/DEPRECATED-mapbox-gl#4 (comment). In Slack, @bdon pointed out that curving Devanagari text would cause the horizontal line to get broken up in much the same fashion as maplibre/maplibre-gl-js#2170. To demonstrate this issue, here are SVGs of Hindi and Arabic text placed on the inner or outer side of a spiral: Chrome (which uses HarfBuzz for text shaping) and Firefox (which uses Graphite) both show bunching on one side of the curve and gaps on the other. Safari makes an utter mess of it; apparently it sends isolated characters to Core Text, just like in mapbox/mapbox-gl-native#7862 (comment). I wonder how other custom text layout engines have addressed shaping calligraphic text along a path. In Arabic, inserting kashida characters could close the gaps as a workaround, but I don’t think there’s an equivalent for Devanagari. In any case, I assume that native speakers would prefer these seams over the status quo. |
Beta Was this translation helpful? Give feedback.
-
MapLibre GL Native currently does not support writing systems like for example Indic scripts or Khmer.
I think we should support more writing systems such that people from all parts of the world can use MapLibre...
Let's use this as a tracking issue to collect ideas and material how we can extend writing system support. Maybe Harfbuzz will be the best tool.
Beta Was this translation helpful? Give feedback.
All reactions