基于HZK16(点阵字库)的汉字显示,这只在嵌入式开发的早期非常常见。
但是,随着对界面美观度要求的提高,HZK16 这种固定点阵的方式就显露出明显的局限性了(比如字体无法无损缩放、边缘锯齿严重、只能用宋体等)。
这时候,FreeType就登场了。
1. 什么是 FreeType?
FreeType是一个完全免费(开源)、可移植、高效的软件库,专门用来加载字体文件并将其渲染成位图(Bitmap)。
它不负责把字画到屏幕上,它的核心作用是:“给我一个字符编码(如 Unicode),我通过计算,给你返回这个字符的像素点阵图(Bitmap)和位置信息。”
- 支持格式:TrueType (
.ttf)、OpenType (.otf)、Type1 等绝大多数矢量字体格式。 - 应用场景:Android、iOS、Linux (PC & Embedded)、Chrome 等系统的字体渲染底层都是它。
2. 为什么要用 FreeType?(对比 HZK16)
为了更直观地理解,将 FreeType 与 HZK16 做个对比:
| 特性 | HZK16 (点阵字体) | FreeType (矢量字体渲染) |
|---|---|---|
| 核心原理 | 每一个字都是画死的0-1矩阵 (0或1) | 每一个字由数学曲线(贝塞尔曲线)描述 |
| 缩放能力 | 差。放大后全是马赛克(锯齿) | 完美。任意放大缩小,边缘永远平滑 |
| 字体样式 | 单一(通常只有宋体) | 丰富。可以使用 Windows/Mac 上的任何.ttf字体 |
| 字符集 | 限制在 GB2312 (约6763字) | 支持Unicode,涵盖全球几乎所有语言 |
| 显示效果 | 黑白分明,边缘生硬 | 支持抗锯齿 (Antialiasing),利用灰度让边缘平滑 |
| 资源占用 | 极小 (无需计算,直接读文件) | 较高 (需要CPU 计算曲线生成位图) |
总结:HZK16 适合资源极度匮乏的单片机;FreeType 适合运行 Linux 的 ARM 芯片,用来做现代化的 UI。
3. FreeType 的工作流程
使用 FreeType 显示一个字符(例如“A”),大致经过以下流水线:
加载库与字体 (Init & Load):
初始化 FreeType 库,加载 .ttf 文件(比如 msyh.ttf 微软雅黑)。
设置大小 (Set Size):
告诉 FreeType 你想要多大的字(例如 24像素)。
加载字符 (Load Glyph):
传入字符编码(Unicode),FreeType 会在字体文件中找到对应的矢量轮廓 (Outline)。
栅格化 (Rasterize):
FreeType 通过数学运算,将矢量的轮廓“光栅化”变成位图 (Bitmap)。
- 注意:这一步生成的位图是存在内存里的,还没上屏。
渲染上屏 (Draw):
你读取 FreeType 生成的内存位图,结合它提供的偏移量信息,用你自己的 lcd_put_pixel 把点画到 Framebuffer 上。
4. 关键概念(编程必须知道)
在写代码前,必须理解 FreeType 的几个核心数据结构和坐标概念:
A. 核心结构体
FT_Library: 指代 FreeType 库的实例【面向对象编程思想的体现之一】。FT_Face: 指代一个打开的字体文件(“Face”在这里就是字体的意思)。face->glyph:字形槽 (Glyph Slot)。这是一个容器,当你加载一个字符后,结果(位图、尺寸、位置)都保存在这里面。
B. 重要的度量值 (Metrics)
FreeType 不仅仅给你像素点,还会给你排版信息。这也是 HZK16 没有的。
bitmap_left(Bearing X): 字符距离光标原点的水平偏移。例如字母j,它的起始点其实在光标左边一点点;或者斜体字。bitmap_top(Bearing Y): 字符最高点距离基线(Baseline)的垂直距离。- 关键点:HZK16 是从左上角无脑画。FreeType 是基于基线 (Baseline)的(就像我们在四线格英语本上写字一样,
g、y的尾巴会掉到基线下面)。
- 关键点:HZK16 是从左上角无脑画。FreeType 是基于基线 (Baseline)的(就像我们在四线格英语本上写字一样,
advance: 步进值。画完这个字后,光标应该向右移动多少像素,以便画下一个字。
C. 笛卡尔坐标系
FreeType 内部计算使用笛卡尔坐标系(Y轴向上),而屏幕(LCD)通常是 Y轴向下。在使用时需要注意坐标转换(不过 FreeType 输出的位图通常已经是转换好的行顺序,只需注意基线对齐)。
5. 如何在开发板上使用?(简略步骤)
要在你的 100ask 开发板上使用 FreeType,通常需要三步:
交叉编译 FreeType 库:
你需要下载 FreeType 源码,用 arm-buildroot-linux-gnueabihf-gcc 编译得到 libfreetype.so 和头文件。(Buildroot 通常已经帮你做好了)。
代码编写:
- 包含头文件:
#include <ft2build.h>和FT_FREETYPE_H。 - 初始化:
FT_Init_FreeType,FT_New_Face。 - 循环处理字符串,对每个字符:
FT_Load_Char-> 获取slot->bitmap-> 也就是一个二维数组 -> 用lcd_put_pixel画出来。
- 包含头文件:
编译命令:
需要告诉编译器头文件在哪,库在哪。
Bash
gcc -o show_font show_font.c -I/usr/include/freetype2 -lfreetype
总结
FreeType 是从“画点”进化到“画字”的关键技术。
- 以前 (HZK16):你像个搬运工,把仓库(HZK文件)里的箱子(点阵)原封不动地搬到屏幕上。
- 现在 (FreeType):你雇了一个画家。你告诉画家“我要个24号的宋体‘中’字”,画家现场画出一幅画(位图)给你,你再把它贴到墙(屏幕)上。