初探FreeType
前言
繪圖API並不支援畫字型的功能,以前使用Direct2D搭配DirectWrite來畫字型,但不幸地現在繪圖引擎要跨平台,Direct2D的方法最多只能在Windows平台使用,FreeType就是我找到的可以跨平台的畫字型方法,這裡把學習心得做個紀錄。
內容
首先先來說說"建置",FreeType自帶的建置個人覺得實在是不怎麼好用,Windows版的建置是由官方給個Visual studio專案直接開啟後建置即可,但Linux的建置就完全不一樣,是類似透過Shell script的方式來建置,Android則是透過NDK的專案來建置,最後我並沒選擇官方的建置是因為FreeType在下載時是在Windows平台,所以裡面的文字檔的換行是"\r\n",結果當我在Ubuntu建置時都會報錯,也就是說跟建置相關的檔案絕不能在Windows的環境編輯,不然上傳後就沒辦法用了。解決的方案很簡單,就是自己建置,還記得官方有自帶一個Visual studio專案嗎?我依據該專案的建置方案來製作Linux與Android的建置,這方法有風險,但我還是做了,幸運的是Linux與Android的建置與Windows是差不多,差別的地方是Linux與Android版並沒有所謂的"Debug"版,編譯時不用加"FT_DEBUG_LEVEL_ERROR"與"FT_DEBUG_LEVEL_TRACE"編譯,其它的部分和Windows版是一樣的。
接著來看看如何使用,先看以下範例
#include "ft2build.h"
#include FT_FREETYPE_H
int main()
{
//...
//
FT_Library library;
FT_Error error=FT_Init_FreeType(&library);
if(error!=0)
return 1;
//
//...
//Free
FT_Done_FreeType(library);
return 0;
}
這個範例會去製造FT_Library,整個程式應該只要製造一個,在程式要結束時,透過FT_Done_FreeType()來釋放。FT_Library製造完後就可以來讀取font檔,範例如下
#include "ft2build.h"
#include FT_FREETYPE_H
int main()
{
//...
//
FT_Library library;
FT_Error error=FT_Init_FreeType(&library);
if(error!=0)
return 1;
//Load font file
FT_Face face;
error=FT_New_Face(library,"arial.ttf",0,&face);
//...
//Free
FT_Done_Face(face);
FT_Done_FreeType(library);
return 0;
}
讀取的方法很簡單,透過FT_New_Face()來讀取,透過FT_Done_Face()來釋放。在Android時,由於Android的Asset不提供Handle,如果要將Font檔放在Asset的話,就要透過FT_New_Memory_Face()來讀取。接下來就來讀取字型的資料,範例如下
#include "ft2build.h"
#include FT_FREETYPE_H
int main()
{
//...
//
FT_Library library;
FT_Error error=FT_Init_FreeType(&library);
if(error!=0)
return 1;
//Load font file
FT_Face face;
error=FT_New_Face(library,"arial.ttf",0,&face);
//Set font size
error=FT_Set_Pixel_Sizes(face,0,60);
//Load glyph
FT_UInt glyphIndex=FT_Get_Char_Index(face,'a');
if(glyphIndex==0)
return 1;
error=FT_Load_Glyph(face,glyphIndex,FT_LOAD_DEFAULT);
if(face->glyph->format!=FT_GLYPH_FORMAT_BITMAP)
{
error=FT_Render_Glyph(face->glyph,FT_RENDER_MODE_MONO);
if(error!=0)
return 1;
}
//Get glyph bitmap data from face->glyph->bitmap.buffer
//...
//Free
FT_Done_Face(face);
FT_Done_FreeType(library);
return 0;
}
透過FT_Set_Pixel_Sizes()來設定字型的大小,接著透過Glyph index來寫資料到"buffer"裡,"buffer"在哪呢?透過face->glyph->bitmap.buffer來取得。
Buffer的資料就是一張圖,整個Buffer的資料的大小為face->glyph->bitmap.pitch*face->glyph->bitmap.rows,"face->glyph->bitmap.rows"就是高,但"face->glyph->bitmap.pitch"並不是寬,每個Pitch指的是把寬度以每8個Pixel存成一個Byte來計算的話會有幾個Byte,如果寬度是60Pixel,Pitch值為8,如果寬度是40Pixel,Pitch值為5,依此類推。
參考資料
FreeType官網
Text Rendering with Direct2D and DirectWrite