龙空技术网

使用 freetype 显示单个文字

韦东山嵌入式Linux 251

前言:

而今姐妹们对“linux查看包含字符1或者包含字符2包含字符3的行”大体比较看重,我们都想要分析一些“linux查看包含字符1或者包含字符2包含字符3的行”的相关文章。那么小编也在网摘上汇集了一些对于“linux查看包含字符1或者包含字符2包含字符3的行””的相关知识,希望咱们能喜欢,兄弟们一起来学习一下吧!

来源:百问网

作者:韦东山

本文字数:5290,阅读时长:7分钟

使用 GIT 下载所有源码后,本节源码位于如下目录:

01_all_series_quickstart\

04_嵌入式 Linux 应用开发基础知识\source\10_freetype\

01_wchar\test_wchar.c

02_freetype_show_font\freetype_show_font.c

03_freetype_show_font_angle\freetype_show_font_angle.c

1、矢量字体引入

使用点阵字库显示英文字母、汉字时,大小固定,如果放大缩小则会模糊甚至有锯齿出现,为了解决这

个问题,引用矢量字体。

矢量字体形成分三步:

① 确定关键点,

② 使用数学曲线(贝塞尔曲线)连接头键点,

③ 填充闭合区线内部空间。

什么是关键点?以字母“A”为例,它的的关键点如下图中的黄色所示。

再用数学曲线(比如贝塞尔曲线)将关键点都连接起来,得到一系列的封闭的曲线,如下图所示:

最后把封闭空间填满颜色,就显示出一个 A 字母,如下图所示:

如果需要放大或者缩小字体,关键点的相对位置是不变的,只要数学曲线平滑,字体就不会变形。

2、Freetype 介绍

Freetype 是开源的字体引擎库,它提供统一的接口来访问多种字体格式文件,从而实现矢量字体显示。我们只需要移植这个字体引擎,调用对应的 API 接口,提供字体文件,就可以让 freetype 库帮我们取出关键点、实现闭合曲线,填充颜色,达到显示矢量字体的目的。

关键点(glyph)存在字体文件中,Windows 使用的字体文件在 c:\Windows\Fonts 目录下,扩展名为 TTF的都是矢量字库,本次使用实验使用的是新宋字体 simsun.ttc。

给定一个字符,怎么在字体文件中找到它的关键点?

首先要确定该字符的编码值:比如 ASCII 码、GB2312 码、UNICODE 码。如果字体文件支持某种编码格式(charset),就可以使用这类编码值去找到该字符的关键点(glyph)。有些字体文件支持多种编码格式(charset),这在文件中被称为 charmaps(注意:这个单词是复数,意味着可能支持多种 charset)。

以 simsun.ttc 为值,该字体文件的格如下:头部含有 charmaps,可以使用某种编码值去 charmaps 中找到它对应的关键点。下图中的“A、B、中、国、韦”等只是 glyph 的示意图,表示关键点。

Charmaps 表示字符映射表,字体文件可能支持哪一些编码,GB2312、UNICODE、BIG5 或其他。如果字体文件支持该编码,使用编码值通过 charmap 就可以找到对应的 glyph,一般而言都支持 UNICODE 码。

有了以上基础,一个文字的显示过程可以概括如下:

① 给定一个字符可以确定它的编码值(ASCII、UNICODE、GB2312);

② 设置字体大小;

③ 根据编码值,从文件头部中通过 charmap 找到对应的关键点(glyph),它会根据字体大小调整关键点;

④ 把关键点转换为位图点阵;

⑤ 在 LCD 上显示出来

下载到“freetype-doc-2.10.2.tar.xz”,下图中的文件就是官方文档:

参照上图中 step1,step2,step3 里的内容,可以学习如何使用 freetype 库,总结出下列步骤:

① 初始化:FT_InitFreetype

② 加载(打开)字体 Face:FT_New_Face

③ 设置字体大小:FT_Set_Char_Sizes 或 FT_Set_Pixel_Sizes

④ 选择 charmap:FT_Select_Charmap

⑤ 根据编码值 charcode 找到 glyph_index:glyph_index = FT_Get_Char_Index(face,charcode)

⑥ 根据 glyph_index 取出 glyph:FT_Load_Glyph(face,glyph_index)

⑦ 转为位图:FT_Render_Glyph

⑧ 移动或旋转:FT_Set_Transform

⑨ 最后显示出来。

上面的⑤⑥⑦可以使用一个函数代替:FT_Load_Char(face, charcode, FT_LOAD_RENDER),它就可以得到位图。

3、在 LCD 上显示一个矢量字体

1. 使用 wchar_t 获得字符的 UNICODE 值

要显示一个字符,首先要确定它的编码值。常用的是 UNICODE 编码,在程序里使用这样的语句定义字符串时,str 中保存的要么是 GB2312 编码值,要么是 UTF-8 格式的编码值,即使编译时使用“-fexec-charset=UTF-8”,str 中保存的也不是直接能使用的 UNICODE 值:

char *str = “中”;

如果想在代码中能直接使用 UNICODE 值,需要使用 wchar_t,宽字符,示例代码如下:

01 #include <stdio.h>02 #include <string.h>03 #include <wchar.h>0405 int main( int argc, char** argv)06 {07 wchar_t *chinese_str = L"中 gif";08 unsigned int *p = (wchar_t *)chinese_str;09 int i;1011 printf("sizeof(wchar_t) = %d, str's Uniocde: \n", (int)sizeof(wchar_t));12 for (i = 0; i < wcslen(chinese_str); i++)13 {14 printf("0x%x ", p[i]);15 }16 printf("\n");1718 return 0;19 }}

以 UTF-8 格式保存 test_wchar.c,编译、测试命令如下:

book@book-virtual-machine:~/10_freetype/01_wchar$ gcc -o test_wchar test_wchar.cbook@book-virtual-machine:~/10_freetype/01_wchar$ ./test_wcharsizeof(wchar_t) = 4, str's Uniocde:0x4e2d 0x67 0x69 0x66

每个 wchar_t 占据 4 字节,可执行程序里 wchar_t 中保存的就是字符的 UNICODE 值。

注意:如果 test_wchar.c 是以 ANSI(GB2312)格式保存,那么需要使用以下命令来编译:

gcc -finput-charset=GB2312 -fexec-charset=UTF-8 -o test_wchar test_wchar.c

2. 使用 freetype 得到位图

参考“freetype-doc-2.10.2\freetype-2.10.2\docs\tutorial\image.c”,使用 freetype 显示一个字

符并不难。

使用 GIT 下载所有源码后,本节源码位于如下目录:

01_all_series_quickstart\04_嵌入式 Linux 应用开发基础知识\source\10_freetype\02_freetype_show_font\freetype_show_font.c

要使用 freetype 得到一个字符的位图,只需要 4 个步骤,代码先贴出来再分析:

① 初始化 freetype 库

158 error = FT_Init_FreeType( &library ); /* initialize library */

② 加载字体文件,保存在&face 中:

161 error = FT_New_Face( library, argv[1], 0, &face ); /* create face object */162 /* error handling omitted */163 slot = face->glyph;

第 163 行是从 face 中获得 FT_GlyphSlot,后面的代码中文字的位图就是保存在 FT_GlyphSlot 里。

③ 设置字体大小

165 FT_Set_Pixel_Sizes(face, font_size, 0);

④ 根据编码值得到位图

使用 FT_Load_Char 函数,就可以实现这 3 个功能:

a. 根据编码值获得 glyph_index:FT_Get_Char_Index

b. 根据 glyph_idex 取出 glyph:FT_Load_Glyph

c. 渲染出位图:FT_Render_Glyph

代码如下:

175 /* load glyph image into the slot (erase previous one) */176 error = FT_Load_Char( face, chinese_str[0], FT_LOAD_RENDER );

3. 在屏幕上显示位图

位图里的数据格式是怎样的?参考 example1.c 的代码,可以得到下面这个图:

要在屏幕上显示出这些位图,并不复杂:

183 draw_bitmap( &slot->bitmap,184 var.xres/2,185 var.yres/2);

draw_bitmap 函数代码如下,由于位图中每一个像素用一个字节来表示,在 0x00RRGGBB 的颜色格式中它只能表示蓝色,所以在 LCD 上显示出来的文字是蓝色的:

4. 编译

编译命令(如果你使用的交叉编译链前缀不是 arm-buildroot-linux-gnueabihf,请自行修改命令):

$ arm-buildroot-linux-gnueabihf-gcc -o freetype_show_font freetype_show_font.c -lfreetype

它会提示如下错误:

freetype_show_font.c:12:10: fatal error: ft2build.h: No such file or directory#include <ft2build.h> ^~~~~~~~~~~~compilation terminated.

我们不是已经编译过 freetype 并且把头文件复制进工具链里了吗?怎么还有这个错误?

我们编译出 freetype 后,得到的 ft2build.h 是位于 freetype2 目录里,我们把整个 freetype2 目录

复制进了工具链里。

但是包括头文件时,用的是“#include <ft2build.h>”,要么改成:

#include <freetype2/ft2build.h>

要么把工具链里 incldue/freetype2/*.h 复制到上一级目录,我们使用这种方法:跟 freetype 文档保持一致。执行以下命令:

book@PC$ cd /home/book/100ask_stm32mp157_pro-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/arm-buildroot-linux-gnueabihf/sysroot/usr/includebook@PC$ mv freetype2/* ./

然后再次执行以下命令:

$ arm-buildroot-linux-gnueabihf-gcc -o freetype_show_font freetype_show_font.c -lfreetype

5. 上机

将编译好的 freetype_show_font 文件与 simsun.ttc 字体文件拷贝至开发板,这 2 个文件放在同一个目录下,然后执行以下命令。

[root@board:~]# ./freetype_show_font ./simsun.ttc 或[root@board:~]# ./freetype_show_font ./simsun.ttc 300

如果实验成功,我们将在屏幕中间看到一个蓝色的“繁”字。

4、在 LCD 上令矢量字体旋转某个角度

使用 GIT 下载所有源码后,本节源码位于如下目录:

01_all_series_quickstart\04_嵌入式 Linux 应用开发基础知识\source\10_freetype\03_freetype_show_font_angle\freetype_show_font_angle.c

在实现显示一个矢量字体后,我们可以添加让该字旋转某个角度的功能,主要代码还是参照 example1.c。

1. 关键代码

① 定义 2 个变量:角度、矩阵,如下:

② 设置角度值:

③ 设置矩阵、交形、加载位图:

2. 编译

编译命令(如果你使用的交叉编译链前缀不是 arm-buildroot-linux-gnueabihf,请自行修改命令):

$ arm-buildroot-linux-gnueabihf-gcc -o freetype_show_font_angle freetype_show_font_angle.c -lfreetype -lm

3. 上机

将编译好的 freetype_show_font_angle 文件与 simsun.ttc 字体文件拷贝至开发板,这 2 个文件放在同一个目录下,然后执行以下命令。

[root@board:~]# ./freetype_show_font_angle ./simsun.ttc 90 200

如果实验成功,我们将在屏幕中间看到一个蓝色的、旋转了 90 度的“繁”字。

「新品首发」STM32MP157开发板火爆预售!首批仅300套

标签: #linux查看包含字符1或者包含字符2包含字符3的行