FreeType编译安装
编译环境:linux系统(Ubuntu 14.01LTS)
Linuxversion 3.11.0-15-generic (buildd@allspice) (gcc version 4.6.3 (Ubuntu/Linaro4.6.3-1ubuntu5) ) #25~precise1-Ubuntu SMP Thu Jan 30 17:39:31 UTC 2014
1. 下载FreeType
FreeType官网:https://www.freetype.org/download.html
下载路径:https://sourceforge.net/projects/freetype/files/
(官网上有两个路径,貌似上面会被公司墙掉,推荐使用如上链接)
Tips: Linux系统下编译FreeType请无直接下载网页上: Looking for the latest version? Download ft28.zip (3.0 MB) Zip解压出来的configure和autorun.sh等文件时dos格式,刚刚接触时候,完全不知道怎么回事,在编译时候会出现莫名其妙的问题。 |
2. 编译
参考:http://blog.csdn.net/subfate/article/details/8752294
$ ./configure --prefix=/home/latelee/bin/freetype
注:如果不使用第三方的zlib,可以使用freetype内部的相关函数,配置如下:
$./configure --prefix=/home/latelee/bin/freetype --without-zlib
$ make ; make install
在/home/latelee/bin/freetype下的include和lib分别为头文件目录及库目录(包括静态库及动态库)
静态库:libfreetype.a
动态库:libfreetype.so
Tips: 红色字体处为编译输出目录的绝对路径,可选择在freetype下建立build/或者install/等文件夹来装载输出结果。这样会比较清爽。
linux, configure --prefix=/有什么用 指定生成文件的安装目录。 不指定prefix,则可执行文件默认放在/usr /local/bin,库文件默认放在/usr/local/lib,配置文件默认放在/usr/local/etc。其它的资源文件放在/usr /local/share。 |
3. 运行demo
下载地址:https://sourceforge.net/projects/freetype/files/
选择下载freetype-doc-2.8.tar.bz2,而不是ft2demos-2.8.tar.bz2。貌似demos对于我这样的初学者还是有点难度,没有细看。直接使用doc里面的例子吧。解压后其实是Freetype的离线说明文档,里面有个tutorial文件夹,里面有几个比较简单的Example,本文档使用最简单的example1.c。
编译脚本:
gcc example1.c -o example1 –I/xxx/mybuild/include/freetype2 –L/xxx/mybuild/lib -lfreetype –lm |
注:其中xxx处请替换成自己的编译结果的绝对路径。
运行脚本:
./example1 Tiresias.ttf A |
注:
example1 |
编译结果,可执行文件 |
Tiresias.ttf |
字库文件,可以替换成其他喜欢的字库 |
A |
要显示的字符,可替换成任何其他字符 |
显示结果:(旋转25度的字符A)
4. 源码注释(好的博文一定要贴源码)
注:源码来源https://sourceforge.net/projects/freetype/files/
/* example1.c */ /* */ /* This small program shows how to print a rotated string with the */ /* FreeType 2 library. */
//标准头文件 #include #include #include
//Freetype 头文件 #include #include FT_FREETYPE_H //Freetype源码中可以看到这个宏定义的是一个头文件 /* 这两个头文件属于标准格式,都要加.前一个是包含了各种后续可以被#include包含的头文件的宏定义;后一个#define FT_FREETYPE_H
#define WIDTH 64 //org 640 #define HEIGHT 48 // org 480,由于是窗口显示范围较小,缩小显示区域
/* origin is the upper left corner */ unsigned char image[HEIGHT][WIDTH];
/* 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 >= WIDTH || j >= HEIGHT ) continue;
image[j][i] |= bitmap->buffer[q * bitmap->width + p]; } } }
void show_image( void ) { int i, j;
for ( i = 0; i < HEIGHT; i++ ) { for ( j = 0; j < WIDTH; j++ ) putchar( image[i][j] == 0 ? '_' : image[i][j] < 128 ? '+' : '*' ); putchar( '\n' ); } }
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; char* text;
double angle; int target_height; int n, num_chars;
if ( argc != 3 ) { fprintf ( stderr, "usage: %s font sample-text\n", argv[0] ); exit( 1 ); }
filename = argv[1]; /* first argument */ text = argv[2]; /* second argument */ num_chars = strlen( text ); angle = ( -25.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, filename, 0, &face );/* create face object */ /* error handling omitted */
/* use 50pt at 100dpi, 50*64中[乘64]是freetype中固定的一种格式,字体大小以像素的1/64来表示 */ error = FT_Set_Char_Size( face, 50 * 64, 0, 100, 0 ); /* set character size */ /* error handling omitted */
slot = face->glyph; //slot对象,待续
/* set up matrix */ // |xx xy| 2x2的二位旋转矩阵 // |yx yy| 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 pen.x = 18 * 64; pen.y = ( target_height - 55 ) * 64;
for ( n = 0; n < num_chars; n++ ) { /* set transformation */ FT_Set_Transform( face, &matrix, &pen );
/* 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, 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; }
/* EOF */ |
5. 关键API说明
5.1 LibraryInitailization
FT_Library library;
error = FT_Init_FreeType( &library );
ü 创建一个Freetype2新实例(instance),并将句柄复制给library变量
ü 加载library中freetype已知的各模块
5.2 Loading a Font Face
有多种方案,常用有两种:从Font file和内存中
a. 从font文件中加载
error = FT_New_Face( library,
"/usr/share/fonts/truetype/arial.ttf",
0,
&face );
FT_New_Face()有四个参数:libraryfilepath face_index face
其中face_index: Index 0always works, though.
b. 从memory中加载
error = FT_New_Memory_Face( library,
buffer, /* first byte in memory */
size, /* size in bytes */
0, /* face_index */
&face );
FT_New_Memory_Face ()有五个参数:libraryfilepath face_index face
和FT_New_Face()相比,font路径换成了buffer地址和大小。
5.3 访问face数据(主要几个属性解析,no API)
Face成员的访问可以直接通过face->num_glyphs的格式访问。
ü num_glyphs: glyphs是一个字符图像,该成员返回字符图像数目。
ü face_flags: 一个32位的标识用来指定face的属性。如FT_FACE_FLAG_SCALABLE指定face的字体格式是可扩展的,字符图像可以被各种像素格式渲染。更多属性请参考freetype官网。
ü num_fixed_sizes: the number of embedded bitmap strikes in thecurrent face. Strike指字符图像序列。字符图像序列个数。
ü available_sizes:指向FT_Bitmap_Size元素的指针。该项标识face上呈现的每一个字符图像组的水平和垂直方向字符像素的大小。
5.4 设置当前字符像素尺寸
FT_Set_Char_Size()
原形:
FT_EXPORT(FT_Error )
FT_Set_Char_Size(FT_Face face,
FT_F26Dot6 char_width,
FT_F26Dot6 char_height,
FT_UInt horz_resolution,
FT_UInt vert_resolution );
Eg) 在300*300dpi的设备上设置字符大小为16pt.
error = FT_Set_Char_Size(
face, /*handle to face object */
0, /* char_widthin 1/64th of points */
16*64, /*char_height in 1/64th of points */
300, /* horizontal device resolution */
300 ); /* vertical deviceresolution */
ü 字符宽高由1/64点为单位指定。一个点是一个物理距离,等于英尺(inch)的1/72.
ü 宽或高等于零,相当于等同高或宽。否则,由其值指定宽高。
ü 设备宽高由dpi(dot-per-inch)为单位指定,显示设备如显示器的标准值为72或96dpi。这个分辨率结合字符宽高用于计算字符像素大小。
ü 设备宽或高等于零,相当于等同高或宽。如果均为0,使用default值72dpi.
ü 函数的第一个参数为一个face对象,而不是一个尺寸大小对象。
5.5 加载字符图像
5.5.1 字符转换为字符图像序列号
glyph_index =FT_Get_Char_Index( face, charcode );
5.5.2 从face加载字符图像
error = FT_Load_Glyph(
face, /* handle to face object */
glyph_index, /* glyph index */
load_flags ); /* load flags, default 0 */
如果在face中查到对应的字符图和像素大小,将之加载到slot。
域face->glyph->format描述用于slot中存储的字符图像的格式。如果该格式不是FT_GLYPH_FORMAT_BITMAP,可以使用API
error = FT_Render_Glyph( face->glyph, /* glyph slot */
render_mode ); /*render mode */
进行立即转换。
一旦有一个字符图像(bitmappedglyph image),就可以直接使用glyph->bitmap进行访问。Glyph->bitmap_left和glyph->bitmap_top用于定位字符。在屏幕显示时候往往需要光学渲染,所以alpha通道应被用于gamma校正中的线型混合。
5.6 字符图像变换
error = FT_Set_Transform(
face, /* target faceobject */
&matrix, /* pointer to 2x2 matrix */
&delta ); /* pointer to 2dvector */
其中设置主体是face,为face设置当前变换。matrix是2x2的二维旋转矩阵,delta是2x1的平移向量。
变换需要注意两个坐标:字符的笛卡尔坐标系,使用传统的^_>坐标;位图坐标系的坐标原点位于左上角(top-left).当我们定义delta的位置或计算位图左上角位置的时候必须做坐标系转换。旋转操作是在笛卡尔坐标系中,旋转之后通过delta向量平移到pen的位置。作为结果,bitmap_left and bitmap_top指的是位图原点在像素空间中的坐标。
该设置属于状态设定,会被用于通过FT_Load_Glyph加载的所有字符图像,且独立于字符的hinting操作。(就是说加载一个24pixels的字符图像和一个放大两倍的12pixels的字符图像是不一样的,因为二者的hints不同,除非你没有使能hints)。
5.7 简单的文字渲染
基本思路:创建一个循环为每一个迭代对象加载字符图像(glyph image),转换成pixmap,在目标表面(surface)绘制,然后移动pen位置。
for ( n = 0; n < num_chars; n++ )
{
/* retrieve glyphindex from character code */
glyph_index =FT_Get_Char_Index( face, text[n] );
/* load glyphimage into the slot (erase previous one) */
error =FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
/* convert to ananti-aliased bitmap */
error =FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL );
/* now, draw toour target surface */
my_draw_bitmap(&slot->bitmap,
pen_x + slot->bitmap_left,
pen_y - slot->bitmap_top);
/* increment penposition */
pen_x += slot->advance.x >>6; // >>6, 相当于1/64
pen_y += slot->advance.y >>6; /* not useful for now */
}
其中slot是一个FT_GlyphSlot类型的对象,这样写可以避免每次都用face->glyph->XXX。
my_draw_bitmap函数是必须的,但是不是Freetype的一部分,需要应用层自己写,这个函数以FT_bitmap的指针和字符左上角坐标为入参。bitmap_top是一个向上的垂直距离的正值;bitmap_left。
5.8 精致版code(Example1)
for ( n = 0; n < num_chars; n++ )
{
/* load glyphimage into the slot (erase previous one) */
error =FT_Load_Char( face, text[n], FT_LOAD_RENDER);
/* now, draw toour target surface */
my_draw_bitmap(&slot->bitmap,
pen_x + slot->bitmap_left,
pen_y - slot->bitmap_top );
/* increment penposition */
pen_x +=slot->advance.x >> 6;
}
直接使用FT_Load_Char来加载对应字符图像。注意和basiccode中的load方式比较。该函数实际上是对FT_Get_Char_Index和FT_Load_Glyph的封装。使用加载标识FT_LOAD_RENDER表明字符图像会被立即转换抗锯齿的位图(bitmap)。
-------------------------------------
暂时更这些,后续有时间再研究。笔者水平有限,如果错误,还请包含指正,谢谢!