Infosec Scribbles

March 30, 2018, updated on August 11, 2018

Ubuntu: Better fonts than Windows

Preamble

As it turns out, font rendering is a highly controversial topic. You are reading the third edition of this blog post.

I spent the first 25 years of my life on Windows and therefore I am biased towards Windows-like font rendering and respecting the pixel grid. I also agree with research which suggests that this rendering approach makes reading easier on the eyes. With that out of the way, let’s proceed.

Technical background

Fonts are vector data that gets rasterized when displayed to the user. Computer displays are low-DPI devices for complex reasons, and such DPI is not enough to display fonts without a myriad of trade-offs. Most notable are subpixel rendering, font hinting and anti-aliasing. You can read up more here and here if you want the full background.

To arrive at this final result, I spent a few days studying the subject as my vacation reading, starting at those whitepapers, continuing into endless forum threads, Reddit comments, blog posts, mailing list discussions and diving into the code of various FreeType patches. This was particularly interesting to me, because in my earlier days of working in web design and development I came across the inconsistencies between rendering text in Adobe Photoshop page designs and in actual browsers. There were multiple font smoothing settings in Photoshop that improved things, but not to the pixel-perfect degree. At the time I didn’t do a deep dive and the mystery remained unsolved until now.

To get Windows-like rendering, anti-aliasing, subpixel rendering and font hinting based on byte code embedded into fonts need to be enabled. This last bit is important, because due to patent issues with that byte code, for the longest time FreeType relied on “autohinting” instead. Autohinting ignored the byte code and attempted to perform guesswork on how to best render the font. It still has its uses for particularly bad fonts that come without hinting information.

Ubuntu, and most Linux distros, use the FreeType library for rendering fonts. FreeType comes with 3 different engines for interpreting TrueType hinting instructions: v35, v38, v40.

v35 is the legacy engine that is used by default on more risk-averse distros, notably RHEL derivatives. It does not use any patented technologies. It used to be the default in the mainline code base before v40 came around and it objectively is crippled compared to Windows or OS X - see font rasterization whitepapers above.

v38 is the “Infinality” engine. Infinality was a set of patches for earlier versions of FreeType that focused on ignoring patent issues and just getting the best possible font rendering in. Some of those were merged into mainline FreeType, but not enabled by default. The author of the patches eventually lost interest and I can’t vouch for how much of it is in and how actively it is maintained by the man behind FreeType. There is also widespread criticism stating that font rendering is visibly slower on v38 because of all those patches, supported by this post on FreeType website. I couldn’t find any profiling with comparisons and for the life of me I can’t see the visibly slower rendering.

v40 is the new engine, based on stripped down Infinality code, as described in the same blog post. This engine uses Microsoft patented technology where the patents have expired.

Ubuntu also enables other seemingly patented technologies disabled by default in FreeType: subpixel rendering and “GX/AAT table validation”. You can read more about the patents in David Turner’s blog post.

On top of FreeType there is the fontconfig configuration layer that allows to toggle the technologies mentioned above on or off for different fonts, their size ranges and so on. Technically, you could have two completely opposite settings for two different font sizes or weights of the same font. You can read the official docs for the full details.

Ubuntu, or any other distro, does not come with Windows standard fonts (Arial, Courier New, Times New Roman etc) that are used throughout the system and also as defaults in web browsing. It does not come with some of the runtime configuration options enabled to make the most of these fonts either.

Funnily enough, in my adventures I learned that some people prefer the fuzzy and blurry rendering of Linux/OS X defaults on Windows. They found a way to replace the Windows rendering engine with FreeType for this purpose and the tool is called MacType.

The v38 way (Infinality)

Why would you use v38? Because it provides objectively better looking font rendering and for the time being it is still kept alive by the FreeType maintainer.

The easiest way to get Infinality rendering is to use the PPA by achaphiv. This comes with all the necessary patches, fontconfig bundle and patched JDK for Java-based applications (separate circle of hell).

To get the PPA installed, do this:

$ sudo add-apt-repository ppa:no1wantdthisname/ppa
$ sudo apt-get update
$ sudo apt-get install libfreetype6 fontconfig-infinality
$ sudo add-apt-repository ppa:no1wantdthisname/openjdk-fontfix
$ sudo apt-get upgrade

If something doesn’t go as expected, the maintainer of the PPA covers pretty much everything in his readmes. The man is truly doing god’s work. At least that is what my eyes say.

The changes will only get applied when we restart X Org, so it makes sense to get through the whole process before doing that.

Note that 18.04 LTS is based on a bugged version of FreeType which results in weird glitches with line heights and font sizes. Until the PPA is updated, you can use my automated scripts based on the PPA to rebuild it yourself using upstream sources.

The v40 way

Why would you use v40? Because it is the default, allegedly works faster and will definitely be maintained longer than v38.

v40 is the default in 18.04, so there is no PPA involved. However, fontconfig bundle for proper rendering is still missing and the gnome-tweaks UI is not flexible enough. The fontconfig bundle that comes from the PPA is extremely bloated and not particularly useful when not running Infinality.

To save time, you can use the following files from it:

  • infinality/styles.conf.avail/infinality/60-group-non-tt-fonts.conf
  • infinality/styles.conf.avail/infinality/60-group-tt-fonts.conf
  • infinality/styles.conf.avail/infinality/61-group-tt-rendering-inf-7-xp.conf

These will address known-good and known-bad fonts and set up their rendering options to the most optimal ones.

Next, configure the defaults more thoroughly than gnome-tweaks allows you to. For example, I found that not explicitly disabling the autohinter and not explicitly enabling BCI hinting instead can cause sub-optimal results that I don’t want to investigate further, it is easier just to set this in stone. You can get my full configuration file with more extras here. If you don’t want those, below is the bare minimum /etc/fonts/local.conf to properly use v40:

