I think I have found details for how to solve font fallback for real this time rather than requiring users to manually specify the fallback list.
https://zachbayl.in/blog/font-fallback-revery.html
This blog post highlights the strategy. Turns out skia (cause of course it does) has a font fallback implementation which works cross platform. It handles fallback by returning a font which is guaranteed to render a give character. So the strategy is that we shape the text getting cluster divides, then loop over every cluster looking for glyphs with id 0. For each of those we query skia for the correct fallback character, load it up, and requery harfbuzz for a new cluster list. Rinse repeat until all the glyphs have ids.
Along with this I discovered https://github.com/RazrFalcon/rustybuzz which looks to have a reasonable and rusty api for shaping which should be equivalent to harfbuzz' implementation. So I plan to incorporate that.
Lastly while I'm in this area, I'd like to cut down on dependencies, so I want to take another stab at using skia's font parsing/metrics rather than font-kit's. By removing both font-kit and skribo I should be able to cut out a TON of dependencies which will result in smaller exe size and faster build times. win win
For now I'm going to comb through all the issues and close any related to font fallback and point them to this issue as this is where development will happen.
I'm reproducing a comment I just made on the opengl issue as it is related here:
I've also been thinking about the text layout approach we've been taking. Generally its pretty dumb because we depend on the shaper to layout what should be a monospace font. The only reason we use the shaper at all is because I need to know what glyph substitutions are necessary to handle ligatures. However if we could use the shaper just for ligatures and then position the glyphs manually our selves based on some estimate (such as the size of "Z") then we wouldn't ever run into this cursor to text positioning mismatch. It would always be positioned the same way every time.
The opengl branch goes part of the way towards doing this by using Rustybuzz instead of skribo for the harfbuzz binding. This way we have a nice api on top of actual harfbuzz rather than a higher level wrapper. I'm struggling to understand how glyphs line up to the original text codepoints though. My understanding is that this is done with clusters, but the documentation is somewhat dense https://harfbuzz.github.io/working-with-harfbuzz-clusters.html and my manual tests get weird results such as skipped cluster indexes when I don't expect it. So I took a break fiddling with it to regroup.
TLDR
To solve these types of problems once and for all, we need some function which when given a string returns a list of glyph ids with matching unicode characters from that string. From that function would could then use skia's font fallback to fill in any gaps, and could draw the glyphs in the correct position assuming they are monospace. If anybody knows anything about how that my work, I'm all ears as it would solve a bunch of problems in neovide today
assuming they are monospace
What about >1 width glyphs
The way I'm thinking about it, thats what we get out of the shaper. By looking up what glyphs are associated with what unicode characters, we can determine what should take up more than a single character size. The difference in above is that we don't rely on the shaper for actually positioning those glyphs, just substituting
Until this is fixed, here is manual fallback instructions:
Find your missing glyph at www.fileformat.info, open, look at "Fonts that support ..." link, you end up at the page like this:
https://www.fileformat.info/info/unicode/char/279c/fontsupport.htm
Find your favorite font, add it to fallback list. My list looks like this:
set guifont=JetBrains\ Mono\ Nerd\ Font,DejaVu\ Sans\ Mono,Iosevka:h24
Until this is fixed, here is manual fallback instructions:
Find your missing glyph at www.fileformat.info, open, look at "Fonts that support ..." link, you end up at the page like this:
https://www.fileformat.info/info/unicode/char/279c/fontsupport.htmFind your favorite font, add it to fallback list. My list looks like this:
set guifont=JetBrains\ Mono\ Nerd\ Font,DejaVu\ Sans\ Mono,Iosevka:h24
Just use fc-match ...
I have a PR which is a promising proof of concept for doing this: https://github.com/Kethku/neovide/pull/701
It currently fails to build, but I'm planning on iterating on it a bit over the next couple days. My current biggest concern is about performance. This will load fonts sorta randomly as it determines it needs to, so we may have to rework how fonts are cached and staled.
Further, this uses the skia font fallback apis, but I'm seeing promising things over at https://github.com/dfrg/fount so if this has subtle issues, there may be a way out over there. Not sure yet.
This has just been merged with the Opengl Branch. Associated issues should be fixed.
Most helpful comment
This has just been merged with the Opengl Branch. Associated issues should be fixed.