开发必备 | LuatOS百变应用,LVGL字体篇来了!!!

打盹儿的消防车 合宙Luat 今天

图片

之前展示过STM32移植LuatOS基于Win32的LuatOS仿真器,其中也演示了LuatOS在Win32上运行LVGL的效果,无须硬件即可轻松调试:

合宙Luat
LuatOS百变应用—LVGL效果演示@合宙Luat

在实际开发应用中字体的使用也必不可少,今天特别带来LuatOS应用的LVGL字体篇:

LVGL字体支持很全,支持UTF-8编码的Unicode字符,分内部字体和外部字体,字体制作工具也很多:LVGL官方的字体制作工具、第三方的LvglFontTool和MCU_Font等。

本文将介绍LVGL内外部字体的制作方法及所用工具,方便大家对其有整体了解。点击文末【阅读原文】链接,可获取相关源码。





1


LVGL内部字体简介




LVGL的内部字体分为 LVGL自带字体和自己制作的自定义内部字体。

1.1 LVGL自带字体

LVGL内部已支持多种字体大小,同时支持多国语言:希伯来语、阿拉伯语、波斯语字母及其所有形式,并且支持中文。不过中文的支持是使用1000多个最常见的部首组成的,实际测试会发现很多汉字都没有。

常用字体通过LV_FONT_… 定义在lv_conf.h 中启用即可。

▼上下滚动,查看全部▼

/* Montserrat fonts with bpp = 4

* https://fonts.google.com/specimen/Montserrat  */

#define LV_FONT_MONTSERRAT_8     0

#define LV_FONT_MONTSERRAT_10    0

#define LV_FONT_MONTSERRAT_12    0

#define LV_FONT_MONTSERRAT_14    1

#define LV_FONT_MONTSERRAT_16    0

#define LV_FONT_MONTSERRAT_18    0

#define LV_FONT_MONTSERRAT_20    0

#define LV_FONT_MONTSERRAT_22    0

#define LV_FONT_MONTSERRAT_24    0

#define LV_FONT_MONTSERRAT_26    0

#define LV_FONT_MONTSERRAT_28    0

#define LV_FONT_MONTSERRAT_30    0

#define LV_FONT_MONTSERRAT_32    0

#define LV_FONT_MONTSERRAT_34    0

#define LV_FONT_MONTSERRAT_36    0

#define LV_FONT_MONTSERRAT_38    0

#define LV_FONT_MONTSERRAT_40    0

#define LV_FONT_MONTSERRAT_42    0

#define LV_FONT_MONTSERRAT_44    0

#define LV_FONT_MONTSERRAT_46    0

#define LV_FONT_MONTSERRAT_48    0
/* Demonstrate special features */

#define LV_FONT_MONTSERRAT_12_SUBPX      0

#define LV_FONT_MONTSERRAT_28_COMPRESSED 0  /*bpp = 3*/

#define LV_FONT_DEJAVU_16_PERSIAN_HEBREW 0 
 
/*Hebrew, Arabic, PErisan letters and all their forms*/

#define LV_FONT_SIMSUN_16_CJK            0
 /*1000 most common CJK radicals*/
/*Pixel perfect monospace font * http://pelulamu.net/unscii/ */

* http://pelulamu.net/unscii/ */

#define LV_FONT_UNSCII_8     0

#define LV_FONT_UNSCII_16     0



当你要使用一些好看的字体,或者中文等LVGL没有集成的字体怎么办呢?当然可以自己制作字库。

1.2 LVGL内部自定义字体

首先介绍使用LvglFontTool制作内部字体,打开LvglFontTool:

抗锯齿选择默认,我们的lvgl是7.11版本,所以此处版本选择6.0版本以上,英文和数字根据自己需要勾选,类型选择内部字体,剩下都勾选上即可,字体名自己设置,包含里加上lvgl.h头文件。

图片



之后点击选择字体:字体我们选择我们的ttf字体,选择字体大小,点击确定。写入需要的汉字或者根据自己需要点击加入常用汉字、全部汉字、图标。

图片

图片


之后点击保存,开始转换,稍作等待:

图片

图片



之后将生成的.c文件放在LuatOS\components\lvgl\font目录下,在luat_lvgl_fonts.h中声明你的字库:

▼上下滚动,查看全部▼

#ifndef LUAT_LIB_FONTS_H

#define LUAT_LIB_FONTS_H


#include "luat_base.h"


#ifdef __cplusplus