<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
    <!-- 
    These are the true system defaults that will override ones from `gnome-tweaks`.
    Unfortunately, `gnome-tweaks` does not provide all of these options in the UI. Without them "full" style hinting looks weird - doesn't seem to use BCI-hinting or attempts to enable both and ends up with a mess. Anyway, this fixes it.
     -->
    <match target="font">
        <edit name="hinting" mode="assign">
            <bool>true</bool>
        </edit>
        <edit name="autohint" mode="assign">
            <bool>false</bool>
        </edit>
        <edit name="antialias" mode="assign">
            <bool>true</bool>
        </edit>
        <edit name="hintstyle" mode="assign">
            <const>hintfull</const>
        </edit>
        <!--
        Italic variants look jagged without forcing the DPI. Default DPI of FreeType is 72. Verify with `fc-match` if in doubt.
         -->
        <edit name="dpi" mode="assign">
            <int>96</int>
        </edit>
    </match>

    <!-- This enables the autohinter for known-bad fonts without hinting instructions regardless of system defaults above -->
    <include>60-group-non-tt-fonts.conf</include>
    <!-- This marks known-good fonts with a tag -->
    <include>61-group-tt-fonts.conf</include>
    <!-- This ensures that known-good fonts will have the right options set regardless of system defaults above -->
    <include>62-group-tt-rendering.conf</include>
</fontconfig>

Extras

Whichever engine you go with, there will be a few more things to address before you can have nice font rendering.

GIMP

If you use GIMP, you may notice weird artifacts in the Text Tool. Create /etc/gimp/2.0/fonts.conf:

<fontconfig>
  <match target="font">
    <edit name="rgba" mode="assign">
      <const>none</const>
    </edit>
  </match>
</fontconfig>

Microsoft Fonts

When you are browsing the internet, a lot of websites make implicit assumptions about your default fonts. If you are coming from the Windows world, a lot of websites will look weird to you and page rendering may be downright broken if the fonts are missing from your system, e.g. plain text files opened in Chrome will have overlapping lines. To fix it, you need to get Windows fonts installed.

The traditional way of achieving this is through installing ttf-mscorefonts-installer or msttcorefonts. The msttcorefonts package looks like some Shenzhen basement knockoff that renders poorly and doesn’t support Unicode. I suspect that these fonts have gone through multiple iterations in every Windows release and that the versions available through the repositories must be from around Windows 95 days.

Try generating some Zalgo and see the empty boxes for yourself. These are not the same fonts included in your Windows installation. If you have these packages installed, ditch them prior to continuing.

The workaround is to grab the fonts from your Windows installation. I Am Not A Lawyer and if you are worried about this going against Microsoft licensing, get legal advice. I just know that it would be illegal for me to provide you with the files, therefore: the fonts are available in C:\Windows\Fonts. You need the following files:

arialbd.ttf   ARIALNB.TTF  ariblk.ttf    consolai.ttf  courbi.ttf    georgiai.ttf  segoeprb.ttf  segoeuib.ttf  segoeuiz.ttf  timesbi.ttf   trebucbi.ttf  verdanai.ttf
arialbi.ttf   ARIALNI.TTF  comicbd.ttf   consola.ttf   couri.ttf     georgia.ttf   segoepr.ttf   segoeuii.ttf  tahomabd.ttf  timesi.ttf    trebucit.ttf  verdana.ttf
ariali.ttf    ARIALN.TTF   comic.ttf     consolaz.ttf  cour.ttf      georgiaz.ttf  segoescb.ttf  segoeuil.ttf  tahoma.ttf    times.ttf     trebuc.ttf    verdanaz.ttf
ARIALNBI.TTF  arial.ttf    consolab.ttf  courbd.ttf    georgiab.ttf  impact.ttf    segoesc.ttf   segoeui.ttf   timesbd.ttf   trebucbd.ttf  verdanab.ttf  webdings.ttf

Depending on how you access that directory, you may have to copy the files based on font family names:

  • Arial
  • Comic Sans MS
  • Consolas
  • Courier New
  • Georgia
  • Segoe UI
  • Times New Roman
  • Trebuchet MS
  • Impact
  • Verdana
  • Webdings

The files go in /usr/share/fonts/MAKE_UP_A_FOLDER_NAME.

Noto Font

Noto font family is an excellent font that supports all the different languages and symbols. It comes in sans, serif and monospace editions, which covers all the OS needs. Install it like this:

$ sudo apt install fonts-noto

Tweak Tool

  • Hinting: Slight. Will be globally overridden if you are using my fontconfig file and per-font overridden if you are using the Infinality one.
  • Anti-aliasing: Subpixel
  • Window Titles: Noto Sans UI Regular 11 or Noto Sans Display Regular 11 (renamed in newer versions)
  • Interface: Noto Sans UI Regular 10 or Noto Sans Display Regular 10 (renamed in newer versions)
  • Documents: Noto Serif Regular 11
  • Monospace: Noto Mono Regular 13

Application Settings

I find that different applications render best with certain font sizes set. Here they are:

  • Terminator: Ubuntu Mono 13.5
  • Sublime Text: Ubuntu Mono 13.4, padding-top 4, padding-bottom 4
  • IntelliJ: Ubuntu Mono 18, line height 1.4

Conclusion

I can rant endlessly about how annoying it is that I had to spend my vacation reading time figuring out all this just to get things to work the way they should work out of the box. Certainly I would prefer to read something more useful or relaxing. Then again, nobody forces anyone to use FOSS. If you are happy with Windows 10 or OS X (I am not), I strongly recommend that you stick with it instead of using Linux. It’s just a reasonable thing to do.