freetype2的FT_Load_Char使用实例分析

测试 Linux linux
编译开源库及编译官方样例

本文使用版本为freetype-2.4.10

$ ./configure CC=gcc --prefix=$PWD/_INSTALL --without-zlib
$ make & make install 

开源库编译过程参考:http://blog.csdn.net/dreamintheworld/article/details/55224529

官方DEMO用例(freetype-2.4.10\src\tools)
test_afm.c
test_bbox.c
apinames.c
编译语句在c文件中有注释;

编写测试样例使用FT_Load_Char

根据编译说明,重新写一个样例(test_main.c)
文件如下:
freetype2的FT_Load_Char使用实例分析_第1张图片
其中需要编译zlib库 http://blog.csdn.net/dreamintheworld/article/details/54933859

// test_main.c
// gcc -I../../include -o test_main test_main.c ./libfreetype.a ./libz.a
#include 
#include

static FT_Library library;
static FT_Face face;

int LoadChar(wchar_t cvalue, int textsize, int *x, int* bitmap_left, 
      int* bitmap_top, int* rows, int* width, unsigned char** buf){
      int ret = FT_Load_Char(face, cvalue, FT_LOAD_RENDER); //0=SUCCESS, otherwise=FAIL
      *x = face->glyph->advance.x;
      *bitmap_left = face->glyph->bitmap_left;
      *bitmap_top = face->glyph->bitmap_top;
      *rows = face->glyph->bitmap.rows;
      *width = face->glyph->bitmap.width;
      *buf = face->glyph->bitmap.buffer;

      printf("%s(%s)\n", __FILE__, __FUNCTION__);
      printf("-------------------------\n");
      printf("%15s = %ld\n", "advance.x", face->glyph->advance.x);
      printf("%15s = %d\n", "bitmap_left", face->glyph->bitmap_left);
      printf("%15s = %d\n", "bitmap_top", face->glyph->bitmap_top);
      printf("%15s = %d\n", "bitmap.rows", face->glyph->bitmap.rows);
      printf("%15s = %d\n", "bitmap.width", face->glyph->bitmap.width);
      printf("%15s = %ld\n", "bitmap.buffer", sizeof(face->glyph->bitmap.buffer));
      printf("%15s = %ld\n", "bitmap_buffer", strlen(face->glyph->bitmap.buffer));
      printf("-------------------------\n");
      unsigned char*  buffer; 
      buffer = face->glyph->bitmap.buffer;
      int i=0, j=0;
      int height = *rows;
      int wid = *width;
      for(j = 0; j < height; j++){
        for(i = 0; i < wid ; i++){
            printf("%02x ", buffer[i + wid*j]);
        }
        printf("\n");
      }
      return 1;
  }

  int main(int argc, char** argv){
      printf("%s(%s)\n", __FILE__, __FUNCTION__);
      int bError = FT_Init_FreeType(&library);
      if(bError) return 0;
      bError = FT_New_Face(library,(char*)"MSYH2.TTF",0, &face);
      if(bError) return 0;

      int textHeight = 20;
      FT_Set_Pixel_Sizes(face, textHeight, 0);

      int left, top, rows, width, x;
      unsigned char* buf;
      wchar_t ch = 'T';
      LoadChar(ch, textHeight, &x, &left, &top, &rows, &width, &buf);
      return 0;   
  }

在这里我随便使用了网上下载的TTF字库文件MSYH2.TTF,可自行更改;
可以看出输出后大体看到’T’字母的轮廓;
freetype2的FT_Load_Char使用实例分析_第2张图片

修改main函数输出汉字

int main( int    argc, char** argv ){
    printf("%s(%s)\n", __FILE__, __FUNCTION__);
    int bError = FT_Init_FreeType(&library);
    if(bError) return 0;
    bError = FT_New_Face(library,(char*)"MSYH2.TTF",0, &face);
    if(bError) return 0;

    int textHeight = 20;
    FT_Set_Pixel_Sizes(face, textHeight, 0);

    int left, top, rows, width, x;
    unsigned char* buf;
    wchar_t *str = L"中文";
    wchar_t ch ;
    ch = str[0];
    LoadChar(ch, textHeight, &x, &left, &top, &rows, &width, &buf);
    return 0;   
}

编译运行结果
freetype2的FT_Load_Char使用实例分析_第3张图片
如果在程序中用到中文字符 需要指定CPP的文件编码为UTF-8
当使用ANSI时出现的情况是

这里写图片描述

这说明当前c或cpp文件里面有GBK编码格式,在Linux环境下无法识别由GBK编码出来的中文字符
需要使用linux所熟悉的utf-8格式(或者把中文字符定义到UTF-8编码的头文件中)
在只用英文字符的情况下 使用ANSI仍然还是能够被Linux环境接受

