数码相框(二)freetype库实现矢量显示

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/JerryGou/article/details/83064822

一、矢量字体原理

将汉字的笔划边缘用直线段描述成封闭的曲线,并将线段各端点的坐标经压缩存储,如下图所示:

由于每个汉字的比划不一样,从而每个汉字数据长度也不同,所以只能采用索引的方法。因而每种矢量字库都是由两部分组成,一部分是汉字的字形(glyph)数据。当显示文字时,便提取出各端点,并通过贝塞尔曲线来连接各个坐标,最后填充封闭空间。

接下来使用freetype库制作矢量字体

二、安装freetype-2.4.10库

freetype库是一个开源的字体引擎,支持多种字符集编码(utf-8等)

安装参考链接:https://blog.csdn.net/JerryGou/article/details/79310663

2.1 如何使用freetype

1)包含头文件:

#include <ft2build.h>
#include FT_FREETYPE_H

2)初始化库:

使用FT_Init_FreeType()函数初始化一个FT_Library类型的变量,例如:

FT_LIBRARY library;                         //库的句柄

error = FT_Init_FreeType( &library );   
if ( error )
{
//初始化失败
}

... ...

3)加载face对象:

通过FT_NEW_Face()打开一个字体文件,然后提取该文件的一个FT_Face类型的face变量,例如:

FT_LIBRARY library;                         //库的句柄
FT_Face face;                        /* face对象的句柄 */

error = FT_Init_FreeType ( &library );   
if ( error )
{... ...}

... ...

error = FT_New_Face( library, "/usr/share/fonts/truetype/arial.ttf", 0, &face ); //字形文件

4)设置字体大小

方法1:

FT_Set_Char_Size( 
    FT_Face  face,
    FT_F26Dot6  char_width,  //字符宽度,单位为1/64点
    FT_F26Dot6  char_height, //字符高度,单位为1/64点
    FT_UInt     horz_resolution, //水平分辨率
    FT_UInt     vert_resolution 
); //垂直分辨率

字符宽度和高度以1/64点为单位表示。点是物理上的距离,一个点代表1/72英寸(2.54cm),分辨率以dpi(dots per inch)为单位表示,表示一个英寸有多少个像素
例如:

error = FT_Set_Char_Size( face, 50 * 64, 0,100, 0 );    //0表示与另一个尺寸值相等。 

得出:
字符物理大小为:50*64* (1/64) * (1/72)英寸
字符的像素为:50*64* (1/64) * (1/72)*100

方法2:

FT_Set_Pixel_Sizes(
    FT_Face  face,
    FT_UInt  pixel_width,     //像素宽度
    FT_UInt  pixel_height 
);  //像素高低

例如:

error = FT_Set_Pixel_Sizes( face, 0,16);      //把字符像素设置为16*16像素, 0表示与另一个尺寸值相等。

5)设置字体位置,以及旋转度数(不设置的话表示原点位于0,0):

error = FT_Set_Transform(
    face, /* 目标face对象 */
    &matrix, /* 指向2x2矩阵的指针,写0表示不旋转,使用正矩形 */
    &delta 
); /*字体坐标位置(用的笛卡尔坐标),以1/64像素为单位表示,写0表示原点是(0,0) */

由于我们LCD的坐标原点是位于左上方
笛卡尔坐标:表示坐标原点位于左下方(与LCD的y轴相反)
所以转换之前填写坐标时,需要转换一下y轴值(总高度-y)
转换成功后还需要转换回来(总高度-y)

比如,旋转25,并在(300,200)处显示:

FT_Vector     pen;                    /*   */
FT_Matrix     matrix;                 /* transformation matrix */

angle = ( 25.0 / 360 ) * 3.14159 * 2;      /* use 25 degrees  */

/*将该文字坐标转为笛卡尔坐标*/
pen.x = 300 * 64;                                         
pen.y = ( target_height - 200 ) * 64;        // target_height: LCD总高度

//设置 矩形参数
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 );

FT_Set_Transform( face, &matrix, &pen );

6)加载字形图像

a)获取编码的索引

