嵌入式应用-详解移植并使用freetype显示文字

article/2025/8/30 9:29:09

目录

前言 

1. freetype和相关概念简介

2.freetype显示文字流程和主要函数

2.1 包含头文件及API头文件:ft2build.h

2.2 初始化: FT_InitFreetype

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

2.4 设置字体大小:FT_Set_Char_Size或FT_Set_Pixel_Size

2.4.5 (可选)选择charmap: FT_Select_Charmap

2.5 得到位图FT_Load_Char

2.6 显示单个文字


前言 

学过单片机的朋友都会用点阵来显示一个字符,无非就是把点阵里的值取出来一个个在屏幕上显示,修改字符大小需重新定义点阵,或者经过运算,freetype是一个矢量字体引擎,可以显示ttf字体文件中的字符。点阵和矢量字体并无优劣,点阵在资源少,显示字符少的情况下更加适合,矢量字体在资源多,显示字符多,显示要求变化大的情况下更加好。

移植freetype详见Linux安装zlib、libpng、freetype给交叉编译工具链使用

1. freetype和相关概念简介

freetype

一个免费的、可移植的字体引擎开源库,提供统一的接口来访问多种字体格式文字。
官网:The FreeType Project

矢量字体(Vector font)

矢量字体又叫Outline font,即轮廓字体。

矢量字体显示有3步:
1)确定关键点;2)使用数学曲线(贝塞尔曲线)连接关键点;3)填充闭合曲线内部空间。

字体的关键点

以字母“A”为例,它的关键点如下图黄色点所示:

然后用数学曲线(如贝塞尔曲线),将这些关键点连接起来:

填充封闭闭合区间,就显示出字母“A”。如下图所示:

字符编码

在计算机里一切都是用数字来表示,字符编码本质上就是解决一个字符用什么数字来表示的问题。比如字符 A,用 0x41 来表示它。我们常见的ASCII码有128个字符,用一个字节,8位表示。

ANSI编码

ANSI不是一种特定的编码

ANSI 是 ASCII 的扩展,向下包含 ASCII。对于 ASCII 字符仍以一个字节来表示,对于非 ASCII 字符则使用 两个字节来表示。并没有固定的 ASNI 编码,它跟“本地化”(locale)密切相关。比如在中国大陆地区, ANSI 的默认编码是 GB2312;在港澳台地区默认编码是 BIG5。以数值“ 0xd0d6”为例,对于 GB2312 编码它表示“中”;对于 BIG5 编码它表示“ 笢”。所以对于 ANSI 编码的 TXT 文件,如果你打开它发现乱码,那么还得再次细分它的具体编码。

UNICODE字符集

在 ANSI 标准中,很多种文字都有自己的编码标准,汉字简体字有 GB2312、繁体字有 BIG5,这难免同一个数值对应不同字符。比如数值“ 0xd0d6”,对于GB2312 编码它表示“中”;对于 BIG5 编码它表示“ 笢”。这造成了使用 ANSI 编码保存的文件,不适合跨地区交流。

UNICODE 字符集(也可以叫编码,实际上叫字符集更加合适)就是解决这类问题:对于地球上任意一个字符,都给它一个唯一的数值。

UNICODE 仍然向下兼容 ASCII,但是对于其他字符会有对应的数值,比如对于“中”、“ 笢”,它们的数值分别是: 0x4e2d、 0x7b22UNICODE 中的数值范围是 0x0000 至 0x10FFFF。

UTF-8编码

Unicode 统一了所有字符的编码,是一个 Character Set,也就是字符集,字符集只是给所有的字符一个唯一编号,但是却没有规定如何存储,一个编号为 65 的字符,只需要一个字节就可以存下,但是编号 40657 的字符需要两个字节的空间才可以装下,而更靠后的字符可能会需要三个甚至四个字节的空间。

这时,用什么规则存储 Unicode 字符就成了关键,我们可以规定,一个字符使用四个字节存储,也就是 32 位,这样就能涵盖现有 Unicode 包含的所有字符,这种编码方式叫做 UTF-32(UTF 是 UCS Transformation Format 的缩写)。UTF-32 的规则虽然简单,但是缺陷也很明显,假设使用 UTF-32 和 ASCII 分别对一个只有西文字母的文档编码,前者需要花费的空间是后者的四倍(ASCII 每个字符只需要一个字节存储)。

