数码相册——FreeType介绍
- 硬件平台:韦东山嵌入式Linxu开发板(S3C2440.v3)
- 软件平台:运行于VMware Workstation 12 Player下UbuntuLTS16.04_x64 系统
- 参考资料:《嵌入式Linux应用开发手册》、《嵌入式Linux应用开发手册第2版》、【FreeType教程】、【FreeType2使用总结】
- 开发环境:Linux 3.4.2内核、arm-linux-gcc 4.3.2工具链
- 源码仓库:https://gitee.com/d_1254436976/Embedded-Linux-Phase-3
目录
一、FreeType简要介绍
FreeType是一个软件字体引擎,被设计成小、高效、可定制和可移植,同时能够产生高质量的输出(字形图像)。它可以用于图形库、显示服务器、字体转换工具、文本图像生成工具以及许多其他产品。
支持单色位图、反走样位图的渲染。FreeType库是高度模块化的程序库,虽然它是使用ANSI C开发,但是采用面向对象的思想,因此,FreeType的用户可以灵活地对它进行裁剪。
在嵌入式环境中,可以只编译那些你的嵌入式工程或环境需要的模块,从而有效的减小FreeType 2 的代码大小。
废话少说,下面结合FreeType的官方教程来进行代码介绍与编程步骤总结。
二、简单的字形装载过程的描述
1.头文件
- 在使用时候,需要包含下列头文件:
在FreeType中有许多头文件的宏定义,需要添加ft2build.h
文件才可以使用这些宏定义。
#include <ft2build.h>
#include FT_FREETYPE_H
2.库初始化
这调用的函数为FT_Init_FreeType()
- 原型
FT_Init_FreeType( FT_Library *alibrary );
- 参数解析
·FT_Library * alibrary:A handle to a new library object.(一个新库对象的句柄) - 返回值
成功执行:0,错误执行:FreeType error code(错误码) - 调用案例
FT_Library library;
...
error = FT_Init_FreeType( &library );
if ( error )
{
... an error occurred during library initialization ...
}
3.加载字体
- 函数原型
FT_New_Face( FT_Library library,
const char* filepathname,
FT_Long face_index,
FT_Face *aface );
- 参数
- FT_Library library — A handle to the library resource(库资源的句柄).
- const char * filepathname — A path to the font file(字体文件的路径).
- FT_Long face_index — The index of the face within the font. The first face has index 0(字体中face的索引。第一个face的索引为0).
- FT_Face * aface — A handle to a new face object. If ‘face_index’ is greater than or equal to zero, it must be non-NULL. See FT_Open_Face for more details(一个新face对象的句柄。如果FACE_INDEX大于或等于零,则必须为非NULL).
- 返回值
成功执行:0,错误执行:FreeType error code(错误码) - 调用案例
FT_Library library; /* handle to library */
FT_Face face; /* handle to face object */
error = FT_Init_FreeType( &library );
if ( error ) { ... }
error = FT_New_Face( library,
"/usr/share/fonts/truetype/arial.ttf",
0,
&face );
if ( error == FT_Err_Unknown_File_Format )
{
... the font file could be opened and read, but it appears
... that its font format is unsupported
}
else if ( error )
{
... another error code means that the font file could not
... be opened or read, or that it is broken...
}
4.访问face数据
可以通过face
句柄进行访问
- 原型
typedef struct FT_FaceRec_
{
FT_Long num_faces;
FT_Long face_index;
FT_Long face_flags;
FT_Long style_flags;
FT_Long num_glyphs;
FT_String* family_name;
FT_String* style_name;
FT_Int num_fixed_sizes;
FT_Bitmap_Size* available_sizes;
FT_Int num_charmaps;
FT_CharMap* charmaps;
FT_Generic generic;
/*# The following member variables (down to `underline_thickness') */
/*# are only relevant to scalable outlines; cf. @FT_Bitmap_Size */
/*# for bitmap fonts. */
FT_BBox bbox;
FT_UShort units_per_EM;
FT_Short ascender;
FT_Short descender;
FT_Short height;
FT_Short max_advance_width;
FT_Short max_advance_height;
FT_Short underline_position;
FT_Short underline_thickness;
FT_GlyphSlot glyph;
FT_Size size;
FT_CharMap charmap;
/*@private begin */
FT_Driver driver;
FT_Memory memory;
FT_Stream stream;
FT_ListRec sizes_list;
FT_Generic autohint; /* face-specific auto-hinter data */
void* extensions; /* unused */
FT_Face_Internal internal;
/*@private end */
} FT_FaceRec;
5.设置字体像素大小
这里也有两种方式:
1、调用FT_Set_Char_Size()
函数
- 原型:
FT_Set_Char_Size( FT_Face face,
FT_F26Dot6 char_width,
FT_F26Dot6 char_height,
FT_UInt horz_resolution,
FT_UInt vert_resolution );
- 参数解析
- char_width(字符的宽度):The nominal width, in 26.6 fractional points. 设置为0时,char_width = char_height
- char_height(字符的高度):The nominal height, in 26.6 fractional points. 设置为0时,char_width = char_height
- horz_resolution(水平方向的分辨率):The horizontal resolution in dpi. 设置为0时,horz_resolution = vert_resolution
- vert_resolution (垂直方向的分辨率):The vertical resolution in dpi. 设置为0时,horz_resolution = vert_resolution
通过查看官方文档可以知道:
高度和宽度的单位是 1 64 \frac{1}{64} 641 point,1 point = 1 72 =\frac{1}{72} =721 inch,分辨率的单位是dpi——每英寸点数
即
1 单位的高度或宽度 = 1 64 =\frac{1}{64} =641 point,1 point = 1 72 =\frac{1}{72} =721 inch,1 单位分辨率 = 1 d p i =1 d p i =1dpi
所以
1 单位的高度或宽度的物理长度 = 1 64 ∗ 72 =\frac{1}{64*72} =64∗721 inch
则
x单位的高度或宽度,y单位分辨率,其字符高度的像素为
= x ∗ ( 1 64 ∗ 1 72 ) =\mathrm{x}^{*}\left(\frac{1}{64} * \frac{1}{72}\right) =x∗(641∗721) inch ∗ y d p i = x ∗ y 6 4 ∗ 72 * \mathrm{y} d p i=\frac{\mathrm{x}^{*} \mathrm{y}}{64^{*} 72} ∗ydpi=64∗72x∗y pixel - 调用实例
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 */
2、对于上面的函数太过复杂,若只关心像素大小,可以使用FT_Set_Pixel_Sizes()
- 原型
FT_Set_Pixel_Sizes( FT_Face face,
FT_UInt pixel_width,
FT_UInt pixel_height );
- face(目标对象face的句柄):A handle to the target face object.
- pixel_width(宽度,单位为像素):The nominal width, in pixels. 设置为0时,pixel_width= pixel_height
- pixel_height(高度,单位为像素):The nominal height, in pixels. 设置为0时,pixel_width= pixel_height
此时设置pixel_width = 100,其高度像素就是100pixel,没有复杂的转换公式了。
6.加载字形图像
这里有两种方法:
- 先调用
glyph_index = FT_Get_Char_Index( face, charcode )
得到当前字符在face
中的glyph
字形索引;后调用FT_Load_Glyph(face, glyph_index, load_flags )
,根据得到的glyph
字形索引,将字形图像加载到slot
插槽中;最后调用FT_Render_Glyph(face-> glyph, render_mode)
,将其转换为位图。 - 直接调用
FT_Load_Char(face,text [n],FT_LOAD_RENDER)
,来替代上面的过程。
7.简单的文本渲染
可以采用如下方式;
- 设置旋转角度:
angle = ( 0.0 / 360 ) * 3.14159 * 2
,0.0代表旋转0度,可以按照自己要求设置 - 设置矩阵(用来旋转字体的时候用):
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 );
- 设置字符原点
注意:此时在FreeType中使用的是笛卡尔坐标,而我们LCD中显示的坐标与转换原理如下:
pen.x = 300 * 64;
pen.y = ( target_height - 200 ) * 64;
- 在循环中执行设置转换参数、渲染文本、存储文本点阵信息
for ( n = 0; n < num_chars; n++ )
{
/* 设置转换参数 */
/* set transformation */
FT_Set_Transform( face, &matrix, &pen );
/* FT_Load_Char == FT_Load_Glyph、FT_Get_Load_Char、FT_Get_Char_Index
* FT_LOAD_RENDER : 渲染 Glyph图像立刻变为位图
*/
/* 得到字符点阵 */
/* load glyph image into the slot (erase previous one) */
error = FT_Load_Char( face, text[n], FT_LOAD_RENDER );
if ( error )
continue; /* ignore errors */
/* 存储点阵信息 */
/* now, draw to our target surface (convert position) */
draw_bitmap( &slot->bitmap,
slot->bitmap_left, /* 笛卡尔坐标的x */
target_height - slot->bitmap_top /* 笛卡尔坐标的y */);
/* increment pen position */
pen.x += slot->advance.x;
pen.y += slot->advance.y;
}