LVGL 本地字库添加和加载操作指南
前言
该文章目的是为了记录,为上一篇搭建的工程项目中,增加中文字体的支持,使用字库文件。
在嵌入式或图形界面开发中,LVGL(Light and Versatile Graphics Library)因其轻量化和跨平台特性被广泛应用。当项目需要支持多语言(尤其是中文)时,本地字库的加载成为关键需求。本指南详细介绍了如何在LVGL工程中集成和管理本地字库文件(如.ttf或.otf格式),包括配置宏开关、文件系统初始化、字体缓存优化及动态加载的实现方法。
该文章是在上篇文章,工程目录搭建的基础上继续的。
一、LVGL SDK 需要开启的宏开关
在lvgl_sdk/include/lv_conf.h中需要开启以下宏:
1. 启用 Tiny_TTF 支持
#defineLV_USE_TINY_TTF12. 启用 Tiny_TTF 文件支持(从文件加载字体)
#ifLV_USE_TINY_TTF#defineLV_TINY_TTF_FILE_SUPPORT1#defineLV_TINY_TTF_CACHE_GLYPH_CNT128// 字形缓存数量#defineLV_TINY_TTF_CACHE_KERNING_CNT256// 字距缓存数量#endif3. 启用 POSIX 文件系统驱动(Tiny_TTF 需要文件系统支持)
#defineLV_USE_FS_POSIX1#ifLV_USE_FS_POSIX#defineLV_FS_POSIX_LETTER'A'// 驱动字母标识符#defineLV_FS_POSIX_PATH""// 工作目录(空表示使用绝对路径)#defineLV_FS_POSIX_CACHE_SIZE0// 缓存大小#endif总结:需要开启LV_USE_TINY_TTF、LV_TINY_TTF_FILE_SUPPORT和LV_USE_FS_POSIX三个宏。
二、文件结构
my_app/ ├── res/ │ ├── res_conf.h # 资源路径配置 │ └── font/ │ ├── font_conf.h # 字体配置文件 │ ├── font_utils.h # 字体工具函数头文件 │ ├── font_utils.c # 字体工具函数实现 │ └── *.otf / *.OTF # 字体文件(如 SOURCEHANSANSCN_REGULAR.OTF) └── main.c # 主程序三、配置文件说明
1.res/res_conf.h- 资源路径配置
#ifndefPROJECT_RES_URL#definePROJECT_RES_URL"./res/"// 资源文件路径(相对于可执行文件)#endif#defineFONT_PATHPROJECT_RES_URL"font/"// 字体文件路径2.res/font/font_conf.h- 字体配置
// 定义字体类型枚举typedefenum{FONT_TYPE_CN=0,// 中文字体FONT_TYPE_CN_LIGHT,// 细体中文字体FONT_TYPE_LETTER,// 字母字体FONT_TYPE_LETTER_LIGHT,// 细体字母字体FONT_TYPE_NUMBER,// 数字字体}FONT_TYPE;// 定义各类型字体的文件路径#defineFONT_TYPE_CN_PATHFONT_PATH"SOURCEHANSANSCN_REGULAR.OTF"#defineFONT_TYPE_CN_LIGHT_PATHFONT_PATH"SOURCEHANSANSCN_LIGHT.OTF"// ... 其他字体路径// 字体初始化宏#defineFONT_INIT()\do{\add_font(FONT_TYPE_CN,FONT_TYPE_CN_PATH);\add_font(FONT_TYPE_CN_LIGHT,FONT_TYPE_CN_LIGHT_PATH);\// ... 添加其他字体}while(0)四、使用流程
步骤 1:初始化 LVGL 和文件系统
在main.c的初始化函数中:
voidapp_init(void){lv_init();// 初始化 LVGL#ifLV_USE_FS_POSIXlv_fs_posix_init();// 初始化 POSIX 文件系统驱动(重要!)#endifFONT_INIT();// 初始化字体(注册字体路径)lv_port_disp_init();lv_port_indev_init();}关键点:
lv_fs_posix_init()必须在FONT_INIT()之前调用- 这是 Tiny_TTF 能够读取字体文件的前提
步骤 2:使用字体
在创建 UI 元素时:
voidlv_example_hello_world(void){// 创建标签lv_obj_t*label=lv_label_create(lv_scr_act());lv_obj_align(label,LV_ALIGN_CENTER,0,0);// 获取字体(类型、大小)lv_font_t*font=get_font(FONT_TYPE_CN,20);// 获取中文字体,大小20// 设置字体if(font!=NULL){lv_obj_set_style_text_font(label,font,0);}// 设置文本(支持中文)lv_label_set_text(label,"你好,世界!Hello, World!");}API 说明:
get_font(type, size): 获取指定类型和大小的字体type: 字体类型(FONT_TYPE_CN等)size: 字体大小(像素)
五、实现原理
1.add_font()- 注册字体路径
voidadd_font(inttype,constchar*font_url);- 功能:将字体类型和文件路径注册到字体类型列表
- 参数:
type: 字体类型枚举值font_url: 字体文件路径(如"./res/font/SOURCEHANSANSCN_REGULAR.OTF")
2.get_font()- 获取字体对象
lv_font_t*get_font(inttype,uint16_tsize);- 功能:根据类型和大小获取字体对象(如果不存在则创建)
- 实现流程:
- 检查字体对象缓存中是否已存在
- 如果不存在,调用
create_font_obj()创建 - 使用
lv_tiny_ttf_create_file()加载字体文件 - 返回
lv_font_t*指针
3. 路径解析机制
font_utils.c实现了智能路径解析:
- 优先查找构建目录:
build/host/res/font/(如果从构建目录运行) - 备选查找源码目录:
my_app/res/font/ - 路径规范化:使用
realpath()消除路径中的..和. - LVGL 文件系统格式:转换为
"A:绝对路径"格式(A:是 POSIX 驱动标识符)
六、字体文件路径格式
由于使用了 LVGL 文件系统抽象层,路径需要特殊格式:
普通路径:/home/user/app/res/font/font.otf
LVGL 路径:A:/home/user/app/res/font/font.otf
其中A:是在lv_conf.h中定义的LV_FS_POSIX_LETTER(这里是 ‘A’)。
font_utils.c会自动处理这个转换。
七、CMake 配置
在CMakeLists.txt中需要:
- 复制字体文件到构建目录:
# 复制字体文件到 build/host/res/font/ file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/res/font) file(COPY ${CMAKE_SOURCE_DIR}/res/font/ DESTINATION ${CMAKE_BINARY_DIR}/res/font/ FILES_MATCHING PATTERN "*.otf" PATTERN "*.OTF" PATTERN "*.ttf" PATTERN "*.TTF" )- 链接数学库(Tiny_TTF 需要):
target_link_libraries(${PROJECT_NAME} PRIVATE m)八、完整示例
// main.cintmain(void){// 1. 初始化 LVGLlv_init();// 2. 初始化文件系统驱动(必须!)#ifLV_USE_FS_POSIXlv_fs_posix_init();#endif// 3. 初始化字体(注册字体路径)FONT_INIT();// 4. 初始化显示和输入设备lv_port_disp_init();lv_port_indev_init();// 5. 创建 UI(使用字体)lv_obj_t*label=lv_label_create(lv_scr_act());lv_font_t*font=get_font(FONT_TYPE_CN,20);if(font!=NULL){lv_obj_set_style_text_font(label,font,0);}lv_label_set_text(label,"你好,世界!");// 6. 主循环while(1){lv_timer_handler();usleep(5000);}return0;}九、注意事项
- 文件系统驱动必须先初始化:
lv_fs_posix_init()必须在FONT_INIT()之前调用 - 字体文件路径:确保字体文件在运行时能够访问(建议使用 CMake 复制到构建目录)
- 字体格式:支持 TTF 和 OTF 格式
- 内存管理:字体对象会被缓存,相同类型和大小的字体只会加载一次
- 字体大小:可以在运行时指定任意大小(Tiny_TTF 支持动态缩放)
十、调试技巧
如果字体加载失败,检查:
- 宏是否开启:
LV_USE_TINY_TTF、LV_TINY_TTF_FILE_SUPPORT、LV_USE_FS_POSIX - 文件系统是否初始化:确认
lv_fs_posix_init()被调用 - 字体文件是否存在:检查路径是否正确,文件是否存在
- 查看日志输出:
font_utils.c中有详细的调试信息