通过FT_Get_Char_Inde()函数将字符编码转换为一个字形(glyph)索引(Freetype默认是utf-16编码类型),例如:

glyph_index = FT_Get_Char_Index( face, charcode );        

glyph_index为NULL,表示没找到字形(glyph)索引,如果使用其他字符编码,则通过FT_Select_Charmap()来获取,例如获取big5编码:

error = FT_Select_Charmap(
    face,            /* 目标face对象 */
    FT_ENCODING_BIG5
); /* big5编码 */

//FT_ENCODING_BIG5枚举定义在FT_FREETYPE_H中
//FT_ENCODING_GB2312 :GB2312编码
//该函数头文件位于:FT_FREETYPE_H (freetype/freetype.h).

b)通过索引,从face中加载字形

获得字形索引后,接下来便根据字形索引,来将字形图像存储到字形槽(glyph slot)中.
字形槽:每次只能存储一个字形图像,每个face对象都有一个字形槽,位于face->glyph
通过FT_Load_Glyph()来加载一个字形图像到字形槽:

error = FT_Load_Glyph
(
    face, /* face对象的句柄 */
    glyph_index, /* 字形索引 */
    load_flags 
); /* 装载标志,一般填FT_LOAD_DEFAULT*/

并更新face->glyph下的其它成员,比如:

FT_Int            bitmap_left;            //该字形图像的最左边的X值
FT_Int            bitmap_top;            //该字形图像的最上边的Y值

c)转为位图

通过FT_Render_Glyph()函数,将字形槽的字形图像转为位图,并存到 face->glyph->bitmap->buffer[]

error = FT_Render_Glyph( face->glyph, /* 字形槽 */
    render_mode ); /* 渲染模式 */

render_mode标志可以设为以下几种:
FT_RENDER_MODE_NORMAL:表示生成位图每个像素是RGB888的
FT_RENDER_MODE_MONO:表示生成位图每个像素是1位的(黑白图)
并更新face->glyph->bitmap下的其它成员,比如:

int             rows;         //该位图总高度,有多少行
int             width;        //该位图总宽度,有多少列像素点
int             pitch:        //指一行的数据跨度(字节数),比如对于24位(3字节)的24*30汉字,则pitch=24*3
char            pixel_mode    //像素模式,1 指单色的,8 表示反走样灰度值
unsigned char*  buffer        //glyph 的点阵位图内存绶冲区

d)也可以直接使用FT_Load_Char()来代替FT_Get_Char_Index()、FT_Get_Load_Glyph()和FT_Render_Glyph().
例如:

error = FT_Load_Char( face, charcode, FT_LOAD_RENDER );

其中FT_LOAD_RENDER:表示直接将图像转为位图,所以不需要使用FT_Render_Glyph()函数
该函数默认生成的位图是默认生成的FT_RENDER_MODE_NORMAL类型,RGB888的
若想生成FT_RENDER_MODE_MONO(黑白图)类型,操作如下:

error = FT_Load_Char( face, charcode, FT_LOAD_RENDER | FT_LOAD_MONOCHROME );

生成出来的位图像素,每8个像素点便表示 face->glyph->bitmap->buffer[]里的一个字节。

三、PC虚拟机里编程例程:example1.c

/* 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. */

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         = ( 0.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, argv[1], 0, &face ); /* create face object */
  /* error handling omitted */

#if 0
  /* use 50pt at 100dpi */
  error = FT_Set_Char_Size( face, 50 * 64, 0,
                            100, 0 );                /* set character size */

	/* pixels = 50 /72 * 100 = 69  */
#else
	FT_Set_Pixel_Sizes(face, 24, 0);
#endif
  /* error handling omitted */

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

3.1 安装freetype到/usr/local/里(给PC机用)

tar -xjf freetype-2.4.10.tar.bz2
mv freetype-2.4.10   freetype-2.4.10_pc
cd freetype-2.4.10_pc/
./configure --host=arm-linux --prefix=/root/code/Project/数码相框/freetype-2.4.10/freetype(自定义目录) //配置
make                                        //编译
make install                           //直接将库安装到根目录/usr/local/里,所以需要加

