字体配置
Fontconfig 是一个用于向应用程序提供可用的字体列表,以及字体渲染配置的库。FreeType 库依此配置渲染字体。Arch 上的 freetype2 字体渲染库启用了字节码解释器(bytecode interpreter,BCI)以优化字体渲染,尤其是在 LCD 屏幕上。参见#预置和字体配置/示例。
尽管大多数类 Unix 系统现在使用 Fontconfig,但部分应用程序仍在使用原始的 X Logical Font Description 作为字体选择与显示方法。
字体路径[编辑 | 编辑源代码]
为了使字体能够被应用程序发现,必须对它们进行编目,以便快速访问。
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 /想要/添加的/字体/路径 # 将一个路径添加到 Xorg 的已知字体路径列表中 xset -fp /想要/移除的/字体/路径 # 将一个路径从 Xorg 的已知字体路径列表中移除
Fontconfig 配置[编辑 | 编辑源代码]
fonts-conf(5) 中有 Fontconfig 的配置文档。
用户配置文件位于 $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 的配置,但只有新运行的程序会使用新的配置。
某些桌面环境(如 GNOME 和 KDE)的字体设置界面会自动创建或覆盖用户的字体配置文件。对于此类桌面环境,最好让设置界面中的字体设置和配置文件相符合。同时请确定桌面的区域设置或 locale 受配置好的字体支持,否则字体配置可能被覆盖。
Fontconfig 配置文件使用 XML 格式,其需要的头部如下:
<?xml version="1.0"?> <!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd"> <fontconfig> <!-- settings go here --> </fontconfig>
文中的配置示例省略了这些标签。
预设[编辑 | 编辑源代码]
预设存放在 /usr/share/fontconfig/conf.avail
。可以通过创建符号链接到此处来启用,无论是单用户配置还是全局配置。这些预设会覆盖各自配置文件中的对应设置。
例如,以下命令启用全局次像素 RGB 渲染:
$ cd /etc/fonts/conf.d # ln -s /usr/share/fontconfig/conf.avail/10-sub-pixel-rgb.conf
以下命令启用用户级次像素 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
抗锯齿(Anti aliasing)[编辑 | 编辑源代码]
字体光栅化将字体从向量数据(比如一个TrueType字体)转换为光栅或者位图数据。由于混叠现象,转换后的字体可能会出现锯齿状边缘。抗锯齿技术可以使边缘看起来更平滑。
Fontconfig默认启用抗锯齿,如要禁用:
<match target="font"> <edit name="antialias" mode="assign"> <bool>false</bool> </edit> </match>
字体微调(hinting)[编辑 | 编辑源代码]
字体微调使用数学指令来调整轮廓字体的显示,使其与光栅化网格(如显示器上的像素网格)对齐。它的预期效果是使字体看起来更清晰,从而使它们更容易阅读。当显示器拥有 300 左右的 DPI 时,字体即使不经微调也能正确排列。
字节码解释器(BCI)[编辑 | 编辑源代码]
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
- 36 - 经典 Windows ClearType 模式,Windows XP 以下的 Windows 使用
- 38 - “无穷”模式,高定制性,被认为性能较低,已不再开发
- 40 - 最小模式(精简版的无穷模式,默认值)
自动微调(autohint)[编辑 | 编辑源代码]
自动微调依自己的算法尝试微调,无视字体内所有的微调指令。以前这是默认选项,因为 TrueType2 字体受专利保护,但现在专利已过期,基本不需要使用它。如果字体的微调指令很少或没有,它的效果会更好,否则效果是不如 BCI 的。常见字体都有完备的微调指令,因此自动微调用处不大,现在是默认关闭的。如要启用:
<match target="font"> <edit name="autohint" mode="assign"> <bool>true</bool> </edit> </match>
微调风格(hint style)[编辑 | 编辑源代码]
微调风格是指对字体进行调整显示、使其与光栅化网格对齐的调整量。支持的值有 hintnone
、hintslight
、hintmedium
和 hintfull
,微调程度依次加深,即字形变得更扭曲、更清晰——hintslight
会使字体更模糊,无法与网格对齐,但在保留字体形状方面会更好(参见 [2]。),而 hintfull
会使字体更清晰,能很好地与像素网格对齐,但会让字体严重变形。对于非 CFF(.otf)字体,hintslight
设置会在竖直方向上隐式使用自动微调,以支持这类字体的原生字体信息。
默认选项是 hintslight
,如要更改:
<match target="font"> <edit name="hintstyle" mode="assign"> <const>hintnone</const> </edit> </match>
像素排布(RGBA)[编辑 | 编辑源代码]
大多数显示器使用 RGB 方式排列像素,但也有例外。Fontconfig 需要知道显示器类型才能正确显示字体。这个选项的值有四个:RGB、BGR、V-RGB(纵向 RGB 排列)或 V-BGR。如果你的显示器旋转使用,可修改这个值。如果找不到相应的资料,这个网站可协助测试。
<match target="font"> <edit name="rgba" mode="assign"> <const>rgb</const> </edit> </match>
次像素渲染[编辑 | 编辑源代码]
次像素渲染(英文维基百科页面)通过单独控制一个像素的三个分色,在一个方向上获得三倍分辨率,以使得字体看看起来更锐利。在 Windows 上,这项技术叫做 zhwp:ClearType。
FreeType2 提供两种次像素渲染方式(FT_CONFIG_OPTION_SUBPIXEL_RENDERING
),Harmony 和 ClearType [3]。
若使用 ClearType 次像素渲染,建议启用 LCD 滤镜(见下)。使用 Harmony 次像素渲染则不需要。
从 FreeType 2.10.3 起,Arch 默认启用 ClearType 次像素渲染。[4]
lcdlight
LCD 滤镜以获得 FreeType 2.10.3 以前的 Harmony 次像素渲染行为(而不是 ClearType)。LCD 滤镜(LCD filter)[编辑 | 编辑源代码]
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 滤镜选项[编辑 | 编辑源代码]
如果对内置的 LCD 过滤器不满意,可以通过构建一个自定义的 freetype2 软件包并修改硬编码的过滤器的方式,来非常具体地调整字体的渲染。Arch 构建系统可用于从源代码构建和安装软件包。
查看 freetype2包 的 PKGBUILD 并下载/解压构建文件。Arch 构建系统#通过 Git 获取 PKGBUILD 源码列出了一些方法。假设使用 asp:
$ asp checkout freetype2 $ cd freetype2/trunk $ makepkg --nobuild
编辑文件 src/freetype-VERSION/include/freetype/config/ftoption.h
并取消对 FT_CONFIG_OPTION_SUBPIXEL_RENDERING
宏的注释,启用 ClearType 次像素渲染。
然后,编辑文件 src/freetype-VERSION/src/base/ftlcdfil.c
并查找常量 default_filter[5]
的定义:
static const FT_Byte default_filter[5] = { 0x10, 0x40, 0x70, 0x40, 0x10 };
这个常量定义了一个应用于渲染的字形的低通滤波器。根据需要对其进行修改。(参考 freetype 邮件列表的讨论)
最后,保存文件,构建并安装自定义软件包:
$ makepkg --noextract # pacman --remove --nodeps freetype2 # pacman --upgrade freetype2-VERSION-ARCH.pkg.tar.xz
重启系统或窗口系统。现在,lcddefault 过滤器应该会以不同方式渲染字体。
某些字体/字形的单独设置[编辑 | 编辑源代码]
自动微调使用复杂而巧妙的方法进行字体渲染,但它常常使粗体字变得太宽。幸运的是,可以关闭粗体字的自动微调,而对其他字形则保留它:
... <match target="font"> <test name="weight" compare="more"> <const>medium</const> </test> <edit name="autohint" mode="assign"> <bool>false</bool> </edit> </match> ...
一些字体也许在 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),或其他值。参见 [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> ...
如果用户只是想在使用的字体缺少相应字形时,回退到默认字体,则不需要上述设置。
字体白名单/黑名单[编辑 | 编辑源代码]
禁用位图字体[编辑 | 编辑源代码]
禁用位图字体缩放[编辑 | 编辑源代码]
自动生成粗体和斜体[编辑 | 编辑源代码]
规则优先级[编辑 | 编辑源代码]
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。
不支持 Fontconfig 的程序[编辑 | 编辑源代码]
有些应用程序,如 Telegram,会忽略 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 resources)。
疑难问题[编辑 | 编辑源代码]
字体模糊[编辑 | 编辑源代码]
系统 DPI 设置与显示器的硬件 DPI 不匹配会导致字体显示模糊不清;关于处理高 DPI 或混合 DPI 显示器的说明,请参见HiDPI。
一些字体在小尺寸下显示不正确(如 Calibri, Cambria, Monaco 等)[编辑 | 编辑源代码]
一些矢量字体内嵌有位图版本,这些位图字体主要用于在较小的尺寸下渲染。在这种情况下,使用公制兼容字体作为替代可以改善渲染效果。
你也可以通过禁用字体的嵌入式位图来强制在所有尺寸下使用矢量字体,但会牺牲一些渲染质量。
应用程序无视 Fontconfig 的微调或抗锯齿设置[编辑 | 编辑源代码]
一些应用程序或桌面环境可能会覆盖默认的 Fontconfig 微调和抗锯齿设置。这种情况可能发生在 GNOME 上,例如,当你使用 vlc包 或 smplayer包 等 Qt 应用程序时。在这种情况下,请使用该应用程序特定的配置程序。对于 GNOME,请尝试使用 gnome-tweaks包。
应用程序无视 GNOME 的微调设置[编辑 | 编辑源代码]
在 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>
在上面的例子中,微调级别被设置为了 "greyscale"。
GTK 应用程序的字体微调不正确[编辑 | 编辑源代码]
在某些桌面环境(尤其是 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
生成的 PDF 文件中的 Helvetica 字体模糊[编辑 | 编辑源代码]
如果执行如下命令
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 基本字体)的自由替代品。
FreeType 破坏了位图字体[编辑 | 编辑源代码]
一些用户报告说,在将 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
或重启显示服务器,以便使受影响的程序能够使用字体别名。
DejaVu 的等宽字体不能显示下划线[编辑 | 编辑源代码]
自 Pango 1.44 起,在以某些字号使用 DejaVu Sans Mono 字体时,下划线会消失。一种解决办法是使用 Liberation Mono 作为等宽字体,见#设置默认或后备字体。
调试 FreeType 字体[编辑 | 编辑源代码]
freetype2-demos包 提供用于调试 FreeType 字体配置的工具。ftview
是它的一个 GUI,你可以在其中实时预览字体的渲染设置。比如:
$ ftview -e unic -d 1024x768x24 -r 96 10 /usr/share/fonts/noto/NotoSans-Regular.ttf
网页将数字和空格显示得很宽[编辑 | 编辑源代码]
这是因为网页优先使用了 emoji 字体。一种情况是,用户在字体配置文件中指定了优先使用 emoji 字体。这种情况只需要删除该配置即可。一种类似的情况是用户在字体配置文件中替换了一部分符号字体(例如使用了noto-color-emoji-fontconfigAUR),这种情况也是删除相关配置(使用该AUR包的可以换用noto-color-emoji-fontconfig-no-bindingAUR)。
另一种情况是,网页做了奇怪的假设,比如「假设有 Apple Color Emoji 的人一定在使用 macOS」,从而优先使用 macOS 才识别的系统字体、然后是 emoji 字体。绕过的办法是,让 fontconfig 假装系统上有这类字体,比如将如下内容保存为 ~/.config/fontconfig/web-ui-fonts.conf
,并在 ~/.config/fontconfig/fonts.conf
开头 <include prefix="xdg">fontconfig/web-ui-fonts.conf</include>
。
<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
<!--
https://caniuse.com/extended-system-fonts
GitHub uses this for code blocks.
-->
<match target="pattern">
<test qual="any" name="family">
<string>ui-monospace</string>
</test>
<edit name="family" mode="assign" binding="same">
<string>monospace</string>
</edit>
</match>
<match target="pattern">
<test qual="any" name="family">
<string>ui-sans-serif</string>
</test>
<edit name="family" mode="assign" binding="same">
<string>sans-serif</string>
</edit>
</match>
<match target="pattern">
<test qual="any" name="family">
<string>ui-serif</string>
</test>
<edit name="family" mode="assign" binding="same">
<string>serif</string>
</edit>
</match>
<match target="pattern">
<test qual="any" name="family">
<string>-apple-system</string>
</test>
<edit name="family" mode="assign" binding="same">
<string>sans-serif</string>
</edit>
</match>
</fontconfig>