freetype显示中英文

freetype显示中英文

参考博客:

04.freetype显示中文_//查无此人的博客-CSDN博客_freetype 中文

freetype的安装与使用_explore_world的博客-CSDN博客_freetype安装

使用freetype来显示中文汉字和英文字符_mlove编程-CSDN博客

3.数码相框-通过freetype库实现矢量显示 - 诺谦 - 博客园 (cnblogs.com)

1 安装freetype

freetype-2.10.0.tar.gz

链接:https://pan.baidu.com/s/1RKOpPdyNfoAr_wPeo-m4nA
提取码:0jcy

./configure
make
sudo make install

安装完后会将freetype的头文件安装到/usr/local/include/freetype2目录下,库文件安装到/usr/local/lib目录下。

2 显示英文

完整代码:english.c

#include <stdio.h>
#include <string.h>
#include <math.h>

#include <ft2build.h>
#include FT_FREETYPE_H


#define WIDTH   80/*打印的范围*/
#define HEIGHT  80

#define X 0/*文字坐标*/
#define Y 40

 #define degrees (0.0)/*字体旋转的角度*/

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

  double        angle;
  int           target_height;
  int           n, num_chars;


  if ( argc != 1 )
  {
    fprintf ( stderr, "usage: %s font sample-text\n", argv[0] );
    exit( 1 );
  }


  text          = "ABC";/*需要显示的文本*/
  num_chars     = strlen( text );
  angle         = ( degrees / 360 ) * 3.14159 * 2;/*旋转degrees度*/
  target_height = HEIGHT;

  error = FT_Init_FreeType( &library );              /* initialize library */
  /* error handling omitted */

  error = FT_New_Face( library, "./msyh.ttc", 0, &face );/* create face object */
  /* error handling omitted */

  #if 0
  /* use 50pt at 100dpi */
  error = FT_Set_Char_Size( face, 50 * 64, 0, 30, 0 );                /* set character size */
  /* error handling omitted */
  #else
  error = FT_Set_Pixel_Sizes( face, 24, 0);/*把字符像素设置为24*24像素, 0表示与另一个尺寸值相等*/
  /* error handling omitted */
  #endif

  slot = face->glyph;

  /*将角度转换成2*2的矩阵*/
  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 );



  /*
  *将该文字坐标转为笛卡尔坐标
  *LCD的坐标原点是位于左上方
  *笛卡尔坐标:表示坐标原点位于左下方(与LCD的y轴相反)
  *所以转换之前填写坐标时,需要转换一下y轴值(总高度-y)
  *转换成功后还需要转换回来(总高度-y)
  */
  pen.x = X * 64;/*在坐标(X,Y)处显示*/
  pen.y = ( target_height - Y ) * 64;/*target_height: LCD总高度*/

  for ( n = 0; n < num_chars; n++ )
  {

FT_Set_Transform( face, &matrix, &pen );

/*
*加载字形图像
*通过索引,从face中加载字形
*转为位图
*
*FT_LOAD_RENDER:表示直接将图像转为位图
*若想生成FT_RENDER_MODE_MONO(黑白图)类型,操作如下:FT_LOAD_RENDER | FT_LOAD_MONOCHROME
*生成出来的位图像素,每8个像素点便表示 face->glyph->bitmap->buffer[]里的一个字节.
*/
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 */

2.1编译运行

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

-I:指定头文件目录

-lfreetype -lm:指定库文件

./english

3 增加中文显示功能

中文在unicode编码中是两个字符,英文是一个字符,如果这样写:char chin[]="韦东山g" 就会出现乱码。

原因如下:

0x97e6 0x4e1c 0x5c71 0x0067

韦东山g的unicode码,共占用了7个字节,所以chin数组有7个元素。而下面是一个一个元素输入进去转换再显示,所以0x97和0xe6就会被分开,认为是两个字符,所以出现了乱码。即使我们在程序上做处理,但是我们并不能分清哪些是中文(两个字符),哪些是英文(一个字符)。

如果用char存储汉字英文等,则还需要判断数据类型,而wchar_t刚好可以放一个unicode字符。

注意:wchar_t在windows占2byte,在linux4bytes.

宽字符:wchar_t

头文件: #include<wchar.h>

通过**wcslen()**判断wchar_t数组大小

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

...

void show_image( void )
{
  int  i, j;
 
 
  for ( i = 0; i < HEIGHT; i++ )
  {
    printf("%02d",i);//添加此行(添加坐标打印信息)
	...
  }
}
    
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;
}