extern "C" {

#endif#include "../src/lv_font/lv_font.h"

LV_FONT_DECLARE(lv_font_opposans_m_8)

LV_FONT_DECLARE(lv_font_opposans_m_10)
LV_FONT_DECLARE(lv_font_opposans_m_12)
LV_FONT_DECLARE(lv_font_opposans_m_14)
LV_FONT_DECLARE(lv_font_opposans_m_16)
LV_FONT_DECLARE(lv_font_opposans_m_18)
LV_FONT_DECLARE(lv_font_opposans_m_20)
LV_FONT_DECLARE(lv_font_opposans_m_22)

LV_FONT_DECLARE(lv_font_simsun_48)


#ifdef __cplusplus

}

#endif

#endif


然后在luat_lib_lvgl_font.c中对lua暴露你的字库就可以了:

▼上下滚动,查看全部▼

/*
获取内置字体
@api lvgl.font_get(name)
@string 字体名称+字号, 例如 opposans_m_10 simsun_48
@return userdata 字体指针
@usage

local font = lvgl.font_get("simsun_48")

*/

int luat_lv_font_get(lua_State *L) {  

  lv_font_t* font = NULL;  

  const char* fontname = luaL_checkstring(L, 1);   

  if (!strcmp("", fontname)) {

   }#

ifdef LV_FONT_MONTSERRAT_14

   else if (!strcmp("montserrat_14", fontname)) { font = &lv_font_montserrat_14;}

#endif

#ifdef LV_FONT_OPPOSANS_M_8

   else if (!strcmp("opposans_m_8", fontname)) { font = &lv_font_opposans_m_8;}

#endif

#ifdef LV_FONT_OPPOSANS_M_10

   else if (!strcmp("opposans_m_10", fontname)) { font = &lv_font_opposans_m_10;}

#endif

#ifdef LV_FONT_OPPOSANS_M_12

   else if (!strcmp("opposans_m_12", fontname)) { font = &lv_font_opposans_m_12;}

#endif#ifdef LV_FONT_OPPOSANS_M_14

   else if (!strcmp("opposans_m_14", fontname)) { font = &lv_font_opposans_m_14;}

#endif

#ifdef LV_FONT_OPPOSANS_M_16

   else if (!strcmp("opposans_m_16", fontname)) { font = &lv_font_opposans_m_16;}

#endif

#ifdef LV_FONT_OPPOSANS_M_18

   else if (!strcmp("opposans_m_18", fontname)) { font = &lv_font_opposans_m_18;}

#endif

#ifdef LV_FONT_OPPOSANS_M_20

   else if (!strcmp("opposans_m_20", fontname)) { font = &lv_font_opposans_m_20;}

#endif

#ifdef LV_FONT_OPPOSANS_M_22

   else if (!strcmp("opposans_m_22", fontname)) { font = &lv_font_opposans_m_22;}

#endif

#ifdef USE_LVGL_SIMSUN_48

   else if (!strcmp("simsun_48", fontname)) { font = &lv_font_simsun_48;}

#endif


   if (font) {

       lua_pushlightuserdata(L, font);        

       return 1;

   }    

       return 0;

}



注意:

编译时别忘了在luat_conf_bsp.h中启用lvgl和字库呦~






2


外部字体简介




LVGL同时支持外部字体,你可以将.bin格式字体放在flash中或sd中,在程序运行中加载字体,这种方式无需修改固件。

这里我们用离线版LVGL官方工具生成外部字体:

https://github.com/lvgl/lv_font_conv

首先安装nodejs这里不做介绍,下载安装即可:

https://nodejs.org/en/download/


打开cmd运行npm i lv_font_conv -g,即可安装好lv_font_conv:

图片

图片图片

下面我们了解一下lv_font_conv命令:


▼上下滚动,查看全部▼

常用命令:

  • --bpp - 每像素位数(抗锯齿)

  • --size - 输出字体大小(像素)

  • -o--output- 输出路径(文件或目录,取决于格式)

  • --format - 输出格式

    • --format dump - 转储字形图像和字体信息,用于调试

    • --format bin- 以二进制形式转储字体

      规范中所述参见:

      https://github.com/lvgl/lv_font_conv/blob/master/doc/font_spec.md

    • --format lvgl- 以LittlevGL格式转储字体

      参见:
      https://github.com/lvgl/lvgl

  • --force-fast-kern-format- 始终使用更快速的 kering 存储格式,但要付出一定的代价。如果出现尺寸差异,则会显示出来

  • --lcd - 生成具有 3 倍水平分辨率的位图,用于子像素平滑

  • --lcd-v - 生成具有 3 倍垂直分辨率的位图,用于子像素平滑

  • --use-color-info- 尝试使用字体中的字形颜色信息来创建灰度图标。由于灰色色调是通过透明度模拟的,因此仅在对比背景上效果会很好

  • --lv-include- 仅与--format lvgl,为 设置备用路径lvgl.h


