LVGL中文字库定制实战:从TTF到嵌入式C文件的完整转换指南
1. 为什么需要自定义中文字库
做嵌入式GUI开发的朋友都知道,LVGL自带的中文字符实在太少了。官方提供的默认中文字库只有1000个常用汉字,在实际项目中根本不够用。比如你要显示产品名称、功能说明或者用户协议,随便一段中文就可能超过这个限制。
我去年做一个智能家居面板项目时就遇到了这个问题。产品需要显示"温湿度传感器异常请检查连接"这样的提示信息,结果发现"感"和"器"这两个字居然不在默认字库中,显示出来就是两个方框,特别影响用户体验。
更麻烦的是,不同项目对字体的需求也不一样。有的需要优雅的宋体,有的需要现代的黑体,还有的需要节省空间的细体。这时候就需要我们自己动手制作字库了。
制作自定义字库的好处很明显:
- 自由选择字体风格:可以用任何你喜欢的TTF或WOFF字体
- 精准控制字符范围:只包含需要的字符,极大减小文件体积
- 统一视觉风格:整个项目的字体表现完全一致
不过也要注意两个限制:一是生成的字库大小固定,不能动态调整大小;二是如果字符集选择不当,生成的文件可能会很大。我曾经不小心生成了一个14MB的字库文件,直接把Flash空间占满了。
2. 准备工作:字体文件与工具选择
2.1 获取字体文件
首先你需要一个字体文件,推荐使用开源免费的字体,避免版权问题。百问网提供了一些不错的中文字体资源,你也可以从Google Fonts、Adobe Fonts等平台下载免费商用的字体。
我个人比较喜欢这几个字体:
- 思源黑体:现代感强,阅读体验好
- 站酷系列字体:国内设计师常用,中文支持完整
- 阿里普惠体:阿里巴巴推出的免费商用字体
下载字体时要注意文件格式,LVGL官方转换工具支持TTF和WOFF格式。WOFF是网页常用格式,通常比TTF文件小一些。
2.2 选择转换工具
LVGL提供了两种字体转换方式:
在线转换工具(推荐新手使用):
- 访问LVGL官网的Font Converter页面
- 图形化界面,操作简单
- 无需安装任何软件
命令行工具(适合批量处理):
- 基于Node.js的lv_font_conv
- 可以写脚本批量生成不同大小的字库
- 支持更高级的定制选项
对于大多数开发者,我建议先从在线工具开始。等熟悉了整个流程后,再考虑使用命令行工具来提升效率。
3. 使用在线转换工具一步步生成字库
3.1 基本参数设置
打开LVGL官网的在线字体转换工具,你会看到一个简洁的界面。首先设置基本参数:
Font name:给生成的字库起个名字,比如lv_font_my_chinese。这个名字会用在后续的C代码中,建议用英文且具有描述性。
Size:字体大小,单位是像素。这里设置的是字体的高度,比如16表示16像素高的字体。要注意的是,这个大小一旦确定就不能更改,如果需要不同大小就得重新生成。
BPP:每个像素的位数,可选1、2、4、8。数值越大显示效果越平滑,但文件体积也越大。对于中文显示,我建议选择4,能在效果和体积间取得较好平衡。
3.2 上传字体文件
点击"Choose file"按钮上传你下载的字体文件。系统支持TTF和WOFF格式,上传后可以在右侧预览区域看到字体效果。
这里有个实用技巧:如果你不确定某个字体是否适合你的项目,可以先选择少量字符测试生成,看看实际显示效果再决定。
3.3 设置字符范围(最关键的一步)
这是最重要的一步,直接决定了生成字库的大小和实用性。LVGL支持多种字符范围设置方式:
Range方式:通过Unicode范围指定字符
- 基本ASCII字符:
0x20-0x7F - 数字:
0x30-0x39 - 大写字母:
0x41-0x5A - 小写字母:
0x61-0x7A - 常用汉字:
0x4E00-0x9FA5(但这样会包含2万多个汉字,不推荐)
List方式:直接列出需要的字符
- 比如:"你好世界abcdefg12345"
- 适合字符数量不多的情况
文件方式:上传一个文本文件,包含所有需要的字符
我的建议是结合使用Range和List方式。先通过Range包含基本的ASCII字符,再用List添加具体的中文字符。
比如做一个智能家居项目,可以这样设置:
0x20-0x7F,你好世界温度湿度传感器异常警告正常开关灯光窗帘空调
3.4 开始转换与下载
设置好所有参数后,点击"Convert"按钮开始转换。转换时间取决于字符数量,一般需要几十秒到几分钟。
转换完成后,页面会自动下载生成的C文件。文件命名格式是字体名_大小.c,比如my_font_16.c。
4. 高级技巧:优化字库体积与性能
4.1 精准选择字符集
字库体积优化的核心是只包含真正需要的字符。我总结了一个实用方法:
首先分析项目实际用到的所有中文文本,提取出所有不重复的汉字。可以用这个Python脚本快速提取:
import sys
def extract_chars(text_file):
with open(text_file, 'r', encoding='utf-8') as f:
content = f.read()
# 提取所有中文字符
chinese_chars = set()
for char in content:
if '\u4e00' <= char <= '\u9fff':
chinese_chars.add(char)
return ''.join(sorted(chinese_chars))
# 使用示例
chars = extract_chars('project_texts.txt')
print(f"需要的中文字符:{chars}")
print(f"总计{len(chars)}个汉字")
4.2 调整BPP参数的影响
BPP对文件体积的影响很大,这里有个实测数据供参考:
| 字体大小 | BPP=1 | BPP=2 | BPP=4 | BPP=8 |
|---|---|---|---|---|
| 16px 500字 | 56KB | 112KB | 224KB | 448KB |
| 24px 500字 | 126KB | 252KB | 504KB | 1008KB |
对于大多数嵌入式项目,BPP=4是个不错的选择。如果你用的是单色屏或者对体积极其敏感,可以考虑BPP=2甚至BPP=1。
4.3 使用子集化减少体积
对于大型项目,可以考虑使用字体子集化技术。基本原理是:
- 在编译时分析项目用到的所有字符
- 动态生成只包含这些字符的字库
- 将字库编译进固件
虽然设置起来稍微复杂,但可以极大减小体积。我曾经用这种方法将字库从2MB减小到200KB。
5. 集成到LVGL项目实战
5.1 添加字库文件到工程
将生成的C文件复制到你的LVGL项目目录中。通常放在src/fonts/这样的目录里,保持项目结构清晰。
然后在编译配置中添加这个文件。如果你用的是Makefile,添加类似这样的规则:
SRCS += src/fonts/my_font_16.c
5.2 在代码中声明和使用字库
在需要使用自定义字体的C文件中,首先声明字库:
/* 在文件顶部添加 */
LV_FONT_DECLARE(my_font_16);
然后在初始化代码中设置字体:
/* 创建样式并使用自定义字体 */
static lv_style_t style;
lv_style_init(&style);
lv_style_set_text_font(&style, &my_font_16);
/* 应用样式到标签 */
lv_obj_t *label = lv_label_create(lv_scr_act(), NULL);
lv_obj_add_style(label, &style, 0);
lv_label_set_text(label, "你好LVGL");
5.3 多字库混合使用技巧
在实际项目中,我们经常需要同时使用多个字库。比如英文用默认字体,中文用自定义字体。LVGL支持这种混合使用:
/* 创建混合字体 */
static lv_font_t *get_chinese_font(const lv_font_t *font, uint32_t unicode) {
if (unicode >= 0x4E00 && unicode <= 0x9FFF) {
return &my_font_16; // 中文字符使用自定义字体
}
return NULL; // 其他字符使用默认字体
}
/* 设置字体回调 */
lv_style_set_text_font(&style, LV_FONT_DEFAULT);
lv_font_set_apply_cb(get_chinese_font);
这种方法既保持了英文的显示效果,又能够正确显示中文,而且不会显著增加体积。
6. 常见问题与解决方案
6.1 字符显示为方框的问题
这是最常见的问题,通常有几个原因:
字符不在字库中:检查生成的字符范围是否包含了所有需要的字符。可以通过在转换工具中重新确认字符范围来解决。
编码问题:确保你的源代码文件保存为UTF-8编码。大多数现代编辑器都支持,但需要确认一下。
字体设置错误:检查代码中是否正确引用了字库变量名。LVGL的字体引用是区分大小写的。
6.2 内存占用过大的优化
如果发现字库占用内存太大,可以尝试这些优化方法:
精简字符集:重新评估真正需要的字符,移除不必要的字符。
降低BPP:如果显示效果可以接受,尝试使用更低的BPP值。
使用外部存储:对于大型字库,可以考虑存储在外部Flash或SD卡中,运行时动态加载。
6.3 显示效果调整
有时候生成的字体显示效果不理想,可以尝试:
调整抗锯齿参数:在线工具中的BPP参数直接影响抗锯齿效果。
尝试不同字体:有些字体在小尺寸下的显示效果更好。比如等线体、细黑体通常比宋体更适合小屏幕显示。
手动调整字距:高级用户可以使用命令行工具调整字距和行距参数。
7. 实际项目中的应用案例
让我分享一个智能家居控制器的实际案例。这个项目需要显示中文界面,但Flash空间只有2MB,系统本身已经占了1.5MB,留给字库的空间很小。
首先我分析了界面文字,提取出所有用到的汉字,结果发现只有268个不重复的汉字。然后选择了站酷细黑体,设置大小为18px,BPP=4。
转换后的字库文件只有86KB,完全在预算范围内。显示效果也很清晰,客户很满意。
另一个案例是工业仪表盘,需要显示数字和单位符号。我专门生成了一个只包含数字和少量符号的字库,文件只有12KB,但显示效果比通用字体好很多。
这些经验告诉我,定制化字库不仅解决了显示问题,还能优化系统资源使用。
更多推荐


所有评论(0)