完整代码:english_chinese.c

#include <stdio.h>
#include <string.h>
#include <math.h>
#include<wchar.h>
#include <ft2build.h>
#include FT_FREETYPE_H


#define WIDTH   80/*打印的范围*/
#define HEIGHT  80

#define X 0/*文字坐标*/
#define Y 40

 #define degrees (0.0)/*字体旋转的角度*/

/* 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++ )
  {
    printf("%02d",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;


  double        angle;
  int           target_height;
  int           n;

  wchar_t  *chinese_str=L"韦东山g";

  if ( argc != 1 )
  {
    fprintf ( stderr, "usage: %s font sample-text\n", argv[0] );
    exit( 1 );
  }


  angle         = ( degrees / 360 ) * 3.14159 * 2;/*旋转degrees度*/
  target_height = HEIGHT;

  error = FT_Init_FreeType( &library );              /* initialize library */
  /* error handling omitted */

  error = FT_New_Face( library, "./msyh.ttc", 0, &face );/* create face object */
  /* error handling omitted */

  #if 0
  /* use 50pt at 100dpi */
  error = FT_Set_Char_Size( face, 50 * 64, 0, 30, 0 );                /* set character size */
  /* error handling omitted */
  #else
  error = FT_Set_Pixel_Sizes( face, 24, 0);/*把字符像素设置为24*24像素, 0表示与另一个尺寸值相等*/
  /* error handling omitted */
  #endif

  slot = face->glyph;

  /*将角度转换成2*2的矩阵*/
  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 );



  /*
  *将该文字坐标转为笛卡尔坐标
  *LCD的坐标原点是位于左上方
  *笛卡尔坐标:表示坐标原点位于左下方(与LCD的y轴相反)
  *所以转换之前填写坐标时,需要转换一下y轴值(总高度-y)
  *转换成功后还需要转换回来(总高度-y)
  */
  pen.x = X * 64;/*在坐标(X,Y)处显示*/
  pen.y = ( target_height - Y ) * 64;/*target_height: LCD总高度*/

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

FT_Set_Transform( face, &matrix, &pen );

/*
*加载字形图像
*通过索引,从face中加载字形
*转为位图
*
*FT_LOAD_RENDER:表示直接将图像转为位图
*若想生成FT_RENDER_MODE_MONO(黑白图)类型,操作如下:FT_LOAD_RENDER | FT_LOAD_MONOCHROME
*生成出来的位图像素,每8个像素点便表示 face->glyph->bitmap->buffer[]里的一个字节.
*/
error = FT_Load_Char( face, chinese_str[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 编译运行

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

./english_chinese

效果图

代码中定义的坐标是(0,40),而实际上很多字都会超出一点。

freetype库中有这么一张图片:

基线

字母的一部分会超出基线一点。
在汉字中,都在原点上面是没有问题的,但是一些英文字母比如g等,都会在基线下面,所以为了兼容所有语言文字,就会把字拉倒基线下面一点,如上图所示。

上图中,xMin表示该字符在x坐标最小处,同理xMax,yMax,yMin。
adevance是本字符的大小,下个字符的位置就是本字符的原点加上advance,程序如下:

 pen.x += slot->advance.x; //pen是下个字符的原点信息
 pen.y += slot->advance.y;

freetype2/ -lfreetype -lm`

./english_chinese

[外链图片转存中…(img-TCaQAtO0-1621067450132)]

代码中定义的坐标是(0,40),而实际上很多字都会超出一点。

freetype库中有这么一张图片:

[外链图片转存中…(img-lnJxtUGm-1621067450133)]

字母的一部分会超出基线一点。
在汉字中,都在原点上面是没有问题的,但是一些英文字母比如g等,都会在基线下面,所以为了兼容所有语言文字,就会把字拉倒基线下面一点,如上图所示。

上图中,xMin表示该字符在x坐标最小处,同理xMax,yMax,yMin。
adevance是本字符的大小,下个字符的位置就是本字符的原点加上advance,程序如下:

 pen.x += slot->advance.x; //pen是下个字符的原点信息
 pen.y += slot->advance.y;
posted @ 2022-06-02 18:15  木丨易  阅读(295)  评论(0)    收藏  举报