-
-
Notifications
You must be signed in to change notification settings - Fork 74
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
Comments
Thanks for taking the time to open this design proposal. |
We would use Harfbuzz for text shaping in MapLibre Native by default, so no special plugins would be required. |
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? |
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. |
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... |
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. |
Exactly! Additionally, if we have an API to define server-generated SDF glyphs we can benefit from:
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. |
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 |
A few thoughts from me as we discussed this on the MapLibre Eastern call a few days ago. Opt-in / not breaking backward compatibilityThe only major concern I remember during the Eastern call was ensuring we don't break existing styles. Meaning, it should be possible to add this behavior to existing styles, so that renderers which support it can upgrade, but older renderers will still be able to get the glyphs as before. Without this property, I doubt it will get wide adoption, as commercial tile providers are unlikely to publish a style that doesn't preserve backward compatibility. I think this is fine as-is. I assume the behavior would be along the lines of "if we have Supporting externally generated glyphsIn my opinion, how the glyphs are generated is an implementation detail. We could swap out the precise implementation on native. We just need to ensure that the style spec is flexible enough. That said, I don't at all mind @wipfli's proposal to add
Valid URLsWould this would work with local URLs (native only, I assume?). I could see wanting to ship a font file or glyphs locally on mobile.
|
How would this proposal work for native? |
I believe this was in response to the approach I started with maplibre/maplibre-gl-js#4564 (comment) and continued in 1ec5/maplibre-gl-js#1. Graceful degradation isn’t the only way to achieve the goal of maintaining compatibility with existing stylesheets. My approach relies on relaxing an existing “optional” requirement in the style specification. In order to adopt extended TinySDF, a style author would intentionally break compatibility with existing versions of MapLibre on all platforms by removing the If we really want, we could implement a fallback strategy on platforms that don’t support extended TinySDF to fall back to a last resort fontstack, either bundled or distributed from maplibre.org. But I don’t think this is necessary, because omitting The alternative would be that style authors have to continue specifying glyph PBFs that they have to generate but hope will never be used. This will become a much larger burden on developers once we expand character support beyond the Basic Multilingual Plane. I don’t think developers will see this as a good tradeoff.
This is infeasible on the Web and unlikely to ever be feasible. Browser vendors are trying to lock down access to native fonts to prevent fingerprinting. The experimental Local Font Access API is only supported by Chromium and requires user permissions. I don’t think MapLibre should require the user to give privacy-related permissions just to view a map. More likely, we’d continue to improve upon the TinySDF technique on the Web to the point that it’s closer to true native text rendering on the native platforms using Harfbuzz. |
I was asking about using OS fonts on native devices using the maplibre-native implantation and how would this spec proposal cater for it. Downloading fonts is less likely for native apps as far as I know (although not my expertise). |
I think it’s much more feasible on native platforms (though you may need to perform expensive reconstructive surgery). It would be inherently native-only, permanently, as opposed to the situation with extended TinySDF, which would only be a temporary situation so that we wouldn’t have to synchronize releases across all three platforms. I suspect direct system font access is kind of redundant on iOS anyways, since you can already get the vectors of the glyph if you really want. And both Android and iOS now provide direct native access to text shaping. |
The other aspect of direct font access is licensing. Mapbox’s original idea behind glyph PBFs is that they’re just collections of screenshots of individual letters, which under U.S. law are ineligible for copyright protection. As soon as you depend on actual font data, the font’s license kicks in. Fortunately, these days, there’s a wealth of fonts licensed for distribution as Web fonts (think Google Fonts), while the landscape for “desktop” fonts is more restrictive. Presumably system fonts are fair game, because you don’t have to embed anything, but then you’re at the mercy of the device’s font selection, which can be highly variable even on iOS, let alone Android. |
I'm not sure I'm following to be honest. |
@HarelM I agree, the spec should be cross-platform and should not have web-specific or native-specific extensions.
MapLibre Native is able handle
Native is already using TinySDF for CJK characters. But the PR from @alanchenboy implements rasterization using FreeType. So this may be a stupid suggestion, I don't know much about the complexities of font rendering. But can we push the complexity to the server and update the {
"glyphs": "https://maplibre.org/font/{fontstack}/{range}.{font_format}"
} For the When a instead of |
Right, I think this would be a limitation of anything that needs to access the actual font data. By default, on every platform, the TinySDF-based local font rendering mechanism for CJK only needs rasterized characters and metrics, which the standard library already provides. Extended TinySDF wouldn’t change much about this; the main difference is just how we’d segment the string to send to TinySDF. Incidentally, the existing CJK mechanism on the native platforms relies on a separate configuration file that overrides what’s in the stylesheet, equivalent to the map constructor option suggested by @HarelM. Putting the option in the style specification would’ve posed a barrier to some cross-platform applications: developers generally want to use system-provided CJK fonts rather than bundling huge custom fonts, but each platform comes with a different set of CJK fonts. |
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,
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
The text was updated successfully, but these errors were encountered: