ICU Layout Engine

Overview

Latin Script,軟件開發者中使用最爲普遍的script,同時也是在顯示的時候最不復雜的script,特別是當用它來書寫英語的時候。使用Latin Script,他們的字符能夠被從左至右順序顯示,就像這些字符在內存中存儲的順序同樣。有些scripts則須要一些比Latin script更爲複雜的渲染的過程。咱們把這些scripts稱爲「複雜scripts」,把用這些scripts書寫的文本稱爲「複雜文本」。複雜scripts的例子有Indic scripts(好比,Devanagari,Tamil,Telugu 和Gujarati),Thai,和阿拉伯。 html

這些複雜scripts展現了Latin script所未曾有的複雜化。下面會列出複雜文本的主要的複雜化: 編程

ICU LayoutEngine就是設計用來經過一個簡單的一致的客戶端接口來處理這些複雜化。客戶端以讀取或「邏輯」的順序提供Unicode 代碼點(Unicode的字符被稱爲代碼點),而後LayoutEngine以正確的順序,提供須要顯示的字形及各個字形的位置信息。 數組

因爲ICU LayoutEngine是平臺獨立的,而文本渲染則固有的依賴於平臺,於是LayoutEngine不能直接顯示文本。它使用一個抽象的基類來訪問字庫文件。這個基類建模了某一特定點大小及設備解析度下的TrueType字庫。TrueType字庫有以下的這樣一些特性: app

  1. 一個字庫是稱爲glyph的圖片的集合。字庫中的每個Glyph經過一個16-bit的glyph id來引用。
  2. 有一個由Unicode 代碼點到glyph ids的映射關係。字庫文件中也許有一些glyphs沒有映射。
  3. 字庫包含了叫作4字節 tags(如, ''GSUB'', ''cmap')的數據表。這些表能夠被讀入內存作處理。
  4. 有一個方法能夠去獲取glyph的寬度。
  5. 有一個方法能夠從glyph中獲取控制點的位置。

因爲複雜文本顯示的許多上下文形式,練字,切分開的字符等沒有Unicode代碼點,於是他們就只能被他們的glyph 索引來指代。於是,LayoutEngine的輸出是一個glyph 索引的列表。這意味着輸出必須用一個接口來顯示,在這個接口中,字符有glyph 索引來講明,而不是代碼點。 ide

必須爲每個目標平臺都寫一個這種基類的具體實例。一個簡單的使用標準C庫訪問TrueType字庫文件的例子,能夠在 icu/source/test/letestPortableFontInstance類。 測試

ICU LayoutEngine以以下的方式支持複雜文本: ui

  1. 若是字庫含有OpenType的表,則LayoutEngine使用這些表。
  2. 若是字庫含有Apple Advanced Typography (AAT)表,那麼LayoutEngine使用這些表。
  3. 對於Arabic和Hebrew,若是沒有OpenType表,則LayoutEngine使用Unicode描述形式。
  4. 對於Thai文本,LayoutEngine使用Microsoft或者Apple Thai形式。

OpenType處理過程在使用OpenType 表以前,,須要先完成某個script的特定處理。ICU LayoutEngine爲Arabic,Devanagari,Bengali,Gurmukhi,Gujarati,Oriya,Tamil,Telegu,Kannada,和Malayalam文本執行這個處理。 spa

因爲它只在自左向右文本中應用默認的features,因此LayoutEngine中的AAT處理則相對簡單。這個處理已經爲Devanagari文本作過測試。因爲AAT處理不是特定script的,它對其餘scripts可能不起做用。 設計

用ICU LayoutEngine 編程

ICU LayoutEngine 被設計出來用於處理一段文本,這段文本的全部glyph能夠在相同的一個字庫文件裏面找到。這段文字具備一致的方向(自左向右或自右向左),同時具備相同的script。客戶端能夠使用ICU的Bidi 處理來肯定文本的方向,並使用icu/source/extra/scrptrun中的ScriptRun類來查找具備相同script的一段文本。因爲字庫文件信息的表示方法因應用而已,ICU沒法協助查找這些文本段。 代碼規範

一旦文本已經被切分紅了LayoutEngine能夠處理的文本片斷,則能夠調用LayoutEngineFactory來建立一個特定於文本的LayoutEngine類的實例。下面的code演示了一個對於LayoutEngineFactory的調用:

LEFontInstace *font   = <the text's font>; 
UScriptCode    script = <the text's script>;
LEErrorCode    error  = LE_NO_ERROR;
LayoutEngine  *engine;

engine = LayoutEngine::layoutEngineFactory(font,
                                         script,
                                         0,  // language - ignored
                                         error);

下面的例子展現瞭如何使用LayoutEngine來處理文本:

LEUnicode text[] = <the text to process>; 

le_int32 offset  = <the starting offset of the text to process>;
le_int32 count   = <the number of code points to process>;
le_int32 max     = <the total number of characters in text>;
le_bool  rtl     = <true if the text is right-to-left, false otherwise>;
float    x, y    = <starting x, y position of the text>;
le_int32 glyphCount;

glyphCount = engine->layoutChars(text, offset, count, max, rtl,
                                               x, y, error);


前面的例子計算了三個數組:一個以顯示順序呈現的glyph索引的數組,一個每一個glyph對應其中一個元素的(x,y)位置對的數組,和一個將輸出的glyph映射回輸入文本數組的數組。使用下面的get 方法來拷貝這些數組:

LEGlyphID *glyphs    = new LEGlyphID[glyphCount];
le_int32 *indices   = new le_int32[glyphCount];
float     *positions = new float[(glyphCount * 2) + 2];

engine->getGlyphs(glyphs, error);
engine->getCharIndices(indices, error);
engine->getGlyphPositions(positions, error);


位置數組包含(glyphCount * 2) + 2項。這是因爲每一個glyph有一個x和一個y位置。額外的兩個位置保存文本段末尾的x,y位置。

一旦用戶獲取了glyph 索引和位置,他們就能夠使用特定於平臺的code來畫出glyphs了。好比,在Windows 2000上,用戶能夠用ETO_GLYPH_INDEX選項來調用ExtTextOut以畫出glyph,而在Linux平臺上,用戶則能夠調用 FT_Load_Glyph來獲取每個glyph的bitmap。然而,用戶必須本身畫出bitmaps。

ICU LayoutEngine是與ICU的其餘部分分開開發的,於是它使用了不一樣的代碼規範和基本類型。爲了以ICU 代碼規範使用LayoutEngine,用戶能夠使用ICULayoutEngine類,這是LayoutEngine類的一個檢點包裝,並且它符合ICU conventions和基本類型。

關於如何調用LayoutEngine更詳細的例子,能夠參考 icu/source/test/letest/letest.cpp。這是一個簡單的用於驗證LayoutEngine是否正常工做的一個測試。它沒有作任何的複雜文本的渲染。

更多詳情,請參考 ICUOpenType SpecificationTrueType Font File Specification

相關文章
相關標籤/搜索