FreeType 學習筆記

GTK+(基於DirectFB)的字體繪製是通過pango+freetype+fontconfig三者協 作來完成的,其中,fontconfig負責字體的管理和配置,freetype負責單個字符的繪製,pango則完成對文字的排版佈局。而我對這一部分 的瞭解,基本上是空白的。這兩天爲了解決一個關於字體的BUG,花了一些時間閱讀相關資料,這裏記錄一些freetype的學習筆記。
 
儘管點陣字體在時間和空間性能上都有較佳的表現,但是由於缺乏靈活性,無法改變字體的大小和風格,除了在一些嵌 入式設備中仍然在使用外,大多數系統都使用矢量字體了。矢量字體不像點陣字體那樣直接記錄字符的字模數據,而是記錄字體描述信息,其中最重要的兩部分是 outline和hint。
 
字體的outline( 輪廓) :這是用來描述字體的基本手段,它一般由直線和貝塞爾(Bézier)曲線組成。貝塞爾(Bézier)曲線是一條由三個點確定的曲線,假設這三點的座標是(Ax , Ay )、(Bx , By ) 和(Cx , Cy ),那麼曲線方程爲:
    px = (1-t)2 .Ax + 2t(1-t).Bx + t2 .Cx
    py = (1-t)2 .Ay + 2t(1-t).By + t2 .Cy
 
字體精調提示(hint) 。Outline已經描述字體的表現形式,但是數學上的正確對人眼來說並不見得合適,特別是縮放到特定的大小和分辨率的時候,字體可能變得不好看,或者不清析。Hint指的是一系列的技術,用來精調字體,讓字體變得更美觀,更清析。
 
在truetype字體中,hint是用一種編程語言來表述的,這種語言有點像彙編語言,每個語句完成一個單一的功能,通常用一個虛擬機來解釋執行。它具有下列特點:
l          支持循環。
l          支持條件分支。
l          支持用戶定義的函數。
l          支持以不同方式操作數據的指令集。
l          支持數學和邏輯指令集。
l          其它一些方法。
 
字符影射表(charmap) 。字符對應的字體數據稱爲glyph,字體文 件中通常帶有一個字符映射表,用來把字符映射到對應glyph的索引值。因爲字符集的編碼方式有多種,所以可以存在多個子映射表,以支持從不同編碼的字符 到glyph索引的映射。如果某個字符沒有對應的glyph,返回索引0,glyph 0通常顯示一個方塊或者空格。
 
矢量字體有多種不同的格式,其中TrueType用得最爲廣泛。它的擴展名通常爲OTF或者TTF,它的文件內容由幾部分組成,文件頭、表目錄和表。文件頭描述了版本號和表的數目等信息,表目錄記錄了表的偏移量和大小,表則是表的實際數據。
 
文件頭的格式爲:
類型
名稱
描述
Fixed
sfnt version
0x00010000 for version 1.0.
USHORT
numTables
Number of tables.
USHORT
searchRange
(Maximum power of 2 <= numTables) x 16.
USHORT
entrySelector
Log2(maximum power of 2 <= numTables).
USHORT
rangeShift
NumTables x 16-searchRange.
 
而表目錄的結構爲:
類型
名稱
描述
ULONG
tag
4 -byte identifier.
ULONG
checkSum
CheckSum for this table.
ULONG
offset
Offset from beginning of TrueType font file.
ULONG
length
Length of this table.
 
而表的內容則與具體的表有關,比如cmap表存放是的字符映射關係、fpgm 表存放的是outline的函數庫、 glyf 表存放的是outline數據、而EBDT表存放的是嵌入式位圖。
 
表EBDT(嵌入式位圖)有什麼用呢,原來是這樣的,矢量字體儘管可以任何縮放,但縮得太小時,仍然存在問題, 字體會變得不好好看或者不清析,即使採用hint精調,效果也不一定好,或者那樣處理太麻煩了,這時可以採用點陣字體來彌補矢量字體的不足,EBDT就是 用來存放點陣字體的字模數據的。
 
矢量字體的處理比較麻煩,即要進行矢量計算,又進行精調處理,相對於點陣字體來說慢多了,會不會存在性能問題呢?可能會的,不過可以通過下列兩種方式緩解性能問題:
l          cache法。把剛計算出來的glyph放到cache中,下次再用到這個字符時,直接從cache中取,而不用重新計算。
l          預先計算法。把常用值預先計算出來,放在hdmx等表中,這可以節省不少計算時間。
 
Freetype是一個操作字體的函數庫,它不但可以處理點陣字體,也可以處理多種矢量字體,包括 truetype字體,爲上層應用程序提供了一個統一的調用接口。Freetype具有良好的可移植性,特別考慮了嵌入式應用環境,字體文件可以在文件系 統中,也可以在ROM中,甚至可以用自定義IO函數來訪問字體數據。Freetype採用模塊化設計,很容易進行擴充和裁減,據說如果只支持 truetype,裁減後的二進制文件大小隻有25K。Freetype是開放源代碼的,它採用FreeType和GPL兩種開源協議,可以用於任何商業 用途。
 
Freetype的使用相對比較簡單:
 
1.         包含freetype的頭文件。
#include <ft2build.h>
#include FT_FREETYPE_H
 
 
2.         初始化freetype
FT_Library library;
error = FT_Init_FreeType( &library );
 
 
3.         加載字體
error = FT_New_Face( library,
                       "/usr/share/fonts/truetype/arial.ttf",
                       0,
&face );
 
或者
error = FT_New_Memory_Face( library,
                              buffer,    /* first byte in memory */
                              size,      /* size in bytes        */
                              0,         /* face_index           */
                              &face );
 
 
4.         設置字體的大小
 error = FT_Set_Char_Size(
            face,    /* handle to face object           */
            0,       /* char_width in 1/64th of points */
            16*64,   /* char_height in 1/64th of points */
            300,     /* horizontal device resolution    */
            300 );   /* vertical device resolution      */
 error = FT_Set_Pixel_Sizes(
            face,   /* handle to face object */
            0,      /* pixel_width           */
            16 );   /* pixel_height          */
 
 
5.         加載字符的glyph
glyph_index = FT_Get_Char_Index( face, charcode );
 error = FT_Load_Glyph(
            face,          /* handle to face object */
            glyph_index,   /* glyph index           */
            load_flags );  /* load flags, see below */
 error = FT_Render_Glyph( face->glyph,   /* glyph slot */
                           render_mode ); /* render mode */
 
 
6.         字體變換(旋轉和縮放)
 error = FT_Set_Transform(
            face,       /* target face object    */
            &matrix,    /* pointer to 2x2 matrix */
&delta );   /* pointer to 2d vector */
 
 
7.         把字符顯示出來(與具體實現有關)
draw_bitmap( &slot->bitmap,
                    pen_x + slot->bitmap_left,
pen_y - slot->bitmap_top );
 
發佈了60 篇原創文章 · 獲贊 12 · 訪問量 39萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章