轉(zhuǎn)載時(shí)請注明出處和作者聯(lián)系方式:http://blog.csdn.net/absurd
作者聯(lián)系方式:Li XianJing <xianjimli at hotmail dot com>
更新時(shí)間:2006-12-19
GTK+(基于DirectFB)的字體繪制是通過pango+freetype+fontconfig三者協(xié)作來完成的,其中,fontconfig負(fù)責(zé)字體的管理和配置,freetype負(fù)責(zé)單個(gè)字符的繪制,pango則完成對文字的排版布局。而我對這一部分的了解,基本上是空白的。這兩天為了解決一個(gè)關(guān)于字體的BUG,花了一些時(shí)間閱讀相關(guān)資料,這里記錄一些freetype的學(xué)習(xí)筆記。
盡管點(diǎn)陣字體在時(shí)間和空間性能上都有較佳的表現(xiàn),但是由于缺乏靈活性,無法改變字體的大小和風(fēng)格,除了在一些嵌入式設(shè)備中仍然在使用外,大多數(shù)系統(tǒng)都使用矢量字體了。矢量字體不像點(diǎn)陣字體那樣直接記錄字符的字模數(shù)據(jù),而是記錄字體描述信息,其中最重要的兩部分是outline和hint。
字體的outline(輪廓):這是用來描述字體的基本手段,它一般由直線和貝塞爾(Bézier)曲線組成。貝塞爾(Bézier)曲線是一條由三個(gè)點(diǎn)確定的曲線,假設(shè)這三點(diǎn)的坐標(biāo)是(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
字體精調(diào)提示(hint)。Outline已經(jīng)描述字體的表現(xiàn)形式,但是數(shù)學(xué)上的正確對人眼來說并不見得合適,特別是縮放到特定的大小和分辨率的時(shí)候,字體可能變得不好看,或者不清析。Hint指的是一系列的技術(shù),用來精調(diào)字體,讓字體變得更美觀,更清析。
在truetype字體中,hint是用一種編程語言來表述的,這種語言有點(diǎn)像匯編語言,每個(gè)語句完成一個(gè)單一的功能,通常用一個(gè)虛擬機(jī)來解釋執(zhí)行。它具有下列特點(diǎn):
l 支持循環(huán)。
l 支持條件分支。
l 支持用戶定義的函數(shù)。
l 支持以不同方式操作數(shù)據(jù)的指令集。
l 支持?jǐn)?shù)學(xué)和邏輯指令集。
l 其它一些方法。
字符影射表(charmap)。字符對應(yīng)的字體數(shù)據(jù)稱為glyph,字體文件中通常帶有一個(gè)字符映射表,用來把字符映射到對應(yīng)glyph的索引值。因?yàn)樽址木幋a方式有多種,所以可以存在多個(gè)子映射表,以支持從不同編碼的字符到glyph索引的映射。如果某個(gè)字符沒有對應(yīng)的glyph,返回索引0,glyph 0通常顯示一個(gè)方塊或者空格。
矢量字體有多種不同的格式,其中TrueType用得最為廣泛。它的擴(kuò)展名通常為OTF或者TTF,它的文件內(nèi)容由幾部分組成,文件頭、表目錄和表。文件頭描述了版本號和表的數(shù)目等信息,表目錄記錄了表的偏移量和大小,表則是表的實(shí)際數(shù)據(jù)。
文件頭的格式為:
類型
|
名稱
|
描述
|
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.
|
而表目錄的結(jié)構(gòu)為:
類型
|
名稱
|
描述
|
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.
|
而表的內(nèi)容則與具體的表有關(guān),比如cmap表存放是的字符映射關(guān)系、fpgm表存放的是outline的函數(shù)庫、glyf表存放的是outline數(shù)據(jù)、而EBDT表存放的是嵌入式位圖。
表EBDT(嵌入式位圖)有什么用呢,原來是這樣的,矢量字體盡管可以任何縮放,但縮得太小時(shí),仍然存在問題,字體會變得不好好看或者不清析,即使采用hint精調(diào),效果也不一定好,或者那樣處理太麻煩了,這時(shí)可以采用點(diǎn)陣字體來彌補(bǔ)矢量字體的不足,EBDT就是用來存放點(diǎn)陣字體的字模數(shù)據(jù)的。
矢量字體的處理比較麻煩,即要進(jìn)行矢量計(jì)算,又進(jìn)行精調(diào)處理,相對于點(diǎn)陣字體來說慢多了,會不會存在性能問題呢?可能會的,不過可以通過下列兩種方式緩解性能問題:
l cache法。把剛計(jì)算出來的glyph放到cache中,下次再用到這個(gè)字符時(shí),直接從cache中取,而不用重新計(jì)算。
l 預(yù)先計(jì)算法。把常用值預(yù)先計(jì)算出來,放在hdmx等表中,這可以節(jié)省不少計(jì)算時(shí)間。
Freetype是一個(gè)操作字體的函數(shù)庫,它不但可以處理點(diǎn)陣字體,也可以處理多種矢量字體,包括truetype字體,為上層應(yīng)用程序提供了一個(gè)統(tǒng)一的調(diào)用接口。Freetype具有良好的可移植性,特別考慮了嵌入式應(yīng)用環(huán)境,字體文件可以在文件系統(tǒng)中,也可以在ROM中,甚至可以用自定義IO函數(shù)來訪問字體數(shù)據(jù)。Freetype采用模塊化設(shè)計(jì),很容易進(jìn)行擴(kuò)充和裁減,據(jù)說如果只支持truetype,裁減后的二進(jìn)制文件大小只有25K。Freetype是開放源代碼的,它采用FreeType和GPL兩種開源協(xié)議,可以用于任何商業(yè)用途。
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,
size,
0,
&face );
|
4. 設(shè)置字體的大小
error = FT_Set_Char_Size(
face,
0,
16*64,
300,
300 );
error = FT_Set_Pixel_Sizes(
face,
0,
16 );
|
5. 加載字符的glyph
glyph_index = FT_Get_Char_Index( face, charcode );
error = FT_Load_Glyph(
face,
glyph_index,
load_flags );
error = FT_Render_Glyph( face->glyph,
render_mode );
|
6. 字體變換(旋轉(zhuǎn)和縮放)
error = FT_Set_Transform(
face,
&matrix,
&delta );
|
7. 把字符顯示出來(與具體實(shí)現(xiàn)有關(guān))
draw_bitmap( &slot->bitmap,
pen_x + slot->bitmap_left,
pen_y - slot->bitmap_top );
|
對于字體處理,我才了解一點(diǎn)皮毛,希望大家不吝賜教。
參考資源:
http://freetype.sourceforge.net
http://www.truetype-typography.com/
~~end~~