自定义U8G2 中文字体
BDF 和TTF
首先明确,所谓的BDF 字体就是一种通用的点阵字体格式,而常见的TTF 字体是矢量字体。两者区别类似像素图和矢量图,矢量字体可以随便放大字号,而点阵字体的字号是固定的。一份BDF 字体文件只能对应一个字体大小,想换个字号只能选择另一个BDF 文件。U8G2 支持的就是这个BDF 字体,而生成自定义字体,基本就是指”裁剪“,从文泉驿之类的通用字体里挑一部分字出来再弄个BDF。
如果要从TTF 字体生成自定义字体,就得先按照需要的字号从TTF 生成一个BDF,再从这个BDF 里裁剪出所需的部分。不过,直接从矢量字体生成点阵字体很可能效果不佳,比如有很明显的毛边,所以我是基于文泉驿9pt 生成,它是BDF 字体。
工具
找到个别人三年前写好的生成工具,不需要自己单独整什么map 文件,可以直接生成C 代码:https://gitee.com/createskyblue/Easy-u8g2-font-generate-tools。工具本身是个Python 脚本,需要本地装好Python 环境。
试用了一下感觉不太顺我的手,于是fork 了一份,修改了交互方式和一些功能:https://gitee.com/etberzin/Easy-u8g2-font-generate-tools。主要修改的部分:
- 原工具只能手动输入要包含的字,或者复制粘贴,我添加了从文本文件读取的功能;
- 原工具必须手动输入源字体文件的路径,现在可以从指定文件夹下选择一个;
- 原工具要固定从TTF 生成BDF,再裁剪,现在可以选择已有的BDF 源字体文件;
- 去掉了输出到命令行的文本颜色,因为在我这里显示效果很差;
使用方法
clone 或者下载工具repo,运行main.py
。
1、输入要生成的字体中包含的字
选择0
表示要手动输入。推荐将要生成的字写进一个txt 文件,然后放进text
文件夹下,这里就会列出可选的txt 文件。
2、输入自定义字体的名称
字体名称固定添加u8g2_font_
前缀。如果是从txt 文件输入,则默认的字体名称就是txt 文件名。输入的字体名称不能包含文件名中禁止出现的符号,比如冒号、斜杠之类的。
3. 选择源字体
选择要从BDF 还是TTF 源字体生成自定义字体。如果选了BDF,接下来就会列出bdf
文件夹下的BDF 字体文件供选择,所以需要事先把需要的源字体放进去。如果选TTF,就列出font
文件夹下的TTF 文件。
选择了BDF 文件后,生成的字体的像素尺寸也就固定了,不能另外设置。9pt 字体生成12x12 像素的字,
- 9pt = 12x12px
- 10pt = 13x13px
- 11pt = 15x15px
- 12pt = 16x16px
大概是这样的关系。
4、字体间距
我不确定这个参数是什么意思,可以直接按回车忽略。
5、ASCII 符号选项
这两项都可以回车按默认设置。默认过滤输入的文本中的ASCII 符号,比如回车之类的;生成的字体中也不包含ASCII 部分的字,比如数字、字母、标点符号之类的,用U8G2 内置的英文字体就行了。
6、生成结果
完成以后会自动创建一张图片:bdf.tga
,可以用HoneyView 打开。
生成的代码文件在code
文件夹下,文件名就是之前输入的字体名称。
c
文件是直接生成的,cpp
里是我在c
文件的基础上加了点东西。然后复制粘贴到项目里,可以弄个头文件,也可以不弄;代码文件必须用UTF-8 编码。和U8G2 内置字体一样,调用setFont
使用。
另外
要显示汉字,除了U8G2 库,常用的办法还有:
- 外挂个字库芯片;
- 外挂个Flash 芯片,里面放字库;
- 自己拿取模软件生成字库;
外挂芯片的方法速度慢,需要实时从字库芯片里读出来字体再显示。当然也可以把之前读过的字体缓存到RAM 里,之后再用就不需要读取,但是太费RAM。不过要是想做个电子书阅读器之类的东西,需要支持大部分常用汉字,那可能就不得不考虑外挂芯片了。
自己取模属于是传统手艺,生成几十个汉字的字库很容易,但要使用这种字库就比较麻烦了,需要自己想办法从字库数组里找到所需的汉字字体对应的位置。要么代码里把要显示的中文字符都提前转换成数组下标,比如要显示“你好"
,代码里实际得写成{0x1288, 0x4400}
,这太恶心了;要么就自己实现个映射机制,比如用utf-16 编码字符串,要显示u"你好"
,先根据这两个字的UTF-16 编码去查映射表,再用查到的值作为数组下标,去数组里取字体数据。这样就相当于自己造轮子,重新发明了BDF 格式,为了方便使用,大概还得整个工具来自动生成映射表,或者叫作map 文件……何必呢,绕一圈不如回来用U8G2 现成的成熟实现。