摘 要:ICU復雜文本布局引擎與其他應用較為廣泛的復雜文本布局引擎相比的一大長處是它的開放源代碼。通過分析ICU源碼,并以此為基礎設計新的復雜文本的布局引擎。首先簡要介紹了復雜文本布局引擎的一般原理,然后以復雜文字語言蒙古文為例,詳細探討了基于ICU的復雜文本布局引擎的設計思路和方法,最后對復雜文本布局引擎的跨平臺應用進行了深入研究。
關鍵詞:復雜文本布局引擎;ICU;跨平臺
中圖法分類號:TP311; TP391文獻標識碼:A
文章編號:1001—3695(2007)02—0219—03
復雜文本布局引擎是專門用來處理復雜文本布局和顯示的一個部件,它是操作系統以及一些大型應用軟件不可缺少的一個組成部分。要實現一個民族的信息化,就必須實現對這個民族文字的計算機處理。從某種意義上說,對于一個使用復雜文字的民族,要實現這個民族的信息化,就必須設計出針對這個民族的復雜文本布局引擎。我國少數民族的蒙古文、藏文、維吾爾文等都是復雜文字,因此復雜文本布局引擎在我國一個重要的應用就是為我國少數民族地區開發支持本民族語言的重要基礎軟件和應用軟件。其中之一就是為我國少數民族地區開發一套適用的辦公套件。復雜文本布局引擎設計及其應用的研究對我國的信息化進程是一個重要的推力,有助于開發支持我國少數民族語言文字的基礎軟件(如基于Linux的操作系統)和應用軟件(如基于OpenOffice的辦公套件)。
1 復雜文本布局引擎機制
1.1 復雜文本布局引擎與OpenType[1]字庫技術
復雜文本布局引擎離不開字體技術的支持,它通過從字體中讀取文本處理的相關數據來完成對復雜文本的處理過程。
目前在復雜文本布局引擎中應用最廣泛的字體技術是OpenType[1]字體技術,它是Microsoft公司和Adobe公司聯合開發的一種基于Unicode且與平臺無關的字體格式。該字體中含有很多重要的表格,其中與復雜文本布局緊密相關的表有字形替換表(GSUB)、字形置位表(GPOS)、字形定義表(GDEF)、字形調整表(JSTF)和基線數據表(BASE)。這幾個表統稱為OpenType布局表。布局表主要的目的是讓字體盡量最大程度地變得智能。其中最主要的是GSUB和GPOS表,這兩個表提供的數據及功能覆蓋了幾乎所有復雜文本處理的要求,它包含了在字形處理過程中用到的所有有關替換和字形置位的信息。這兩個表都開始于一個定義了文字鏈表(ScriptList)、特征鏈表(FeatureList)和查找鏈表(LookupList)偏移的表頭,GSUB/GPOS表中每一個替換/置位格式類型對應一個或多個Lookup數據。Lookup結構包含了替換和置位操作的具體數據信息。
1.2 復雜文本布局引擎的工作原理
對于復雜文本語言,輸入的Unicode名義字符串必須經過布局引擎處理,才能得到正確的顯現字形序列及字形之間正確的位置數據。圖1為布局引擎流程結構圖。
圖中橫向虛線表示布局引擎部分,縱向虛線表示OpenType字體的具體替換和置位類型操作的實施模塊。字體解釋器負責從字體中讀取各種信息及光柵化字形,并向其客戶提供這些信息,它完全屏蔽了字體文件的細節和復雜性。通過布局引擎流程結構圖,我們可以把復雜文本布局引擎按照先后順序分為三大處理模塊,即分成片段處理模塊、文字處理模塊和替換、置位操作實施模塊。
1.3 目前主要使用的復雜文本布局引擎
目前主要使用的復雜文本布局引擎有Microsoft的Uniscribe(Unicode文字處理),Linux平臺下基于GTK庫的Pango和IBM的ICU[2](International Component of Unicode),其工作原理基本一致。當前它們均基本實現了對印度文、泰文、阿拉伯文和希伯萊文的支持。
本文重點涉及的ICU[2]是由IBM開發的專門用來處理基于Unicode文本的開放源碼的函數庫,用于支持基于Unicode的軟件的國際化和本地化。它能夠提供對各種復雜文本的處理,并能夠加入新的代碼來支持對新的復雜文本的處理。ICU布局引擎(LayoutEngine)是ICU中獨立的模塊結構,用于處理復雜文本語言。目前,已經實現的復雜文本語言有阿拉伯文、印度文、泰文、希伯萊文。
2 基于ICU的復雜文本布局引擎設計方法
2.1 ICU布局引擎結構及接口分析
ICU布局引擎UML結構[3]如圖2所示。
圖2中類LayoutEngine是布局引擎的基類。類LEFontInstance是字體解釋器庫,在ICU中,它是純虛類,只提供接口。OpenOffice處理多語言的布局引擎就是采用ICU布局引擎,并以FreeType字體解釋器庫實現類LEFontInstance的方法。在類OpenTypeLayoutEngine中,依次定義了三個函數來實現布局引擎功能:
(1)characterProcessing()。對應文字處理模塊部分,作OpenType字符相關處理,為字符分配OpenType特征標簽。它應用特定的語言知識分析字符串,并在需要處理的字符上綁定特征標簽,對字符進行插入、刪除、重排等操作。它的輸出就是字符與綁定在其上的特征標簽。
(2)glyphProcessing()。應用GSUB表進行字符到字形的映射。它先將字符映射到字形,開始利用綁定在字形上的特征標簽找到對應的Lookup數據,實施替換操作,從數據結構中找到要輸出的變體顯現形式。
(3)adjustGlyghPositions()。利用GPOS表特征標簽實施置位操作調整字形位置。
2.2 基于ICU的蒙文復雜文本布局引擎設計
通過上面分析我們可以看出,要讓布局引擎提供對新的復雜文本的實現,需要定義一個繼承自OpenTypeLayoutEngine的新類,然后結合該語言文本的語言知識和處理規則來重寫上述實現布局引擎功能的三個函數。
下面我們以蒙古文為例,定義一個繼承自OpenTypeLayoutEngine的子類:MongoOpenTypeLayoutEngine,并在子類中應用蒙古文的語言知識和處理規則重寫characterProcessing(),glyphProcessing(),adjustGlyghPositions()即可。
2.2.1 蒙古文語言知識和處理規則
蒙古文類文字(Mongolian Script)是個性很強的復雜文本(Complex Text)文字。蒙古文雖屬于音素文字,但具有一字多形、多字同形,字母以詞為單位豎向連寫,行序從左到右。
(1)蒙古文字符集。這里所指的蒙古文字符集是傳統蒙古文字符集。其中包括傳統蒙古文用標點符號、蒙古文數字、控制字符及傳統蒙古文字母,還包括傳統蒙古文編輯排版所需的常用標點符號。
①標點符號:BIRGA、省略號、逗號、句號、冒號、四點、NIRUGU 等。
②蒙古文數字:[U+1810]—[U+1819]。
③控制字符:FVS1、FVS2、FVS3、MVS、NNB-SP、零寬連接符和零寬禁連符等。
④傳統蒙古文字母(字符):[U+1820]—[U+1842]。
⑤其他常用符號:問號、嘆號、[U+2048](?!)、[U+2049](!?)、蒙古文常用括弧括號(()、〔〕、〈〉、《》)等。
(2)蒙古文標簽集。總結歸納出蒙古文的標簽類別,對于定義標簽數組,實現貼標簽算法,應用標簽算法等具有重要意義。其標簽可以分為
①詞內位置變體(Isolate,Initial,Medial,Final)
isol:輸出字母獨立形式;init:輸出字母詞首形式;medi:輸出字母詞中形式;fina:輸出字母詞尾形式。
②自由變體(Ligature)
liga:輸出為某種字符詞內位置的自由變體。這是個多對一替換(Ligature)標簽,在蒙古文中只進行二對一的替換。
③組合變體(Record Ligature)
rlig:通過字符上下文組合進行“整形”,這個標簽重點處理音節和斷層的“整形”問題。這是個多對多替換(Context)標簽。
2.2.2 蒙古文文字引擎
(1)貼標簽及標簽算法。文字引擎的第一步工作是為字符串貼標簽(Feature Tag),然后根據這個標簽訪問字庫中相應的特征列表(Feature List),以得到正確字形。通過前面的關于蒙古文復雜文本特征的分析總結得出,蒙古文字母的字形與其詞內位置、詞性和上下文有直接的關系,即蒙古文字母的顯現形式會同時受其前后有沒有字符以及有什么字母的影響,因此蒙古文不可能通過單層標簽就實現字形的替換過程。鑒于此,我們將采用多層標簽的方案。首先根據字符在詞中的位置貼第一層標簽,該層標簽根據字符在詞中的位置替換成默認的獨立形、詞首形、詞中形和詞尾形;然后結合蒙古文的控制符貼第二層標簽,該層標簽依據蒙古文的三個自由變體選擇符選擇字形的相應變體;第三層標簽根據字符組合(上下文)來處理,并獲得每個字符的相應變形。字符串貼標簽算法歸納如下:
(2)應用標簽。其主要就是應用標簽的字形替換表規則(數據)。蒙古文也需要貼多層標簽,類似于阿拉伯文,并且比阿拉伯文還要復雜。所以應用標簽時也需要一層一層地順序應用。在應用標簽之前,文字引擎完成如下準備工作:確定被匹配的字庫是不是蒙古文OpenType 字庫;取得并預處理OpenType 字庫的各種相關表的數據,如CMAP 表、GSUB 表、GPOS 表等;依據字庫的CMAP表,將蒙古文字符串的Unicode 字符編碼替換成字形ID(GlyphID)序列。接下來就開始應用標簽了,將分三步進行:
①應用第一層標簽,解決與位置(Isolate,Initial,Medial,Final)相關的字形替換。每個字形根據其標簽替換為默認獨立形、詞首形、詞中形和詞尾形的字形ID。
②應用第二層標簽,處理蒙古文字母的無條件變體(Ligature)的替換,即處理與自由變體選擇符(FVS1,FVS2,FVS3)相關的替換。如果蒙古文字符之后出現自由變體選擇符,則對這一組合進行替換。
③應用第三層標簽,處理蒙古文字母的上下文(Record Ligature)相關的自行替換,即完成音節、斷層的變形問題。
最后,文字引擎將通過應蒙古文標簽而得到的GlyphID 序列及其順序表一同返回給上層的系統服務模塊。
通過對蒙古文特征及語義規則的分析,我們可以定義出其特征標簽,并應用上面的貼標簽及應用標簽的算法設計出蒙古文的布局引擎。圖3為沒有應用蒙文布局引擎的記事本打開的蒙文字符(左)和應用了蒙文布局引擎的例子程序打開的蒙文字符(右)的對比截圖。
圖3 使用復雜文本布局引擎前后對比
3 基于ICU的復雜文本布局引擎跨平臺應用
3.1 ICU復雜文本布局引擎跨平臺過程調用概述
ICU庫提供的接口本身是跨平臺的。下面我們可以簡要描述一下對ICU處理復雜文本引擎的調用過程[5]:
//首先調用布局引擎類工廠生成針對某具體文字的布局引擎
一旦獲得了字形和位置信息,就可以通過在不同的平臺下調用不同的函數來顯示字形了。例如在Windows下我們可以調用ExtTextOut,而在Linux下可以調用TT_Load_Glyph。
通過上面的介紹可以看出,盡管基于ICU的復雜文本布局引擎具有跨平臺性,但是具體的跨平臺工作還是必須由程序設計者完成。尤其是在OpenOffice中的跨平臺調用,我們要完成OpenOffice在Windows和Linux平臺下調用ICU布局引擎,必須結合具體情況在OpenOffice原有代碼上進行改寫。
3.2 OpenOffice中對ICU的跨平臺調用
OpenOffice在Linux平臺和Windows平臺下調用文本布局引擎的UML結構[4]如圖4所示。
從圖4可以看出,OpenOffice在Linux平臺下是通過調用ICU布局引擎來處理復雜文本的布局和顯示輸出,而在Windows平臺下,則是調用Uniscribe布局引擎來處理復雜文本的。
OpenOffice在Linux平臺下就是通過調用ICU來完成復雜文本的處理。因此,跨平臺要解決的主要問題就是實現在Windows平臺下OpenOffice對ICU的調用。目前,OpenOffice在Windows平臺下主要通過微軟的Uniscribe布局引擎來完成對復雜文本的處理。由于Uniscribe布局引擎是不公開源碼的,所以我們也不能對它進行增改,從而導致很多我國少數民族語言文字無法在Windows平臺下完成相應的處理。因此解決問題的辦法是要在Windows平臺下實現對ICU的調用。結合上面的UML結構圖,要實現對ICU的調用,其方法有二:與在Linux下調用一樣,可以重新構造一個新的繼承自SalLayout的子類取名如WinICULayout,在其中封裝對ICU布局引擎的調用方法。但是,此種方法需要重寫的代碼量大、開發周期長。因此我們主要采用了第二種方法。這種方法的思想是:重用現有的UniscribeLayout類的代碼,在其中加入部分代碼來調用ICU布局引擎獲得字形、位置信息,然后把這些信息交給Uniscribe布局引擎繼續處理。這樣,我們只需要在UniscribeLayout::layouttext()方法中定義相關參數并調用ICU布局引擎接口,簡單易行。
4 結束語
本文通過開源ICU接口分析并以蒙古文為例,詳細探討了復雜文本布局引擎的設計思路和方法。對任何一種復雜文字語言,都可按照這樣的思路:在ICU中添加相應的復雜文本布局引擎代碼,這包括我國的維吾爾文和藏文,并且這些工作在我們的項目中有的已經完成設計任務,有的則正在開展。另外,對于ICU在Windows中的調用,我們目前用了3.2節中所說的簡易方法。但是,盡管這樣的方法重用了Uniscribe已有代碼,但卻并不是完美的。其中一個問題就是ICU與Uniscribe在字符到字形的映射方法不一致。因此,以后的工作應該立足解決這樣的問題或完全拋開Uniscribe布局引擎而重新設計一個WinICULayout類來完成在Windows下對ICU的調用。
本文中所涉及到的圖表、注解、公式等內容請以PDF格式閱讀原文。