由于example1.c的打印范围是640*480,而我们secureCRT没有那么大,所以修改example1.c

#define WIDTH   640
#define HEIGHT  480
改为:
#define WIDTH   80
#define HEIGHT  80

然后将119行处的文字显示坐标:

pen.x = 300 * 64;
pen.y = ( target_height - 200 ) * 64;
改为:
pen.x = 0 * 64;
pen.y = ( target_height - 40 ) * 64;

3.2 编译运行

gcc -o example1 example1.c

所以通过-I,直接指定头文件目录:

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

发现这些出错的都是函数,其中FT开头的是freetype库的函数,cos等都是数学库的函数,
freetype库的文件名是 libfreetype.so
数学库的文件名是libm.so

所以编译时,加上-l,指定库文件:

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

3.3 运行example1

将C:\Windows\Fonts下的simsun.ttc(宋体)字体文件拷到虚拟机里,输入./example1   simsun.ttc  agf,发现是斜的:

这是因为example1.c里通过FT_Set_Transform()设置了字体旋转

3.4 修改example1.c

关闭字体旋转,将

FT_Set_Transform( face, &matrix, &pen );

改为

FT_Set_Transform( face, 0, &pen );

修改字体大小,将

error = FT_Set_Char_Size( face, 50 * 64, 0, 100, 0 );

改为

error = FT_Set_Pixel_Sizes( face, 24, 0 );             //24*24像素

编译运行:

3.5 显示汉字

如果用char存储汉字英文等,则还需要判断数据类型,而wchar_t刚好可以放一个unicode字符。
注意:wchar_t在windows占2byte,在linux占4bytes.
宽字符:wchar_t
头文件: #include<wchar.h>
通过wcslen()判断wchar_t数组大小
修改example1.c

...
#include<wchar.h>    //添加此行
...

int main( int argc,char**  argv )
{
    ... ...
    wchar_t  *chinese_str=L"韦东山g";    //添加此行
    ... ...
    for ( n = 0; n <wcslen(chinese_str); n++ )  //修改此行
    {
        FT_Set_Transform( face, 0, &pen );     //字体转换
        
        /* load glyph image into the slot (erase previous one) */
        error = FT_Load_Char( face, chinese_str[n], FT_LOAD_RENDER );    //修改此行
        ... ...
    } 

    return 0;
}

通过另存为文件,来看看文件本身是什么编码格式
如下图所示,看到是ANSI编码, 对于中文PC,ANSI编码对应的是GBK编码:

linux默认是utf-8编码,所以编译时,需要指定字符集:

gcc -o example1 example1.c  -I /usr/local/include/freetype2/ -lfreetype -lm -finput-charset=GBK -fexec-charset=utf-8
// -finput-charset:告诉编译器,文件里的字符是GBK格式
//-fexec-charset:告诉编译器,需要先将里面的内容转换为utf-8格式后,再来编译

运行代码:

添加打印坐标:

发现,我们打印坐标是在(40,0),为什么文字坐标还会超过原点?,参考以下图所示:

advance: 位于face->glyph-> advance,用来存放每个文字之间的间隔信息,每当加载一个新的图像时,系统便会更新该数据。

3.6 获取位图文字的信息

当我们每次将新的字形图像(face->glyph)转为位图后,而存放的前一个字形图像就会被删除.
当有时候,有可能需要提取字形图像的坐标,该怎么做?

1)首先添加头文件:

#include FT_GLYPH_H

2)通过FT_Get_Glyph()将一个字形图像(face->glyph)存到FT_Glyph类型的变量里,例如

FT_Glyph  glyph;    /* a handle to the glyph image */
...

  error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NORMAL );
//通过字符编码,获取字形图像存到face->glyph里,并转为位图存到face->glyph->bitmap->buffer[]里

  if ( error ) { ... }

  error = FT_Get_Glyph( face->glyph, &glyph );         //将字形图像(face->glyph)存到glyph里
  if ( error ) { ... }

3) 通过FT_Glyph_Get_CBox()获取文字的xMin, xMax, yMin, yMax坐标信息