字体命令:

  • --font- 字体文件的路径(ttf/woff/woff2/otf)。可多次用于合并

  • -r--range- 单个字形或范围 + 可选映射,属于先前声明的--font. 可以多次使用。例子:

    • -r 0x1F450 - 单值、十进制或十六进制格式

    • -r 0x1F450-0x1F470 - 范围

    • -r '0x1F450=>0xF005' - 带有映射的单个字形

    • -r '0x1F450-0x1F470=>0xF005' - 带映射的范围

    • -r 0x1F450 -r 0x1F451-0x1F470 - 2个范围

    • -r 0x1F450,0x1F451-0x1F470- 同上,但定义为 single -r

  • --symbols- 要复制的字符列表(而不是 中的数字格式-r

    • --symbols 0123456789., - 提取字符以显示数字

  • --autohint-off - 不要强制自动提示(默认情况下“灯”是打开的)

  • --autohint-strong - 使用更强大的自动提示(会破坏字距调整)


其他调试选项:

  • --no-compress - 禁用内置 RLE 压缩

  • --no-prefilter - 禁用位图线过滤器(XOR),用于提高压缩率

  • --no-kerning - 删除字距调整信息以减小大小(不推荐)

  • --full-info - 不要缩短“font_info.json”(包括像素数据)



我们输入以下命令,即可生成我们想要的.bin外部字库了:

lv_font_conv--no-compress --format bin --font H:\OPPOSans-M.ttf -o H:\myfontd\opposans_m_8.bin --bpp 4 --size 8 -r 0x30-0x39 -r 0x41-0x5A -r 0x61-0x7A -r 0x4E00-0x9FFF


不想自己做?
好的,我已经做好一些放在以下目录了呦~

LuatOS\docs\markdown\exts\lvgl\fonts

图片图片






3


字体使用示例




LVGL字体使用非常简单,内部字体使用以下指令设置字体即可:
lvgl.obj_set_style_local_text_font

外部字体文件需要使用lvgl.font_load函数加载。

注意:使用后记得释放字体。

接下来,我们看一下内部/外部字体的使用示例:

内部字体使用示例





- 示例源码 -

local screen_label = lvgl.label_create(nilnil) lvgl.label_set_text(screen_label, "中文测试abcdABCD1234")
local style_screen_label_main = lvgl.style_create() lvgl.style_set_text_font(style_screen_label_main, lvgl.STATE_DEFAULT, lvgl.font_get("opposans_m_12")) lvgl.obj_add_style(screen_label, lvgl.LABEL_PART_MAIN, style_screen_label4_main)    lvgl.scr_load(screen_label)


- 示例效果 -

图片图片



外部字体使用示例





- 示例源码 -

local screen_label = lvgl.label_create(nil, nil)

lvgl.label_set_text(screen_label, "这是一个中文字体测试程序abcdABCD1234")  
local font = lvgl.font_load("/OPPOSans.bin")

lvgl.obj_set_style_local_text_font(screen_label, lvgl.LABEL_PART_MAIN, lvgl.STATE_DEFAULT, font)
lvgl.scr_load(screen_label)


- 示例效果 -

图片图片




今天的内容就分享到这里了,LVGL字体使用你了解了吗?如果需要同时使用几种字体,也按照本文所说方法操作即可,只要内存够,多少都行。更多开发相关问题,欢迎加入技术群交流沟通~

- 相关开发资料链接 -

LuatOS-SoC仓库

https://gitee.com/openLuat/LuatOS

LVGL官方仓库

https://github.com/lvgl/lvgl

LuatOS BSP-Win32

https://gitee.com/openLuat/LuatOS/tree/master/bsp/win32



图片

- 合宙技术交流微信群 -

图片

即刻微信/企业微信扫码加入

每个建议都值得关注

每个技能都值得分享


图片

- 更多精彩等你参与 -

敬请关注公众号及社群更多互动活动

图片



收录于话题
11
下一篇 征名活动 | "以我之姓,冠你之名",LuatOS需要一个中文名字