Fontconfig

Fontconfig lives on most Unix and Unix-like systems that have a graphical interface.  The official documentation is terrible, and examples of how to do things correctly are few and far between. 

All examples have been tested under "Bash on Windows" (WSL) and macOS.  Examples below should be put in your $HOME folder, named .fonts.conf. 

Example: Specify a new font's family

I got several useful tips from Eevee blog.  I will note that I think Eevee got some examples backwards (but Fontconfig will still work anyway).  As noted on Eevee blog, many common default fonts are already set-up by the default Fontconfig configuration files.  However, new fonts are automatically considered to belong to sans-serif, which may not be correct.  The following include some monospace fonts that I installed that needed family corrections. 

The second half of the same sample, also from Eevee, is the code to remove these fonts from the sans-serif family.  I also show code for stripping sans-serif from fonts identified as cursive.


<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
    <alias>
        <!-- sterm alias pattern here (below) -->
    </alias>
    <selectfont>
        <!-- Blacklist rejectfont pattern here (below) -->
    </selectfont>
    <!-- Font Family Corrections -->
    <alias>
        <family>monospace</family>
        <accept>
            <family>Ubuntu Mono</family>
            <family>Source Code Pro Medium</family>
        </accept>
    </alias>
    <!-- Remove auto sans-serif font family -->
    <match>
        <test>
            <string>sans-serif</string>
        </test>
        <test>
            <string>monospace</string>
        </test>
        <edit mode="delete" name="family"/>
    </match>
    <match>
        <test>
            <string>sans-serif</string>
        </test>
        <test>
            <string>cursive</string>
        </test>
        <edit mode="delete" name="family"/>
    </match>
</fontconfig>

Example: Globally Blacklist a Font

The rejectfont keyword, sadly, is not able to be used within an alias section.  More correctly, even if it is within another section, it will take affect globally.  The following forces 'Comic Sans MS' and '.LastResort' fonts to never be selected for anything. 

.LastResort is on my macOS system, and it does not play well with X terminal programs that try to cache already open fonts (instead of having Fontconfig re-open fonts for every new glyph).  I find it extremely useful to be able to simply blacklist the font in this way.


<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
    <alias>
        <!-- sterm alias pattern here (below) -->
    </alias>
    <selectfont>
        <rejectfont>
            <patelt name="family">
                <string>Comic Sans MS</string>
            </patelt>
        </rejectfont>
        <rejectfont>
            <patelt name="family">
                <string>.LastResort</string>
            </patelt>
        </rejectfont>
    </selectfont>
    <alias>
        <!-- Font family correction pattern (above) -->
    </alias>
</fontconfig>

Example: Made Up Family

I use this configuration for st and use sterm as the default font name in my st/config.h file.

The sections, prefer, accept and default are in order of preference.  It should be noted that font list expansions may happen automatically, by Fontconfig between each of these sections.  The fonts that should never be seen, accept in an absolute emergency, belong in the default section. 


<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
    <alias>
        <family>sterm</family>
        <prefer>
            <family>Ubuntu Mono</family>
        </prefer>
        <accept>
            <family>Source Code Pro Medium</family>
            <family>Microsoft YaHei</family>
            <family>EmojiOne</family>
        </accept>
        <default>
            <family>Unidings</family>
            <family>OpenSymbol</family>
            <family>Noto</family>
            <family>Noto Emoji</family>
            <family>Unifont</family>
            <family>Unifont CSUR</family>
        </default>
    </alias>
    <selectfont>
        <!-- Blacklist rejectfont pattern here -->
    </selectfont>
</fontconfig>

Why that choice?

Ubuntu Mono because it includes regular, bold, italic and bold-italic varients AND it includes a dot in the zero.  The suckless terminal utilizes all four varients nicely. 

I personally find Adobe's Source Code Pro to be much prettier than Ubuntu Mono.  However, it includes some Chinese Glyphs that are rendered as single-width, which is near impossible to read.  If you don't use Chinese Glyphs (including numbers), then Source Code Pro is a really nice choice. 

NOTE: The Source Code Pro weight, Regular, does not have an Italic varient, so a terminal that wants both italic and non-italics will not find the weight Medium Italic.  This is why I specify Medium, directly, in the examples above. 

EmojiOne comes before Noto Emoji for two reasons.  First, I think EmojiOne is just a prettier presentation.  Second, some people have reported stability issues while using Noto Emoji in some terminal programs.  Note: I've experienced stability issues that I don't experience anymore, but I can't attribute that to Noto Emoji with any level of confidence. 

Google's Noto Fonts are not primary for me, mostly, because they do not present with a distinct zero.  However, I find them very important for filling holes in glyph coverage for languages that I don't run into frequently.  I think my use of the fonts fits well with Google's attempt to have 'no more tofu'. 

Rejecting Comic Sans MS, well, I'm not actually.  The Internet loves to joke about how terrible it is, but it also has never come up as a font on my computers' terminals before, even though it is installed.  If something IS requesting a Cursive/handwriting style font, I would personally prefer Comic Sans MS to something like Segoe Script.

Valid CSS!   Valid XHTML 1.0 Strict