Tuesday, July 13, 2021

Setting the default monospace font on Raspberry Pi OS: An exercise in frustration

Many Linux distributions, including Debian GNU/Linux and Raspberry Pi OS (which is derived from Debian), use a system-wide font configuration framework called fontconfig. This uses a series of XML files to set default fonts, fine-tune font rendering, automatically detect new fonts, and more. By providing a centralized mechanism to manage fonts, fontconfig helps ensure a consistent look and feel across applications.

CUPS, the standard printing system on most Linux distributions as well as on Apple macOS, is among the numerous applications that use fontconfig. The configuration determines how CUPS renders documents that do not specify fonts, such as plain text files, for printing. For example, plain text files are printed using the default monospace font.

I followed the Arch Linux documentation for font configuration and Angelos Orfanakos's blog post on setting fonts in Debian to edit the font configuration manually. System-wide settings can be placed in ~/.config/fontconfig/fonts.conf, while per-user settings use ~/.config/fontconfig/fonts.conf.

On my Raspberry Pi 4, I was trying to change the default monospace font because the font it normally uses (Liberation Mono) looked very ugly when printed. Instead, I wanted it to use Courier New, from the Microsoft TTF Core Fonts, using the following configuration in /etc/fonts/local.conf:

<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
    <alias>
        <family>monospace</family>
        <prefer>
            <family>Courier New</family>
        </prefer>
    </alias>
</fontconfig>

However, the system wouldn't honor the setting, and it took a lot of fiddling to get it to work. I tried placing the configuration in both /etc/fonts/local.conf and ~/.config/fontconfig/fonts.conf and nothing worked. After extensive fiddling, it turns out that in Raspberry Pi OS, the monospace font is explicitly defined in /etc/fonts/conf.d/31-mono-substitute.conf. The way this is set up causes it to not accept manual changes to the monospace font in local configuration files. This is specific to Raspberry Pi OS, and is presumably there to match official documentation and educational materials released by the Raspberry Pi Foundation.

Renaming the 31-mono-substitute.conf file to disabled-31-mono-substitute.conf worked. I'd suspect it won't be kept during updates, so I subsequently created a file containing no configuration data (as above, but with nothing between the fontconfig tags) in its place to ensure that it's preserved during updates.

Now the system accepts the local font settings and plain text documents are printed with the much cleaner Courier New font. It took me two hours for me to sort this out and it frustrated me to no end.

Draco