一、FreeType2簡介
1. 是一個免費、開源、可移植且高質量的字體引擎;
2. 支持多種字體格式文件,並提供了統一的訪問接口;
3. 支持單色位圖、反走樣位圖渲染,這使字體顯示質量達到Mac的水平;
4. 採用面向對象思想設計,用户可以靈活的根據需要裁剪。
二、FreeType2字形約定
2.1 基本概念
字形:
字符映像叫做字形,單個字符能夠有多個不同的映像,即多個字形。多個字符也可以有一個字形。
(可以理解為一個字形就是一種書寫風格)
字符圖:
字體文件包含一個或多個表,叫做字符圖。用來將某種字符碼轉換成字形索引。一種字符編碼方式(如ASCII、Unicode、Big5)對應一張表。
2.2字形輪廓
點:
字形文本的大小通常用點(point)表示。點是一種簡單的物理單位,數字印刷中,一點等於1/72英寸。
設備的分辨率通常使用dpi(每英寸點數)表示的兩個數。
點數大小和像素數的轉換公式:
像素大數 = 點數*分辨率/72
輪廓線:
字形輪廓的源格式是一組封閉的路徑,稱為輪廓線。每個輪廓線劃定字形的外部或內部區域,它們可以是線段或者Bezier曲線。
EM正方形:
字體在創建字形輪廓時,字體創建者所使用的假象的正方形。他可以將此想象成一個畫字符的平面。它是用來將輪廓線縮放到指定文本尺寸的參考;它的尺寸越大,可以達到更大的字形分辨率。
注意:字形可以自由的超出EM正方形。
位圖渲染:
指從字形輪廓轉換成一個位圖的過程。
2.3 字形度量
基線、筆和佈局:
基線是一個假象的線,用來在渲染文本時知道字形,它可以是水平或垂直的。而且,為了渲染文本,在基線上有一個虛擬的點,叫做筆位置或原點,它用來定位字形。每種佈局使用不同的規約來放置字形:
對水平佈局,字形簡單地擱在基線上;
對於垂直佈局,字形在基線上句中放置。
圖1. 水平佈局及其度量
圖2.垂直佈局及其度量
重要的字體度量參數:
上下高度(ascent): 從基線到放置輪廓點最高(上)的距離;
下行高度(descent):從基線到放置輪廓點最低(下)的距離;
左跨距(bearingX): 從當前筆位置到輪廓左邊界的水平位置;
上跨距(bearingY): 從當前筆位置到輪廓上邊界的垂直位置;
步進寬度(advanceX): 相鄰兩個筆位置的水平距離(字間距);
字形寬度(width): 字形的水平長度;
字形高度(height): 字形的垂直長度。
三、FreeType2基本數據結構及API
3.1 基本數據結構
FT_Library(庫對象):
FreeType庫句柄對象
(不用關心其成員)
FT_Face(外觀對象):
成員:
num_faces: 字體文件所含外觀數
face_index: 當前外觀索引值
num_glyphs: 當前外觀所含字形文件數
num_charmaps: 字符表數
charmaps: 字符表數組
charmap: 當前字符表
glyph: 字形槽對象
size: 字形尺寸
FT_Size(尺寸對象):
成員:
face: 指向父對象(FT_Face對象)
metrics: 字形尺寸對象
FT_Size_Metrics(EM度量對象):
成員:
x_ppem: EM正方形水平像素數
y_ppem: EM正方形垂直像素數
ascender: EM正方形上行距離
descender: EM正方形下行距離
height: EM正方形高度
max_advance: 最大步進寬度
FT_GlyphSlot(字形槽對象):
成員:
face: 指向父對象(FT_Face對象)
metrics: 字形尺寸對象
advance: 步進對象
format: 字形槽格式
bitmap: 字形位圖
bitmap_top: 位圖上行距離
bitmap_left: 位圖左行距離
outline: 字形輪廓線
FT_Vector(步進向量):
成員:
x: 水平步進值
y: 垂直步進值
FT_Bitmap(字形位圖對象):
成員:
row: 位圖行數(高度)
width: 位圖寬度
buffer: 位圖數據(默認8位灰度值)
FT_Glyph_Metrics(字形槽度量對象):
成員:
width: 字符映像寬度
height: 字符映像高度
horiBearingX: 左跨距(水平佈局)
horiBearingY: 右跨距(水平佈局)
horiAdvance: 水平步進
vertBearingX: 左跨距(垂直佈局)
vertBearingY: 右跨距(垂直佈局)
vertAdvance: 垂直步進
3. 2 基本API
FT_ErrorFT_Init_FreeType(FT_Library *alibrary):
函數功能:
實例化一個FreeType庫對象,並返回給alibrary;
返回值:
若實例化成功則返回0。
FT_ErrorFT_Done_FreeType(FT_Library library):
函數功能:
銷燬FreeType庫對象library,包括其所有子對象;
FT_ErrorFT_New_Face(FT_Library library, const char*
filepathname, FT_Longface_index,FT_Face*aface ):
函數功能:
打開filepathname所指定的字體文件,加載第index個字體外觀,並返回給aface指定的地址。
FT_ErrorFT_Set_Char_Size(FT_Face face,
FT_F26Dot6 char_width, FT_F26Dot6 char_height,
FT_UInthorz_resolution,FT_UIntvert_resolution ):
函數功能:
設置字體大小;
輸入參數:
char_width: 以1/64點為單位的字符寬度;
char_height: 以1/64點為單位的字符高度;
horz_resolution: 設備水平分辨率;
vert_resolution: 設備垂直分辨率。
注意:
字符寬度或高度可設置為0,這意味着寬度或高度與另一個參數(高度或寬度)相同;
水平或垂直分辨率設置為0時表示使用默認的72dpi。
FT_UIntFT_Get_Char_Index(FT_Face face,
FT_ULong charcode):
函數功能:
在選定的字符表中,查找與給出的字符碼對應的字形索引。
返回值:
如果沒有字符表被選中,這個函數簡單返回字符碼;
如果該字符表總沒有該字符碼對應的字形圖像,返回0。
注意:
0對應特殊的字符圖像,通常會顯示一個框或空格;
新建一個face時,默認是Unicode編碼的字符表。
FT_Error FT_Load_Glyph( FT_Face face, FT_UInt
glyph_index, FT_Int32load_flags):
函數功能:
從face中裝載第index個字形圖像到字形槽中(face->glyph)。
輸入參數:
load_flags:裝載標誌,默認FT_LOAD_DEFAULT。此時優先裝載嵌入位圖,若無,則裝載該字形的縮放後的輪廓線。
face->glyph->format描述了字形圖像的格式。若它的值是FT_GLYPH_FORMAT_OUTLINE,則可調用FT_Outline_Embolden加粗輪廓線;若它的值不是FT_GLYPH_FORMAT_BITMAP,則可通過FT_Render_Glyph把它轉換成位圖。
FT_Error FT_Outline_Embolden(FT_Outline* outline,FT_Pos strength):
函數功能:
將輪廓線加粗strength(26.6像素格式)。
FT_Error FT_Render_Glyph(FT_GlyphSlot slot,FT_Render_Moderender_mode):
函數功能:
將字形槽對象(slot)中的字形圖像轉換成字形位圖。
輸入參數:
render_mode:渲染模式位標誌集合,默認使用
FT_RENDER_MODE_NORMAL渲染模式,表示渲染為一個高質量的抗鋸齒(256級灰度)位圖。
int main()
{
FT_Library library;
FT_Face face;
FT_Error error;
FT_UInt charIdx;
wchar_t wch = 'a';
char* buffer; // 用户申請的顯示區域空間
int startX, startY; // 字符圖像開始裝入的位置
// 1. 初始化freetype2庫
error = FT_Init_FreeType(&library);
// 2. 創建一個face
error = FT_New_Face(library, "C:\\windows\\font\\SURSONG.TTF", 0, &face);
// 3. 設置字體尺寸
error = FT_Set_Char_Size(face, 16*64, 16*64, 96, 96);
// 4. 獲取字符圖像索引
charIdx = FT_Get_Char_Index(face, wch);
// 5. 加載字符圖像
FT_Load_Glyph(face, charIdx, FT_LOAD_DEFAULT);
if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
{
FT_Outline_Embolden(&(face->glyph->outline), 16); // 加粗輪廓線
}
// 6. 獲取字符位圖
if (face->glyph->format != FT_GLYPH_FORMAT_BITMAP)
{
FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
}
// 7. 拷貝字符位圖到用户的buffer中(用户私人函數)
// 注意左邊的計算方法
ft2CopyBitmapToBuf(buffer, startX+face->glyph->bitmap_left,
startY+face->size->metrics.ascender/64-face->glyph->bitmap_top,
face->glyph->bitmap);
startX += face->glyph->advance.x/64;
}