参考: /freetype-2.4.10/docs/reference/ft2-index.html

FT_Glyph_Get_CBox( 
    FT_Glyph  glyph,             //该值通过FT_Get_Glyph()来获取
    FT_UInt   bbox_mode,        //模式,填入FT_GLYPH_BBOX_TRUNCATE即可
    FT_BBox  *acbox 
);        //用来存放获取到的xMin, xMax, yMin, yMax信息

其中FT_GLYPH_BBOX_TRUNCATE表示:获取的坐标信息是像素坐标,而不是点坐标

修改example1.c,使它能打印每个汉字的坐标信息:

#include FT_GLYPH_H      //添加此行
... ...

int main( int     argc, char**  argv )
{
    FT_Glyph  glyph;
    FT_BBox   acbox;
    ... ...

    for ( n = 0; n < wcslen(chinese_str); n++ )
    { 
        ... ...

        error = FT_Load_Char( face,chinese_str[n], FT_LOAD_RENDER );
        if ( error )
          continue;                 /* ignore errors */

        error = FT_Get_Glyph( face->glyph, &glyph );                   //添加此行
        FT_Glyph_Get_CBox(  glyph,FT_GLYPH_BBOX_TRUNCATE,&acbox );     //添加此行
        printf("0x%x:xMin=%ld,xMax=%ld,yMin=%ld,yMax=%ld\n",chinese_str[n],acbox.xMin,acbox.xMax,acbox.yMin,acbox.yMax);    //添加此行
... ...

编译运行:

表示韦字(97e6)的笛卡尔坐标 :  X坐标在0~23,y坐标在37~60,是个24*24字体.
由于笛卡尔坐标的原点坐标位于左下方.
所以对应韦字(97e6)的LCD坐标: X坐标在0~23 ,y坐标为20~43

四、在LCD上显示矢量文字

安装freetype到交叉编译目录里(供arm-linux-gcc编译)

4.1首先查看,需要安装到哪个lib和include目录

1)通过$PATH找到arm-linu-gcc交叉编译位于:/work/tools/arm-linux-gcc-4.3.2/usr/local/arm/4.3.2/bin然后进入.../arm/4.3.2/目录,通过find查找stdio.h文件,找到:

 

所以编译出来的头文件应该放入:/work/tools/arm-linux-gcc-4.3.2/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include

2)通过find查找lib,找到:

 

由于ARM9属于ARMv4T架构,所以编译出来的库文件应该放入:/work/tools/arm-linux-gcc-4.3.2/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib

4.2 安装

参考:freetype-2.4.10/docs/INSTALL.CROSS

tar -xjf freetype-2.4.10.tar.bz2   
mv freetype-2.4.10 freetype-2.4.10_arm
cd freetype-2.4.10_arm
mkdir   tmp                                    //创建安装的临时目录,后面会拷贝到交叉编译目录里
./configure --host=arm-linux  --prefix=$PWD/tmp  //配置交叉编译,安装前缀
make
make install
 
cd tmp/

