INFINALITY 补丁的“终极”进化:在 Linux 中启用字体微调和次像素渲染的正确姿势(一)

虽然微软的字体渲染经常被某些果粉嘲笑,但是平心而论,微软的 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

2赞

表示根本看不懂.我现在基本追求能够看清楚就好了,所以我会尽量将字号调到 16+.

哪里开始看不懂的哈?论坛的目的就是交流,不妨说说我好去改进。

我最近升级到 Tumbleweed,发现 home:nick31:INFINALITY-ULTIMATE 这个源已经不存在了,而且 github 上 infinality-ultimate 也已经废弃。但是 2.7.1 集成了大部分 infinality 的功能(我还没细看怎么调整),我在 build.opensuse.org/package/show/home:stecue/freetype2 (我的个人 OBS 源)里打开了 subpixel rendering 和 TrueType Interpretor v38 的选项,而且雅黑补丁仍然必须并且适用。大家可以用这个源看看。至于如何在 FreeType 2.7 的时代继续在运行期调整渲染选项,我再研究研究。

哇 反应真快,我也是发现 nick31 源里所有的内容都被清空了,刚想发帖来者问来着…
INFINALITY-ULTIMATE 在我这里有点问题,就是某些页面的字体在不断的进行微调,不知道你有注意到这个显现没?

其实是我为了适配新的 AMD Ryzen 1700,需要 Kernel 4.10+,必须升级到 Tumbleweed,结果 KDE5 必须依赖 FreeType 2.7, 才发现 nick31 源的情况的。用 2.6.3 的 FreeType 会出现“符号无法找到”的错误,无法进入 KDE。

你说的“字体不断微调”,是 chrome/chromium 吗?反正我这里是 chrome/chromium 对同一页面内的字体渲染不一致,感觉似乎是 LCD Filter 没有应用到所有页面内容导致的。从 2.5.5 到 2.7.1 一直存在。打不打 INFINALITY 补丁都一样。

[/attachment]
(注意那几个“是”的渲染效果)

你的图片这个在我的可接受范围之内。我这里使用 INFINALITY-ULTIMATE 补丁 (我试过两个,一个是叫 GNorth 的源。2.63 的,另外一个 nick31 的 tw 源)两个都会在某些页面出现 “字体”在动态的微调的情况,就是在某些页面下,字体先是清晰然后变得稍微模糊,然后再变清晰,这个间隔是 2-3 秒。我打个比方,就好像那种老式的 CRT 显示器,我每隔 2-3 秒的时间在调节显示器的 聚焦 功能一样,一开始字体聚焦良好,但 2-3 秒后字体开始变虚,在隔 2-3 秒又变得清晰… 我用的火狐 51 ,系统是 42.2 ,而且只有部分页面这样子,最明显的是 百度贴吧 首页 往下 “热门动态” 和 “个性动态” 看标题栏最清楚,截图不太好展示,我试着截两张看看:



你看,以上两张图,在鼠标光标处的 “帮” 字,在不断的变化字形,先是图 1 效果,过 2 秒就变成图 2 。这里我要说明的是,不是只有那个字在微调字形,整个标题都在不断微调,只是“帮”字比较显眼,细看整个标题,你会发现图 1 字体边缘有毛边,图 2 要好的多(如果我反应足够快,就能截到一张字体边缘 异常清晰的出来) ,整个过程中我啥都没干,就这么等着就出这个现象…

现在我用的老的 infinality,freetype 被降级了, 而且老的有些字体渲染有些异常。

另外,我想问下, TrueType Interpretor v38 是什么情况,不是说 2.7.0 以上默认开 TrueType Interpretor v40 么?

这种情况我没见过。但我觉得似乎因为页面是动态的,内容其实在不断刷新。可能 FreeType 也采取了“先快速加载简略预览,再加载最终结果”的策略,使得预览和最终结果不一样。每次后台刷新都重复这一过程,就导致显示效果不断变化。或者由于启用了用户脚本,字体实际上也在变化?

TrueType Interpretor v38 就是 Infinality 贡献的解释器。但是我不知道怎么在运行时调整渲染参数,也没见到任何官方文档说可以调整。如果不能在运行时调整,那其实相对 Infinality 的最初补丁就把一个主要部分给缩水掉了…… v40 是 FreeType 的人觉得 v38 渲染太慢,做的一个简化版本。2.7.0 以上默认只编译 v40,而且默认也根本不启用。如果要启用“次像素渲染”和“次像素微调”,都必须在编译期修改源码中的宏定义开关。

我也觉得和应该和动态的标题有关…
系统默认的渲染就不会有这种现象,老的 infinality 也不会,只有 Ultimate 才出现反复刷新,我看久了要晕… 所以我退一步用了老的 infinality

另外感谢@netcap 的提醒,如果你觉得笔画太细,而且有 Win7 的雅黑 6.02,可以试试这个版本。

再另外,由于 infinality-ultimate 已经不再维护,主贴里的内容有些过时了。现在要使用雅黑,可以用如下两个源:

v38 解释器(FreeType 内置的 Infinality 引擎)+ 雅黑补丁: software.opensuse.org//download.html?project=home%3Astecue&package=freetype2
或者
v40 解释器: software.opensuse.org//download.html?project=home%3Astecue%3ATTv40&package=freetype2

v38 解释器由于基本等于 Infinality 补丁(配置除外),不加补丁会导致雅黑的笔画缺失。v40 解释器则没有这个问题。