注:本人已购买韦东山第三期项目视频,内容来源《数码相框项目视频》、数码相框-通过freetype库实现矢量显示,只用于学习记录,如有侵权,请联系删除。
在数码相框(三、LCD显示文字)中使用字体的点阵数据显示文字,这种LCD显示文字的方法比较简单,但它有一个缺点,一旦选定了字库,字体的大小就确定了,无法更改。矢量字体可以弥补点阵字体无法更改字体大小的缺点,而且矢量字体无论放大、缩小,都可以清晰显示。
1. 矢量字体原理
在矢量字体文件中存储的是字符若干闭合曲线的关键点,把这些关键点使用数学曲线(贝塞尔曲线)连接在一起,并填充闭合曲线的闭合空间,就形成了一个矢量字符。例如,字母“B”,如下图所示。红色点为字体的关键点,使用数学曲线把关键点连接在一起,形成闭合的曲线(即字体的轮廓线),然后填充闭合空间(即灰色的填充区域)。
由于每个字符的笔划不一样,从而每个字符数据长度也不同,所以只能采用索引的方法。因而每种矢量字库都是由两部分组成,一部分是汉字的索引信息,一部分是汉字的字形(glyph)数据(即字符的关键点)。
2. Freetype库
FreeType库是一个完全免费(开源)的、高质量的且可移植的字体引擎,用于处理矢量字体文件的。
freetype-2.4.10库下载:https://sourceforge.net/projects/freetype/files/freetype2/2.4.10/
freetype-2.4.10英文参考文档下载:https://sourceforge.net/projects/freetype/files/freetype-docs/2.4.10/
FreeType 中文使用参考:
https://wenku.baidu.com/view/2d24be10cc7931b765ce155b.html
https://wenku.baidu.com/view/e7149f6748d7c1c708a14574.html
2.1 freetype-2.4.10的使用
(1) 想象一个文字的显示过程:
① 给定一个文字,例如,‘A’, 0x41, “中”, GBK、UNICODE,可以确定它的编码值;
② 根据上面的编码值,从字体库中找到“glyph”,glyph 中含有那些关键点;
③ 设置字体大小;
④ 用某些函数把glyph里的点缩放成第③步中指定的字体大小;
⑤ 把 glyph 转换为位图点阵;
⑥ 把字体的位图点阵在LCD显示出来。
(2) 代码的过程:
① 包含头文件:
#include <ft2build.h>
#include FT_FREETYPE_H
② 初始化库:(使用FT_Init_FreeType()函数初始化一个FT_Library类型的变量)
FT_LIBRARY library; /*库的句柄*/error = FT_Init_FreeType( &library );
if ( error )
{
//初始化失败
}
... ...
③ 装载一个字体 face:(应用程序通过FT_NEW_Face()函数打开一个字体文件,然后提取该文件的一个FT_Face类型的face变量(一个 face 对象描述了一个特定的字样和风格,例如,’ Times New Roman Regular’和’ Times New Roman Italic’对应两个不同的 face))
FT_LIBRARY library; /*库的句柄*/FT_Face face; /* face对象的句柄 */error = FT_Init_FreeType ( &library );
if ( error )
{... ...}... ...error = FT_New_Face( library,
"/usr/share/fonts/truetype/arial.ttf", //字形文件
0,
&face );
④ 设置字体大小: 设置字体大小有两种方法:
方法一:
FT_Set_Char_Size( FT_Face face,FT_F26Dot6 char_width, /*字符宽度,单位为1/64点, 字符宽度为0意味着与字符高度相同*/FT_F26Dot6 char_height, /*字符高度,单位为1/64点,字符高度为0意味着与字符宽度相同*/FT_UInt horz_resolution, /*水平分辨率,为0意味着与垂直分辨率相同*/FT_UInt vert_resolution ); /*垂直分辨率,为0意味着与水平分辨率相同*/
注:
a. 字符宽度和高度以 1/64 点为单位表示;
b. 点是物理上的距离,一个点代表1/72英寸(1英寸 = 2.54cm);
c. 设备的水平和垂直分辨率以每英寸点数(dpi)为单位表示,表示一个英寸有多少个像素;
例如:
error = FT_Set_Char_Size( face, 50 * 64, 0,100, 0 ); /*0表示与另一个尺寸值相等。 */
可知:
字符物理大小为:50*64* (1/64) * (1/72)英寸;
字符的像素为: 50*64* (1/64) * (1/72)*100。
方法二:
FT_Set_Pixel_Sizes(FT_Face face,FT_UInt pixel_width, //像素宽度FT_UInt pixel_height ); //像素高低
例如:
error = FT_Set_Pixel_Sizes( face, 24, 0); //把字符像素设置为24*24像素, 0表示与另一个尺寸值相等。
⑤ 字体的变换: 使用FT_Set_Transform()设置字体的位置、移动、旋转的角度等
error = FT_Set_Transform(face, /*目标face对象 */&matrix, /*指向2x2矩阵的指针,写0表示不旋转,使用正矩形*/&delta ); /*字体坐标位置(用的笛卡尔坐标),以1/64像素为单位表示,写0表示原点是(0,0)*/
如下图所示,在LCD的坐标系中,原点在屏幕的左上角。对于笛卡尔坐标系,原点在左下角。freetype使用笛卡尔坐标系,在显示时需要转换为LCD坐标系。从下图可知,X方向坐标值是一样的。在Y方向坐标值需要换算,假设LCD的高度是V。在LCD坐标系中坐标是(x, y),那么它在笛卡尔坐标系中的坐标值为(x, V-y)。反过来也是一样的,在笛卡尔坐标系中坐标是(x, y),那么它在LCD坐标系中坐标值为(x, V-y)。
例如:设置字体旋转25度,并在(300, 200)显示,在example1.c有如下代码:
FT_Vector pen; /* */
FT_Matrix matrix; /* transformation matrix */
double angle;angle = ( 25.0 / 360 ) * 3.14159 * 2; /* use 25 degrees *//* set up matrix */
matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );
matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );
matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L );
matrix.yy = (FT_Fixed)( cos( angle ) * 0x10000L );/* the pen position in 26.6 cartesian space coordinates; */
/* start at (300,200) relative to the upper left corner */
pen.x = 300 * 64;
pen.y = ( target_height - 200 ) * 64; /*其中target_height为LCD的总高度*/FT_Set_Transform( face, &matrix, &pen );
⑥ 根据字符的编码值,加载 glyph:
a. 根据编码值,找到字体文件的索引:
glyph_index = FT_Get_Char_Index( face, charcode );
b. 通过索引,把字形图像存 face->glyph成员中:(通过调用 FT_Load_Glyph()函数来装载一个字形图像到字形槽(glyph slot)中,如下:)
error = FT_Load_Glyph(face, /* face 对象的句柄 */glyph_index, /* 字形索引 */load_flags ); /* 装载标志,用来指示某些特殊操作的。其默认值是 FT_LOAD_DEFAULT 即 0。*/
注:字形槽:每次只能存储一个字形图像,每个face对象都有一个字形槽,位于face->glyph
c. 转换为位图:得到字形槽后,可以通过 FT_Render_Glyph()函数把它直接转换为一个位图,并存到 face->glyph->bitmap->buffer[] 里:
error = FT_Render_Glyph(face->glyph, /* 字形槽 */render_mode); /* 渲染模式,render_mode 参数是一个位标志集合,用来指示如何渲染字形图像。*/
render_mode有两种渲染模式:
FT_RENDER_MODE_NORMAL: 渲染出一个高质量的抗锯齿(256 级灰度)位图;
FT_RENDER_MODE_MONO: 表示生成位图每个像素是1位的(黑白图)。
以上a、b、c三步等价于函数:
FT_Load_Char(face,charcode,FT_LOAD_REND); /*FT_LOAD_RENDER表示直接将图像转为位图, 并保存到face->glyph->bitmap->buffer[]*/
2.2 在PC上测试Freetype
(1) 解压、配置、编译、安装 freetype:
tar -xjf freetype-2.4.10.tar.bz2 /*解压*/
cd freetype-2.4.10/
./configure /*配置*/
make /*编译*/
sudo make install /*接将库安装到根目录/usr/local/ */
(2) 编译example1.c:(example1.c在freetype-doc-2.4.10/freetype-2.4.10/docs/tutorial目录下)
gcc -o example1 example1.c
编译出现如下错误:
上面的错误提示说不存在freetype/config/ftheader.h这个文件,但在/usr/local/include/freetype2/freetype/config/是存在ftheader.h这个文件的,如下图所示:
所以需要通过 -I 指定头文件目录:
gcc -o example1 example1.c -I /usr/local/include/freetype2/
编译再次出现错误,错误如下图所示:
从上面的错误可知:出错的都是函数,其中FT开头的是freetype库的函数,cos等都是数学库的函数;freetype库的文件名是 libfreetype.so,数学库的文件名是libm.so。
所以编译的时候,还需添加 -l 指定库文件:
gcc -o example1 example1.c -I /usr/local/include/freetype2/ -lfreetype -lm
(3) 运行example1.c:
将C:\Windows\Fonts下的simsun.ttc(宋体)字体文件拷问到虚拟机example1所在的目录下,运行:
./example1 simsun.ttc abc
运行的结果如下:
example1.c的打印范围是640*480,从上图打印的结果可知,这个打印范围显然过大,只能看到打印字体的一部分,所以我们需要把example1.c的打印范围调小,调为80*80。因此需要把example1.c中的如下代码:
#define WIDTH 640
#define HEIGHT 480
改为:
#define WIDTH 80
#define HEIGHT 80
然后,然后将119行处的文字显示坐标:
pen.x = 300 * 64; /*在坐标(300,200)处显示*/
pen.y = ( target_height - 200 ) * 64;
改为:
pen.x = 0 * 64; /*在坐标(0,40)处显示*/
pen.y = ( target_height - 40 ) * 64;
修改后,重新编译,运行的结果如下图所示:
从打印的结果可知,打印的字符abc是斜体。通过检查example1.c代码发现,通过FT_Set_Transform()函数设置了字体旋转,并在95行设置了旋转的角度为25度,因此需要把旋转角度设置代码:
angle = ( 25.0 / 360 ) * 3.14159 * 2; /* use 25 degrees */
修改为0度:
angle = ( 0 / 360 ) * 3.14159 * 2; /* use 0 degrees */
修改后,重新编译,运行的结果如下图所示:
从上图我们发现,显示不全,下面我们把字体大小改小一点,把example1.c的105行设置字体大小的代码:
/* use 50pt at 100dpi */error = FT_Set_Char_Size( face, 50 * 64, 0,100, 0 ); /* set character size */
改为 24*24的字体大小:
error = FT_Set_Pixel_Sizes( face, 24, 0 ); /* 24*24像素 */
修改后,重新编译,运行:
./example1 simsun.ttc abc
打印结果如下图所示:最终显示正常。
(4) 修改example1.c代码显示汉字:
① 包含宽字符头文件:#include <wchar.h>;
② 通过wcslen()函数判断wchar_t数组大小;
注:wchar_t在windows占2byte,在linux占4bytes。
为了显示汉字,对example1.c做了如下修改:
...
#include <wchar.h> /*1.添加宽字符头文件*/
.../*main函数修改为如下*/
int main( int argc, char** argv )
{FT_Library library;FT_Face face;FT_GlyphSlot slot;FT_Matrix matrix; /* transformation matrix */FT_Vector pen; /* untransformed origin */FT_Error error;char* filename;double angle;int target_height;int n;wchar_t *chinese_str = L"韦gif";filename = argv[1]; /* first argument */angle = ( 0 / 360 ) * 3.14159 * 2; /* use 25 degrees */target_height = HEIGHT;error = FT_Init_FreeType( &library ); /* initialize library *//* error handling omitted */error = FT_New_Face( library, argv[1], 0, &face ); /* create face object *//*设置字体大小*/error = FT_Set_Pixel_Sizes( face, 24, 0 ); /* 24*24像素 *//* error handling omitted */slot = face->glyph;/* set up matrix */matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L );matrix.yy = (FT_Fixed)( cos( angle ) * 0x10000L );/* the pen position in 26.6 cartesian space coordinates; *//* start at (300,200) relative to the upper left corner */pen.x = 0 * 64;pen.y = ( target_height - 40 ) * 64;for ( n = 0; n < wcslen(chinese_str); n++ ){/* set transformation */FT_Set_Transform( face, &matrix, &pen );/* load glyph image into the slot (erase previous one) */error = FT_Load_Char( face, chinese_str[n], FT_LOAD_RENDER );if ( error )continue; /* ignore errors *//* now, draw to our target surface (convert position) */draw_bitmap( &slot->bitmap,slot->bitmap_left,target_height - slot->bitmap_top );/* increment pen position */pen.x += slot->advance.x;pen.y += slot->advance.y;}show_image();FT_Done_Face ( face );FT_Done_FreeType( library );return 0;
}
在Ubuntu虚拟机使用vim编辑器修改example1.c(vim 编辑器默认为UTF-8编码格式),编译程序:
gcc -o example1 example1.c -I /usr/local/include/freetype2/ -lfreetype -lm
若example1.c文件格式为ANSI编码(ANSI编码),因为linux默认是UTF-8编码,所以编译时,需要指定字符集:
gcc -o example1 example1.c -I /usr/local/include/freetype2/ -lfreetype -lm -finput-charset=GBK -fexec-charset=utf-8
// -finput-charset:告诉编译器,文件里的字符是GBK格式
//-fexec-charset:告诉编译器,需要先将里面的内容转换为utf-8格式后,再来编译
运行:
./example1 simsun.ttc
运行打印结果如下:
在example1.c中的 show image() 函数添加打印坐标信息,如下图红色框所示:
重新编译,运行打印结果如下图所示:
从上图可知,文字的显示超出了原点坐标(40,0),这是为什么呢?如下图所示:
在显示一行文字时,这些文字会基于同一个基线来绘制位图:baseline。在baseline上,每一个字符都有它的原点(origin),例如上图中baseline左边的黑色圆点就是字母“g”的原点。当前origin加上advance就可以得到下一个字符的origin,比如上图中baseline右边的黑色圆点。在显示一行中多个文件字时,后一个文字的原点依赖于前一个文字的原点及advance。
字符的位图是有可能越过baseline的,比如上图中字母“g”在baseline下方还有图像。上图中红色方框内就是字母“g”所点据的位图,它的四个角落不一定与原点重合。 我们通过FT_Glyph_Get_CBox()函数可以获取上图中字体的xMin、xMax、yMin、yMax参数,这些参数会保存在一个FT_BBox结构体中,该结构体的代码如下图所示:
(5) 获取位图文字的信息:
① 首先添加头文件:
#include FT_GLYPH_H
② 通过FT_Get_Glyph()将一个字形图像(face->glyph)存到FT_Glyph类型的变量里,例如:
FT_Glyph glyph; /* a handle to the glyph image */
...
/*通过字符编码,获取字形图像存到face->glyph里,并转为位图存到face->glyph->bitmap->buffer[]里*/
error = FT_Load_Char(face,charcode,FT_LOAD_REND);
if ( error ) { ... }error = FT_Get_Glyph( face->glyph, &glyph ); //将字形图像(face->glyph)存到glyph里
if ( error ) { ... }
③ 通过FT_Glyph_Get_CBox()获取文字的xMin, xMax, yMin, yMax坐标信息:
FT_Glyph_Get_CBox( FT_Glyph glyph, //该值通过FT_Get_Glyph()来获取FT_UInt bbox_mode, //模式,填入FT_GLYPH_BBOX_TRUNCATE即可FT_BBox *acbox ); //用来存放获取到的xMin, xMax, yMin, yMax信息
其中FT_GLYPH_BBOX_TRUNCATE表示:获取的坐标信息是像素坐标,而不是点坐标。
④ 修改example1.c,打印汉字坐标:
#include FT_GLYPH_H /*添加*/
...
int main(int argc, char** argv )
{...FT_Glyph glyph; /*添加*/FT_BBox acbox; /*添加*/...error = FT_Load_Char( face, chinese_str[n], FT_LOAD_RENDER );if ( error )continue; /* ignore errors */error = FT_Get_Glyph(face->glyph, &glyph); /*添加*/ //将字形图像(face->glyph)存到glyph里if(error ) /*添加*/continue; /*添加*/FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_TRUNCATE, &acbox); /*添加*/printf("0x%04x:xMin=%ld,xMax=%ld,yMin=%ld,yMax=%ld\n",chinese_str[n],acbox.xMin,acbox.xMax,acbox.yMin,acbox.yMax); /*添加*/...}
重新编译,运行打印的结果如下:
例如:第一行表示“韦”字的笛卡尔坐标: X坐标在0~23,y坐标在37~60,是个24*24字体。前面讲过,笛卡尔坐标原点位于左下方,LCD坐标原点位于左上方,所以,“韦”字的LCD坐标为: X坐标在0~23,y坐标在20~43(LCD的大小为:80*80)。
3. 在JZ2440开发板LCD显示矢量字体
3.1构建交叉编译环境(arm-linux-gcc 4.4.3)
(1) 交叉编译 freetype:
tar xjf freetype-2.4.10.tar.bz2
mkdir tmp
cd freetype-2.4.10/
./configure --host=arm-linux 或 ./configure --host=arm-none-linux-gnueabi (有时候--host=arm-linux时,编译出来的libfreetype.so是x86-64格式的(file libfreetype.so 可知它是个符号连接指向libfreetype.so.6.9.0,执行file libfreetype.so.6.9.0可知格式为x86-64),这可能是为系统的问题,建议配置时用第二个。)
make
make DESTDIR=$PWD/../tmp install /*安装到tmp目录*/
(2) 编译出来的头文放入:/work/tools/arm-linux-gcc-4.4.3/lib/gcc/arm-none-linux-gnueabi/4.4.3/include目录
cp tmp/usr/local/include/* /work/tools/arm-linux-gcc-4.4.3/lib/gcc/arm-none-linux-gnueabi/4.4.3/include -rf
cd /work/tools/arm-linux-gcc-4.4.3/lib/gcc/arm-none-linux-gnueabi/4.4.3/include
mv freetype2/freetype . /*代码中用的是 freetype,不是 freetype2*/
(3) 编译出来的库文件放入:/work/tools/arm-linux-gcc-4.4.3/arm-none-linux-gnueabi/lib目录
cp tmp/usr/local/lib/* /work/tools/arm-linux-gcc-4.4.3/arm-none-linux-gnueabi/lib -d -rf
(4) 把tmp/usr/local/lib/目录下所以的so文件,复制到开发根文件系统的lib目录下,如下图所示:
3.2 在LCD上显示矢量字体
(1) 交叉编译example1.c
arm-linux-gcc -o example1 example1.c -lfreetype -lm
若example1.c文件格式为ANSI编码(ANSI编码),因为linux默认是UTF-8编码,所以编译时,需要指定字符集:
arm-linux-gcc -o example1 example1.c -lfreetype -lm -finput-charset=GBK -fexec-charset=utf-8
// -finput-charset:告诉编译器,文件里的字符是GBK格式
//-fexec-charset:告诉编译器,需要先将里面的内容转换为utf-8格式后,再来编译
把交叉编译出的可知文件拿到开发板运行,发现运行的结果是在终端显示,并非在开发板的LCD显示。
(2) 修改example1.c代码,在开发板LCD显示矢量字体: 修改后的代码如下:
/* example1.c */
/* */
/* This small program shows how to print a rotated string with the */
/* FreeType 2 library. */#include <stdio.h>
#include <string.h>
#include <math.h>
#include <wchar.h>
#include <linux/fb.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H#define WIDTH 80
#define HEIGHT 80/* origin is the upper left corner */
//unsigned char image[HEIGHT][WIDTH];int fd_fb;
struct fb_var_screeninfo var; /* Current var */
struct fb_fix_screeninfo fix; /* Current fix */
int screen_size;
unsigned char *fbmem;
unsigned int line_width;
unsigned int pixel_width;/** @brief 在LCD指定位置显示指定的颜色** @param[in] x 预显示位置的横坐标** @param[in] y 预显示位置的纵坐标** @param[in] color 预显示的颜色** @return 无** @note 颜色color 的格式是 0x00RRGGBB*/
void lcd_put_pixel(int x,int y,unsigned int color)
{unsigned char *pen_8 = fbmem + y * line_width + x * pixel_width;unsigned short *pen_16;unsigned int *pen_32;unsigned int red, green, blue;pen_16 = (unsigned short *)pen_8;pen_32 = (unsigned int *)pen_8;switch(var.bits_per_pixel){case 8: *pen_8 = color;break; /*对于8BPP:color 为调色板的索引值,其颜色取决于调色板的数值*/case 16:{red = (color >> 16) & 0xff;green = (color >> 8) & 0xff;blue = (color >> 0) & 0xff;color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3); /*格式:RGB565*/*pen_16 = color;break;}case 32: *pen_32 = color;break;default: printf("can't surport %dbpp",var.bits_per_pixel);break;}
}/* Replace this function with something useful. */
void
draw_bitmap( FT_Bitmap* bitmap,FT_Int x,FT_Int y)
{FT_Int i, j, p, q;FT_Int x_max = x + bitmap->width;FT_Int y_max = y + bitmap->rows;for ( i = x, p = 0; i < x_max; i++, p++ ){for ( j = y, q = 0; j < y_max; j++, q++ ){if ( i < 0 || j < 0 ||i >= var.xres || j >= var.yres )continue;// image[j][i] |= bitmap->buffer[q * bitmap->width + p];lcd_put_pixel(i, j, bitmap->buffer[q * bitmap->width + p]); }}
}int main( int argc, char** argv )
{FT_Library library;FT_Face face;FT_Glyph glyph;FT_BBox acbox;FT_GlyphSlot slot;FT_Matrix matrix; /* transformation matrix */FT_Vector pen; /* untransformed origin */FT_Error error;char* filename;double angle;int target_height;int n;wchar_t *chinese_str = L"韦gif";if( argc != 2){printf ("usage: %s font_file \n", argv[0] );return -1; }fd_fb = open("/dev/fb0", O_RDWR);if(fd_fb < 0){printf("can't open /dev/fb0\n");return -1;}if(ioctl(fd_fb, FBIOGET_VSCREENINFO, &var)){printf("can't get var\n");return -1;}if(ioctl(fd_fb, FBIOGET_FSCREENINFO, &fix)){printf("can't get fix\n");return -1;}line_width = var.xres * var.bits_per_pixel / 8;pixel_width = var.bits_per_pixel / 8;screen_size = var.xres * var.yres * var.bits_per_pixel / 8;fbmem = (unsigned char *)mmap(NULL, screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);if(fbmem == (unsigned char*)-1){printf("can't mmap\n");return -1;}/*清屏*/memset(fbmem, 0, screen_size);filename = argv[1]; /* first argument */angle = ( 0 / 360 ) * 3.14159 * 2; /* use 25 degrees */target_height = HEIGHT;error = FT_Init_FreeType( &library ); /* initialize library *//* error handling omitted */error = FT_New_Face( library, argv[1], 0, &face ); /* create face object *//*设置字体大小*/error = FT_Set_Pixel_Sizes( face, 24, 0 ); /* 24*24像素 *//* error handling omitted */slot = face->glyph;/* set up matrix */matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L );matrix.yy = (FT_Fixed)( cos( angle ) * 0x10000L );/* the pen position in 26.6 cartesian space coordinates; *//* start at (300,200) relative to the upper left corner */pen.x = 0 * 64;pen.y = ( target_height - 40 ) * 64;for ( n = 0; n < wcslen(chinese_str); n++ ){/* set transformation */FT_Set_Transform( face, &matrix, &pen );/* load glyph image into the slot (erase previous one) */error = FT_Load_Char( face, chinese_str[n], FT_LOAD_RENDER );if ( error )continue; /* ignore errors */error = FT_Get_Glyph(face->glyph, &glyph); //将字形图像(face->glyph)存到glyph里if(error )continue;FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_TRUNCATE, &acbox);printf("0x%04x:xMin=%ld,xMax=%ld,yMin=%ld,yMax=%ld\n",chinese_str[n],acbox.xMin,acbox.xMax,acbox.yMin,acbox.yMax);/* now, draw to our target surface (convert position) */draw_bitmap( &slot->bitmap,slot->bitmap_left,target_height - slot->bitmap_top );/* increment pen position */pen.x += slot->advance.x;pen.y += slot->advance.y;}FT_Done_Face ( face );FT_Done_FreeType( library );return 0;
}
/* EOF */
重新编译,运行的结果如下图所示: