轻量级的lvgl的字体转换工具lv_font_conv
继lv_img_conv图片转换工具之后,我做了lvgl另一个常用的轻量级工具——字体转换工具lv_font_conv。仿照先前 lv_img_conv的思路,用C++和FreeType写了一个轻量版的lvgl字体转换工具, 目前也主要是在Linux下命令行的方式使用,因为先前在windows下用的是里飞大佬的 LvglFontTool,因此很多地方都是模仿着写的,不过我也加入了一个新的功能。
项目链接:https://gitee.com/Jumping99/lv_font_conv
工具的制作原理就是通过freetype读取ttf字体文件,然后生成对应文字的字模信息和位图,然后根据需要写入C文件或者bin文件。这个工具还是做的比较久的,主要是花了很多时间搞清楚lvgl对字体的渲染和一些参数的意义,当然少不了的还是找bug修bug了。
工具目前支持1bpp、2bpp、4bpp、8bpp的字体转换,转换的字体主要是从.txt文本文件获取,把需要转换的文字写入到.txt文本文件就可以使用这个工具转换了,当然工具有提供参数可以便捷转换,比如添加ascii字符,添加常用的汉字或者所有的汉字,只需要指定一个参数即可,不需要特地创建txt文件再写入转换。在字体的存储方面也支持内部c数组字体和外部bin文件字体的方式,而且外部字体还分为2个等级,这便是我开头所说的新功能,具体见文件末尾吧。
不过目前有个小bug,转换为1bpp的字体时,有部分字符会错乱,我猜想可能跟lvgl内部对1bpp的处理和绘制有关,由于常用的都是2bpp或者4bpp的抗锯齿字体,因此后续也没有花太多时间去研究了,有兴趣的朋友可以自己尝试查找和修复一下。
先上个效果图:

最后说一下上文所说的外部字体等级, 其实就是当使用外部字体时,c文件保存的字体信息等级,对于level 0的外部字体,c文件除了函数和lvgl的字体变量外,其余均存储到bin文件中;而对于level 1的外部字体,c文件存储了字体的信息,包括每个字模的高度、宽度,以及这个字体所有文字的unicode表,为什么要这样分呢,原因在下面。
根据里飞大佬的LvglFontTool生成的外部字体bin文件, 读一个字体的位图需要进行3次文件IO、一次字体的信息需要进行2次文件IO,而且没有缓存,如果有很多字体需要显示,会对帧率产生比较大的影响。 而我将内部字体和外部字体进行结合,即除了字体位图保存到bin文件外,其余均与内部字体无异,这样不仅只需要在读取字体位图时进行1次文件IO, 而且还具备了缓存的功能,如果当前要显示的字体与上一个字体相同,则可以不需要重新读取字体位图数据。
不过这样做会增加编译后的程序固件大小,每一个文字需要占用14byte的空间保存文字信息,当然如果字体的位图特别大,这点空间也不算什么了。 但如果你设备的flash空间实在吃紧,也可以使用level 0级别,将除了lvgl的字体描述和相关函数保存在C文件,其余均保存在bin文件,这也就是 里飞大佬的LvglFontTool的做法了,能最大限度节省flash空间。当然,如果你的ram够大,将字库直接加载到ram中,读取时采用直接返回首地址+偏移量的方式,是最高效的方法了。
总结来说,如果ram很大足够用,直接将lvgl字体加载到ram中就可以了,最高效;
如果空闲ram不足以加载整个lvgl字体,但flash空间有较大的空闲可以容纳字体的信息却不足以容纳字体的位图,这样可以使用level 1的外部字体,将全部的信息保存在c文件,仅将字体的位图这一最庞大的部分保存到bin文件中,以提升效率;
而level 0适用于flash没有多少空闲空间的设备了,尽可能将字体的信息保存到bin文件中。
工具的具体安装和使用方法可以看上面链接的gitee仓库,里面有详细的介绍。欢迎使用和指出bug。