Fonts, where are you?
tl;dr: If you want to implement a way to find fonts for every Unicode codepoint, don’t. Do fc-list : file family charset
. Simple parsing code here.
Edit: Screwtape on lobsters told me that fc-list ":charset=1F511"
is valid. It finds fonts for a single codepoint.
The writing quality of this article is like this because I don’t want to spend more time on this issue.
The story
Recently I was making a GUI application. I don’t want to ship fonts with my application. The user’s computer has probably fonts for every language they need to read, so I can just use that. Probably.
The first implementation I used is to load every Noto Sans font. It worked! Noto is really “no tofu”.
fc-list | grep "NotoSans" | cut -f1 -d: | rg Regular | sort | uniq
I should have just stopped here.
Yak shaking
While the simple solution works, it still felt janky to me, because all the font belongs to different font families (“Noto Sans” isn’t the same as “Noto Sans Math”). Also, it might be an issue if Noto fonts are not installed.
Then, I wondered, how UI libraries like GTK, Firefox do it.
GTK… it’s not there.
mozilla-central… it’s not there.
I found the list in Servo. It turns out that Servo embeds a incomplete list of font family names. That’s not it either. It does contain some code copied from GTK+Gecko though.
Let me check what info are in font files with fc-query /usr/share/fonts/noto/NotoSansMath-Regular.ttf
. Not useful either.
Well, it seems like fontconfig is a dead end.
In the end I gave up on this route. It looks like Alacritty does something about this, but I don’t want to touch this any more.
fontconfig, why you be like this
When I wanted to query fc-list with multiple attributes, I tried the following. None of it worked.
fc-list ":weight=80 style=Regular"
fc-list ":weight=80+style=Regular"
fc-list ":weight=80,style=Regular"
fc-list ":weight=80&style=Regular"
So, I turned to the man pages. Still none.
man fc-list
man FcPatternFormat
It turns out at the bottom of man fc-list
it says
The fontconfig user’s guide, in HTML format: /usr/share/doc/fontconfig/fontconfig-user.html.
thanks fontconfig
The final command to list “Regular” fonts (no italic, no bold) is fc-list ":weight=80:style=Regular" file family weight
If you want to query by font family, then do fc-list "Noto Sans:weight=80:style=Regular"
.
The solution that’s not quite elegant
Since I don’t know how Firefox finds the best font for a codepoint, let’s try to see if I can find all fonts for a given codepoint.
This turns out to be simple. fc-list : file family charset
shows the codepoints a font file supports in hex.