《FreeType Glyph Conventions》中譯版
FreeType字形約定
一、基本印刷概念
1、字型檔、格式和資訊
字型是一組可以被顯示和列印的多樣的字元映像,在單個字型中共用一些共有的特性,包括外表、風格、襯線等。按印刷領域的說法,它必須區別一個字型家族和多種字型外觀,後者通常是從同樣的模板而來,但是風格不同。例如,Palatino Regular 和 Palatino Italic是兩種不同的外觀,但是屬於同樣的家族Palatino。
單個字型術語根據上下文既可以指家族也可指外觀。例如,大多文文書處理器的使用者用字型指不同的字型家族,然而,大多這些家族根據它們的格式會通過多個資料檔案實現。對於 TrueType來講,通常是每個外觀一個檔案(arial.ttf對應Arial Regular外觀,ariali.ttf對應Arial Italic外觀)這個檔案也叫字型,但是實際上只是一個字型外觀。
數字字型是一個可以包含一個和多個字型外觀的資料檔案,它們每個都包含字元映像、字元度量,以及其他各種有關文本布局和特定字元編碼的重要訊息。對有些難用的格式,像Adobe的Type1,一個字型外觀由幾個檔案描述(一個包含字元映象,一個包含字元度量等)。在這裡我們忽略這種情況,只考慮一個外觀一個檔案的情況,不過在FT2.0中,能夠處理多檔案字型。
為了方便說明,一個包含多個外觀的字型檔我們叫做字型集合,這種情況不多見,但是多數亞洲字型都是如此,它們會包含兩種或多種表現形式的映像,例如橫向和縱向布局。
2、字元映象和圖
字元映象叫做字形,根據書寫、用法和上下文,單個字元能夠有多個不同的映象,即多個字形。多個字元也可以有一個字形(例如Roman??)。字元和字形之間的關係可能是非常複雜,本文不多述。而且,多數字型格式都使用不太難用的方案儲存和訪問字形。為了清晰的原因,當說明FT時,保持下面的觀念
* 一個字型檔包含一組字形,每個字形可以存成位元影像、向量表示或其他結構(更可縮放的格式使用一種數學表示和控制資料/程式的結合方式)。這些字形可以以任意順序存在字型檔中,通常通過一個簡單的字形索引訪問。
* 字型檔包含一個或多個表,叫做字元圖,用來為某種字元編碼將字元碼轉換成字形索引,例如ASCII、Unicode、Big5等等。單個字型檔可能包含多個字元圖,例如大多TrueType字型檔都會包含一個Apple特定的字元圖和Unicode字元圖,使它在Mac和Windows平台都可以使用。
3、字元和字型度量
每個字元映象都關聯多種度量,被用來在渲染文本時,描述如何放置和管理它們。在後面會有詳述,它們和字形位置、游標步進和文本布局有關。它們在渲染一個文本串時計算文字資料流時非常重要。
每個可縮放的字型格式也包含一些全域的度量,用概念單位表示,描述同一種外觀的所有字形的一些特性,例如最大字形外框,字型的上行字元、下行字元和文本高度等。
雖然這些度量也會存在於一些不可縮放格式,但它們只應用於一組指定字元維度和解析度,並且通常用象素表示。
二、字形輪廓
1、象素、點和裝置解析度
當處理電腦圖形程式時,指定象素的物理尺寸不是正方的。通常,輸出裝置是螢幕或印表機,在水平和垂直方向都有多種解析度,當渲染文本是要注意這些情況。
定義裝置的解析度通常使用用dpi(每英寸點(dot)數)表示的兩個數,例如,一個印表機的解析度為300x600dpi表示在水平方向,每英寸有300 個象素,在垂直方向有600個象素。一個典型的電腦顯示器根據它的大小,解析度不同(15’’和17’’顯示器對640x480象素大小不同),當然圖形模式解析度也不一樣。
所以,文本的大小通常用點(point)表示,而不是用裝置特定的象素。點是一種簡單的物理單位,在數字印刷中,一點等於1/72英寸。例如,大多羅馬書籍使用10到14點大小印刷文字內容。
可以用點數大小來計算象素數,公式如下:
象素數 = 點數*解析度/72
解析度用dpi表示,因為水平和垂直解析度可以不同,單個點數通常定義不同象素文本寬度和高度。
2、向量表示
字型輪廓的源格式是一組封閉路徑,叫做輪廓線。每個輪廓線劃定字形的外部或內部地區,它們可以是線段或是Bezier曲線。
曲線通過控制點定義,根據字型格式,可以是二次(conic Beziers)或三次(cubic Beziers)多項式。在文獻中,conic Bezier通常稱為quadratic Beziers。因此,輪廓中每個點都有一個標誌表示它的類型是一般還是控制點,縮放這些點將縮放整個輪廓。
每個字形最初的輪廓點放置在一個不可分割單元的網格中,點通常在字型檔中以16位整型網格座標儲存,網格的原點在(0,0),它的範圍是-16384到-16383(雖然有的格式如Type1使用浮點型,但為簡便起見,我們約定用整型分析)。
網格的方向和傳統數學二維平面一致,x軸從左至右,y軸從下到上。
在建立字形輪廓時,一個字型設計者使用一個假想的正方形,叫做EM正方形。他可以想象成一個畫字元的平面。正方形的大小,即它邊長的網格單元是很重要的,原因是
* 它是用來將輪廓縮放到指定文本尺寸的參考,例如在300x300dpi中的12pt大小對應12*300/72=50象素。從網格單元縮放到象素可以使用下面的公式
象素數 = 點數 × 解析度/72
象素座標= 網格座標*象素數/EM大小
* EM尺寸越大,可以達到更大的解析度,例如一個極端的例子,一個4單元的EM,只有25個點位置,顯然不夠,通常TrueType字型之用2048單元的EM;Type1 PostScript字型有一個固定1000網格單元的EM,但是點座標可以用浮點值表示。
注意,字形可以自由超出EM正方形。網格單元通常交錯字型單元或EM單元。上邊的象素數並不是指實際字元的大小,而是EM正方形顯示的大小,所以不同字型,雖然同樣大小,但是它們的高度可能不同。
3、Hinting和位元影像渲染
儲存在一個字型檔中的輪廓叫“主”輪廓,它的點座標用字型單元表示,在它被轉換成一個位元影像時,它必須縮放至指定大小。這通過一個簡單的轉換完成,但是總會產生一些不想要的副作用,例如像字母E和H,它們主乾的寬度和高度會不相同。
所以,優秀的字形渲染過程在縮放“點”是,需要通過一個網格對齊(grid-fitting)的操作(通常叫hinting),將它們對齊到目標裝置的象素網格。這主要目的之一是為了確保整個字型中,重要的寬度和高度能夠一致。例如對於字元I和T來說,它們那個垂直筆劃要保持同樣象素寬度。另外,它的目的還有管理如stem和overshoot的特性,這在小象素字型會引起一些問題。
有若干種方式來處理網格對齊,多數可縮放格式中,每種字形輪廓都有一些控制資料和程式。
* 顯式網格對齊
TrueType格式定義了一個基於棧的虛擬機器(VM),可以藉助多於200中作業碼(大多是幾何操作)來編寫程式,每個字形都由一個輪廓和一個控製程序組成,後者可以處理實際的網格對齊,他由字型設計者定義。
* 隱式網格對齊(也叫hinting)
Type1格式有一個更簡單的方式,每個字形由一個輪廓以及若干叫hints的片斷組成,後者用來描述字形的某些重要特性,例如主乾的存在、某些寬度勻稱性等諸如此類。沒有多少種hint,要看渲染器如何解釋hint來產生一個對齊的輪廓。
* 自動網格對齊
有些格式很簡單,沒有包括控制資訊,將字型度量如步進、寬度和高度分開。要靠渲染器來猜測輪廓的一些特性來實現得體的網格對齊。
下面總結了每種方案的優點和缺點
方案 優點 缺點
顯式 品質:對小字型有很好的結果,這對螢幕顯示非常重要。 速度:如果程式很複雜,解釋位元組碼很慢
一致性:所有渲染器產生同樣的字形位元影像。 大小:字形程式會很長。
技術難度:編寫優秀的hinting程式非常難,沒有好的工具支援。
隱式 大小:Hint通常比顯式字形程式小的多 品質:小字型不好,最後結合反走樣
速度:網格對齊會非常快 不一致:不同渲染器結果不同,甚至同一引擎不同版本也不同。
自動 大小:不需要控制資訊,導致更小的字型檔 品質:小字型不好,最後結合反走樣
速度:依賴對齊演算法,通常比顯式對齊快。 速度:依賴演算法
不一致:不同渲染器結果不同,甚至同一引擎不同版本也不同。
三、字形度量
1、基準(baseline)、筆(pen)和布局(layout)
基準是一個假想的線,用來在渲染文本時知道字形,它可以是水平(如Roman)和是垂直的(如中文)。而且,為了渲染文本,在基準上有一個虛擬點,叫做筆位置(pen position)或原點(origin),他用來定位字形。
每種布局使用不同的規約來放置字形:
* 對水平布局,字形簡單地擱在基準上,通過增加筆位置來渲染文本,既可以向右也可以向左增加。
兩個相鄰筆位置之間的距離是根據字形不同的,叫做步進寬度(advance width)。注意這個值總是正數,即使是從右往左的方向排列字元,如Arabic。這和文本渲染的方式有些不同。
筆位置總是放置在基準上。
* 對垂直布局,字形在基準上置中放置:
2、印刷度量和邊界框
在指定字型中,定義了多種外觀度量。
* 上行高度(ascent)。從基準到放置輪廓點最高/上的網格座標,因為Y軸方向是向上的,所以它是一個正值。
* 下行高度(descent)。從基準到放置輪廓點最低/下的網格座標,因為Y軸方向是向上的,所以它是一個負值。
* 行距(linegap)。兩行文本間必須的距離,基準到基準的距離應該計算成
上行高度 - 下行高度 + 行距
* 邊界框(bounding box,bbox)。這是一個假想的框子,他儘可能緊密的裝入字形。通過四個值來表示,叫做xMin、yMin、xMax、yMax,對任何輪廓都可以計算,它們可以是字型單元(測量原始輪廓)或者整型象素單元(測量已縮放的輪廓)。注意,如果不是為了網格對齊,你無需知道這個框子的這個值,只需知道它的大小即可。但為了正確渲染一個對齊的字形,需要儲存每個字形在基準上轉換、放置的重要對齊。
* 內部leading。這個概念從傳統印刷業而來,他表示字形出了EM正方形空間數量,通常計算如下
internal leading = ascent – descent – EM_size
* 外部leading。行距的別名。
3、跨距(bearing)和步進
每個字形都有叫跨距和步進的距離,它們的定義是常量,但是它們的值依賴布局,同樣的字形可以用來渲染橫向或縱向文字。
* 左跨距或bearingX。從當前筆位置到字形左bbox邊界的水平距離,對水平布局是正數,對垂直布局大多是負值。
* 上跨距或bearingY。從基準到bbox上邊界的垂直距離,對水平布局是正值,對垂直布局是負值。
* 步進寬度或advanceX。當處理文本渲染一個字形後,筆位置必須增加(從左向右)或減少(從右向左)的水平距離。對水平布局總是正值,垂直布局為null。
* 步進高度或advanceY。當每個字形渲染後,筆位置必須減少的垂直距離。對水平布局為null,對垂直布局總是正值。
* 字形寬度。字形的水平長度。對未縮放的字型座標,它是bbox.xMax-bbox.xMin,對已縮放字形,它的計算要看特定情況,視乎不同的網格對齊而定。
* 字形高度。字形的垂直長度。對未縮放的字型座標,它是bbox.yMax-bbox.yMin,對已縮放字形,它的計算要看特定情況,視乎不同的網格對齊而定。
* 右跨距。只用於水平布局,描述從bbox右邊到步進寬度的距離,通常是一個非負值。
advance_width – left_side_bearing – (xMax-xMin)
是水平布局所有的度量
是垂直布局的度量
4、網格對齊的效果
因為hinting將字形的控制點對齊到象素網格,這個過程將稍稍修改字元映象的尺寸,和簡單的縮放有所區別。例如,小寫字母m的映象在主網格中有時是一個正方形,但是為了使它在小象素大小情況下可以辨別,hinting試圖擴大它已縮放輪廓,以讓它三條腿區分開來,這將導致一個更大的字元位元影像。
字形度量也會受網格對齊過程的影響:
* 映象的寬度和高度改變了,即使只是一個象素,對於小象素大小字形區別都很大;
* 映象的邊界框改變了,也改變了跨距;
* 步進必須更改,例如如果被hint的位元影像比縮放的位元影像大時,必須增加步進寬度,來反映擴大的字形寬度。
這有一些含義如下,
* 因為hinting,簡單縮放字型上行或下行高度可能不會有正確的結果,一個可能的方法時保持被縮放上行高度的頂和被縮放下行高度的底。
* 沒有容易的方法去hint一個範圍內字形並步進它們寬度,因為hinting對每個輪廓工作都不一樣。唯一的方法時單獨hint每個字形,並記錄傳回值。有些格式,如TrueType,包含一些表對一些通用字元預先計算出它們的象素大小。
* hinting依賴最終字元寬度和高度的象素值,意味著它非常依賴解析度,這個特性使得正確的所見即所得 (WYSIWYG)布局非常難以實現。
在FT 中,對字形輪廓處理2D變換很簡單,但是對一個已hint的輪廓,需要注意專有地使用整型象素距離(意味著FT_Outline_Translate() 函數的參數應該都乘以64,因為點座標都是26.6固定浮點格式),否則,變換將破壞hinter的工作,導致非常難看的位元影像。
5、文本寬度和邊界框
如上所示,指定字形的原點對應基準上筆的位置,沒有必要定位字形邊界框的某個角,這不像多數典型的位元影像字型格式。有些情況,原點可以在邊界框的外邊,有時,也可以在裡邊,這要看給定的字形外形了。
同樣,字形的步進寬度是在布局時應用於筆位置的增量,而不是字形的寬度,那是字形邊界的寬度。對文本串,具有相同的規約,這意味著:
* 指定文本串的邊界框沒有必要包含文本游標,也不需要後邊的字形放置在它的角上。
* 字串的步進寬度和它的邊界框大小無關,特別時它在開始和最後包含空格或tab。
* 最後,附加的處理如間距調整能夠建立文本串,它的大小不直接依賴單獨字形度量並列排列。例如,VA的步進寬度不是V和A各自的步進之和。
四、字元間距調整
字元間距調整這個術語指用來在一個文本串中調整重合字形的相對位置的特定資訊。
1、字元間距調整對
字元間距調整包括根據相鄰字形的輪廓修改它們之間的距離。例如T和y可以貼得更近一點,因為y的上緣正好在T的右上方一橫的下邊。
當僅僅根據字形的標準寬度來布局文本,一些連續的字元看上去有點太擠和太松,例如中A和V的就顯得距離太遠。
比較一下,同樣的單詞,A和V的距離拉近些
可以看到,這個調整可以導致很大的區別。有的字型外觀包含一個表,它包含文本布局所需的指定字形對的字距距離。
* 這個對是順序的,AV對的距離和VA對不一定一致;
* 依據布局或書寫,字距可以表示水平或垂直方向。
* 字距表示成網格單元,它們通常是X軸方向的,意味著負值表示兩個字形需要在水平方向放的更近一點。
2、應用字元間距調整
在渲染文本時應用字據調整是一個比較簡單的過程,只需要在寫下一個字形時,將縮放的字距加到筆位置即可。然而,正確的渲染器要考慮的更細一點。
“滑動點”問題是一個很好的例子:很多字型外觀包括一個大寫字元(如T、F)和一個點.之間的字元間距調整,以將點正好放置在前者的主腿的右側。
根據字元的外形,有時候需要在點和隨後的字元間作附加的調整,當應用“標準”的字元間距調整,上面的句子如下
這顯然太緊湊了。一個方案是,只在需要時滑動點,當然這需要對文本的意思有瞭解。如果當我們在渲染特定段落的最後一個點時,上面的調整就不適合了。這隻是一個例子,還有很多其他例子顯示一個真正的印刷工人需要恰當地布局文本。
有一個很簡單地演算法,可以避免滑動點問題。
1. 在基準上放置第一個字形;
2. 將筆位置儲存到pen1;
3. 根據第一個和第二個字形的字距距離調整筆位置;
4. 放置第二個字形,並計算下個筆位置,放到pen2;
5. 如果pen1大於pen2,使用pen1作為下個筆位置,否則使用pen2。
五、文本處理
1、書寫簡單文本串
在第一個例子中,我們將產生一個簡單的Roman文字串,即採用水平的自左向右布局,使用專有的象素度量,這個過程如下:
1. 將字串轉換成一系列字形索引;
2. 將筆放置在游標位置;
3. 獲得或裝入字形映象;
4. 平移字形以使它的原點匹配筆位置;
5. 將字形渲染到目標裝置;
6. 根據字形的步進象素增加筆位置;
7. 對剩餘的字形進行第三步;
8. 當所有字形都處理了,在新的筆位置設定文本游標。
注意字元間距調整不在這個演算法中。
2、子象素定位
在渲染文本時使用子象素定位有時很有用。這非常重要,例如為了提供半所見即所得 (WYSIWYG)的文本布局,文本渲染的演算法和上一節很相似,但是有些區別:
* 筆位置表示成小數形式的象素;
* 因為將一個已經hint過的輪廓平移一個非整型距離將破壞網格對齊,字形原點的位置在渲染字元映象前必須取整;
* 步進寬度表示成小數形式的象素,沒有必要是整型。
這裡是演算法的改進版本:
1. 將字串轉換成一系列字形索引;
2. 將筆放置在游標位置,這可以是一個非整型點;
3. 獲得或裝入字形映象;
4. 平移字形以使它的原點匹配取整後的筆位置;
5. 將字形渲染到目標裝置;
6. 根據字形的步進象素寬度增加筆位置,這個寬度可以是小數形式;
7. 對剩餘的字形進行第三步;
8. 當所有字形都處理了,在新的筆位置設定文本游標。
注意使用小數象素定位後,兩個指定字元間的空間將不是固定的,它右先前的取整操作堆積的數決定。
3、簡單字元間距調整
在基本文本渲染演算法上增加字元間距調整非常簡單,當一個字元間距調整對發現了,簡單地在第4步前,將縮放後的調整距離增加到筆位置即可。淡然,這個距離在演算法1需要被取整,演算法2不必要。
4、自右向左布局
布局Arabic或Heberw文字的過程非常相似,區別只是在字形渲染前,筆位置需要減少(記住步進寬度總是正值)
5、垂直布局
布局垂直文字也是同樣的過程,重要的區別如下:
* 基準是垂直的,使用垂直的度量而不是水平度量;
* 左跨距通常是負的,但字形原點必須在基準上;
* 步進高度總是正值,所以筆位置必須減少以從上至下書寫;
6、所見即所得 (WYSIWYG)布局
六、FT輪廓
1、FT輪廓描述和結構
a. 輪廓曲線分解
一個輪廓是2D平面上一系列封閉的輪廓線。每個輪廓線由一系列線段和Bezier弧組成,根據檔案格式不同,曲線可以是二次和三次多項式,前者叫quadratic或conic弧,它們在TrueType格式中用到,後者叫cubic弧,多數用於Type1格式。
每條弧由一系列起點、終點和控制點描述,輪廓的每個點有一個特定的標記,表示它用來描述一個線段還是一條弧。這個標記可以有以下值:
FT_Curve_Tag_On 當點在曲線上,這對應線段和弧的起點和終點。其他標記叫做“Off”點,即它不在輪廓線上,但是作為Bezier弧的控制點。
FT_Curve_Tag_Conic 一個Off點,控制一個conic Bezier弧
FT_Curve_Tag_Cubic 一個Off點,控制一個cubic Bezier弧
下面的規則應用於將輪廓點分解成線段和弧
* 兩個相鄰的“on”點表示一條線段;
* 一個conic Off點在兩個on點之間表示一個conic Bezier弧,off點是控制點,on點是起點和終點;
* 兩個相鄰的cubic off點在兩個on點之間表示一個cubic Bezier弧,它必須有兩個cubic控制點和兩個on點。
* 最後,兩個相鄰的conic off點強制??在它們正中間建立一個虛擬on點。這大大方便定義連續的conic弧。TrueType規範就是這麼定義的。
注意,在單個輪廓線中可以混合使用conic和cubic弧,不過現在沒有那種字型驅動產生這樣的輪廓。
b. 輪廓描述符
FT輪廓通過一個簡單的結構描述
FT_Outline
n_points 輪廓中的點數
n_contours 輪廓中輪廓線數
points 點座標數組
contours 輪廓線端點索引數組
tags 點標記數組
這裡,points是一個FT_Vector記錄數組的指標,用來儲存每個輪廓點的向量座標。它表示為一個象素1/64,也叫做26.6固定浮點格式。
contours是一組點索引,用來劃定輪廓的輪廓線。例如,第一個輪廓線總是從0點開始,以contours[0]點結束。第二個輪廓線從contours[0]+1點開始,以contours[1]結束,等等。
注意,每條輪廓線都是封閉的,n_points應該和contours[n_controus-1]+1相同。最後,tags是一組位元組,用來存放每個輪廓的點標記。
2、邊界和控制框計算
邊界框(bbox)是一個完全包含指定輪廓的矩形,所要的是最小的邊界框。因為弧的定義,bezier的控制點無需包含在輪廓的邊界框中。例如輪廓的上緣是一個Bezier弧,一個off點就位於bbox的上面。不過這在字元輪廓中很少出現,因為大多字型設計者和建立工具都會在每個曲線拐點處放一個on點,這會使hinting更加容易。於是我們定義了控制框(cbox),它是一個包含輪廓所有點的最小矩形,很明顯,它包含bbox,通常它們是一樣的。不想 bbox,cbox計算起來非常快。
控制框和邊界框可以通過函數FT_Outline_Get_CBox()和 FT_Outline_Get_BBox()自動計算,前者總是非常快,後者在有外界控制點的情況下會慢一點,因為需要找到conic和cubic弧的末端,如果不是這種情況,它和計算控制框一樣快。
注意,雖然大多字形輪廓為易於hint具有相同的cbox和bbox,這在它們進行變換以後,如旋轉,就不再是這種情況了。
3、座標、縮放和網格對齊
輪廓點的向量座標表示為26.6格式,即一個象素的1/64。因此,座標(1.0,-2.5)存放整型對(x:64,y:-192)。
在主字形輪廓從EM網格縮放到當前字元大小後,hinter負責對齊重要的輪廓點到象素網格。雖然這個過程很難幾句話說清楚,但是它的目的也就是取整點的位置,以保持字形重要的特性,如寬度、主乾等。下面的操作可以用來將26.6格式的向量距離取整到網格:
round(x) == (x + 32) & -64
floor(x) == x & -64
ceiling(x) == (x + 63) & -64
一旦一個字形輪廓經過對齊或變換,在渲染之前通常要計算字形的映象象素大小。做到這一點,必須考慮如下:
掃描線轉換器畫出所有中心在字形形狀中的象素,他也可以檢測drop-outs???
這導致如下的計算:
* 計算bbox;
* 對齊bbox如下:
xmin = floor(bbox.xMin)
xmax = ceiling(bbox.xMax)
ymin = floor(bbox.yMin)
ymax = ceiling(bbox.yMax)
* 返回象素尺寸,即
width = (xmax-xmin) / 64
和
height = (ymax-ymin) / 64
通過對齊bbox,可以保證所有的象素中心將畫到,包括那些從drop-out控制來的,將在調整後的框子之中。接著,框子的象素尺寸可以計算出來。
同時注意,當平移一個對齊的輪廓,應該總是使用整型距離來移動。否則,字形的邊緣將不再對齊象素網格,hinter的工作將無效,產生非常難看的位元影像。
七、FT位元影像
1、向量座標和象素座標組比
這裡闡述了向量座標的象素座標的區別,為了更清楚的說明,使用方括弧來表示象素座標,使用圓括弧表示向量座標。
在象素座標中,我們使用Y軸向上的規約,座標[0,0]總是指位元影像左下角象素,座標[width-1, rows-1]是右上方象素。在向量座標中,點座標用浮點單位表示,如(1.25, -2.3),這個位置並不是指一個特定象素,而是在2D平面上一個非實質性的點。
象素其實在2D平面上是一個方塊,它的中心是象素座標值的一半,例如位元影像的左下角象素通過方塊(0,0)-(1,1)界定,它的中心位於 (0.5,0.5)。注意這兒用的是向量座標表示。這對計算距離就會發生一些區別。例如,[0,0]-[10.0]一條線的象素長度是11,然而, (0,0)-(10,0)的向配量度覆蓋了10個象素,因此它的長度是10。
2、FT位元影像和象素圖描述符
一個位元影像和象素圖通過一個叫FT_Bitmap的單一結構描述,他定義在<freetype/ftimage.h>中,屬性如下
FT_Bitmap
rows 行數,即位元影像中的水平線數
width 位元影像的水平象素數
pitch 它的絕對值是位元影像每行占的位元組數,根據位元影像向量方向,可以是正值或是負值
buffer 一個指向位元影像象素緩衝的無類型指標
pixel_mode 一個枚舉值,用來表示位元影像的象素格式;例如ft_pixel_mode_mono表示1位單色位元影像,ft_pixel_mode_grays表示8位反走樣灰階值
num_grays 這隻用於灰階象素模式,它給出描述反走樣灰階層級的級數,FT預設值為255。
pitch 屬性值的正負符號確定象素緩衝中的行是升序還是降序存放。上面說道FT在2D平面上使用Y軸向上的規約,這意味著(0,0)總是指向位元影像的左下角。如果 picth是正值,按照向量減少的方向儲存行,即象素緩衝的第一個位元組表示位元影像最上一行的部分。如果是負值,第一個位元組將表示位元影像最下一行的部分。對所有的情況,pitch可以看作是在指定位元影像緩衝中,跳到下一個掃描行的位元組增量。
通常都使用正pitch,當然有的系統會使用負值。
3、輪廓轉換到位元影像和象素圖
使用FT從一個向量映象轉換到位元影像和象素圖非常簡單,但是,在轉換前,必須理解有關在2D平面上放置輪廓的一些問題:
* 字形轉載器和hinter在2D平面上放置輪廓時,總將(0,0)匹配到字元原點,這意味著字形輪廓,及對應的邊界框,可以在平面中放置於任何地方。
* 目標位元影像映射到2D平面上,左下角在(0,0)上,這就是說一個[w,h]大小的位元影像和象素圖將被映射到(0,0)-(w,h)界定的2D矩形視窗。
* 當掃描轉換輪廓,所有在這個位元影像視窗的部分將被渲染,其他的被忽略。
很多使用FT的開發人員都會有個誤解,認為一個裝入的輪廓可以直接渲染成一個適當大小的位元影像,下面的映像表明這個問題。
* 第一個圖表明一個2D平面上一個裝入的輪廓;
* 第二個表示一個任意大小[w,h]維護的目標視窗;
* 第三個表示在2D平面上輪廓和視窗的合并;
* 最後一個表示位元影像實際被渲染的部分。
實際上,幾乎所有的情況,裝入或變換過的輪廓必須在渲染成目標位元影像之前作平移操作,以調整到相對目標視窗的位置。
例如,建立一個單獨的字形位元影像正確的方法如下:
* 計算字形位元影像的大小,可以直接從字形度量計算出來,或者計算它的邊界框(這在經過變換後非常有用,此時字形度量不再有效)。
* 根據計算的大小建立位元影像,別忘了用背景色填充象素緩衝;
* 平移輪廓,使左下角匹配到(0,0)。別忘了為了hinting,應該使用整型。通常,這就是說平移一個向量(-ROUND(xMin), -ROUND(yMin))。
* 調用渲染功能,例如FT_Outline_Render()函數。
在將字形映象直接寫入一個大位元影像的情況,輪廓必須經過平移,以將它們的向量位置對應到當前文本游標/字元原點上。