虽然微软的字体渲染经常被某些果粉嘲笑,但是平心而论,微软的 ClearType 技术和相关字体仍然是追求清晰的广大低分辨率屏幕桌面使用者的最佳选择。大名鼎鼎的 Infinality 补丁大家可能都听说过,其主要开发目的之一就是获得类似 ClearType 的效果,而不是为了追求什么几乎毫无 hinting,完全糊成一团的“OS X 近视眼”效果(颇为吊诡和具有讽刺意味 (Ironically) 的是,三个 hinting 专利其实都是苹果的,详见 freetype.org/patents.html)。但是在中文 Linux 世界所能 google 到的似乎全都是误解和过时的信息。所以在进入正题之前,首先介绍一下背景以正本清源。简言之,自由软件作者 Infinality 主要做了如下几件很不微小的工作:
1,为 freetype 开发了类似于 ClearType 的 subpixel hinting 技术。之前的 freetype 只有 subpixel rendering,而 hinting 本身是完全基于“全像素”的。这种不匹配会导致渲染出来的字体过细,字体变形过大(比如 Arial 的“D” 就不是半圆的而近似于旋转了 90° 的等腰梯形),或者是内置 hinting 完全无效(比如 Calibri 等 ClearType Collection 系列字体)。
2, 为 freetype 添加了很多在运行时 (runtime) 调整参数的能力。比如 lcdfilter 的参数,原版的 freetype 似乎是 hard-coded 的,没法任意修改。
3, 为了配合 freetype 的补丁, 增加了相应的 fontconfig 配置文件,修改了 cairo 等高层的库。
其中 1 是最主要的,而且已经在 2.4.x 的某个版本进入 freetype2 主干,就是 TT_CONFIG_OPTION_SUBPIXEL_HINTING 这个开关。Infinality 亲自添加了 2012-06-18 这一天的更新日志。在这之后 Infinality 本人就逐渐淡出了 Infinality 补丁的开发(因为最重要的部分已经被 FreeType 接纳并且他太忙了,他自己的解释在这里: infinality.net/forum/viewtopic.php?f=2&t=350 )。
之后的主要工作就是继续为不同字体优化 Infinality 补丁的参数。 Infinality 本人淡出之后,ArchLinux 的打包者 bohoomil 接手了后续的维护工作。大概是为了与最早的没有进入 FreeType 主干之前的 Infinality 补丁区分,bohoomil 维护的包叫做 freetype2-infinality-ultimate,也就是题目里提到的 “终极进化”版。他不仅维护着 freetype2 相关补丁,还在 ArchLinux 上收集了一大堆精选过的字体。这就是“Infinality bundle & Fonts” 项目,主页在 bohoomil.com。显然,ArchLinux 的用户是这个项目的“一等公民”。不过 OpenSUSE 有 OBS,虽然不能打包字体,也有半官方的 INFINALITY-ULTIMATE 补丁源:https://build.opensuse.org/project/show/home:nick31:INFINALITY-ULTIMATE。维护者 nick31 从 bohoomil 接手之初就向 bohoomil 承包了 INFINALITY-ULTIMATE 的打包(仍然看这里 infinality.net/forum/viewtopic.php?f=2&t=350)。更新的速度大概仅次于 ArchLinux 的版本。
以上几段历史回顾的目的就是,大家不要再乱找 Infinality 补丁包了,现在已经是 Infinality-Ultimate 的时代了。当然,我发这个帖子的目的其实是想强调,subpixel-hinting 也并不完美。对于本来就采用了 subpixel-hinting 或者“ClearType”技术的来说——也就是微软的 Segoe UI, ClearType Collection 那些,当然是必须采用 subpixel hinting 才能得到较好的渲染效果 (bugs.archlinux.org/task/35274)。对于微软较早发布的 Core fonts for the Web 和 Linux 下常用的 DejaVu Sans 之类的字体,subpixel hinting 也会有一定改善,至少不会造成渲染错误(很显然 Infinality 对这些字体比较熟,优化算法的时候也是以这些字体为目标的)。但是(终于有“但是”了),对于微软雅黑,subpixel hinting 反而会造成严重的渲染错误,看起来好像是笔画 snap 方向错误或者用力过猛,尤其是设置了 “hintfull” 之后,比如:
注意常规体的“据”,“最”,“嵌”字,12px-14px 几个大小的横的 hinting 明显不对。
如何解决呢?目前的 Infinality-Ultimate 似乎并没有提供在运行时对某些字体禁用 subpixel hinting 的方案。幸好我发现 freetype 有内置的 “tricky fonts" 选项,虽然是 hard-coded 的,并且其原意是在前 Infinality 时代强制开启全像素(不是次像素!)的灰度 hinting,但是歪打正着的副作用就是 subpixel hinting 被(看起来部分)绕过了。硬编码无非就是需要打个补丁而已,Infinality-Ultimate 的补丁都打了还差这一个吗?所以我就在 OBS 编译了一个针对微软雅黑优化的 libfreetype6 的包,(openSUSE Leap 的一键安装 software.opensuse.org/ymp/home:stecue:INFINALITY-ULTIMATE_YaHei/openSUSE_Leap_42.1/libfreetype6.ymp?base=openSUSE%3ALeap%3A42.1&query=libfreetype6,项目主页 build.opensuse.org/package/show?project=home%3Astecue%3AINFINALITY-ULTIMATE_YaHei&package=freetype2-iu。目前仅包含 freetype2-ui,请与 nick31 提供的 fontconfig-iu 和 cairo-iu 配合使用)。效果如下:
现在常规体的“据”,“最”,“嵌”等字的横的位置就对了。
我目前只发现微软雅黑需要这么特殊处理。补丁的具体内容请查看项目主页(https://build.opensuse.org/package/view_file/home:stecue:INFINALITY-ULTIMATE_YaHei/freetype2-iu/bypass-subpixel-hinting-YaHei.patch?expand=1)。大家发现有其他字体也要如法炮制的话,请不吝通知我哈。另外,有可能安装了补丁包还需要调整设定,请继续关注本系列的下一个帖子,主讲 INFINALITY 参数的设定: forum.suse.org.cn/viewtopic.php?f=38&t=4497 。