您的位置:首页 > 其它

数码相框——矢量字体原理(1)

2014-03-05 16:25 393 查看
在上一节里面,我们显示的是点阵字体。这种字体比较简单,但是它有一个缺点就是,一旦选定了字库,每个字符的大小就确定了,无法更改。在本节里面我们将引入矢量字体的概念,矢量字体将弥补点阵字体无法更改字体大小的缺点。

1、原理简述
一个字可以用多条曲线来表示,而对于每条曲线我们保存其关键点,这样就可以用来表示这个字了。
我们想要显示的时候,就取出这些关键点,并采用平滑的曲线将这些关键点连接起来,最后填充闭合空间。
想要放大或缩小的时候,只需要按比例缩放改变关键点的相对位置就可以了!

2、显示过程
(1)在字体文件中保存着对应着不同编码类型的文字,当然其保存的方法就是保存关键点以及相对位置
(2)根据文字的编码值从字体文件中找到对应的文字,即glyph,当然找到的是其关键点和相对位置
(3)设置字体大小
(4)用某些函数把glyph里的点缩放为设置的字体大小
(5)转换为位图点阵
(6)在LCD上显示出来

3、freetype2
上面我们说了矢量字体的显示过程,那么具体应该怎么操作呢?这就需要freetype2了,下面我们来详细说一下:

(1)初始化库:FT_Init_FreeType
(2)加载字体face:
FT_New_Face:从文件中加载字体
FT_New_Memory_Face:从内存中加载字体
(3)设置大小
FT_Set_Char_Size
FT_Set_Pixel_Sizes
(4)根据字符的编码值加载glyph
a:FT_Select_CharMap( face, FT_ENCODING_BIG5 );
 选择编码方式

b:FT_Get_Char_Index( face, charcode )
把字符编码转换为索引值,根据该索引就可以找到glyph

c:FT_Load_Glyph( face,glyph_index,  load_flags );
从face中取出glyph

d:FT_Render_Glyph( face->glyph, render_mode );
将glyph转换为位图

(5)变换:移动、旋转
FT_Set_Transform

测试FreeType提供的demo程序(1)

简介:

2.3 使用freetype来显示任意大小的文字

2.3.1节_数码相框_freetype理论介绍

2.3.2节_数码相框_在PC上测试freetype

在PC:安装freetype-2.4.10.tar.bz2

tar xjf freetype-2.4.10.tar.bz2

./configure

make

sudo make install

编译

gcc -o example1 example1.c  -I /usr/local/include/freetype2 -lfreetype -lm

指定字符

gcc -finput-charset=GBK -fexec-charset=UTF-8 -o example1 example1.c  -I /usr/local/include/freetype2 -lfreetype -lm

测试

./example1 ./simsun.ttc abc

一  代码如下

/* example1.c 
* This small program shows how to print a rotated string with the
* FreeType 2 library.
*/
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#define WIDTH   80
#define HEIGHT  80

/* origin is the upper left corner */
unsigned char image[HEIGHT][WIDTH];

/* Replace this function with something useful. */
voiddraw_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         = ( 0.0 / 360 ) * 3.14159 * 2;     /* 角度    */
  target_height = HEIGHT;

  FT_Init_FreeType( &library );  /* initialize library,详见注释1 */

  FT_New_Face( library, argv[1], 0, &face );
/* create face object ,详见注释2*/
 
  FT_Set_Pixel_Sizes(face, 24, 0); //见注释3

  slot = face->glyph;  

  /* set up matrix */
  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 (0,40) relative to the upper left corner  */
  pen.x = 0 * 64;
  pen.y = ( target_height - 40 ) * 64;

  for ( n = 0; n < num_chars; n++ )
  {
    /* set transformation ,见注释4*/
    FT_Set_Transform( face, &matrix, &pen );

    /* load glyph image into the slot (erase previous one) */
    error = FT_Load_Char( face, text
, FT_LOAD_RENDER );//见注释5
    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 ); //见注释6

    /* 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;
}

注释1:FT_Init_FreeType( &library );
功能:这是初始化一个库,所谓库我们可以简单的理解为一个空间,用来存放所有的资源。

注释2:FT_New_Face( library, argv[1], 0, &face );
功能:读取字体文件中指定类型的字体,并用face来描述它
参数1:表示库
参数2:要打开的文件
参数3:表示要加载的字体的类型,0表示任何类型都可以
参数4:face
一个文件里面可能会含有多种字体,每个字体对应着一个face,也就是说face用来描述某一种字体。

注释3:FT_Set_Pixel_Sizes(face, 24, 0);
功能:设置字符的像素大小
参数1:face
参数2:每行多少像素,0表示与列相同
参数3:每列多少像素,0表示与行相同

注释4:FT_Set_Transform( face, &matrix, &pen );
功能:设置传输
参数1:face
参数2:用于设置字体的旋转角度
参数3:用于设置字体的平显示位置

注释5:FT_Load_Char( face, text
, FT_LOAD_RENDER );
功能:将一个字型的点阵信息记录在face->glyph中
参数1:face
参数2:要记录的字型的编码
参数3:参数

注释6:draw_bitmap( &slot->bitmap , slot->bitmap_left , target_height - slot->bitmap_top
);  
功能:将字符的点阵存放在一个结构体里面
参数1:用于描述点阵信息的结构体
参数2:x坐标
参数3:y坐标
注意:我们这里的坐标是笛卡尔坐标系,也就是y坐标向上,x坐标向右!而在LCD上的显示坐标系y轴是反向的,所以显示的时候需要将y轴处理一下!

我们来总结一下显示一个矢量字符我们都做了什么:
1、初始化一个库
2、加载字体,并用创建一个face来描述字体
3、设置字体的像素大小
4、设置字体的旋转角度以及显示位置
5、找到字型的点阵信息并记录下来
6、显示点阵

二、测试
1、解压
2、进入到解压文件的根目录
3、配置:./configure
4、编译:make
5、安装:make install
库文件安装到了:/usr/local/lib
头文件安装到了:/usr/local/include/freetype2/freetype/
6、编译应用程序:
gcc -o example1 example1.c  -I /usr/local/include/freetype2 -lfreetype -lm
-I:用于指定头文件的目录
-l紧跟库的名字:用于指定库
-lm:指明要用数学函数库
7、将编译好的文件与字体文件放在同一个文件夹里面
8、测试: ./example1 ./simsun.ttc agfaaa

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  项目班