from:https://www.cnblogs.com/lifexy/p/8503070.html
freetype中文文档:https://wenku.baidu.com/view/2d24be10cc7931b765ce155b.html
freetype教程中文:https://wenku.baidu.com/view/e7149f6748d7c1c708a14574.html
COTENT
1、矢量字体文件原理
2、一个文字的显示过程
3、如何使用freetype
·· 1)包含头文件
·· 2)初始化库
·· 3)加载face对象
·· 4)设置字体大小
·· 5)根据字符的索引值加载glyphy
1、矢量字体原理
矢量字体原理:
① 将字体描述成若干条闭合曲线,提取关键点
② 贝塞尔曲线连接关键点
③ 填充封闭空间
font16X8和hzk得到的点阵是固定的,而矢量字体可以设置大小
什么是矢量字体库?
每种矢量字库(.ttf .ttc)都是由两部分组成,一部分是汉字的索引信息(charmaps),一部分是汉字的字形(glyph)数据。
freetype库的作用?
从矢量字体库中把关键点取出,使用freetype库,生成位图点阵。
2、矢量文字的显示过程
① 给定一个文字,可以确定它的编码值
② 根据编码值(freetype支持多种编码),从字体文件中找汉字的字形数据(glyphy)
③ 设置字体大小
④ 用某些函数把glyphy里的关键点,缩放为设置的大小
⑤ 把glyphy转换为位图
⑥ 在LCD上显示出来
3、如何使用freetype
1)包含头文件
#include <ft2build.h>
#include FT_FREETYPE_H
2)初始化库
使用FT_Init_FreeType()函数初始化一个FT_Library类型的变量
#include <ft2build.h>
#include FT_FREETYPE_H
FT_Library library; //库的句柄
...
error = FT_Init_FreeType( &library );
if ( error )
{
... an error occurred during library initialization ...
}
3)加载face对象
a. 从字体文件中加载
通过FT_NEW_Face()打开一个字体文件,然后提取该文件的一个FT_Face类型的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 );
b.从内存中加载
error = FT_New_Memory_Face( library,
buffer, /* first byte in memory */
size, /* size in bytes */
0, /* face_index */
&face );
c.其他来源
4)设置字体大小
error = FT_Set_Char_Size(
face, /* handle to face object */
0, /* char_width in 1/64th of points */
16*64, /* char_height in 1/64th of points */
300, /* horizontal device resolution */
300 ); /* vertical device resolution */
error = FT_Set_Pixel_Sizes(
face, /* handle to face object */
0, /* pixel_width */
16 ); /* pixel_height */
5)根据字符的索引值加载glyphy
a. 选择charmap(支持多种编码方式)
使用其它字符编码,则通过FT_Select_Charmap()来获取
error = FT_Select_Charmap(
face, /* 目标face对象 */
FT_ENCODING_BIG5 ); /* big5编码 */
//FT_ENCODING_BIG5枚举定义在FT_FREETYPE_H中
//FT_ENCODING_GB2312 :GB2312编码
//该函数头文件位于:FT_FREETYPE_H (freetype/freetype.h).
b. 获取编码的索引(找到)
通过FT_Get_Char_Index()函数将字符编码转换为一个字形数据(glyph)索引 (Freetype默认是utf-16编码类型)。若glyph_index为NULL,表示没找到字形(glyph)索引。
glyph_index = FT_Get_Char_Index( face, charcode );
c. 通过索引,从face中加载字形(取出)
获得字形索引后,接下来便根据字形索引,来将字形图像存储到字形槽(FT_GlyphSlot slot;)中.
字形槽: 每次只能存储一个字形图像。 slot = face->glyph;
error = FT_Load_Glyph(
face, /* face对象的句柄 */
glyph_index, /* 字形索引 */
load_flags ); /* 装载标志,一般填FT_LOAD_DEFAULT*/
d.转为位图
通过FT_Render_Glyph()函数,将字形槽的字形图像转为位图,并存到 face->glyph->bitmap->buffer[]里
error = FT_Render_Glyph( face->glyph, /* 字形槽 */
render_mode ); /* 渲染模式 */
render_mode标志可以设为以下几种:
FT_RENDER_MODE_NORMAL:表示生成位图每个像素是RGB888的
FT_RENDER_MODE_MONO :表示生成位图每个像素是1位的(黑白图)
并更新face->glyph->bitmap下的其它成员,比如:
int rows; //该位图总高度,有多少行
int width; //该位图总宽度,有多少列像素点
int pitch: //指一行的数据跨度(所占字节数),比如对于24位(3字节)的24*30汉字,则pitch=24*3
char pixel_mode //像素模式,1 指单色的,8 表示反走样灰度值
unsigned char* buffer //glyph 的点阵位图内存绶冲区
以水平方向为例:在笛卡尔坐标系下如图所示
FT_GlyphSlot slot = face->glyph;
bitmap结构体的成员与图中对应关系:
slot->bitmap_left = bearingX; //距离左边的空余像素
slot->bitmap_top = bearingY; //
slot->advance.x = advance; //在竖直方向上:slot->advance.y = advance;
slot->advance.y = 0; //在竖直方向上:slot->advance.x = 0;
slot->bitmap.width = width;
slot->bitmap.rows = height;
e. 变换——移动、旋转
FT_Vector delta;
delta.x = 0;
delta.y = 0;
error = FT_Set_Transform(
face, /* 目标face对象 */
&matrix, /* 指向2x2矩阵的指针,写0表示不旋转,使用正矩形 */
&delta ); /*字体坐标位置(用的笛卡尔坐标),以1/64像素为单位表示,写0表示原点是(0,0) */
matrix = 0则不旋转
f. 用FT_Load_Char()来代替FT_Get_Char_Index()、FT_Get_Load_Glyph()和FT_Render_Glyph()
error = FT_Load_Char( face, charcode, FT_LOAD_RENDER );
其中FT_LOAD_RENDER:表示直接将图像转为位图,所以不需要使用FT_Render_Glyph()函数
该函数默认生成的位图是默认生成的FT_RENDER_MODE_NORMAL类型,RGB888的。
若想生成FT_RENDER_MODE_MONO(黑白图)类型,操作如下:
error = FT_Load_Char( face, charcode, FT_LOAD_RENDER | FT_LOAD_MONOCHROME );
生成出来的位图像素,每一个像素1bit,每8个像素点便表示 face->glyph->bitmap->buffer[]里的一个字节。