1. TouchGFX 字体基础:字体在嵌入式 GUI 中的角色
做嵌入式 GUI 开发,说白了就是在跟「像素」打交道。而字体,就是把这些像素组织成可读文字的那套规则。我刚开始接触 TouchGFX 时,觉得字体不就是把 PC 上的 .ttf 文件丢进去编译吗?后来踩了几个坑才明白——嵌入式环境下的字体处理,远比想象中复杂。
1.1 字体在嵌入式 GUI 中的角色
你想想看,一个嵌入式设备上,用户第一眼看到的是什么?不是炫酷的动画,不是流畅的滑动,而是屏幕上的文字。字体直接决定了产品的专业度和用户体验。
- 信息传递:菜单、状态、数值,全靠字体呈现
- 品牌识别:定制字体能让产品更有辨识度
- 资源消耗:字体数据占用的 Flash 和 RAM,往往超出你的预期
核心观点:在嵌入式系统中,字体不是「拿来就用」的素材,而是需要精心裁剪和优化的资源。选错字体或压缩策略,轻则界面卡顿,重则 Flash 爆满。
我在一个工业手持设备项目里,就因为用了全套 Unicode 字库,导致固件体积直接翻倍。后来才学会——嵌入式字体,够用就好,别贪多。
1.2 TouchGFX 字体引擎架构
TouchGFX 的字体引擎,说白了就是一套「从字形数据到屏幕像素」的流水线。我画了张图,帮你理清它的内部结构。
这个架构里,我最想强调的就是字形缓存。为什么?因为栅格化一个汉字,在低端 MCU 上可能要花几毫秒。如果不做缓存,滚动列表时每一帧都在重新栅格化,帧率直接崩掉。
我的经验:TouchGFX 默认的缓存策略是 LRU(最近最少使用)。如果你的界面频繁切换页面,建议手动调整缓存大小。太小了命中率低,太大了浪费 RAM。一般我建议设为界面可见字符数的 1.5 倍。
1.3 字体文件格式与 TouchGFX 的兼容性
TouchGFX 支持两种主流字体格式:TrueType (.ttf) 和 OpenType (.otf)。但支持归支持,实际用起来有不少坑。
| 特性 | .ttf (TrueType) | .otf (OpenType) |
|---|---|---|
| 轮廓技术 | 二次贝塞尔曲线 | 三次贝塞尔曲线 (CFF) |
| 文件体积 | 通常较小 | 可能更大(含更多特性) |
| TouchGFX 支持度 | 完全支持 | 支持,但部分特性被忽略 |
| 常见问题 | 较少 | 连字、变体可能失效 |
| 推荐场景 | 嵌入式首选 | 需要特殊字形时 |
避坑指南:我曾经在一个项目里用了 .otf 字体,结果某些特殊字符(比如带变音符号的字母)在 TouchGFX 里显示成了方框。排查了两天才发现——TouchGFX 的字体转换工具不支持 OpenType 的 GSUB 特性。从那以后,我所有嵌入式项目都只用 .ttf。
1.4 字体转换流程
TouchGFX 不能直接使用 .ttf 或 .otf 文件。你需要通过 TouchGFX Font Converter 工具,把它们转成专用的二进制格式。流程是这样的:
- 选择字体文件:确保是 .ttf 格式,避免 .otf 的兼容性问题
- 指定字符集:只包含界面用到的字符,别贪多
- 设置字号:TouchGFX 不支持运行时缩放,字号必须在转换时固定
- 选择渲染模式:灰度抗锯齿还是单色?灰度效果好但占 Flash 多
- 生成 .ttf 文件:TouchGFX 专用的字体二进制文件
关键参数对比:
- 灰度抗锯齿:每个像素 4 位(16 级灰度),效果好,体积大
- 单色:每个像素 1 位,边缘锯齿明显,体积小
- 亚像素渲染:需要 LCD 子像素排列支持,慎用
我个人习惯在开发阶段用灰度抗锯齿,方便调试。到了量产阶段,如果 Flash 吃紧,再切回单色。你想想看,一个 16x16 的汉字,灰度模式要 128 字节,单色只要 32 字节。界面里如果有 200 个汉字,差距就是 19KB 对 6KB。
1.5 字体资源管理策略
嵌入式系统的 Flash 和 RAM 都是稀缺资源。字体管理得好不好,直接决定了你的产品能不能塞进目标芯片。
| 策略 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 全字库嵌入 | Flash > 16MB 的设备 | 无需运行时加载 | 占用大量 Flash |
| 子集化嵌入 | 界面字符固定 | 体积小,效率高 | 不支持动态文本 |
| 外部存储加载 | Flash 紧张,有 SPI Flash | 按需加载 | 读取延迟 |
| 运行时栅格化 | RAM 充足,CPU 性能好 | 灵活 | CPU 开销大 |
我的建议:对于大多数 STM32 项目,子集化嵌入是最稳妥的方案。先用工具扫描整个 UI 用到的字符,生成最小字库。如果后续需要添加新字符,重新跑一遍转换流程就行。