排版技術(shù)札記(2):文本渲染技術(shù)(shaping篇)
首先需要聲明,這是一篇類(lèi)似綜述的東西。之所以不涉及細(xì)節(jié),是因?yàn)橐阉屑?xì)節(jié)寫(xiě)出來(lái),一百?gòu)圓4紙可能才夠(有大量的細(xì)節(jié)說(shuō)明和示意圖)。
文本渲染
通常提到的文本渲染技術(shù),容易混淆,主要可以指兩個(gè),一個(gè)是shaping,另一個(gè)是rasterization。前者可以轉(zhuǎn)換為等效的繪制指令,后者一般指圖形學(xué)的柵格化。
文本為什么需要處理?
對(duì)于人們來(lái)說(shuō),書(shū)寫(xiě)是一種很簡(jiǎn)單的東西。漢字的書(shū)寫(xiě),似乎沒(méi)什么復(fù)雜的地方,但是世界上還有幾種不一樣的書(shū)寫(xiě)類(lèi)型,比如有一種依賴上下文的,字母在不同位置會(huì)表現(xiàn)成不一樣的形態(tài),如阿拉伯文;比如有一種依賴上下文且會(huì)在字母四周加符號(hào)的,比如緬甸文。
這些文字,在紙上書(shū)寫(xiě),過(guò)程似乎沒(méi)有太大的區(qū)別。但是一旦轉(zhuǎn)換場(chǎng)景,送入計(jì)算機(jī),如何編碼,就變成了需要約定的事情。
這種約定,一般先需要編碼(encoding)。但是編碼還不夠,還需要約定能夠表現(xiàn)書(shū)寫(xiě)文字的最小單位和最大單位,這個(gè)一般稱(chēng)為grapheme和grapheme cluster。
這兩件事做了,事情還沒(méi)完。grapheme和grapheme cluster都是以string形式存在的,簡(jiǎn)單說(shuō),就是一維的數(shù)組。但是文字呈現(xiàn),卻是二維的,從特定的string轉(zhuǎn)換到帶坐標(biāo)屬性的string,就是所謂shaping要做的東西。
不過(guò),一般這種二維的帶屬性的string,會(huì)轉(zhuǎn)換成特定字體的glyph的數(shù)組。這個(gè)glyph,本質(zhì)上是圖,是送給人眼看的東西,它可能是一個(gè)編碼元素,也可能是幾個(gè)編碼元素,也有可能是一個(gè)編碼元素的一部分。
文本處理的理論
計(jì)算機(jī)中的文本處理。熟悉形式語(yǔ)言學(xué)會(huì)有很大的幫助。如果不熟悉形式語(yǔ)言學(xué),那么最少要掌握正則表達(dá)式一項(xiàng)技術(shù)。其次,如果對(duì)于關(guān)于書(shū)寫(xiě)的學(xué)科——書(shū)寫(xiě)系統(tǒng)——有所了解的話,對(duì)于理解文本處理會(huì)更加具體。
第二個(gè)需要掌握的是Unicode本身。一般來(lái)說(shuō),Unicode組織每年都會(huì)更新Unicode的內(nèi)容。試圖一勞永逸地解決所有問(wèn)題,是不可能的。Unicode的東西,需要隨時(shí)看,年年看,老的文檔要看,新的文檔也要看。
文本的呈現(xiàn)基礎(chǔ):字體
這里就切入核心的技術(shù)難點(diǎn)之一了。字體,文件本身,已經(jīng)沒(méi)有什么秘密了。一般要實(shí)現(xiàn)shaping庫(kù)的,都需要從頭解析字體獲取shaping相關(guān)的數(shù)據(jù)。
但是,解析這事,本身可就有一些難點(diǎn)了。讀的問(wèn)題可能還沒(méi)什么問(wèn)題。寫(xiě)的問(wèn)題可能就大一些。這兩個(gè)都做過(guò),對(duì)于二進(jìn)制解析,就沒(méi)有什么難度了。
文本的shaping過(guò)程
文本,使用regex分割文本,對(duì)分割后的文本進(jìn)行調(diào)整,使用字體信息進(jìn)行運(yùn)算,獲得二維glyph數(shù)據(jù)。
如何使用regex分割文本,需要看約定俗成的shaping model文檔。這部分,在微軟的OpenType相關(guān)文檔中可以看到。如果需要看到歷史版本,則需要去archive.org中查找。
林林總總的Shaping?Model
第一類(lèi)是不需要怎么處理的,通常稱(chēng)為standard?scripts,比如拉丁文,希臘文,西里爾文,漢字。
第二類(lèi)是需要處理位置變體的,比如阿拉伯文,希伯來(lái)文,敘利亞文。通常這類(lèi)文字,也有bidirectional上的處理。
第三類(lèi)是需要處理復(fù)雜附加符號(hào)的,比如印度的一組文字。印度的這一組文字,有兩個(gè)shaping model,對(duì)應(yīng)著不同的unicode版本,現(xiàn)在的版本是第二版。
第三類(lèi)是需要處理mark異常情況的,比如泰文和老撾文。
第四類(lèi)是一大類(lèi),微軟稱(chēng)為universal shaping model。這個(gè)大模型處理的語(yǔ)言比較多,主要是受印度文字影響的一些文字,不過(guò)也有例外,它包含了古埃及的圣書(shū)文字。
第五類(lèi),基本上是單一語(yǔ)言特定處理,比如高棉文,緬甸文,諺文。
上面五類(lèi)主要是OpenType的處理模型分類(lèi)。此外,還有自帶自動(dòng)機(jī)的字體技術(shù),Apple的AAT和SIL的Graphite,這相當(dāng)于把上面的模型所描述的東西直接寫(xiě)入字體。
回到現(xiàn)實(shí)
現(xiàn)實(shí)中,這些文字處理的事情,基本上都有現(xiàn)成的解決方案。比如微軟的uniscribe和directwrite,macOS的coretext,Linux和Android中使用的harfbuzz。
但是這些東西不一定都能夠滿足用戶的使用需求。比如一個(gè)庫(kù)需要熱更新修正渲染行為的時(shí)候。這些東西在TeX里面其實(shí)是需要的。不過(guò)在TeX里面,有時(shí)候連glyph和metric都需要熱更新。
自2015年,我開(kāi)始構(gòu)想自己的shaping庫(kù),已經(jīng)過(guò)去八年。我覺(jué)得我現(xiàn)在的想法??足夠成熟了??梢蚤_(kāi)始搞了。