One of the hardest parts of building beautiful Linux systems is fonts. Font precedence on Linux is generally handled with fontconfig.
fontconfig is used to permit many fonts to be installed and uninstalled over time without breaking applications which specify a font or font family, while letting users configure which fonts are used when a missing font, font family, or missing glyph is requested.
This is really useful piece of technology; having a defined configuration system for which fonts are used in which scenarios is a boon for configurability, but fontconfig has no real GUI editors or usable interactive configuration tools. Users are expected to manually edit XML configuration files.
As with most Unix styling topics, Eevee has a great piece on fontconfig’s complexities. She digs into how to disable and re-configure fonts, how to set fallbacks, and how to verify that the correct resolution order is set. Fontconfig relies on a set of config files, generally in
/etc/fonts/conf.d, which are loaded in alphabetical order. These are usually prefixed with a number, so it’s easy to determine the order.
Unfortunately, it can be very complex to determine where a specific font or option is configured. In my recent case, I wanted to switch from
DejaVu as my default to
Bitstream Vera, and I spent the better part of an hour flipping around different files changing mentions of
Deja Vu X to
Bitstream Vera X.
Eventually, I settled on the following methodology:
- Identify problematic resolution result (either by observing it or using
rgto search for the incorrectly resolved font (e.g.
rg DejaVu .*).
- Open highest-numbered file with a match. For me, this was
- Determine whether or not this config file is causing the problematic match. In the case of
69-language-selector-zh-tw.conf, it was only selecting DejaVu Sans Mono for language
zh-tw, which is actually correct as Bitstream Vera Mono doesn’t include
- If that file might be causing the problematic match, modify it.
- Check if the problematic resolution still occurs (using fc-match). If so, repeat.
I’ve been very successful with this methodology so far. In my specific case, I had to modify
56-emojione.conf, which was setting the default serif, sans serif, and monospace fonts to resolve to DejaVu followed by Emoji One.