在存储和网络传输中,通常使用更为节省空间的变长编码方式 UTF-8,UTF-8 代表 8 位一组表示 Unicode 字符的格式,使用 1 - 4 个字节来表示字符。

wchar_t

char型的常见编码方式是ASCII,ASCII编码是一种基于8位二进制数的字符编码算法,能表示256种可能的字符。

wchar_t的出现,是出于程序兼容多语言的需求,因为在很多语言中,字符的数量远远大于256。因此wchar_t出现了,wchar_t全称是wide character type,也就是宽字符。

wchar_t *a=“哈”

哈字的UNICODE值就被保存在a指向的地址了。

我们编写 C 程序时,输入的字符本身(如上面的哈字)可以使用 ANSI 编码,或是 UTF-8 编码;在编译程序时,可以使用以下的选项告诉编译器:

-finput-charset=GB2312
-finput-charset=UTF-8

如果不指定“ -finput-charset”, GCC 就会默认 C 程序的编码方式为 UTF-8,即使你是以 ANSI 格式保存,也会被当作 UTF-8 来对待。对于编译出来的可执行程序,可以指定它里面的字符是以什么方式编码,可以使用以下的选项编译器:

-fexec-charset=GB2312
-fexec-charset=UTF-8

2.freetype显示文字流程和主要函数

2.1 包含头文件及API头文件:ft2build.h

#include <ft2build.h>
#include FT_FREETYPE_H // 基础的FreeType 2 API
#include FT_GLYPH_H // 管理Glyph Images

2.2 初始化: FT_InitFreetype

初始化FreeType库

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

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

face描述了一个给定(印刷)字体和样式

FT_Face       face;   
error = FT_New_Face( library, 字体文件路径, 0, &face ); /* create face object */

2.4 设置字体大小:FT_Set_Char_Size或FT_Set_Pixel_Size

FT_Set_Char_Size:设置字符尺寸(nominal size in points,1pt=0.376mm);

这个函数是设置物理上的大小,freetype会根据设备分辨率调整像素,一般不怎么用这个

FT_Set_Pixel_Size:设置字符尺寸(nominal size (in pixels),单位是像素点);

这个函数是设置像素大小,一半用这个比较多。

2.4.5 (可选)选择charmap: FT_Select_Charmap

一个字体可能可以支持不同的编码,支持哪些编码的信息会被放在字体文件的charmaps中。face对象创建时,默认从字体文件中查找Unicode charmap,也就是如果使用Unicode就不需要指定charmap了。如果想要改变,可以调用该函数。

当前charmap可以通过face->charmap来访问。

我们这里不需要设置。

2.5 得到位图FT_Load_Char

FT_Load_Char(face, charcode, FT_LOAD_RENDER),可以直接得到glyph对应的bitmap。

wchar_t *chinese_str = L"哈";
error = FT_Load_Char( face, chinese_str[0], FT_LOAD_RENDER );

可以看到,传入的是2.3中定义的FT_Face  face;。生成一个字符的点阵位图时,位图保存在哪里?

FT_Face结构体内部有一个结构体成员, FT_GlyphSlot      glyph

FT_GlyphSlot结构体内部有一个成员,FT_Bitmap         bitmap;

生成第2个字符位图时,也会保存在这,会覆盖第1个字符的位图。 

我们往往自己定义一个FT_GlyphSlot结构体slot,在加载字体后就将face->glyph传给他。

FT_GlyphSlot  slot;slot = face->glyph;

这些结构体都是指针,所以其实就是赋值了地址face->glyph->bitmap发生了变化,slot->bitmap也会变化。

FT_Bitmap 结构体:

  typedef struct  FT_Bitmap_{int             rows;int             width;int             pitch;unsigned char*  buffer;short           num_grays;char            pixel_mode;char            palette_mode;void*           palette;} FT_Bitmap

重要的成员是rows、width,buffer,含义如下图,其他成员作用可以自己搜一下。 

由于位图中每一个像素用一个字节来表示,为8位灰度图。

参考:

嵌入式Linux入门-Framebuffer应用编程在Linux系统下画个点

 到这应该就知道怎么在屏幕上显示了吧。

