终极指南:如何用RPFM快速上手《全面战争》游戏模组开发
2026/6/1 20:05:14
该文章目的是为了记录,为上一篇搭建的工程项目中,增加中文字体的支持,使用字库文件。
在嵌入式或图形界面开发中,LVGL(Light and Versatile Graphics Library)因其轻量化和跨平台特性被广泛应用。当项目需要支持多语言(尤其是中文)时,本地字库的加载成为关键需求。本指南详细介绍了如何在LVGL工程中集成和管理本地字库文件(如.ttf或.otf格式),包括配置宏开关、文件系统初始化、字体缓存优化及动态加载的实现方法。
该文章是在上篇文章,工程目录搭建的基础上继续的。
在lvgl_sdk/include/lv_conf.h中需要开启以下宏:
#defineLV_USE_TINY_TTF1#ifLV_USE_TINY_TTF#defineLV_TINY_TTF_FILE_SUPPORT1#defineLV_TINY_TTF_CACHE_GLYPH_CNT128// 字形缓存数量#defineLV_TINY_TTF_CACHE_KERNING_CNT256// 字距缓存数量#endif#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 # 主程序res/res_conf.h- 资源路径配置#ifndefPROJECT_RES_URL#definePROJECT_RES_URL"./res/"// 资源文件路径(相对于可执行文件)#endif#defineFONT_PATHPROJECT_RES_URL"font/"// 字体文件路径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)在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()之前调用在创建 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: 字体大小(像素)add_font()- 注册字体路径voidadd_font(inttype,constchar*font_url);type: 字体类型枚举值font_url: 字体文件路径(如"./res/font/SOURCEHANSANSCN_REGULAR.OTF")get_font()- 获取字体对象lv_font_t*get_font(inttype,uint16_tsize);create_font_obj()创建lv_tiny_ttf_create_file()加载字体文件lv_font_t*指针font_utils.c实现了智能路径解析:
build/host/res/font/(如果从构建目录运行)my_app/res/font/realpath()消除路径中的..和."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会自动处理这个转换。
在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" )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()之前调用如果字体加载失败,检查:
LV_USE_TINY_TTF、LV_TINY_TTF_FILE_SUPPORT、LV_USE_FS_POSIXlv_fs_posix_init()被调用font_utils.c中有详细的调试信息