Freetype编译,demo运行,关键API解析。

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解压出来的configureautorun.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     //freetype头文件

#include FT_FREETYPE_H  //Freetype源码中可以看到这个宏定义的是一个头文件

/*  这两个头文件属于标准格式,都要加.前一个是包含了各种后续可以被#include包含的头文件的宏定义;后一个#define FT_FREETYPE_H  ,定义在ftheader.h。它包含了一些安装专用的宏,来命名Freetype2 API的公共头文件 */

 

#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 (300,200) relative to the upper left corner  调整了位置适应新的分辨率*/

  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)。

-------------------------------------

暂时更这些,后续有时间再研究。笔者水平有限,如果错误,还请包含指正,谢谢!

你可能感兴趣的:(Computer,Graphics,Graphics,字体)