2. LVGL内置字体详解:内置字体种类、字体大小与风格、内置字体的使用限制

好,咱们进入第二章。上一章我们聊了LVGL字体系统的整体架构,这一章我打算把LVGL内置的那些字体彻底讲透。说白了,内置字体就是你开箱即用、不用额外折腾的那部分字体资源。很多新手上来就急着做自定义字库,结果连内置字体有哪些坑都没摸清楚——嗯,我当年也干过这事儿。

2.1 内置字体有哪些?

LVGL官方维护了一套内置字体,放在 lvgl/src/font/ 目录下。它们都是基于 Montserrat 和 FontAwesome 这两个字体族编译出来的。我个人习惯把它们分成三类:

  • 标准字体:Montserrat 的各种字号和风格变体
  • 图标字体:FontAwesome 的图标集
  • 特殊字体:比如 lv_font_unscii_8 这种像素风字体

具体来说,你可以在代码里直接引用的内置字体有这些:

字体名称 字号(px) 风格 适用场景
lv_font_montserrat_8 8 常规 极小状态栏、角标
lv_font_montserrat_10 10 常规 小尺寸标签、辅助文字
lv_font_montserrat_12 12 常规 列表项、按钮文字
lv_font_montserrat_14 14 常规 正文、对话框内容
lv_font_montserrat_16 16 常规 标题、中等强调文字
lv_font_montserrat_18 18 常规 大标题、弹窗标题
lv_font_montserrat_20 20 常规 主标题、数值显示
lv_font_montserrat_22 22 常规 大号数字、强调信息
lv_font_montserrat_24 24 常规 时钟、大数值
lv_font_montserrat_26 26 常规 超大标题
lv_font_montserrat_28 28 常规 超大数值
lv_font_montserrat_30 30 常规 极限大字号
lv_font_montserrat_32 32 常规 极限大字号
lv_font_montserrat_34 34 常规 极限大字号
lv_font_montserrat_36 36 常规 极限大字号
lv_font_montserrat_40 40 常规 极限大字号
lv_font_montserrat_48 48 常规 极限大字号
lv_font_montserrat_12_16 12 常规+16px行高 固定行高排版
lv_font_montserrat_14_18 14 常规+18px行高 固定行高排版
lv_font_montserrat_16_20 16 常规+20px行高 固定行高排版
lv_font_montserrat_18_22 18 常规+22px行高 固定行高排版
lv_font_montserrat_20_24 20 常规+24px行高 固定行高排版
lv_font_montserrat_22_26 22 常规+26px行高 固定行高排版
lv_font_montserrat_24_28 24 常规+28px行高 固定行高排版
lv_font_montserrat_26_30 26 常规+30px行高 固定行高排版
lv_font_montserrat_28_32 28 常规+32px行高 固定行高排版
lv_font_montserrat_30_34 30 常规+34px行高 固定行高排版
lv_font_montserrat_32_38 32 常规+38px行高 固定行高排版
lv_font_montserrat_40_44 40 常规+44px行高 固定行高排版
lv_font_montserrat_48_52 48 常规+52px行高 固定行高排版
lv_font_unscii_8 8 像素风 复古UI、调试信息
lv_font_unscii_16 16 像素风 复古UI、游戏界面
小提示: 带两个下划线的字体名(如 lv_font_montserrat_12_16),前一个数字是字号,后一个数字是行高。这在做精确排版时特别有用,我经常在表格和列表里用它们。

2.2 字体大小与风格

你可能会问:为什么LVGL要内置这么多字号?直接给一个通用的,然后缩放不行吗?

原因很简单——LVGL的字体是位图字体,不是矢量字体。每个字号都是预先渲染好的像素点阵,不能像TrueType那样随意缩放。所以你需要什么字号,就得用对应的内置字体文件。

关于风格,内置字体目前只提供了常规(Regular)这一种字重。没有Bold、Italic、Light这些变体。我刚开始用的时候也觉得挺受限的,后来想通了:嵌入式设备资源有限,搞那么多字重,Flash先扛不住了。