设置字体大小
在FT_Load_Char之前调用函数FT_Set_Pixel_Sizes

int LoadChar(wchar_t cvalue, int textsize, int *x, int* bitmap_left, int* bitmap_top,
    int* rows, int* width, unsigned char** buf){
    FT_Set_Pixel_Sizes(face, textsize, 0);
    int ret = FT_Load_Char(face, cvalue, FT_LOAD_RENDER);
    *x = face->glyph->advance.x;
    printf("%15s = %d(%dx%d)\n", "textsize", textsize, face->glyph->bitmap.width, 
        face->glyph->bitmap.rows);
}

字体大小和像素点的关系(当设置字体大小为50时)
freetype2的FT_Load_Char使用实例分析_第4张图片
字体大小和像素点对应关系做了一部分测试
textsize = 10(5x6)
textsize = 20(9x12)
textsize = 30(12x18)
textsize = 40(16x24)
textsize = 50(19x29)
textsize = 100(38x58)
设置字体大小就是设置字体高度的像素点 约保持10:6的比例关系控制高度
宽度由字库和字体高度决定 跟中英文也有特别大的关系 中文而言 宽度值必然更大

添加字体颜色

typedef struct tagRGBQUAD { 
    unsigned char rgbBlue;
    unsigned char rgbGreen;
    unsigned char rgbRed;
    unsigned char rgbReserved;
} RGBQUAD;

unsigned long * pDst;
RGBQUAD srcchar;
srcchar.rgbRed = (unsigned char)textColor;
srcchar.rgbGreen = (unsigned char)(textColor >> 8);
srcchar.rgbBlue = (unsigned char)(textColor >> 16);

for(j = 0; j < rows; j++){
    for(i = 0; i < width; i++){
        srcchar.rgbReserved = buffer[i + width*j];
        pDst[i] = *(unsigned long*)&srcchar;
    }
    pDst = pDst + CANVAS_WIDTH;
}

这里添加的字体颜色,因为rgbReserved在绘制的过程中RGB的排序是,B–G–R
所以颜色的值是相反的,需要做相关调整,这是开发过程中出现的小问题;

要进行字符串的输出,可以通过控制LoadChar()中的传入的left, top值进行相应的计算得出绘制坐标依次绘制输出位图的数据即可

开源库API文档
开源库的API说明文档存放于:/freetype-2.4.10/docs/reference/ft2-index.html中;
FT_Library library; FT_Face face; FT_Init_FreeType(); FT_New_Face();…….
等等接口的使用说明不做详细说明了;

freetype2的FT_Load_Char使用实例分析_第5张图片


编译出现错误
skipping incompatible
编译过程中出现了一个小插曲,我使用了g++编译出来的静态库libfreetype.a,在使用gcc链接到程序中时出现了一个错误
/usr/bin/ld: skipping incompatible /freetype-2.4.10/src/tools/lib/libfreetype.a when searching for -lfreetype
因为我的系统路径下安装的libfreetype.a库,在编译阶段gcc搜索到系统下的库,编译仍然通过;
第一次因为编译语句为-L.. -lfreetype -lz -static ,只是添加了静态库搜索路径,没有指定对应的库,
所以编译过程中gcc找到了系统目录下的libfreetype.a;

所以建议修改库后使用指定的库进行编译而不是仅仅增加库的搜索路径,否则出现编译通过效果没出来的尴尬情况

错误ftheader.h: No such file or directory
使用指定目录的头文件编译出现的错误是

$ make
gcc -nostdinc \
                -I../include \
                -I../include/freetype2/freetype \
                -I../include/freetype2/freetype/config \
                -I/usr/include/freetype2/freetype/config \
                -o test_main test_main.c ./libfreetype.a ./libz.a
In file included from test_main.c:3:
../include/ft2build.h:56: fatal error: freetype/config/ftheader.h: No such file or directory
compilation terminated.
make: *** [exe] Error 1

这是因为在编译libfreetype2库的时候产生的所有的头文件都是使用了尖括号包含,所以需要直接搜索系统目录下的头文件;
如果需要指定使用头文件则需要把相关的尖括号使用双引号引用头文件;

所以为了方便在编译阶段不使用–prefix指定编译后输出的路径,直接输出到系统中(/usr/include/),更方便使用开源库的相关例程

关于wchar_t

在32位的Linux系统中sizeof(wchar_t)=4
所以wchar_t本身是4个字节
freetype2使用了wchar_t作为字符的参数保存中文字符时能够确保不会丢失数据
即使是UTF-8这种不确定长度的编码规则 大部分中文字符也是在3个字节以内就可以完成编码

你可能感兴趣的:(Linux,freetype2)