2.6 显示单个文字

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;//printf("x = %d, y = %d\n", x, y);for ( j = y, q = 0; j < y_max; j++, q++ ){for ( i = x, p = 0; i < x_max; i++, p++ ){if ( i < 0      || j < 0       ||i >= var.xres || j >= var.yres )continue;//image[j][i] |= bitmap->buffer[q * bitmap->width + p];lcd_put_pixel(i, j, bitmap->buffer[q * bitmap->width + p]);}}
}

参数里的x,y是在显示的位置的坐标。

下面函数为在lcd上画一个点的函数。

lcd_put_pixel(int x, int y, unsigned int color)

显示一行文字你可以用位图,一个个显示字,但是并不完美,更好的方式可以参考【硬核】韦东山:使用freetype显示一行文字 - 知乎


http://chatgpt.dhexx.cn/article/IZb0gP3b.shtml

相关文章

freetype用法

freetype用法 文章目录 freetype用法0.实现1.变量定义2.lcd操作获取屏幕信息3.freetype初始化4.绘画 1.字形度量2.类1.FT 中的面向对象2.FT_Library 类3.FT_Face 类4 FT_Size 类5 FT_GlyphSlot 类 3.函数1.把一个字符码转换为一个字形索引FT_Get_Char_Index函数2.从 face 中装…

FreeType使用

前言 在openGL绘制字体&#xff0c;我们一般都使用freeType字体库&#xff0c;如下图所示 下载 freeType官网 编译源码 使用CMake编译源码 如果嫌麻烦&#xff0c;我这里有编译好的库&#xff0c;包括头文件、lib静态库、dll动态库 编译好的lib和dll库下载地址 例子 …

【C++】字体文件解析(FreeType)

目录 字体文件解析 一、前言 二、基本排版概念 1.字体文件 2.字符图像和字符表 3.字符和字体指标 三、字形轮廓 四、字形指标 1.基线、笔和布局 2.排版指标和边界框 3.方位与步进 4.网格拟合的效果 5.文本宽度与边界框 五、代码实现 六、使用实例 七、合并缓存优…

FreeType 用法

Freetype是一个跨平台、开源的字体渲染器&#xff0c;网上很多文章介绍&#xff0c;本人就不啰嗦了。本文重点在于实现文章标题所属的各种效果&#xff0c;不是Freetype的基本使用方法介绍文档&#xff0c;所以对于Freetype不熟悉的同学们请先学习下Freetype的基本用法&#xf…

freetype 使用解析---矢量字体

屏幕显示字体(字体点阵)&#xff1a; 在内核中有对应的文件fontdata_8x16.c&#xff0c;将字体通过数组8*16来描述&#xff0c;0表示为空&#xff0c;1表示描点&#xff0c;通过通过各个点形成一个字体点阵显示在屏幕上&#xff0c;而在我们所有终端中显示的字体也可以是通过点…

freetype简介与测试

目录 一、简要 二、文字显示过程 三、freetype中的step1 四、在PC上测试freetype 4.1 分析main函数 4.2 修改main函数 4.3 在PC上测试 4.4 得到CBox 一、简要 从点阵文件中把字母或者汉字的字模取出来在LCD上显示这个方式有个缺点&#xff0c;这个文字的大小就固定了不…

Freetype 的安装与使用

4 交叉编译程序 4.1 程序运行的一些基础知识 编译程序时去哪找头文件&#xff1f; 系统目录&#xff1a;就是交叉编译工具链里的某个 include 目录&#xff1b; 也可以自己指定&#xff1a;编译时用 “ -I dir ” 选项指定。 链接时去哪找库文件&#xff1f; 系统目录&#x…

java和web哪个难_web前端和java哪个难学?哪个简单?

说到java很多都人都熟知&#xff0c;但是说到web前端可能是很多人并不知道&#xff0c;随着最近几年的发展&#xff0c;web前端开发人越来越吃香&#xff0c;无论是薪资待遇还是岗位的招聘数量比java差不了多少&#xff0c;最近有同学在咨询web前端和java哪个难学这个问题&…

js和java那个难_javascript与java哪个难?

javascript与java哪个难&#xff1f;答案是&#xff1a;JavaScript比Java更难。那么这是为什么&#xff1f;下面本篇文章就来给大家介绍一下&#xff0c;希望对大家有所帮助。 原因&#xff1a; JavaScript有太多东西需要你自己去理解&#xff0c;这些东西里有很多要么Java已经…