不过,LVGL提供了一些字体风格修饰标志,你可以通过 lv_style_set_text_font() 配合 LV_FONT_DECLARE 来切换字体。但注意,这只是换字体文件,不是对同一个字体做风格变换。

核心要点: 内置字体只有 Regular 字重。如果你需要 Bold 效果,要么用自定义字库,要么通过 lv_style_set_text_opa() 配合描边模拟——但效果嘛,只能说凑合。

2.3 内置字体的使用限制

这部分我得重点说说。内置字体虽然方便,但坑也不少。我在项目里踩过好几次,今天一并给你讲清楚。

2.3.1 字符集限制

内置字体默认只包含 ASCII 字符(0x20-0x7F),外加一些常用的标点和符号。这意味着:

  • 不支持中文——一个汉字都没有
  • 不支持俄文、阿拉伯文等非拉丁字符
  • 不支持扩展拉丁字符,比如 é、ü、ñ 这些

我曾经在一个面向欧洲市场的项目里,直接用内置字体显示德语界面,结果所有的变音符号都显示成了方框。嗯,那场面挺尴尬的。后来老老实实做了自定义字库。

注意: 如果你在 lv_conf.h 中启用了 LV_FONT_MONTSERRAT_12 之类的宏,它只代表这个字体文件被编译进固件,不代表它包含所有字符。字符范围是固定的,改不了。

2.3.2 内存占用

每个内置字体都是一个完整的位图数组,编译后直接放在Flash里。字号越大,占用的Flash空间就越大。我整理了一下大概的数据:

字体 近似Flash占用 包含字符数
lv_font_montserrat_12 ~1.2 KB 95
lv_font_montserrat_16 ~2.8 KB 95
lv_font_montserrat_24 ~6.5 KB 95
lv_font_montserrat_32 ~12.3 KB 95
lv_font_montserrat_48 ~28.6 KB 95

你想想看,如果每个字体都启用,光内置字体就能吃掉你上百KB的Flash。对于Flash只有512KB甚至256KB的MCU来说,这可不是小数目。

2.3.3 无法自定义字符范围

内置字体的字符表是编译时写死的。你不能说「我只想要数字和冒号,其他不要」。要么全要那95个ASCII字符,要么一个都别用。这在做时钟、计数器这类只需要数字的界面时,其实挺浪费的。

2.3.4 抗锯齿效果固定

内置字体默认开启了 4级抗锯齿(即 LV_FONT_ANTIALIAS 为 4)。这在小屏上看着还行,但在大屏或高PPI屏幕上,边缘会有点糊。而且你没法改成8级或关掉抗锯齿——除非你自己重新编译LVGL源码。

2.4 内置字体知识体系

下面这张图帮你把内置字体的核心脉络理清楚:

LVGL内置字体知识体系 LVGL内置字体知识体系 内置字体 种类 大小与风格 使用限制 标准字体 图标字体 特殊字体 8px ~ 48px 仅Regular字重 位图不可缩放 仅ASCII字符 Flash占用大 字符范围固定 抗锯齿固定4级 总结:内置字体适合快速原型和纯英文界面 中文、多语言、大字号场景需使用自定义字库 LVGL内置字体知识体系 · 第2章

2.5 什么时候该用内置字体?

根据我自己的项目经验,给你几个判断标准:

  • 原型验证阶段:用内置字体快速搭界面,确认布局和交互逻辑
  • 纯英文/数字界面:比如仪表盘、计数器、状态指示器
  • Flash资源极度紧张:内置字体比自定义字库小得多
  • 不需要特殊排版:比如不需要竖排、不需要混合字体
我的建议: 如果你的产品最终要显示中文、俄文、阿拉伯文,或者需要特殊字重(Bold/Italic),或者字号不在内置列表里——别犹豫,直接上自定义字库。内置字体只适合做「能用就行」的场景。