cp  ./include/*  /work/tools/arm-linux-gcc-4.3.2/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include/ -rfd 
  //将include下的头文件拷贝到交叉编译里去

cp lib/*  /work/tools/arm-linux-gcc-4.3.2/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib/  -rfd 
 //将lib下的库文件拷贝到交叉编译里去

cp lib/ * /work/nfs_root/3.4_fs_mini_mdev/lib/  -rfd    
//将lib下的库文件拷贝到nfs文件系统去

4.3 写代码(参考上章代码和example1.c)

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <string.h>
#include <linux/fb.h>
#include <math.h>
#include<wchar.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H

unsigned char *fbmem;
unsigned char *hzkmem;

struct fb_var_screeninfo fb_var;
struct fb_fix_screeninfo fb_fix;

unsigned int screensize;
#define FONTDATAMAX 4096

static const unsigned char fontdata_8x16[FONTDATAMAX] = {
//ASCII码点阵太长,省略...
};

/*rgb565*/
void pixel_show(int x,int y, unsigned int color)
{
       unsigned int red,green,blue;
       switch(fb_var.bits_per_pixel)        //rgb   像素
        {
            case 32:
            {
                unsigned int  *addr=(unsigned int  *)fbmem+(fb_var.xres*y+x);
                *addr=color;   
                 break;
            }
            case 24:
           {
                unsigned int  *addr=(unsigned int  *)fbmem+(fb_var.xres*y+x);
                *addr=color;
                 break;
           }
           case 16:            //将RGB888 转为RGB565
           {
                unsigned short  *addr=(unsigned short  *)fbmem+(fb_var.xres*y+x);
                red   = (color >> 16) & 0xff;
                green = (color >> 8) & 0xff;
                blue  = (color >> 0) & 0xff;
                color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
                *addr = color;
                break;
           }
           case 8:
          {
               unsigned char  *addr=(unsigned char  *)fbmem+(fb_var.xres*y+x);
               *addr = (unsigned char)color;
               break;
          }

          default:
         {
            printf("can't  surport %dbpp \n",fb_var.bits_per_pixel);
            break;
         }
       }
}

/*显示ascii码*/
void lcd_put_char(int x,int y, unsigned char  s)
{
     unsigned char  *index=(unsigned char *)&fontdata_8x16[s*16];
     unsigned char i,j;
      for(i=0;i<16;i++)          //8*16
      for(j=0;j<8;j++)           
    {
           //从高位到低
         if(index[i]&(1<<(7-j)))         //亮
                pixel_show(x+j,y+i, 0xffffff);        //白色
        else             //灭
                pixel_show(x+j,y+i, 0x0);          //黑色       
    }
}
 
/*显示GBK码*/
void lcd_put_chinese(int x,int y, unsigned char  *s)
{
    unsigned char i,j,k;  
    //将编码转为区码
    unsigned int   index=(s[0]-0xA1)*94+(s[1]-0xA1);

    //转为点阵码(每个汉字32字节)
    unsigned char  *dots=hzkmem+index*32;

     for(i=0;i<16;i++)          //16*16
     for(k=0;k<2;k++)
     for(j=0;j<8;j++)
    {
          if((dots[i*2+k]>>(7-j))&0X01)         //亮
               pixel_show(x+8*k+j,y+i, 0xffffff);        //白色

          else             //灭
                pixel_show(x+8*k+j,y+i, 0x0);          //黑色   
       }
}

void lcd_put(int x,int y, unsigned char  *s)
{
    while(*s)
   {
        if(*s<0xA1)         //ASCII码8*16
        {
           printf("ASCII %x  \r\n",*s  );
            lcd_put_char(x,y,*s);
            s+=1;
            x+=8;       
        }
        else                  //GB2313   16*16
        {
           printf("GBK %x %x\r\n",*s, *(s+1));
           lcd_put_chinese(x,y,s);       
           s+=2;
           x+=16; 
        }
   }
}

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;        //x:当前X位置, bitmap->width:该字宽度
  FT_Int  y_max = y + bitmap->rows;

  for ( i = x, p = 0; i < x_max; i++, p++ )   //i:lcd的x轴
  {
    for ( j = y, q = 0; j < y_max; j++, q++ )  //j:lcd的y轴
    {
      if ( i < 0      || j < 0       ||
           i >= fb_var.xres || j >= fb_var.yres )
        continue;
        pixel_show( i, j,  bitmap->buffer[q * bitmap->width + p]);
    }
  }
}

