1. 字体渲染基础:点阵字体与矢量字体的区别、字符编码、字体文件格式概述

做嵌入式图形界面这些年,我踩过最多的坑,其实不是屏幕驱动,也不是触摸校准,而是字体。你想想看,一个界面好不好看,七成功力都在字上。但嵌入式系统资源就那么点,怎么把字又快又漂亮地画出来?这得从最基础的东西说起。

1.1 点阵字体 vs 矢量字体

先说点阵字体。说白了,就是用一个二维点阵来记录每个字符的形状。比如一个 16x16 的汉字,就是 256 个像素点,每个点要么黑要么白。我最早做 MP3 播放器界面时,用的就是这种。

点阵字体的核心特点:

  • 每个字符对应一个固定大小的位图
  • 放大后会出现锯齿(马赛克效果)
  • 占用内存小,渲染速度快
  • 适合小尺寸、低分辨率屏幕

矢量字体就不一样了。它用数学曲线来描述字形轮廓,最常见的是贝塞尔曲线。你放大多少倍,它都光滑如初。但代价就是计算量大,渲染慢。

对比维度 点阵字体 矢量字体
存储方式 像素位图 数学曲线
缩放效果 锯齿明显 平滑无损
内存占用 固定,较小 较大,与复杂度相关
渲染速度 极快(直接拷贝) 较慢(需计算曲线)
适用场景 小屏、低资源 MCU 高分辨率、大屏

我的经验:在 STM32F4 这类 MCU 上做 128x64 OLED 屏,点阵字体是首选。但如果你用带 GPU 的芯片(比如 i.MX RT 系列),矢量字体配合硬件加速,效果会好很多。

1.2 字符编码:从 ASCII 到 Unicode

字体文件里存的是字形,但你怎么知道要显示哪个字?这就靠字符编码了。我刚开始做嵌入式时,在这上面吃过不少亏。

ASCII 是最早的编码方案,只有 128 个字符,包括英文字母、数字和标点。一个字节就能搞定。但中文怎么办?

Unicode 的出现就是为了解决这个问题。它给全世界所有字符都分配了一个唯一的编号。比如汉字「中」的 Unicode 码点是 U+4E2D。但 Unicode 只是编号,怎么存储还得看具体实现。

UTF-8 是目前最流行的实现方式。它的特点是变长编码:

  • ASCII 字符用 1 个字节(兼容 ASCII)
  • 拉丁文、希腊文等用 2 个字节
  • 常用汉字用 3 个字节
  • 一些生僻字用 4 个字节

避坑指南:我曾经在一个项目里直接用 GB2312 编码,结果客户要求支持繁体中文,整个编码层都得重写。后来我学乖了,嵌入式系统里统一用 UTF-8,省心。

// UTF-8 编码示例:汉字「中」(U+4E2D)
// 0x4E2D 的二进制:0100 1110 0010 1101
// UTF-8 编码规则:3字节,格式为 1110xxxx 10xxxxxx 10xxxxxx
// 结果:0xE4 0xB8 0xAD

unsigned char utf8_bytes[] = {0xE4, 0xB8, 0xAD};
// 这就是「中」字在内存中的实际存储

1.3 字体文件格式:BDF、PCF、TTF

搞清楚了编码,接下来就是字体文件本身了。嵌入式领域常见的格式有这么几种。

BDF(Bitmap Distribution Format)

这是点阵字体的文本格式。说白了就是纯文本,你可以用记事本打开看。每个字符都明明白白写着哪些像素该点亮。

// BDF 文件片段示例
STARTCHAR 中
ENCODING 20013
BBX 16 16 0 -2
BITMAP
0000
0000
...
ENDCHAR

优点是可读性好,方便调试。缺点就是文件大,解析慢。我一般只在开发阶段用 BDF,正式发布前会转成 PCF。

PCF(Portable Compiled Format)

PCF 是 BDF 的二进制编译版本。它把 BDF 里的文本信息压缩成二进制结构,加载速度更快,占用空间更小。X Window 系统里用的就是它。

BDF vs PCF 对比:

  • BDF:文本格式,可读性强,文件大
  • PCF:二进制格式,加载快,文件小
  • 转换工具:bdftopcf(Linux 自带)

TTF(TrueType Font)

TTF 是矢量字体的代表格式。它用二次贝塞尔曲线描述字形,还包含 hinting(微调)信息,告诉渲染引擎在小字号时怎么优化显示效果。

我记得第一次在嵌入式设备上解析 TTF 时,被它的表结构吓了一跳。光是头部就有十几个表:cmap(字符映射)、glyf(字形数据)、head(全局信息)、hhea(水平排版)等等。

实用建议:如果你的 MCU 没有浮点运算单元(FPU),解析 TTF 的贝塞尔曲线会非常慢。这时候要么用点阵字体,要么提前把矢量字体光栅化成点阵存起来。

1.4 本章知识体系

下面这张图把本章的核心知识点串起来了。你可以看到,从字符编码到字体格式,再到最终的渲染方式,是一条完整的技术链路。

字体渲染基础 - 知识体系 字符编码 ASCII Unicode UTF-8 字体文件格式 BDF(点阵) PCF(点阵) TTF(矢量) 渲染方式 直接位图拷贝 曲线计算 + 填充 硬件加速渲染 核心思路 编码决定字符编号 格式决定存储方式 渲染决定显示效果

嗯,到这里第一章的内容就差不多了。点阵和矢量的区别、编码方案的选择、文件格式的取舍,这些都是后面章节的基础。我个人觉得,理解这些概念比直接上手调库更重要——方向对了,后面才不会走弯路。