Same here, I use dark themes for everything, but theno-stem-darkening=0 options were the best solution in my case (27" screen, 82 DPI), thinner and less blurry letters.
Font Setup
These notes are for my setup (no hinting, grayscale antialising). I have a 218 ppi HiDPI monitor (an old iMac), 200% scaling, and use Manjaro (Arch) Gnome. I get fantastic font rendering, very close to Mac OS X quality. You will need to adjust for your setup.
General
Use Opera browser
Opera has the darkest/thickest font rendering. Firefox is next. And then all the chrome-based browsers are worse. I suspect Opera sets:
if (is_linux) {
defines += [
"SK_GAMMA_EXPONENT=2.2",
"SK_GAMMA_CONTRAST=0.0",
]
in their chromium build parameters.
Use modern Fonts
Arial may be useful for compatibility but modern fonts like Inter, IBM Plex Sans, IBM Plex Mono look far better on modern displays. My default browser font is Inter. The metric compatible Liberation Sans/Serif/Mono family may also render better than Arial/Times/Courier.
Use OTF Fonts
Adobe’s CFF engine used for rendering OTF fonts is higher quality than the TTF engine. Stem darkening on Linux only works properly for OTFs. The OTF format is also more advanced than TTF. Most modern fonts will have an OTF version if you look at their GitHub repo. For older fonts install FontForge and run the following Python script to losslessly convert all your TTFs to OTFs (Save the code in a plain text file as ttf2otf.py and run it by typing python ttf2otf.py in a terminal opened in each font folder on your system, you may need to use sudo)
import fontforge
import os
fonts = [f for f in os.listdir('.') if f.endswith('.ttf')]
for font in fonts:
f = fontforge.open(font)
f.generate(font[:-3] + 'otf') # changes extension from ttf to otf
os.remove(font)
exit()
Stem Darkening
Put the following in etc/profile.d/freetype2.sh. The default numbers are 500, 400, 1000, 275, 1333, 275, 2333, 0. Multiply the countrol points (1st, 3rd, 5th, 7th numbers) by your display scale factor; e.g. I have 200% scaling so *2. Adjust the darkening amounts (2nd, 4th, 6th, 8th numbers) to your preference; 0 is no darkening 500 is max darkening.
export FREETYPE_PROPERTIES=\
"autofitter:no-stem-darkening=0\
autofitter:darkening-parameters=1000,500,2000,500,3334,500,4666,0\
cff:no-stem-darkening=0\
cff:darkening-parameters=1000,500,2000,500,3334,500,4666,0\
type1:no-stem-darkening=0\
type1:darkening-parameters=1000,500,2000,500,3334,500,4666,0\
t1cid:no-stem-darkening=0\
t1cid:darkening-parameters=1000,500,2000,500,3334,500,4666,0"
Control fonts for non-native apps (browsers etc.)
Create a text file in ~/.config/fontconfig/fonts.config
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<match>
<edit name="antialias" mode="assign">
<bool>true</bool>
</edit>
</match>
<match>
<edit name="hinting" mode="assign">
<bool>false</bool>
</edit>
</match>
<match>
<edit name="autohint" mode="assign">
<bool>false</bool>
</edit>
</match>
<match>
<edit name="rgba" mode="assign">
<const>none</const>
</edit>
</match>
<match>
<edit name="embolden" mode="assign">
<bool>false</bool>
</edit>
</match>
<alias binding="same">
<family>Arial</family>
<prefer>
<family>Helvetica Neue</family>
</prefer>
</alias>
</fontconfig>
Gnome specific
Gnome Tweaks or Refine app
Set hinting and antialiasing options using GUI
Dconf Editor or Terminal
turn off auto font hinting:
gsettings set org.gnome.desktop.interface font-rendering 'manual'
Home folder config files
turn off GTK4 hinting by adding a text file to ~/.config/gtk-4.0/settings.ini containing
[Settings]
gtk-font-rendering=manual
gtk-hint-font-metrics=0
gtk-xft-hintstyle=hintnone
gtk-xft-hinting=0
or for lower resolution displays:
[Settings]
gtk-font-rendering=manual
gtk-hint-font-metrics=1
gtk-xft-hintsyle=hintfull
gtk-xft-antialias=0
gtk-xft-hinting=1
turn off GTK3 hinting by adding a text file to ~/.config/gtk-3.0/settings.ini
[Settings]
gtk-xft-hintstyle=hintnone
gtk-xft-hinting=0
Hardware
Playing with hinting and antialiasing only gets you so far. If you really want fantastic font rendering you need a display > 200 ppi. These are the options:
- A second hand Apple Retina iMac - these are a fairly cheap option, and snappy performance running Linux. Comes in two sizes - 21.5" and 27". The smaller one feels as spacious as a 24" monitor thanks to the pixel density.
- A second hand LG 27" 5K Ultrafine Monitor
- A 27" 5K monitor from Japannext, Asus, BenQ, Samsung, Kuycon, or HTC.
IMO disabling subpixel rendering and hinting on non-HiDPI monitors is a bad idea, it looks worse. The issue becomes progressively less relevant with each scaling factor, because you simply get more pixels for your fonts.
The OTF vs TTF thing is interesting, I wonder if it applies to browsers as well. Chromium uses Fontations stuff everywhere so it might not matter what format you have in your system, as it will just use its own fonts.
Opera is indeed a bit better, you’re probably right about the gamma exponent and contrast defines. I’m not willing to use it, though, because it’s borderline spyware. I’ll try to ask the Vivaldi team about making a similar change.
I’ve opened a sister thread on Vivaldi’s forums.
Fontations is an alternative rendering engine to Freetype for pages that specify their own webfonts (.woff). It has no effect on pages that use your system fonts.
The WhatFont browser extension is useful to know what fonts a page is using.
Make sure you are using the beveled, colour-balanced, normalised, five-tap filter for subpixel rendering, otherwise known as lcddefault. See here to check
Otherwise, you could always buy a > 200 ppi monitor. I posted some options above.
Thanks for clarifying. I do use lcddefault explicitly, though I have tried compiling Freetype with other filters and nothing resolved this issue.
And buying a monitor is not a solution to bad font rendering. It works fine on other OSes, I see no reason why it shouldn’t on Linux, too. In that case “you could always use Windows instead” is also a valid option.
“Works fine” still means a low-DPI monitor will be significantly worse than HiDPI. Hinting is essentially truncating the curved edges of fonts, and subpixel antialiasing is not equivalent to having a monitor with 3x more pixels (it is estimated that you actually gain about 1.25x more resolution than your physical pixel density).
If you want on-screen text to look like a printed page the only solution is a HiDPI monitor.
It’s computationally challenging to calculate the correct subpixel antialiasing for text on a dynamic background, updating at 60Hz. That’s why Apple, GTK4, and some modern apps only use grayscale antialiasing. See what an Apple engineer says here: https://news.ycombinator.com/item?id=17477526.
But I agree that, where possible, e.g. in browsers, good subpixel antialiasing should still be available.