void lcd_vector_show(char *argv,wchar_t  *str)
{
    FT_Library    library;
    FT_Face       face;
    FT_GlyphSlot  slot;
    FT_Vector     pen;                    /* untransformed origin  */
    unsigned char error;
    unsigned char  n,font_size;

    error = FT_Init_FreeType( &library );              /* initialize library */
      if(error)
       {
            printf("FT_Init_FreeType ERROR\n");
            return ;
        }

     error = FT_New_Face( library, argv, 0, &face ); /* create face object */
     if(error)
        {
            printf("FT_New_Face ERROR\n");
            return ;
        }

     slot = face->glyph;

     /*显示坐标(从LCD中间显示)
      *x=fb_var.xres /2
      *y=fb_var.yres-fb_var.yres/2-16   (减16,是因为笛卡尔坐标以左下方开始计算坐标值的)
      */
     pen.x = fb_var.xres /2* 64;
     pen.y = ( fb_var.yres/2-16) * 64;  

     for ( n = 0; n < wcslen(str); n++ )
  {
    font_size=(n%6)*4+20;            // 20*20  24*24  28*28  32*32  36*36 40*40  

    error = FT_Set_Pixel_Sizes( face, 0,font_size);     /* set character size */

    FT_Set_Transform( face, 0, &pen );

    error = FT_Load_Char( face,str[n], FT_LOAD_RENDER );
      if ( error )
         {
         printf("FT_Load_Char ERROR\n"); 
         continue; 
        }

        draw_bitmap( &slot->bitmap,
                 slot->bitmap_left,
                 fb_var.yres- slot->bitmap_top );

    pen.x += slot->advance.x;
    pen.y += slot->advance.y;
   }
    FT_Done_Face( face );
     FT_Done_FreeType( library );
}

int main(int argc,char **argv)
{
    int fd_fb,fd_hzk;
    struct stat  hzk_start;             //HZK16文件信息

    unsigned char  s[]="abc 中国chinese";
    wchar_t  *chinese_str=L"韦东山g h ";

    if ( argc != 2 )
    {
      printf ("usage: %s  font_file \n", argv[0] );
      return 0;
    }

    fd_hzk=open("HZK16",O_RDONLY);
    if(fd_hzk<0)
    {
        printf("can't open HZK16 \n");
        return 0;
    }

    if(fstat(fd_hzk,&hzk_start)<0)         //获取HZK16文件信息
    {
        printf("can't get fstart \n");
        return 0;
    }

    hzkmem =(unsigned char *)mmap(NULL,hzk_start.st_size, PROT_READ,MAP_SHARED,
                  fd_hzk, 0);                       //映射HZK16文件
    if(!hzkmem)
    {
        printf("can't map HZK16 \n");
        return 0;
    }
 
    fd_fb=open("/dev/fb0", O_RDWR);
    if(fd_fb<0)
    {
        printf("can't open /dev/fb0 \n");
        return 0;
     }

    if(ioctl(fd_fb,FBIOGET_VSCREENINFO,&fb_var)<0)
    {
        printf("can't get var \n");
        return 0;
    }

   if(ioctl(fd_fb,FBIOGET_FSCREENINFO,&fb_fix)<0)
    {
        printf("can't get fix \n");
        return 0;
    }

    screensize=fb_var.xres*fb_var.yres*(fb_var.bits_per_pixel/8);       //显存大小

    fbmem =(unsigned char *)mmap(NULL,screensize, PROT_READ|PROT_WRITE,MAP_SHARED,
                  fd_fb, 0);                       //映射fb0

    if(!fbmem)
    {
        printf("can't map /dev/fb0 \n");
        return 0;
    }
    memset(fbmem, 0, screensize);            //清屏黑色

    /*显示数据*/
    lcd_put(0,fb_var.yres/2,s);     

    /*显示矢量文字*/
    lcd_vector_show(argv[1], chinese_str);

    munmap(hzkmem,hzk_start.st_size);
    munmap(fbmem,screensize);
    return 0;
}

4.4 编译程序

编译报错: 56:38: error: freetype/config/ftheader.h: No such file or directory

通过find找到ftheader.h的位置是位于:../include/freetype2/freetype/config/ftheader.h

输入:

cd ./arm-none-linux-gnueabi/libc/usr/include/freetype2 
mv freetype/ ../freetype //将freetype2下的freetype移到include目录下

编译:

arm-linux-gcc -o show_font show_font.c -lfreetype -lm -finput-charset=GBK -fexec-charset=GBK

运行:

 (发现,显示16*16字体时,会乱码, 新宋字体simsun不支持16点阵大小的字体)

猜你喜欢

转载自blog.csdn.net/JerryGou/article/details/83064822
今日推荐