自定义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。主要修改的部分:

  1. 原工具只能手动输入要包含的字,或者复制粘贴,我添加了从文本文件读取的功能;
  2. 原工具必须手动输入源字体文件的路径,现在可以从指定文件夹下选择一个;
  3. 原工具要固定从TTF 生成BDF,再裁剪,现在可以选择已有的BDF 源字体文件;
  4. 去掉了输出到命令行的文本颜色,因为在我这里显示效果很差;

使用方法

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 库,常用的办法还有:

  1. 外挂个字库芯片;
  2. 外挂个Flash 芯片,里面放字库;
  3. 自己拿取模软件生成字库;

外挂芯片的方法速度慢,需要实时从字库芯片里读出来字体再显示。当然也可以把之前读过的字体缓存到RAM 里,之后再用就不需要读取,但是太费RAM。不过要是想做个电子书阅读器之类的东西,需要支持大部分常用汉字,那可能就不得不考虑外挂芯片了。

自己取模属于是传统手艺,生成几十个汉字的字库很容易,但要使用这种字库就比较麻烦了,需要自己想办法从字库数组里找到所需的汉字字体对应的位置。要么代码里把要显示的中文字符都提前转换成数组下标,比如要显示"你好",代码里实际得写成{0x1288, 0x4400},这太恶心了;要么就自己实现个映射机制,比如用utf-16 编码字符串,要显示u"你好",先根据这两个字的UTF-16 编码去查映射表,再用查到的值作为数组下标,去数组里取字体数据。这样就相当于自己造轮子,重新发明了BDF 格式,为了方便使用,大概还得整个工具来自动生成映射表,或者叫作map 文件......何必呢,绕一圈不如回来用U8G2 现成的成熟实现。

相关推荐
GiraKoo9 分钟前
【GiraKoo】C++11的新特性
c++·后端
不午睡的探索者12 分钟前
告别性能瓶颈!Python 量化工程师,进击 C++ 高性能量化交易的“必修课”!
c++·github
OpenC++13 分钟前
【C++】观察者模式
c++·观察者模式·设计模式
老歌老听老掉牙22 分钟前
粒子群优化算法实现与多维函数优化应用
c++·pso·粒子群算法
myloveasuka1 小时前
信号操作集函数
linux·运维·服务器·c语言·c++·vscode
山野万里__1 小时前
C++与Java内存共享技术:跨平台与跨语言实现指南
android·java·c++·笔记
Mr_Xuhhh2 小时前
网络基础(1)
c语言·开发语言·网络·c++·qt·算法
几个几个n2 小时前
STM32-第二节-GPIO输入(按键,传感器)
单片机·嵌入式硬件
醇醛酸醚酮酯2 小时前
std::promise和std::future的使用示例——单线程多链接、多线程单链接
网络·c++·算法
背影疾风3 小时前
C++之路:类基础、构造析构、拷贝构造函数
linux·开发语言·c++