Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flexible font define in style #868

Open
alanchenboy opened this issue Oct 21, 2024 · 8 comments
Open

Flexible font define in style #868

alanchenboy opened this issue Oct 21, 2024 · 8 comments
Labels
enhancement New feature or request

Comments

@alanchenboy
Copy link

alanchenboy commented Oct 21, 2024

Design Proposal: Flexible font define in style

Motivation

MapLibre inherits the font pbf design from Mapbox, this is a limit to rendering complex text. We must let the core reach the font file to finish shaping and rendering complex text like Indic, Khmer, Burmese, etc.

Proposed Change

The design looks like CSS unicode-range with font-face,

"font-faces": [
      {
          "text-font": ["Noto Sans Regular"],
          "font-files": [
              {
                  "url": "https://alanchenboy.github.io/harfbuzzResource/fonts/Noto%20Sans%20Regular/khmer.ttf",
                  "unicode-range": [
                      "U+1780-17FF"
                  ]
              },
              {
                  "url":"https://alanchenboy.github.io/harfbuzzResource/fonts/Noto%20Sans%20Regular/myanmar.ttf",
                  "unicode-range": [
                      "U+1000-109F", "U+A9E0-0xA9FF", "U+AA60-0xAA7F"
                  ]
              },
              {
                  "url":"https://alanchenboy.github.io/harfbuzzResource/fonts/Noto%20Sans%20Regular/devanagari.ttf",
                  "unicode-range": [
                      "U+0900-097F", "U+A8E0-0xA8FF"
                  ]
              }
              
          ]
      }
  ],

full style:
https://alanchenboy.github.io/harfbuzzResource/hindi.json

API Modifications

A new feature for complex font rendering, it's transparent for the map users.

Here is an example of how to render complex text on the native side.
maplibre/maplibre-native#1439.

Migration Plan and Compatibility

N/A

Rejected Alternatives

N/A

@HarelM
Copy link
Collaborator

HarelM commented Oct 21, 2024

Thanks for taking the time to open this design proposal.
Can you clarify the relation between this property and glyphs? It is not clear when one should be selected over the other.
Also, will using this require some configuration in the rendering part? special build? a plugin?
We don't have other style properties that has external requirements in order to work as far as I know...

@louwers
Copy link
Collaborator

louwers commented Oct 21, 2024

We would use Harfbuzz for text shaping in MapLibre Native by default, so no special plugins would be required.

@HarelM
Copy link
Collaborator

HarelM commented Oct 21, 2024

Wouldn't this require a special build? Or is the default build comes with Harfbuzz and you can reduce build size if you need, but this would be the special build - i.e without it?

@louwers
Copy link
Collaborator

louwers commented Oct 21, 2024

The latter: we would enable it by default, although it would be possible to drop out if you have binary size constraints and you make your own builds. The default build is the 'kitchen sink' build. Most users don't care that much about binary size.

@wipfli
Copy link
Contributor

wipfli commented Oct 21, 2024

Thank you for the proposal @alanchenboy. Can we add to the proposal a way to load glyph SDFs from a server?

When rasterizing glyphs on the client with TinySDF, i.e., make gray-scale image then convert to SDF with Felzenszwalb/Huttenlocher distance transform, the visual quality is lower than when using font maker or similar which operates directly on Bezier curves to get the SDFs...

@alanchenboy
Copy link
Author

This approach means that if a font is defined here by font-face, then the selected Unicode point will be shaped with Harfbuzz and then rasterized with FreeType.
In addition to rendering complex fonts, this also has the implicit benefit of saving traffic by the font files actually smaller than the pre-rendered pbf files.

@wipfli
Copy link
Contributor

wipfli commented Nov 4, 2024

Exactly! Additionally, if we have an API to define server-generated SDF glyphs we can benefit from:

  • Clients MapLibre GL JS and MapLibre Native do not have to use FreeType
  • Bezier-based SDF generation which is more precision and looks better than TinySDF-based SDF generation

The API could maybe look something like this:

"font-faces": [
      {
          "text-font": ["Noto Sans Regular"],
          "font-files": [
              {
                  "url": "https://alanchenboy.github.io/harfbuzzResource/fonts/Noto%20Sans%20Regular/khmer.ttf",
                  "unicode-range": [
                      "U+1780-17FF"
                  ],
                  "glyphs": "https://alanchenboy.github.io/harfbuzzResource/glyphs//Noto%20Sans%20Regular/khmer/{range}.pbf"
              },
              {
                  "url":"https://alanchenboy.github.io/harfbuzzResource/fonts/Noto%20Sans%20Regular/myanmar.ttf",
                  "unicode-range": [
                      "U+1000-109F", "U+A9E0-0xA9FF", "U+AA60-0xAA7F"
                  ],
                  "glyphs": "https://alanchenboy.github.io/harfbuzzResource/glyphs//Noto%20Sans%20Regular/myanmar/{range}.pbf"
              },
              {
                  "url":"https://alanchenboy.github.io/harfbuzzResource/fonts/Noto%20Sans%20Regular/devanagari.ttf",
                  "unicode-range": [
                      "U+0900-097F", "U+A8E0-0xA8FF"
                  ],
                  "glyphs": "https://alanchenboy.github.io/harfbuzzResource/glyphs//Noto%20Sans%20Regular/devanagari/{range}.pbf"
              }
              
          ]
      }
  ],

Some fonts have several hundred glyphs so it might make sense to split the glyphs up into ranges of 256 like we do with normal MapLibre fonts. The difference to normal fonts would be that the index is actually the glyph index from the font .ttf file and not simply the unicode codepoint.

@1ec5
Copy link
Contributor

1ec5 commented Nov 4, 2024

Bezier-based SDF generation which is more precision and looks better than TinySDF-based SDF generation

FYI, maplibre/maplibre-gl-js#4564 would lean more heavily on TinySDF, and I have a half-baked idea in maplibre/maplibre-gl-js#4564 (comment) to use it exclusively if the top-level glyphs property is missing (which is currently an error). The idea would be to rely on Web Fonts (or the native equivalent) for any custom fonts, without requiring any MapLibre-specific server-side changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants