Font Rending 的 Hint 機制對排版的影響【轉】
在設計一種 Font 時,設計者使用的是一個抽象的單位,叫做 EM,來源于大寫 M 的寬度(通常英文字體中大寫 M 的寬度最大)。EM 即不同于在屏幕顯示時用的像素(Pixel)也不同于打印時用的點(Point; 1/72 inch),他是一種相對單位,隨著字體和字號的不同變化。通常對于一個 12 號的字體一個 EM 的長度等于 12pt。
實際設計時會將 EM 分成更小的單位,一般成為 EM Unit,TrueType 中一般是 2048 Units = 1 EM,Type1 中一般是 1000 Unit = 1EM。假設在我們設計的字體中字母 a 的寬度為 998 Units,如果我們用 12 號字顯示它,我們得到的字寬為 12 * 998 / 2048 = 5.84765625 Point。如果我們將這個字打印到紙上,在 2000 dpi 的打印機上我們需要放置 5.84765625 / 72 * 2000 = 162.434895833 個 Dot(可以將 Dot 理解成墨滴)。而實際上我們不可能得到 0.43 個 Dot,我們只能用 162 個點來描述字母 a。如果我們將同樣的一個字母顯示在屏幕上,一般來說屏幕多為 72dpi 或 96dpi,以 96dpi 為例也字母 a 需要 5.84765625 / 72 * 96 = 7.796875 個像素來顯示,實際上我們得到的是 8 個。在排版時我們需要根據一個字符的寬度來計算下一個字符的位置,這里的問題是:由于輸出設備的限制我們永遠也不可能將字母放在理論中的位置,設備的分辨率越低結果偏差的越大。反鋸齒能夠在一定程度上緩解這個問題,但不總是能的到好的結果。
另外在字體渲染時有時候會出現這樣的問題,字母 H 的兩個豎筆畫不一樣粗,這通常跟字母在屏幕上的位置有關,為了解決類似的問題,字體設計時都會提供一些額外的信息來根據輸出設備的分辨率調整筆畫。這就是 Hint 機制,或者叫 Grid-Fitting。由于 Hint 的存在,同一個字母在不同的設備上輸出會有不同的寬度,這對排版有很大影響。所見即所得的排版要求我們在屏幕和紙上有相同的排版結果。如果我們按照理論值排版,在屏幕上我們可能會看到不美觀的輸出,參見截圖。如果我們按照屏幕 Fitting 值排版則不能夠最大化的利用字體設計師的工作,他們仔細調整過的字寬不能在紙上還原。
下圖是個程序示例(Java),展示了不同的渲染方式會得到不同的字體寬度和不同的渲染結果。圖中左右半部分分別是沒有使用反鋸齒(左)和使用反鋸齒(右)的效果,而圖中上下半部分分別是使用整數坐標(上)和使用分數坐標(下)的效果。
在圖上可以看出使用分數坐標的 M 具有不一致的間距。所有的這些都對實現“所見即所得”的排版軟件帶來了很大困難,在 FreeType 的主頁上有一些有關的文章,參見這里。其中提出了兩種解決方案:
There are two ways to achieve this: either use the scaled and unhinted glyph metrics when laying out text both in the rendering and printing processes, or simply use whatever metrics you want and store them with the text in order to get sure they are printed the same on all devices (the latter being probably the best solution, as it also enables font substitution without breaking text layouts).
為了確定主流排版/字處理軟件是如何解決這個問題的,我使用同樣的基準文檔(Tahoma 12pt 大寫 M)做了測試。在 MS Word 2007 & MS Word 2003 中的結果如下:
可以看出 MS Word 的渲染結果也有不一致的間距,另外每個 M 字符都完全相同,這意味著 MS Word 是將一個字符渲染出來,然后不斷的貼圖。這也是常見的做法,優點是速度快,不需要在每個位置重復渲染。
在 Adobe InDesign 中以高質量顯示的結果如下:
可以看出 InDesign 的渲染結果也有不一致的間距,但是明顯 Adobe 具有更好的反鋸齒算法,視覺上很難發現不同,但放大后還是能夠看得比較清楚。另外 InDesign 的每個 M 字符都不相同,也就是說 InDesign 是對每個字符單獨進行渲染,難怪效果會好。
結論
1. 使用設備無關的(高精度的)方式進行排版.
2. 顯示效果不好時,使用每個字符單獨渲染的策略.
3. 有些時候需要根據輸出設備的限制進行 Grid Fitting,比如在 AFP 中對字符的位置/寬度有很大限制.