字体配置
Fontconfig 是一个用于向应用程序提供可用字体列表,以及字体渲染配置的库。
FreeType 库依此配置渲染字体。freetype2包 字体渲染包启用了字节码解释器(bytecode interpreter,BCI)以优化字体渲染,尤其是在 LCD 屏幕上。参见#Fontconfig 配置和字体配置/示例。
尽管Fontconfig在现代类Unix系统中广泛使用,但部分应用程序仍在使用原始的X Logical Font Description(XLFD)作为字体选择与显示方法。
为了使字体能够被应用程序发现,必须对它们进行编目,以便快速访问。
Fontconfig 的默认字体路径是 /usr/share/fonts/ 和 ~/.local/share/fonts(以及过时的 ~/.fonts/)。Fontconfig 将在这些路径下递归查找字体。为了便于安装与管理,在安装字体时,建议使用这些路径。
以下命令列出 Fontconfig 已知的字体文件:
$ fc-list ':' file
fc-list(1) 中有更多的输出格式。
Xorg 已知的字体路径可通过其日志了解:
$ grep /fonts ~/.local/share/xorg/Xorg.0.log
- 也可使用
xset q命令查看 Xorg 的已知字体。 - 若 Xorg 以根用户权限运行,应查看
/var/log/Xorg.0.log。
Xorg 不像 Fontconfig 一样递归查找 /usr/local/share/fonts。添加路径时,必须像这样添加绝对路径:
Section "Files"
FontPath "/usr/share/fonts/local/"
EndSection
有关 Xorg 读取配置的更多细节,请阅读Xorg#配置。如果要为用户单独配置字体路径,可以像这样修改对应的 ~/.xinitrc 来添加或移除默认的字体路径:
xset +fp /usr/share/fonts/local/ # 将一个自定义字体路径添加到 Xorg 的已知字体路径列表开头 xset -fp /usr/share/fonts/sucky_fonts/ # 从 Xorg 的已知字体路径列表中移除指定路径
要查看 Xorg 已知的字体列表,可使用 xorg-xlsfonts包 软件包中的 xlsfonts 命令。
Fontconfig 的配置文档见 fonts-conf(5)。
用户配置文件位于 $XDG_CONFIG_HOME/fontconfig/fonts.conf 中(通常是 $HOME/.config/fontconfig/fonts.conf)。全局配置文件位于 /etc/fonts/local.conf。
用户配置优先级高于全局配置。两个文件使用相同的语法。
- 需要启用
50-user.conf预设才能让用户配置生效,启用51-local.conf预设才能让全局配置生效。阅读#预设一节了解如何启用这些预设。 -
~/.fonts.conf/、~/.fonts.conf.d/和~/.fontconfig/*.cache-*已过时,以后的包将不再读取这些路径和文件。对应的新路径分别是$XDG_CONFIG_HOME/fontconfig/fonts.conf、$XDG_CONFIG_HOME/fontconfig/conf.d/NN-name.conf和$XDG_CACHE_HOME/fontconfig/*.cache-*。如果使用第二个路径,确保文件命名正确(NN是两位数,如00、10和99)。
Fontconfig 把所有配置集中到一个单独的中心文件(/etc/fonts/fonts.conf)中。Fontconfig 升级时会替换这个文件,因此不应当直接修改它。支持 Fontconfig 的程序查看这个文件以获取可用的字体及如何渲染之;重启这类程序即可载入新的配置。该文件是全局配置(/etc/fonts/local.conf)、预设配置(/etc/fonts/conf.d/)、用户配置($XDG_CONFIG_HOME/fontconfig/fonts.conf)的组合。使用 fc-cache 命令重建 Fontconfig 的配置,但只有新运行的程序会使用新的配置。
Fontconfig 配置文件使用 XML 格式,其需要的头部如下:
<?xml version="1.0"?> <!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd"> <fontconfig> <!-- settings go here --> </fontconfig>
文中的配置示例省略了这些标签。
预设存放在 /usr/share/fontconfig/conf.avail。可以通过创建符号链接到此处来启用,无论是单用户配置还是全局配置。这些预设会覆盖各自配置文件中的对应设置。
例如,以下命令启用全局次像素 RGB 渲染:
# ln -s /usr/share/fontconfig/conf.avail/10-sub-pixel-rgb.conf /etc/fonts/conf.d/
以下命令启用用户级次像素 RGB 渲染:
$ mkdir $XDG_CONFIG_HOME/fontconfig/conf.d $ ln -s /usr/share/fontconfig/conf.avail/10-sub-pixel-rgb.conf $XDG_CONFIG_HOME/fontconfig/conf.d
字体光栅化将字体从向量数据(比如一个TrueType字体)转换为光栅或者位图数据。由于混叠现象,转换后的字体可能会出现锯齿状边缘。抗锯齿技术可以使边缘看起来更平滑。
Fontconfig默认启用抗锯齿,如要禁用:
<match target="font">
<edit name="antialias" mode="assign">
<bool>false</bool>
</edit>
</match>
字体微调使用数学指令来调整轮廓字体的显示,使其与光栅化网格(如显示器上的像素网格)对齐。它的预期效果是使字体看起来更清晰,从而使它们更容易阅读。当显示器拥有 300 左右的 DPI 时,字体即使不经微调也能正确排列。
TrueType 字体的微调指令由 FreeType 的解释器使用 BCI 微调渲染。通常来说,微调指令完备的字体使用 BCI 微调效果很好。
微调是默认启用的,如要禁用:
<match target="font">
<edit name="hinting" mode="assign">
<bool>false</bool>
</edit>
</match>
/etc/profile.d/freetype2.sh 中修改,通过传递参数 truetype:interpreter-version=NN 设置解释器。NN 对应所选择的版本,传递给脚本中的 FREETYPE_PROPERTIES 变量。一些流行的选项如下:
- 35 - 经典模式,模拟 Windows 98
- 40 - 最小模式(精简版的无穷模式,默认值)
自动微调依自己的算法尝试微调,无视字体内所有的微调指令。以前这是默认选项,因为 TrueType2 字体受专利保护,但现在专利已过期,基本不需要使用它。如果字体的微调指令很少或没有,它的效果会更好,否则效果是不如 BCI 的。常见字体都有完备的微调指令,因此自动微调用处不大,现在是默认关闭的。如要启用:
<match target="font">
<edit name="autohint" mode="assign">
<bool>true</bool>
</edit>
</match>
微调风格是指对字体进行调整显示、使其与光栅化网格对齐的调整量。支持的值有 hintnone、hintslight、hintmedium 和 hintfull,微调程度依次加深,即字形变得更扭曲、更清晰——hintslight 会使字体更模糊,无法与网格对齐,但在保留字体形状方面会更好(参见 [2]。),而 hintfull 会使字体更清晰,能很好地与像素网格对齐,但会让字体严重变形。对于非 CFF(.otf)字体,hintslight 设置会在竖直方向上隐式使用自动微调,以支持这类字体的原生字体信息。
默认选项是 hintslight,如要更改:
<match target="font">
<edit name="hintstyle" mode="assign">
<const>hintnone</const>
</edit>
</match>
Fontconfig 需要知道你的次像素排布才能正确显示字体。使用 次像素排布显示器测试(The Lagom LCD 显示器测试页面的一部分)来找出你的次像素排列。
次像素几何通过 rgba 属性配置,可以是:
-
rgb— 红、绿、蓝 — 最常见,大多数现代显示器使用 bgr-
vrgb— 纵向 vbgr-
none— 无次像素渲染
<match target="font">
<edit name="rgba" mode="assign">
<const>rgb</const>
</edit>
</match>
不支持 "Pentile" 和 "RGBY" 等不常见的次像素排布,这些排布偶尔出现在电视、OLED 和移动屏幕上。对于这些设备,最好放弃次像素渲染,使用 none 选项依赖灰度。
次像素渲染(英文维基百科页面)通过单独控制一个像素的三个分色,在一个方向上获得三倍分辨率,以使得字体看看起来更锐利。在 Windows 上,这项技术叫做 zhwp:ClearType。
FreeType2 提供两种次像素渲染方式(FT_CONFIG_OPTION_SUBPIXEL_RENDERING),Harmony 和 ClearType [3]。从 FreeType 2.10.3 起,Arch 默认启用 ClearType 次像素渲染 [4]。
启用 ClearType 次像素渲染时建议使用 LCD 滤镜。Harmony 次像素渲染不需要设置 LCD 滤镜,在默认 LCD 几何下,它等同于 ClearType 使用 lcdlight 滤镜 [5]。参见下一节了解如何启用 LCD 滤镜及其好处。
LCD 滤镜是用来减轻 ClearType 次像素渲染的色边现象的。这是 FreeType 2 API 文档对其的描述,其中 FT_LcdFilter 一节解释了各个选项。这个网页展示了各个 LCD 滤镜的测试效果。
大多数用户可使用 lcddefault。其他选项包括:适合太粗或模糊的字体使用的滤镜 lcdlight、原始的 Cairo 滤镜 lcdlegacy 、完全关闭 LCD 滤镜的选项 lcdnone。
<match target="font">
<edit name="lcdfilter" mode="assign">
<const>lcddefault</const>
</edit>
</match>
如果对内置的 LCD 过滤器不满意,可以通过构建一个自定义的 freetype2 软件包并修改硬编码的过滤器的方式,来非常具体地调整字体的渲染。Arch 构建系统可用于从源代码构建和安装软件包。
查看 freetype2包 的 PKGBUILD 并下载/解压构建文件。Arch 构建系统#通过 Git 获取 PKGBUILD 源码列出了一些方法。
编辑文件 src/freetype-VERSION/include/freetype/config/ftoption.h 并取消对 FT_CONFIG_OPTION_SUBPIXEL_RENDERING 宏的注释,启用 ClearType 次像素渲染。
然后,编辑文件 src/freetype-VERSION/src/base/ftlcdfil.c 并查找常量 default_weights 的定义:
static const FT_LcdFiveTapFilter default_weights =
{ 0x10, 0x40, 0x70, 0x40, 0x10 };
这个常量定义了一个应用于渲染的字形的低通滤波器。根据需要对其进行修改。(参考 freetype 邮件列表的讨论)
最后,保存文件,构建并安装自定义软件包:
$ makepkg --noextract # pacman --remove --nodeps freetype2 # pacman --upgrade freetype2-VERSION-ARCH.pkg.tar.zstd
重启 X。现在,lcddefault 过滤器应该会以不同方式渲染字体。
一些字体也许在 BCI 自动微调下外观不佳。可以为这些字体禁用微调:
...
<match target="font">
<test name="family" qual="any">
<string>My Font</string>
</test>
<edit name="hinting" mode="assign">
<bool>false</bool>
</edit>
</match>
...
设置默认或后备字体的一个可靠方法是添加一个 XML 片段来进行匹配测试。例如,通过设置 "binding" 属性,下面的设置将使 Georgia 回退到 Gentium。
... <match target="pattern"> <test qual="any" name="family" compare="eq"><string>Georgia</string></test> <edit name="family" mode="assign" binding="same"><string>Gentium Book Plus</string></edit> </match> ...
在上面的例子中,"compare" 属性可以是 "eq"(即完全等于 Georgia)、"contains"(例如,匹配 Georgia 或 Georgia Pro),或其他值。参见 fonts-conf(5)。
另一种方法是使用 <alias> 来设置“首选”字体。<family> 元素指定的字体在匹配到实际字体前,会被修改为 <prefer> 字体列表中的一个字体,顺序由上至下。下面的例子使 Helvetica 回退到 Bitstream Vera Sans:
...
<alias>
<family>Helvetica</family>
<prefer>
<family>Bitstream Vera Sans</family>
</prefer>
</alias>
...
<alias> 也可以用来指定当缺少某些字形时使用的后备字体。例如,一个用户将 Noto Sans 设置为默认的无衬线字体后,安装了 Helvetica Neue,想用它书写拉丁文字。由于很多版本的 Helvetica Neue 并不包括希腊字符,这位用户希望使用 FreeSans 来书写希腊文字,因为它与 Helvetica 很像。但事实上,希腊文字将会回退到用户设置的默认字体 Noto Sans,而使用下面的方法则可以实现:
...
<alias>
<family>Helvetica Neue LT Pro</family>
<prefer>
<family>Helvetica Neue LT Pro</family>
<family>FreeSans</family>
</prefer>
</alias>
...
如果用户只是想在使用的字体缺少相应字形时,回退到默认字体,则不需要上述设置。
位图字体有时会作为缺失字体的后备字体,可能导致文本渲染为像素化或过大。使用 70-no-bitmaps-except-emoji.conf #预设来禁用此行为。
要禁用所有字体的嵌入式位图:
...
<match target="font">
<edit name="embeddedbitmap" mode="assign">
<bool>false</bool>
</edit>
</match>
...
如果要禁用所有字体的嵌入式位图,仍可以为特定字体启用它们,以防该字体在没有嵌入式位图时无法正常工作。例如,对于 Noto Color Emoji:
{{bc|<nowiki>
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd">
<fontconfig>
<match target="font">
<edit name="embeddedbitmap" mode="assign">
<bool>false</bool>
</edit>
</match>
<match target="font">
<test name="family" qual="any">
<string>Noto Color Emoji</string>
</test>
<edit name="embeddedbitmap">
<bool>true</bool>
</edit>
</match>
</fontconfig>
要禁用位图字体的缩放(这通常会使它们模糊),删除 /etc/fonts/conf.d/10-scale-bitmap-fonts.conf。
注意这可能会破坏 Segoe UI Emoji 等表情符号字体的缩放,使它们变得巨大。
要重新启用位图字体的缩放,重新创建符号链接:
# ln -s /usr/share/fontconfig/conf.avail/10-scale-bitmap-fonts.conf /etc/fonts/conf.d/
Fontconfig 按数字顺序处理 /etc/fonts/conf.d 中的文件。因此,01-aaa.conf 和 02-bbb.conf 的规则将与单个 01-aaabbb.conf 文件具有相同的效果——首先包含 01-aaa 的规则,然后是 02-bbb 的规则。
通常来说,这意味着前缀较小文件将具有较高的优先级。但是,Fontconfig 的语法很灵活,允许新规则优先于现有规则。因此,建议#查看当前设置来测试规则相互作用的结果。
$XDG_CONFIG_HOME/fontconfig/fonts.conf 和目录 $XDG_CONFIG_HOME/fontconfig/conf.d 中定义的用户规则是通过文件 /etc/fonts/conf.d/50-user.conf 载入的,并且通常优先于以较大数字开头的文件中定义的规则。要查看当前生效的设置,可使用 fc-match --verbose。例如:
$ fc-match --verbose Sans
family: "DejaVu Sans"(s) hintstyle: 3(i)(s) hinting: True(s) ...
可在 font-config(5) 中查询数字的意义。例如,hintstyle: 3 代表 hintfull。
某些应用程序如 URxvt 会忽略 Fontconfig 设置。你可以通过使用 ~/.Xresources 来解决这个问题,但它不如 Fontconfig 灵活。示例(选项说明见 #Fontconfig 配置):
~/.Xresources
Xft.autohint: 0 Xft.lcdfilter: lcddefault Xft.hintstyle: hintslight Xft.hinting: 1 Xft.antialias: 1 Xft.rgba: rgb
确保 X 启动时使用 xrdb -q 正确加载这些设置(更多信息请参阅 X 资源)。
系统 DPI 设置与显示器的硬件 DPI 不匹配会导致字体显示模糊不清;关于处理高 DPI 或混合 DPI 显示器的说明,请参见HiDPI。
一些矢量字体内嵌有位图版本,这些位图字体主要用于在较小的尺寸下渲染。在这种情况下,使用公制兼容字体作为替代可以改善渲染效果。
你也可以通过禁用字体的嵌入式位图来强制在所有尺寸下使用矢量字体,但会牺牲一些渲染质量。
一些应用程序或桌面环境可能会覆盖默认的 Fontconfig 微调和抗锯齿设置。这种情况可能发生在 GNOME 上,例如,当你使用 vlc包 或 smplayer包 等 Qt 应用程序时。在这种情况下,请使用该应用程序特定的配置程序。对于 GNOME,请尝试使用 gnome-tweaks包。
在 GNOME 下,有时会发生这样的情况:即使在 GNOME 设置中将微调设置为"无",Firefox 之类的应用也会使用"完全"微调设置渲染字体,导致字体变得宽而锐利。在这种情况下,你必须在你的 fonts.conf 文件中添加微调设置:
<?xml version="1.0"?> <!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd"> <fontconfig> <match target="font"> <edit mode="assign" name="hinting"> <bool>false</bool> </edit> </match> </fontconfig>
在上面的例子中,微调级别被设置为了 grayscale。
在某些桌面环境(尤其是 GNOME 和 Plasma 之外的)中,一些 GTK 应用程序无法正确读取字体配置。为了解决这个问题,请安装 xsettingsd包 或 xsettingsd-gitAUR 并在每次系统启动时运行它。更多信息请参见 Xsettingsd 和xsettingsd wiki。
对于此问题,可以使用以下配置:
~/.xsettingsd
Xft/Hinting 1 Xft/HintStyle "hintslight" Xft/Antialias 1 Xft/RGBA "rgb"
如果这在一些应用程序中依然不起作用,可以安装 xorg-xrdb包 并使用以下配置:
~/.Xresources
Xft.hinting: 1 Xft.hintstyle: hintslight Xft.antialias: 1 Xft.rgba: rgb
然后在每次系统启动时执行脚本 xrdb -merge ~/.Xresources 来应用这些设置。参见 X resources 和 #不支持 Fontconfig 的程序。
此外,使用 GTK4 和 libadwaita 的程序会忽略字体微调设置。可以创建或修改以下配置来修正:
~/.config/gtk-4.0/settings.ini
[Settings] gtk-hint-font-metrics=true
如果执行如下命令
fc-match helvetica
返回
helvR12-ISO8859-1.pcf.gz: "Helvetica" "Regular"
那么由 xorg-fonts-75dpi包 提供的位图字体就有可能被嵌入到各种应用程序的"打印到文件"或"导出"功能所生成的 PDF 文件中。该位图字体可能是在安装整个 xorg包组 包组的时候安装的(通常不推荐这样做)。要解决这个问题,可以卸载该软件包,并安装gsfonts包(Type 1)或tex-gyre-fonts包(OpenType)字体,以获得 Helvetica(以及其他 PostScript/PDF 基本字体)的自由替代品。
一些用户报告说,在将 freetype2包 升级到 2.7.1 版本后,各个位图字体的名称发生了变化,导致终端模拟器和其他一些程序(如 dwm 或 dmenu)的字体混乱,因为它们会回退到另一种不同的字体进行显示。该问题是由 PCF 字体族格式的改变造成的,这在他们的发布说明[6]中有所描述。从旧格式过渡到新格式的用户可以通过创建字体别名来解决这个问题,就像[7]中描述的解决方案一样;该方案同时在下面给出:
假设我们想为terminus-font包创建一个别名,在之前提到的 freetype2包 更新中,它从{ {ic|Terminus}} 被改名为 xos4 Terminus,那么在 /etc/fonts/conf.d/ 中创建一个文件,用于设置字体别名:
/etc/fonts/conf.d/99-TerminusPCFFont.conf
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd">
<fontconfig>
<alias>
<family>Terminus</family>
<prefer><family>xos4 Terminus</family></prefer>
<default><family>fixed</family></default>
</alias>
</fontconfig>
现在,一切都应该能够像之前一样正常工作,但务必重新加载 .Xresources 或重启显示服务器,以便使受影响的程序能够使用字体别名。
自 Pango 1.44 起,在以某些字号使用 DejaVu Sans Mono 字体时,下划线会消失。一种解决办法是使用 Liberation Mono 作为等宽字体,见#设置默认或后备字体。
freetype2-demos包 提供用于调试 FreeType 字体配置的工具。ftview 是它的一个 GUI,你可以在其中实时预览字体的渲染设置。比如:
$ ftview -e unic -d 1024x768x24 -r 96 10 /usr/share/fonts/noto/NotoSans-Regular.ttf
某些应用程序(如 Chromium/Electron)没有正确应用伽马校正,有些在特定场景(灰度)下禁用了伽马校正,这会导致深色背景上的小文字模糊不清,在 <=1080p 的屏幕上出现难以阅读的文字。这是 Chromium/Electron 的一个长期存在的问题,一个解决方法是使用 FREETYPE_PROPERTIES="cff:no-stem-darkening=0 autofitter:no-stem-darkening=0" 环境变量来启用 stem darkerning。
你可以使用 font-config-info-gitAUR 收集有效的字体配置信息。它会从 多个 GTK 源、X resources、XSETTINGS 协议和 fontconfig包 查询信息。
- Xft 教程 by Keith Packard
- X11 中的字体
- FreeType 2
- FreeType 2 API 参考:控制 FreeType 模块
- Gentoo 字体渲染讨论
- 关于轻微提示