闲聊文本渲染技术的近期发展

在今年 7 月的 [GUADEC](http://www.grancanariadesktopsummit.org/) 上 Behdad Esfahbod 做了一个题为 [State of Text Rendering](http://behdad.org/text/) 的讲座,系统地综述了当前文本渲染技术的现状,顺带强调主要由他开发的 [harfbuzz-ng](http://www.freedesktop.org/wiki/Software/HarfBuzz) 是未来发展的方向,4 个月过去了,最近文本渲染技术有了什么发展呢?这里谈谈我的一些印象和见解。

首先,harfbuzz-ng 到底想做成什么样子?我们知道底层的字体格式支持,开放的有 [FreeType](http://www.freetype.org) 一枝独秀,各平台私有的有 Win32 的 GDI font, Mac OS X 有 ATS 和 [CGFont](http://developer.apple.com/mac/library/documentation/GraphicsImaging/Reference/CGFont/Reference/reference.html),上层的文本布局排版引擎,现在各家自有一套到两套:Windows 的 [DirectWrite](http://en.wikipedia.org/wiki/DirectWrite) 和 Uniscribe;Mac OS X 有 Core Text 和 ATSUI,有 [NSLayoutManager](http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Reference/ApplicationKit/Classes/NSLayoutManager_Class/Reference/Reference.html);GTK+ 有 [pango](http://www.pango.org/),都是比较成熟的接口了,那 harfbuzz-ng 是要取代他们吗?

不是,也完全说不通,毕竟 pango 就是 Behdad Esfahbod 自己维护的,没理由拆自己的台。但是开放的 pango 等平台一直缺失的部分是 OpenType 复杂排版特性的支持,这一点 FreeType 没来得及解决,也因为和排版引擎关系太紧密,所以没法完全靠 FreeType 这种“字体格式解析库”来解决。harfbuzz-ng 要做的,正是在原来的 FreeType OpenType 排版代码的基础上,构建一个类似 [ICU LayoutEngine](http://userguide.icu-project.org/layoutengine) 的、有简洁的 C API 的、支持 OpenType 特性的,而且还要比 pango 底层一些的库。

那不是和 ICU 重合了吗?ICU 一来是 C++ 的 API 用着比较累,而来确实也比较笨重,移植的时候够受的。ICU 虽然在近期版本里也开始提供 C 的排版引擎 API,但也只是试验性的。

所以总的看起来,Linux 下的文本渲染层次还真是够多的:GTK+ → pango/[cairo](http://cairographics.org) → harfbuzz-ng → FreeType,同时 harfbuzz-ng 还可能用到 ICU, [Graphite](http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&cat_id=RenderingGraphite),在 Mac OS X 上还要用到 Core Text 和 Core Graphics。

细分层带来的好处就是不同的需求可以选择合适的 API 来实现:比如你要在图形界面上显示一段文字,就用 GTK+ 的 label;要绘制小段的文本,就用 cairo 和 pango;要高效率的、轻量地绘制大量的文本,就用 harfbuzz-ng 来自己攒一个排版引擎 — 大部分浏览器都是这样,只不过在没有 harfbuzz-ng 的情况下,或者要直接用 FreeType,不得不多写很多代码,或者就用 pango 这种重量级的,性能又得不到保证。

在 8 月份,harfbuzz-ng 的 [API 提议](http://lists.freedesktop.org/archives/harfbuzz/2009-August/000359.html)已经出现,并在不断讨论中完善 (要我说,本来这个星球上有经验参与讨论的也最多不超过 20 个人,不如大家到一个屋子里开个会搞定得了)。

[XeTeX](http://www.tug.org/xetex/) 的作者 Jonathan Kew 虽然仍然在开发 [TeXworks](http://www.tug.org/texworks/),但工作的重心已经放到了 Mozilla Firefox 3.6 的 [WOFF](http://hacks.mozilla.org/2009/10/woff/) 格式和 OpenType 复杂排版支持上,最近的一个视频里 Jonathan 提供了一个[很棒的概览](http://hacks.mozilla.org/2009/10/font-control-for-designers/),有这样的一些特性之后,在浏览器里做一些**认真的**文本排版才可能成为现实 — 可惜浏览器仍然缺乏好的断行算法实现。这部分工作其实就是基于 harfbuzz-ng 的。而 WebKit-GTK 版本也开始了基于 harfbuzz-ng 的实现。

当然了,畅想了一番美好未来之后还是要回到现实,目前我想做的一个项目,是开发一套能跨 iPhone OS 和 Mac OS X 的、轻量级的排版引擎,专门给[文本阅读器](http://www.jjgod.org/projects/textus)用。这个工作的出发点是:

1. iPhone 上缺少 (按我的标准) 足够好的文本阅读器,而既然我已经开始写 Textus 了,不如把它移植到 iPhone 上;
2. iPhone 上没有 Core Text 这个层次的框架,要渲染文本要么用 `NSAttributedString`,要么用 `WebView`,他们的额外开销都太多,太重量级了;
3. 轻量的方法有神秘的 private API [`CGFontGetGlyphsForUnichars`](http://www.google.com/search?q=CGFontGetGlyphsForUnichars),如果不愿意用 private API 呢,就只好像 [cocos2d-iphone](http://code.google.com/p/cocos2d-iphone/) 那样自己去实现 [cmap 载入的代码](http://code.google.com/p/cocos2d-iphone/source/browse/trunk/external/FontLabel/FontLabelStringDrawing.m),非常痛苦;
4. 即使这样,也不支持复杂的 OpenType 排版特性,甚至简单一点的连字 (ligature) 都不支持,对于一个文本阅读器这是不能忍受的。

所以觉得写个这样的引擎会比较有用:

* 做到后端独立,比如可以选用 ICU (iPhone OS 上), Core Text (Mac OS X 上), harfbuzz-ng
* 能够支持 OpenType 复杂排版特性
* 至少支持好大部分西方字符和 CJK 字符
* API 尽可能的简单

最近刚刚开始做一些试验,比如用 Core Graphics 完成了一个简单的 [CGFontInstance](http://github.com/jjgod/texo/tree/master/icu/) 给 ICU 用,这在目前还没看到类似的工作。