Users browsing this thread: 1 Guest(s)
venam
Administrators
Hello nixers,

In this thread we'll talk about a topic that came up on IRC yesterday: font fallback.

Many of the popular desktop environments already come with a preset of fonts that has good support for a wide range of unicode characters.

However, what if you want more power over these, over the order in which they will fallback, or what about building your own font fallback font line.

Font fallback is software based, that means it's upon the software to handle it. Normally, software that relies on fontconfig will ask it for information regarding a name, let's say "monospace", and fontconfig will return a list of all the fonts, in order, that can support characters that are monospace. Then the software will try to draw a character by searching for it within the first font in the list, if it doesn't find it, it'll continue to the second, and so forth.

You can test that by doing:
Code:
fc-match 'monospace'

Monospace isn't a font that exists but an alias for many fonts that can fulfill it.

If you want more info about this, I've written a bit about FcNameMatch and fc_finding_pattern here. The crux of it, is that it tries to match via properties.

So in theory, you can start with your favorite font, which you know supports the characters you use the most, and then add to the list other fonts that support lesser known characters such as emojis.

Here's a good list of unicode fonts I found, please share yours too:
  • Symbola
  • Noto Emoji
  • Twitter Color Emoji
  • Pan-CJK

But, that's for the case in which we can actually control the exact fallback order that will be taken. Otherwise, we have to rely on the fontconfig mechanism for fontfallback.
Both the ArchWiki and this article mention ways to do so. But if you dislike editing XML files via text editors, I propose using the fontweak tool instead.

Here's a screenshot of it:

[Image: tiGcFAK.png]


So, how do you handle font fallback. Which fonts do you use? Does it display properly in your terminal and across your environment?
z3bra
Grey Hair Nixers
I made some research on the topic because I wanted cool emojis in the terminal. Ended up managing it directly with the fontconfig configuration XML:

Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<!-- $HOME/.config/fontconfig/fonts.conf -->
<fontconfig>
  <!-- Generic name aliasing -->
  <alias>
    <!-- Because helvetica sucks, yet many people insist on using it on the web -->
    <family>Helvetica</family>
    <prefer>
      <family>IBM Plex Sans</family>
      <family>Symbola</family>
    </prefer>
  </alias>
  <!-- the following define fonts to use for "generic aliases", and which font to fallback to (Symbola being a font for emojis) -->
  <alias>
    <family>sans-serif</family>
    <prefer>
      <family>IBM Plex Sans</family>
      <family>Symbola</family>
    </prefer>
  </alias>
  <alias>
    <family>serif</family>
    <prefer>
      <family>IBM Plex Serif</family>
      <family>Symbola</family>
    </prefer>
  </alias>
  <alias>
    <family>monospace</family>
    <prefer>
      <family>IBM Plex Mono</family>
      <family>Symbola</family>
    </prefer>
  </alias>
</fontconfig>
movq
Long time nixers
Honestly, I mostly gave up on it. It’s one of the main reasons why I wrote xiate: It uses VTE and thus GTK/pango, which does all the nasty magic. Emojis and other fancy stuff displays just fine in my terminals. (Needless to say, I spend most of my time in terminals, so that matters the most.)

My WM, though, uses simple Xft and that means I’d have to implement font fallback myself (see various suckless tools, they do it). I’m too lazy for that. The code without font fallback is easy to read – *with* fallback, it’s a spaghetti mess. If I needed font fallback, I’d probably sacrifice a goat and just use pango. There actually is a “pango” branch in my private repo of my WM, but I hardly ever need font fallback in window titles, so it’s just not worth it.

I have noto-fonts-emoji and ttf-unifont installed, which covers a lot of things. Never needed to fiddle with fontconfig (in that regard).

The glyphs (?) I need the most are part of my main font (https://uninformativ.de/git/qsqs). It’s not a lot. The rest comes from uw-ttyp0 (https://people.mpi-inf.mpg.de/~uwe/misc/uw-ttyp0/) and univga (http://www.inp.nsk.su/~bolkhov/files/fonts/univga/). And then probably fallback to DejaVu Sans Mono.

tl;dr: GTK/pango is fine due to witchcraft, everything else is a mess. :-)

Wasn’t there a command line utility of fontconfig that could show you which font is used to display a certain character? I don’t remember anymore. Would be interesting.
venam
Administrators
(11-08-2020, 07:00 AM)vain Wrote: Wasn’t there a command line utility of fontconfig that could show you which font is used to display a certain character? I don’t remember anymore. Would be interesting.

There's the script found here, that'll I'll paste:

Code:
#!/bin/sh
for range in $(fc-match --format='%{charset}\n' "$1"); do
    for n in $(seq "0x${range%-*}" "0x${range#*-}"); do
        printf "%04x\n" "$n"
    done
done | while read -r n_hex; do
    count=$((count + 1))
    printf "%-5s\U$n_hex\t" "$n_hex"
    [ $((count % 10)) = 0 ] && printf "\n"
done
printf "\n"

Beware that printf with \U isn't POSIX, so run it like this
Code:
bash ./ls-chars 'monospace'
movq
Long time nixers
(11-08-2020, 08:26 AM)venam Wrote: There's the script found here, that'll I'll paste:

Ah, I was thinking about the opposite, but that’s helpful, too.

What I meant was this:

https://repolinux.wordpress.com/2013/03/...character/

Given a certain character, which font is used to display it? I need a different level for `FC_DEBUG`, though (as determined by trial and error, so this may be wrong):

Code:
$ FC_DEBUG=4096 pango-view -q -t a | grep -o 'family: "[^"]\+' | tail -n 1
family: "DejaVu Serif
$ FC_DEBUG=4096 pango-view -q -t 🐧 | grep -o 'family: "[^"]\+' | tail -n 1
family: "Noto Color Emoji
$ FC_DEBUG=4096 pango-view -q -t ༀ | grep -o 'family: "[^"]\+' | tail -n 1
family: "Unifont
$ FC_DEBUG=4096 pango-view -q -t दी | grep -o 'family: "[^"]\+' | tail -n 1
family: "IBM Plex Sans Devanagari
seninha
Long time nixers
My programs use Xft and I have to implement font fallback myself, I used suckless software as a base but tried to simplify their code. I ended up writing a function that, given a character, tries to find a font that supports it: here it is.
Suckless code for doing that is completely spaghettish and unreadable. I tried to do my best. In the end it works the same, but with a saner algorithm. I splited Suckless' drw_text() function into three functions: drawtext(), getfontucode() and getnextutf8char().

First it searches among the fonts the user listed in the configuration, and then it searches the system for a font that contains a given character.

I first tried to use pango, but then decided to study more how font fallback is done and then could implement myself.

If you try, for example, a CJK glyph on xmenu or xprompt, they will do their best to find a font that support it.

I never needed to change fontconfig, except for setting my default monospaced font.

The problem is when the font contains a colored emoji, then, due to a strange Xft bug, the program crashes, depending on the system you are. There are some patched versions of libXft in some distros. Here in OpenBSD the program just don't render the colored emoji. But on most Linux systems the program crashes.
venam
Administrators
(16-08-2020, 06:39 PM)phillbush Wrote: My programs use Xft and I have to implement font fallback myself, I used suckless software as a base but tried to simplify the code. I ended up writing a function that, given a character, tries to find a font that supports it: here it is.
I have a similar example here when I tried to recreate Xft for XCB, but I've left it to the reader to guess that they should loop in the rest of the fallback faces. It would be better to additionally search for a font based on a charset parameter, like you did. It isn't ideal, but as you said, it does the trick.