没学历学java很难找工作吗

说实话不是学Java很难找工作&#xff0c;是以后找工作基本都会看学历&#xff0c;学历这个东西说重要也重要&#xff0c;因为它决定了你的简历能不能呈现到面试官面前&#xff0c;如果你的学历不够的话很有可能在第一轮简历就被刷下去了&#xff0c;它根本就不会呈现在面试官面…

java最难的部分_java最难学的是那一块?

原标题&#xff1a;java最难学的是那一块&#xff1f; 对于那些打算通过学习java来找到一份工作的同学来说&#xff0c;可以分为三个学习阶段&#xff0c;初级&#xff0c;中级&#xff0c;高级。不同的学习阶段有不同的难点&#xff0c;下来我就简单的和大家仔细的聊聊&#x…

学习Java开发难不难?好学吗?

学习Java难不难&#xff1f;这是很多希望学习Java的人比较纠结的问题。实际上&#xff0c;Java语言是非常易学的&#xff0c;Java语言机遇&#xff23;语言&#xff0c;却又高于&#xff23;语言。Java语言简单易学的特性使得大多数程序员很容易学习和使用Java。 Java是个简单…

零基础Java难学吗?自学怎么样?

在零基础上学习Java难吗?自学呢?要回答这个问题,我们应该从多方面来回答。首先,谁更适合学习Java?   如果仅仅从兴趣上说那么人人都可以胜任,那就像姜子牙70多年的探险生涯。47岁的刘邦在沛县召集民众响应陈胜武广起义。古代的年龄相当于我们现在的六十岁。齐白石,一位…

java学习路线,一个初中生学java要多久,java难学吗

一门永不过时的编程语言——Java 软件开发 java难学吗 java不难&#xff0c;你可以做如下学习 一、到相应的培训机构付费学习 别在这说培训机构没用什么的&#xff0c;不过一定要找正规的培训机构&#xff0c;不然容易被坑。培训机构里面的课程都是现在工作中需要用到的&am…

学Java难吗

Java这门语言你要是单独拎出来&#xff0c;那还是挺复杂的&#xff0c;但你要是把它放到编程里面&#xff0c;那算不上难&#xff0c;因为编程这门行业本来就难&#xff0c;而且&#xff0c;现在大学计算机专业的学生&#xff0c;大学期间&#xff0c;会设置Java这门课程&#…

c语言难还是java难_C语言真的比Java难学吗?

原标题&#xff1a; C语言真的比Java难学吗&#xff1f; 千锋小编觉得C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。C语言语法比较简单便捷&#xff0c;而且性能快速&#xff0c;只比汇编语言…

学习Java很难吗

没有简单的语言,编程语言各有各的优势,同时也各有各的难点,不过这些难点也可以是他们的特点。就像C++难的是语言的细节,Java难的是各种库,各种函数的调用,它的基本语法很简单,但只靠基础是做不出什么东西的,必须去熟悉各种轮子才能进行开发。 第一、 Java入门很简单…

Java难学吗

学习Java说难其实也不难&#xff01; 毕竟世上无难事&#xff0c;只怕有心人。 Java是编程语言中比较难学的一门语言&#xff0c;它的难度并不低&#xff0c;相对比于C语言来说&#xff0c;Java的学习难度要小一些。 Java的学习中最难得就是&#xff0c;各种各样的框架&#x…

java学起来难不难?

同学们问的最多的一个关于Java的问题就是java学起来到底难不难&#xff1f;java好不好学&#xff1f;小千综合过去毕业学员给大家介绍一下学Java到底难不难。 java语言 单单来说学Java这件事的话&#xff0c;小千认为是不难的&#xff0c;实际上Java经常会用到的代码结构无非就…

关于 高内聚 和 低耦合 的理解

随着一个程序逻辑越来越多&#xff0c;就难免需要微服务来保证程序的高可用性。一个服务宕机或者出问题了&#xff0c;不影响其他的服务。 只要有微服务的存在&#xff0c;两个服务之间有许多代码需要共用。 高内聚低耦合是一种程序设计的思想&#xff0c;高内聚的本质也就抽…