Freetype 是一个操作字体的函数库,它不但可以处理点阵字体,也可以处理多种矢量字体,包括truetype字体,为上层应用程序提供了一个统一的调用接口。Freetype具有良好的可移植性,特别考虑了嵌入式应用环境,字体文件可以在文件系统中,也可以在ROM中,甚至可以用自定义IO函数来访问字体数据。Freetype采用模块化设计,很容易进行扩充和裁减,据说如果只支持truetype,裁减后的二进制文件大小只有25K。Freetype是开放源代码的,它采用FreeType和GPL两种开源协议,可以用于任何商业用途。Freetype的使用相对比较简单,下面将以一个小例子来讲解一下如何使用Freetype的函数来获取字符的位图,该例子是取32 * 32大小的位图,注释部分为详细讲解Freetype的函数,因此字可能会比较多。不多说了,来看例子吧:
#include
/************************************************************************************************************************************************
Ft2build.h包含了接下来要#include的公共FreeType2头文件的宏声明.
FT_FREETYPE_H宏包含主要的FreeType2 API头文件.
注意:从FreeType 2.1.6开始,旧式的头文件包含模式将不会再被支持.即不支持:
#include
#include
这种头文件包含模式.
************************************************************************************************************************************************/
#include
#include FT_FREETYPE_H
#define CHARSIZE 32 // 字符位图的大小设为32 * 32
int GetCharBitmap(int iCharSize, unsigned int uiCharCode);
int main(int argc, char** argv)
{
unsigned int uiCharCode = 0x0061; // 字母a的ucs2编码.
GetCharBitmap(CHARSIZE, uiCharCode);
return 0;
}
int GetCharBitmap(int iCharSize, unsigned int uiCharCode)
{
FT_Library ftLibrary;
/*********************************************************************************************************************************************
初始化一个freetype2库,函数原型: FT_EXPORT( FT_Error ) FT_Init_FreeType( FT_Library *alibrary ); *********************************************************************************************************************************************/
FT_Error ftError = FT_Init_FreeType(&ftLibrary);
if(ftError)
{
printf("Init freetype library fail!/n");
return -1;
}
/*********************************************************************************************************************************************
FT_New_Face函数从一个字体文件装载一个字体face,一个face对象描述了一个特定的字样和风格,其返回值为FT_Err_Unknown_File_Format,表示可以打开,读这个文件,但是不支持它的格式,其他非零的返回值,表示不能打开跟读该文件.返回零表示装载成功. 函数原型为:
FT_EXPORT( FT_Error )
FT_New_Face( FT_Library library, // 库的句柄
const char* filepathname, // 字体文件路径名
FT_Long face_index, // 字体face的索引,该索引指示你想装载的face如果这个值太大,函数将会返回一个错误Index为0总是正确的。
FT_Face *aface ); // 一个指向新建的face对象的指针
freetype还提供从内存装载字体face的函数,函数原型为:
FT_EXPORT( FT_Error )
FT_New_Memory_Face( FT_Library library, // 库的句柄
const FT_Byte* file_base, // 指向字体数据的第一个字节
FT_Long file_size, // 缓存的大小(以字节表示)
FT_Long face_index, // face索引
FT_Face *aface ); // face对象的指针
*********************************************************************************************************************************************/
FT_Face ftFace;
ftError = FT_New_Face( ftLibrary, "ukai.ttc", 0, &ftFace );
if(ftError == FT_Err_Unknown_File_Format)
{
printf("Error! Could not support this format!/n");
return -1;
}
else if(ftError)
{
printf("Error! Could not open file ukai.ttc!/n");
return -1;
}
/*********************************************************************************************************************************************
设置字符像素大小,尺寸中的任一个为0意味着与另一个尺寸值相等, 函数原型为:
FT_EXPORT( FT_Error )
FT_Set_Pixel_Sizes( FT_Face face, // face对象句柄
FT_UInt pixel_width, // 象素宽度
FT_UInt pixel_height ); // 象素高度
*********************************************************************************************************************************************/
ftError = FT_Set_Pixel_Sizes(ftFace, iCharSize, 0);
if(ftError)
{
printf("Set pixel sizes to %d*%d error!/n", iCharSize, iCharSize);
return -1;
}
/*********************************************************************************************************************************************
装载一个字形图像,把一个字符码转换为一个字形索引.这里的字符码为Unicode,很多TrueType字体包含两个字符表,一个用来转换Unicode字符码到字形索引,另一个用来转换Apple Roman编码到字形索引.当新建一个face对象时,它默认选择Unicode字符表。
*********************************************************************************************************************************************/
FT_UInt uiGlyphIndex = FT_Get_Char_Index(ftFace, uiCharCode);
/*********************************************************************************************************************************************
一旦你获得了字形索引,你便可以装载对应的字形图像.在不同的字体中字形图像存储为不同的格式.对于固定尺寸字体格式,每一个图像都是一个位图.对于可伸缩字体格式,使用名为轮廓(outlines)的矢量形状来描述每一个字形.这里我要的是位图数据,因此对于矢量图就不说了.
字形图像存储在一个特别的对象――字形槽(glyph slot)中.就如其名所暗示的,一个字形槽只是一个简单的容器,它一次只能容纳一个字形图像.每一个face对象都有一个字形槽对象,可以通过face->glyph来访问.
通过调用FT_Load_Glyph来装载一个字形图像到字形槽中,其函数原型为:
FT_EXPORT( FT_Error )
FT_Load_Glyph( FT_Face face, // face对象的句柄
FT_UInt glyph_index, // 字形索引
FT_Int32 load_flags ); // 装载标志,其默认值是FT_LOAD_DEFAULT即0
*********************************************************************************************************************************************/
FT_Load_Glyph(ftFace,uiGlyphIndex, FT_LOAD_DEFAULT);
/*********************************************************************************************************************************************
字段face->glyph->format描述了字形槽中存储的字形图像的格式.如果它的值不是FT_GLYPH_FORMAT_BITMAP,你可以通过FT_Render_Glyph把它直接转换为一个位图.其函数原型为: FT_EXPORT( FT_Error )
FT_Render_Glyph( FT_GlyphSlot slot, // 字形槽
FT_Render_Mode render_mode ); // 渲染模式
render_mode参数是一个位标志集合,用来指示如何渲染字形图像.把它设为FT_RENDER_MODE_NORMAL渲染出一个高质量的抗锯齿(256级灰度)位图.这是默认情况,如果想生成黑白位图,可以使用FT_RENDER_MODE_MONO标志.
*********************************************************************************************************************************************/
FT_Render_Glyph(ftFace->glyph, FT_RENDER_MODE_MONO);
/*********************************************************************************************************************************************
生成了黑白位图后,其数据存放在ftFace->glyph->bitmap中,其原型为:
typedef struct FT_Bitmap_
{
int rows; // 位图的行数
int width; // 位图的宽度,也表示每行有多少个像素
int pitch; // 偏移值,当往上时为负数,往下时为正数,它的绝对值为位图的一行所占的字节数.不够一个字节当一个字节算.
unsigned char* buffer; // 指向位图缓冲区的指针
short num_grays; // 该值只应用于FT_PIXEL_MODE_GRAY模式
char pixel_mode; // 像素模式
char palette_mode; // 色块像素模式
void* palette; // 调色板
} FT_Bitmap;
*********************************************************************************************************************************************/
int iRow = 0, iCol = 0;
for(iRow = 0; iRow < ftFace->glyph->bitmap.rows; iRow++)
{
for(iCol = 0; iCol < ftFace->glyph->bitmap.width; iCol++)
{
if((ftFace->glyph->bitmap.buffer[iRow * ftFace->glyph->bitmap.pitch + iCol/8] & (0xC0 >> (iCol % 8))) == 0)
{
printf("_");
}
else
{
printf("0");
}
}
printf("/n");
}
return 0;
}