注:本人已购买韦东山第三期项目视频,内容来源《数码相框项目视频》、数码相框-通过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 */

重新编译,运行的结果如下图所示:

数码相框(四、使用freetype库实现矢量字体显示)相关推荐

  1. 3.数码相框-通过freetype库实现矢量显示

    本章主要内容如下: 1)矢量字体原理 2)使用freetype库实现矢量字体显示 1. 矢量字体原理 将汉字的笔划边缘用直线段描述成封闭的曲线,并将线段各端点的坐标经压缩存储,如下图所示: 由于每个汉 ...

  2. freetype 使用解析---矢量字体

    屏幕显示字体(字体点阵): 在内核中有对应的文件fontdata_8x16.c,将字体通过数组8*16来描述,0表示为空,1表示描点,通过通过各个点形成一个字体点阵显示在屏幕上,而在我们所有终端中显示 ...

  3. 利用Python理解TTF矢量字体显示原理

    本文从微软雅黑字体MSYH.TTF中抽取出2次B样条曲线和直线的控制节点坐标数据,利用Python将汉字轮廓绘制出来. MSYH字体轮廓是由2次B样条曲线和直线构成的,下图(fontforge软件获取 ...

  4. WindML、FreeType和TrueType三者相结合实现矢量字体的显示

    1 VxWorks5.5点阵字库的局限性 VxWorks5.5 是美国风河公司开发的嵌入式操作系统,图形系统采用WindML3.0,支持点阵字显示,不支持矢量字体显示.点阵字采用内存模式加载,使用前需 ...

  5. FreeTpye库学习笔记:将矢量字体解析为位图

    目录 一.前言 二.FreeType解析矢量(.ttf)字体 2.1 包含头文件 2.2 初始化 FreeType 库 2.3 加载 FT_Face 2.4 设置字体编码方式 2.5 设置字体大小 2 ...

  6. linux显示点阵字体,Fedora 17中文字体显示点阵状的解决方法

    在Fedora 17中文字体的显示变成点阵状了,为什么在Fedora 16下中文字体是文泉驿正黑.到Fedora 17之后,中文字体由文泉驿正黑(WenQuanYi Zen Hei)变为WenQuan ...

  7. 数码相框——2、3、1 freetype库实现任意大小的字体 理论介绍

    from:https://www.cnblogs.com/lifexy/p/8503070.html freetype中文文档:https://wenku.baidu.com/view/2d24be1 ...

  8. 数码相框(五、使用freetype库在LCD显示几行文字)

    注:本人已购买韦东山第三期项目视频,内容来源<数码相框项目视频>,只用于学习记录,如有侵权,请联系删除. 1.在LCD显示几行文字 (1) 在LCD显示几行文字,我们分为两种显示方法: ① ...

  9. linux图像显示(五)使用freetype处理矢量字体

    linux图像显示 linux图像显示(一)framebuffer操作 linux图像显示(二)bmp图片 linux图像显示(三)使用libjpg处理jpg图片 linux图像显示(四)使用libp ...

最新文章

  1. 计算机基本组成: 触发器
  2. Python3 range()函数
  3. 关于UNION ALL与 UNION 用法和区别
  4. 理解Java字符串常量池与intern()方法
  5. PHPexcel实列
  6. 披星“戴”云,百治百效
  7. 科学家研究:生女有撇步 多钙少碰香蕉
  8. awk 匹配_linux的awk命令详解,通俗易懂
  9. php删除oracle数据记录日志文件,Oracle手动切换日志文件和清空日志文件
  10. Git服务器Gitosis安装设置
  11. 10硬盘锁怎么解除_鉴定二手iPad是否拼装,扩容,隐藏ID锁的详细方法
  12. File Manipulation
  13. 获取DataGridView上选中的一行并转换为一个DataRow类型
  14. Ubuntu下使用Atom将Markdown文件转换为PDF的一个异常
  15. js判断是否是数组的几种方法
  16. 淘宝技术这十年(淘宝技术大学校长解密淘宝十年)
  17. python画螺旋状图形教程_如何快速绘制一个“螺旋状”图形?
  18. 01 复杂度分析(上):时间、空间复杂度讲解
  19. 【Python】 matplotlib 以pdf形式保存图片
  20. 麦田守望者--走出软件作坊:三五个人十来条枪 如何成为开发正规军(四十三)

热门文章

  1. 【一级倒立摆】基于simulink的一级倒立摆控制器系统仿真
  2. 这个vue3的应用框架你学习了吗?
  3. windows杀死进程
  4. Android 动态代理以及利用动态代理实现 ServiceHook
  5. SDN 教程[2]: SDN基础操作
  6. nginx日志格式配置
  7. 链表之Reverselist
  8. 论Cardano修仙之路,聊ADA现状分析
  9. linux安全(1)
  10. 常见测试场景用例设计(1):登录页面测试用例