============================================================================================
一、FreeType使用详解
参考来源:
1、freetype-doc-2.10.1.tar/freetype-doc-2.10.1/freetype-2.10.1/docs/tutorial/step1.html(文字说明)
2、freetype-2.10.1.tar/freetype-2.10.1/docs/reference/site/ft2-base_interface.html(函数定义)
3、韦东山视频:freetype介绍。
4、项目1数目相框_笔记\04\freetype-doc-2.10.1.tar\freetype-doc-2.10.1\freetype-2.10.1\docs\tutorial\example1.c(freetype-2.10.1工程自带的C代码)。
技巧:如果想更好地理解代码每个函数的定义,可以在source insight添加freetype-2.10.1.tar工程, 结合对应文档进行理解
============================================================================================
I. Simple Glyph Loading(简单字形加载)
1. Header Files(头文件)
Include the file named ft2build.h.(包含头文件 )
#include <ft2build.h>
#include FT_FREETYPE_H
2. Library Initialization(库初始化)
To initialize the FreeType library, create a variable of type FT_Library named, for example, library, and call the function FT_Init_FreeType.
用法:为了初始化FreeType library。需要的创建一个FT_Library类型的变量,比如library。然后调用函数FT_Init_FreeType。
FT_Init_FreeType的用法:{FT_Init_FreeType( &library );}返回值:0表示成功。返回错误码见fterrdef.h.
3. Loading a Font Face(用三种方式,1、从一个字库文件创建Face对象;2、从From Memory创建一个Face对象;3、其他方式)
a. From a Font File(通过调用FT_New_Face打开一个字库文件从而创建一个新的face(这个可以理解为一个平面)对象,其代表一个字体文件。)调用函数FT_New_Face{FT_New_Face( library,
"/usr/share/fonts/truetype/arial.ttf",
0,
&face )}参数1:FT_Library类型的变量;参数2:字库文件路径();参数3:经常使用0;参数4:为一指针,用来描述face这一个对象。返回值:成功为0.其他看对应文档
要知道给定字体文件包含多少个面,可以将第三参数设置为-1,然后检查face->num_faces的值,该值指示字体文件中嵌入了多少个面。
b. From Memory(不常使用)
调用函数FT_New_Memory_Face( library,
buffer, /* first byte in memory */
size, /* size in bytes */
0, /* face_index */
&face );
4. Accessing the Face Data(访问Face对象中数据)
可以使用的face−>num_glyphs等等一些成员.方式访问其中的数据。
5. Setting the Current Pixel Size(设置当前像素大小,即填充生成Face)
a、使用到的函数(设置一个字符宽和高各多少像素点)定义:
FT_Set_Char_Size( FT_Face face,
FT_F26Dot6 char_width,
FT_F26Dot6 char_height,
FT_UInt horz_resolution,
FT_UInt vert_resolution );
参数1: 之前得到的Face;参数2:字符的高度:参数3:字符宽度;参数4:水平方向分辨率;参数5:竖直方向分辨率
参数2、3如何设置:
The character widths and heights are specified in 1/64th of points,A point is a physical distance, equaling 1/72th of an inch。也就是说字符高度和宽度的单位是的1/64*1/72英寸。如果第二个参数的值是0,则表明宽度和高度相等。
参数4、5如何设置:
The horizontal and vertical device resolutions are expressed in dots-per-inch, or dpi。也就是说每英寸里面存在多少像素。如果第二个参数0,则表明水平和竖直相等。 If both values are zero, 72 dpi is used for both dimensions.如果都为0,表明都使用72dpi。
如何计算一个字符里面包含多少个像素点呢:
举例说明:
char_width= 100
char_height= 100
horz_resolution= 200
vert_resolution= 200
计算一个字符宽度由几个像素组成:100*1/64*1/72*200=4.3像素:同理计算字符高度需要多少像素。
b、如果我们不想使用FT_Set_Char_Size,我们可以使用FT_Set_Pixel_Sizes
函数定义: FT_Set_Pixel_Sizes( FT_Face face,
FT_UInt pixel_width,
FT_UInt pixel_height );
因为使用FT_Set_Char_Size最终是得到了一个字符需要多少个像素组成,而对于使用FT_Set_Pixel_Sizes我们可以直接使用这个函数设置pixel_width和pixel_height。
6. Loading a Glyph Image
a. Converting a Character Code Into a Glyph Index
知识点:
如果我们想要得到一个字符的glyph(关键信息),我们就需要提供这个字符的(唯一的)字符码(ascii、unicode、GBK等等。)。每一个字库文件中都存在一个charmap表。我可以通过这个表把提供字符码(可能是ascii也有点可能是unicode)作为索引在字库文件中找到该字符对应的glyph。
使用的函数: FT_Get_Char_Index( FT_Face face,
FT_ULong charcode );
b. Loading a Glyph From the Face
说明:
1、加载找到的The glyph image到 face->glyph插槽中即slot中;
The glyph image is always stored in a special object called a glyph slot,Each face object has a single glyph slot object that can be accessed as face->glyph.每一个Face都有一个slot object,slot object用来的存储The glyph image
Loading a glyph image into the slot is performed by calling FT_Load_Glyph.加载一个a glyph image到这个插槽对象中,用法如下:
函数:FT_Load_Glyph( FT_Face face,
FT_UInt glyph_index,
FT_Int32 load_flags );
2、将slot(face->glyph)中The glyph image转化为位图(真正的图像,也就是字符点阵)
The field face−>glyph−>format describes the format used for storing the glyph image in the slot. If it is not FT_GLYPH_FORMAT_BITMAP, one can immediately convert it to a bitmap through FT_Render_Glyph.
说明:如果face−>glyph−>format里面图像格式不是FT_GLYPH_FORMAT_BITMAP,那就立即将slot(face->glyph)中的图像立即的转化为a bitmap(位图),需要使用的函数:
FT_Render_Glyph( FT_GlyphSlot slot,
FT_Render_Mode render_mode );
参数1:face->glyph变量。
参数2:位图的呈现模式
c. Using Other Charmaps
在6.a步骤中,如果我们不想使用face中charmap表格默认的索引(unicode),我们提供可能是其他编码,我们可以通过相应的函数修该对应的charmaps
函数:error = FT_Select_Charmap(
face, /* target face object */
FT_ENCODING_BIG5 ); /* encoding
参数2含义:指定使用编码,这里是FT_ENCODING_BIG5
那么如何确定已经打开的字库文件中包含多少charmaps,可以用以下代码:
for ( n = 0; n < face->num_charmaps; n++ )
{
charmap = face->charmaps[n];
if ( charmap->platform_id == my_platform_id &&
charmap->encoding_id == my_encoding_id )
{
found = charmap;
break;
}
d. Glyph Transformations
如果的我们需要将显示字符做一个平移或者旋转,就需要使用一个函数:
FT_Set_Transform( FT_Face face,
FT_Matrix* matrix,
FT_Vector* delta );
参数介绍:
参数2:指向一个matrix的指针,首先定义一个FT_Matrix的变量。对该变量进行初始化(旋转多少度。)。
参数3:这个字符基点(原点)在定义的显示区域的位置。
设置参数3有一个知识点:
字库文件中的字符基点(原点)使用的是笛卡尔坐标(位于左下角)。而对于LCD而言话,其坐标原点位于屏幕的左上角,因此设置FT_Vector类型变量时。需要将字符位置进行一个转换。矢量坐标表示为1/64个像素(也称为26.6个定点数,因此需要乘以一个64)。
7. Simple Text Rendering
The idea is to create a loop that loads one glyph image on each iteration, converts it to a pixmap, draws it on the target surface, then increments the current pen position.(其思想是创建一个循环,在每次迭代中加载一个字形图像,将其转换为像素图,在目标表面绘制它,然后增加当前笔的位置。)
========================================================================================================
a. Basic Code(基本的代码)
========================================================================================================
... initialize library ...
... create face object ...
... set character size ...
pen_x = 300; //字符显示的位置
pen_y = 200;
for ( n = 0; n < num_chars; n++ ) //使用一个循环遍历整个所要显示的字符
{
FT_UInt glyph_index;
/* retrieve glyph index from character code */
glyph_index = FT_Get_Char_Index( face, text[n] ); //循环内step1 寻找第n个字符对应的index
/* load glyph image into the slot (erase previous one):将的生成的image放进slot */
error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); //循环内step2,根据index找到其对应的字形轮廓
if ( error )
continue; /* ignore errors */
/* convert to an anti-aliased bitmap:转化为位图(位图是点阵吗?) */
error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL ); //循环内step3,将字形轮廓转化为位图
if ( error )
continue;
/* now, draw to our target surface */ //循环内step4
my_draw_bitmap( &slot->bitmap,
pen_x + slot->bitmap_left,
pen_y - slot->bitmap_top );
/* increment pen position */
pen_x += slot->advance.x >> 6; //循环内step5
pen_y += slot->advance.y >> 6; /* not useful for now */
}
总结:
这一快代码是循环体内最基本代码,目前我的疑惑:
my_draw_bitmap函数如何实现(看了源码现在也不太懂(目前不知道slot->bitmap放的是什么,点阵?,那应该是一堆的0和1。但是结合后面调用的show image函数中的{putchar( image[i][j] == 0 ? ' '
: image[i][j] < 128 ? '+'
: '*' );},又好像不对 。现在无法解决。))
=======================================================================================================
b.Refined code(精简的代码)建议使用为什么有这一部分b呢(主要是与a进行对比,不同在for循环体内)
========================================================================================================
for ( n = 0; n < num_chars; n++ )
{
/* load glyph image into the slot (erase previous one) */
error = FT_Load_Char( face, text[n], FT_LOAD_RENDER ); //step1
if ( error )
continue; /* ignore errors */
/* now, draw to our target surface */
my_draw_bitmap( &slot->bitmap,
pen_x + slot->bitmap_left,
pen_y - slot->bitmap_top );
/* increment pen position */
pen_x += slot->advance.x >> 6;
}
总结:对比a. Basic Code(基本的代码)和bRefined code(精简的代码)
a中循环内step1~step3被b中step1替代同样可以达到效果(将得到的glyph转化为位图)
============================================================================================
二、使用韦老师提供的freetype-2.4.10源码进行编译安装 freetype,然后运行韦老师的代码
============================================================================================
因为编写的代码代码需要调用的安装freetype所生成的库文件(包括头文件,函数的定义等等)。
自己的体会:
1、如何安装freetype。可从源码根目录中READM出发,查看安装的过程。
2、安装freetype之后,就会在/user/local(默认)下面的目录(环境变量)中生成库文件。安装文档中也有讲。
3、下面就是执行韦老师的程序了
gcc -o example1 example1.c
出错信息:/usr/local/include/ft2build.h:56:38: fatal error: freetype/config/ftheader.h: No such file or directory
但是经过查看/usr/local/include/ft2build.h中56行 #include <freetype/config/ftheader.h>。在进行查看发现/usr/local/include/freetype2/freetype/config/ftheader.h存在头文件。这表示程序未找到对应路径因此需要指定路径:gcc -o example1 example1.c -I /usr/local/include/freetype2/。也就是说在freetype2/然后执行#include <freetype/config/ftheader.h>。执行发现
example1.c:(.text+0x25b): undefined reference to `FT_Init_FreeType'
example1.c:(.text+0x284): undefined reference to `FT_New_Face'
example1.c:(.text+0x29d): undefined reference to `FT_Set_Pixel_Sizes'
example1.c:(.text+0x2c4): undefined reference to `cos'
example1.c:(.text+0x2f5): undefined reference to `sin'
example1.c:(.text+0x332): undefined reference to `sin'
example1.c:(.text+0x363): undefined reference to `cos'
example1.c:(.text+0x3b6): undefined reference to `FT_Set_Transform'
example1.c:(.text+0x3de): undefined reference to `FT_Load_Char'
example1.c:(.text+0x465): undefined reference to `FT_Done_Face'
example1.c:(.text+0x471): undefined reference to `FT_Done_FreeType'
提示是未定义,但是,我们已经包含了对应的头文件,因此程序链接的时候未找到安装freetype生成的库文件,因此的需要指定生成的库文件(注意:去掉lib前缀):
gcc -o example1 example1.c -I /usr/local/include/freetype2/ -lfreetype 执行发现:
example1.c:(.text+0x2c4): undefined reference to `cos'
example1.c:(.text+0x2f5): undefined reference to `sin'
example1.c:(.text+0x332): undefined reference to `sin'
example1.c:(.text+0x363): undefined reference to `cos'
表明链接的时候未找到对应的数学库,因此执行(不能加-lmath而是加-lm):
gcc -o example1 example1.c -I /usr/local/include/freetype2/ -lfreetype -lm 成功
然后执行./example1 BROADW.TTF abc.
执行成功
============================================================================================
三、使用韦老师提供的freetype-2.4.10源码进行编译安装 freetype,然后运行自己写的代码
============================================================================================
自己写的代码,是可以运行出结果,只能显示单个字符,如果是多个字符的话,就会导致,字符存在重合,我的代码里面已经使用
pen.x += slot->advance.x;
pen.y += slot->advance.y;
者这句代码,但是实验的结果,表明第二字符之后origin(原点仍然没用移动),后面解决这个问题。
使用FreeType在电脑端显示(字母或者汉子)
最新推荐文章于 2022-02-10 15:27:57 发布