Fedora 25 字体渲染引擎 freetype 及字体配置工具 fontconfig 采用的是未经优化的编译及设置,字体渲染效果比较差。而某些 Linux 发行版的桌面字体渲染看起来很好,甚至能够接近苹果 mac OS 系统的效果,实际上是对 freetype 字体渲染引擎进行了修改的缘故。为此,我们可以通过安装经过修改的 freetype 及 fontconfig 软件包来实现基于 Infinality 的字体渲染效果。
Infinality 是一个致力于改善 Fedora 等主流 Linux 操作系统字体渲染效果的解决方案,包括重新优化编译的 freetype 库,fontconfig 配置包等。原 Infinality 网站已经很久没有再更新了,现在又有新的开发人员在 github 上继续进行 Infinality 的开发,并为 Fedora 23/24 提供了打包好的 repo 软件源。新的 Infinality 官网为 https://danielrenninghoff.com (目前2017.4.19,FZUG 已添加了最新版本的 freetype, fontconfig 软件包)。
Infinality 安装配置方法
- 安装基于 Infinality 优化的
freetype
字体渲染引擎库和fontconfig
字体配置包
$ dnf install --allowerasing cairo-infinality fontconfig-infinality freetype-infinality
注意,通过 --allowerasing
参数可以使 dnf 卸载有冲突的老库再安装新的 Infinality 库。
- 编辑 Infinality 配置文件
安装完毕后,可在 /usr/share/doc 目录下找到两个目录:freetype-infinality
和fontconfig-infinality
。这两个目录中都有 README 等自述文件比较详细地介绍了 Infinality 优化编译字体渲染引擎库的相关配置方法。根据其文档说明,我们需要执行以下操作:
$ cp /usr/share/doc/freetype-infinality/infinality-settings-generic /etc/profile.d/infinality-settings-generic.sh $ cp /usr/share/doc/freetype-infinality/infinality-settings.sh /etc/X11/xinit/xinitrc.d/ $ chmod a+x /etc/X11/xinit/xinitrc.d/infinality-settings.sh
上述配置是关键的字体渲染效果配置文件,具体的配置说明可以参考这两个文件的描述。
一般而言,比较合适的配置是
将 /etc/profile.d/infinality-settings-generic.sh
文件中的 XFT_SETTINGS
变量中的 Xft.autohint
设置为 0
;
Xft.hinting
设置为 1
;
将 Xft.hintstyle
设置为 hintfull
;
将 USE_STYLE
设置为 INFINALITY
(作者推荐设置);
将 /etc/X11/xinit/xinitrc.d/infinality-settings.sh
文件的 INFINALITY_FT
设置为 ultimate3
(作者推荐)。
这里注意,之所以将 Xft.hintstyle
设置为 hintfull
,是因为 Infinality 优化后的字体渲染引擎内部对 full
级别的微调指令做了更好的优化,特别是搭配 google 官方的 Noto Sans CJK 字体(经过 hinted)能够达到最好效果,比 hintslight
要好很多!这个情况 Infinality 作者也在 /etc/profile.d/infinality-settings-generic.sh
文件注释中解释得比较清楚了。
其他微调
另外要注意,Noto Sans CJK 字体基线高度和 DejaVu Sans 字体不同,如果采用混用方式,即拉丁字母采用 DejaVu,中文采用 Noto,会导致文字行间隔太小,影响美观。所以最好的办法是,所有字符全都用 Noto Sans CJK 字体来显示,包括 Mono 等宽字符情况。虽然 Infinality 优化字体渲染软件包安装后会自带一些 fontconfig 配置,但是对于中文字体来说,我们希望 Infinality 提供的 Noto Sans CJK SC 中文字体能够具有最高优先级,
我们可以创建一个名为 65-0-nonlatin-custom.conf
的文本文件,放置于 /etc/fonts/conf.d
目录下,文件内容如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE fontconfig SYSTEM "fonts.dtd"> <fontconfig> <match> <test name="lang" compare="contains"> <string>zh-cn</string> </test> <test name="family"> <string>monospace</string> </test> <edit name="family" mode="prepend"> <string>Noto Sans Mono CJK SC</string> </edit> </match> <match> <test name="lang" compare="contains"> <string>zh-tw</string> </test> <test name="family"> <string>monospace</string> </test> <edit name="family" mode="prepend"> <string>Noto Sans Mono CJK TC</string> </edit> </match> <match> <test name="lang" compare="contains"> <string>jp</string> </test> <test name="family"> <string>monospace</string> </test> <edit name="family" mode="prepend"> <string>Noto Sans Mono CJK JP</string> </edit> </match> <match> <test name="lang" compare="contains"> <string>zh-cn</string> </test> <test name="family"> <string>serif</string> </test> <edit name="family" mode="prepend"> <string>Noto Sans CJK SC</string> </edit> </match> <match> <test name="lang" compare="contains"> <string>zh-tw</string> </test> <test name="family"> <string>serif</string> </test> <edit name="family" mode="prepend"> <string>Noto Sans CJK TC</string> </edit> </match> <match> <test name="lang" compare="contains"> <string>jp</string> </test> <test name="family"> <string>serif</string> </test> <edit name="family" mode="prepend"> <string>Noto Sans CJK JP</string> </edit> </match> <match> <test name="lang" compare="contains"> <string>zh-cn</string> </test> <test name="family"> <string>sans-serif</string> </test> <edit name="family" mode="prepend"> <string>Noto Sans CJK SC</string> </edit> </match> <match> <test name="lang" compare="contains"> <string>zh-tw</string> </test> <test name="family"> <string>sans-serif</string> </test> <edit name="family" mode="prepend"> <string>Noto Sans CJK TC</string> </edit> </match> <match> <test name="lang" compare="contains"> <string>jp</string> </test> <test name="family"> <string>sans-serif</string> </test> <edit name="family" mode="prepend"> <string>Noto Sans CJK JP</string> </edit> </match> </fontconfig>
同时也要注意在 /etc/fonts/conf.d
目录中将其他 65 开头含有 nonlatin 字样的字体配置文件中 Noto Sans CJK 字体或者 Noto Sans Mono CJK 字体优先级排到最高。为了能够使 hint 设置最终有效,还要在 /etc/fonts 目录下创建一个 local.conf 文件(如果有则直接修改),具体内容如下:
<?xml version="1.0"?> <!DOCTYPE fontconfig SYSTEM "fonts.dtd"> <fontconfig> <match target="font"> <edit name="autohint" mode="assign"> <bool>false</bool> </edit> <edit name="hinting" mode="assign"> <bool>true</bool> </edit> <edit name="hintstyle" mode="assign"> <const>hintfull</const> </edit> </match> </fontconfig>
关于 Java 字体
对于 Java 程序而言,在 Linux 环境下其字体渲染总是比系统原生字体渲染效果要差。主要原因在于 Oracle 官方的 Java 内建了一套私有的字体渲染引擎,无法使用系统的 freetype 及 fontconfig 配置,且渲染效果比较差,属于和微软 cleartype 相似的渲染效果。OpenJDK 则采用的是 freetype 字体渲染引擎,但是默认并不读取系统 fontconfig 配置,且字体渲染的设置是固定的,也类似于微软 cleartype 效果,所以也不太理想。最好的办法就是,对 OpenJDK 源代码进行必要的修改,使之能够使用系统 freetype 字体渲染引擎的同时,能够读取当前系统 fontconfig 配置,并以此灵活调整 Java 中 freetype 的字体微调效果。如果自己编译 OpenJDK 的话难度较大,而 Infinality 已经提供了针对 freetype 及 fontconfig 优化编译打包好的 OpenJDK 软件包(目前基于 OpenJDK 8u92 版本代码),因此可通过 dnf 直接从 Infinality 软件源下载安装。(FZUG 未打包)
$ dnf install --allowerasing java-1.8.0-openjdk-infinality java-1.8.0-openjdk-infinality-headless java-1.8.0-openjdk-infinality-devel
其中,前两个软件包是 OpenJDK JRE 的必要软件包,最后一个软件包是 OpenJDK JDK 的必要软件包(对于 Java 开发)。注意,不要安装java-1.8.0-openjdk-infinality-accessibility
软件包,因为这个软件包是 OpenJDK 为 GTK+/GNOME ATK 组件提供的接口,而 ATK 已经被废弃了,如果安装了 java-1.8.0-openjdk-infinality-accessibility
后会导致运行很多大型 Java Swing 程序出现错误(特别是在 Swing 使用 GTK+ 本地主题时)。Infinality 优化过的 OpenJDK 安装后,其具体位置及系统中多个 Java 如何切换当前环境变量的问题,可参考 Linux 下的 alternatives
命令及其使用说明,alternatives
命令是专门用于在 Linux 中为同时安装存在的同名但不同版本的多个软件进行切换使用而设计的,比如系统中同时安装了不同版本的 Java(JDK 或 JRE)就可以使用 alternatives 来进行当前使用版本的切换操作,很方便。
在安装完 OpenJDK 后,仍需要进行基本的 Java 内建字体规则配置,这么做的好处是定义好 Java 内建的 Dialog、DialogInput、Monospace 等逻辑字体与系统真实字体之间的映射关系,以便在 Java Swing 程序使用各种主题的时候,如果采用默认的逻辑字体可以按照我们的要求使用 google noto sans cjk 字体。OpenJDK 仍然采用 JRE 标准的 fontconfig.OS.properties 字体配置文件,其中 OS 为当前操作系统的名字,比如 Fedora、Ubuntu 等。这里给出一个 Fedora 24 下的参考配置,文件名为 fontconfig.Fedora.properties,必须放置在 jre/lib 目录下,注意这里的拉丁字符也采用 Noto Sans CJK 字体显示,避免 DejaVu Sans 混合显示导致行间距过小问题。
这里要注意,Oracle 官方的 JRE 根据优先级规则,可以识别 fontconfig.properties,但 OpenJDK 不能识别,必须是以 fontconfig.OS.properties 这种文件名才行(OS 是当前系统的名字,比如 Fedora、Ubuntu 等)。
在安装了 Infinality 优化过的 Java 后,运行 Java Swing 程序将会发现 Swing 中的字体渲染已经完全与系统原生字体渲染完全一致,且能够跟随系统原生字体渲染调整而变化了。google 的 Noto Sans CJK 字体(官方 hinted 过)在 Infinality 优化过的 OpenJDK 中的显示效果非常好,字体 hint 微调指令起到了很好的作用。