Adafruit GFX Library字体规范
陈拓 2021/06/29-2021/06/30
1. 概述
- 什么是Adafruit GFX Library
看看Adafruit官方网站的介绍。
https://learn.adafruit.com/adafruit-gfx-graphics-library/overview
Arduino的Adafruit_GFX库为我们所有的LCD和OLED显示器(Adafruit的网站上有卖各种显示器)提供了通用语法和一组图形函数。这使得Arduino sketches (Arduino的内置例程称为sketches)可以很容易地在不同类型的显示器之间进行调整,任何新的功能、性能改进和错误修复都能很容易的呈现在所有显示器上。
- Adafruit GFX库
Adafruit GFX Library在GitHub上开源:
https://github.com/adafruit/Adafruit-GFX-Library
这是用于我们所有显示器的核心图形库,它提供了一组通用的图形原语(点、线、圆等)。对于每个显示设备,它需要与特定于硬件的库配对(以处理较低级别的功能)。
Adafruit投入时间和资源提供此开源代码,请通过购买Adafruit的产品来支持Adafruit和开源硬件!
2. Adafruit GFX Library工具
有一些工具可以和Adafruit GFX Library一起使用。
- Image2Code
Image2Code是一个小的Java GUI实用程序,用于将BMP图像文件转换为字节数组,可以用作Adafruit GFX库中的位图。
https://github.com/ehubin/Adafruit-GFX-Library/tree/master/Img2Code
- drawXBitmap函数
您可以使用GIMP照片编辑器保存一个.xbm文件,并使用文件中保存的数组通过drawXBitmap函数绘制位图。
开源代码:
https://github.com/adafruit/Adafruit-GFX-Library/pull/31
- 字体
Fonts文件夹包含用于最近(1.1及更高版本)Adafruit_GFX的位图字体。
- fontconvert
fontconvert文件夹包含一个命令行工具,用于将TTF字体转换为Adafruit_GFX格式。
- GFX字体定制工具
一个为Adafruit GFX库定制像素字体的小工具
https://tchapi.github.io/Adafruit-GFX-Font-Customiser/
开源代码:
https://github.com/tchapi/Adafruit-GFX-Font-Customiser
3. Adafruit GFX字体格式
Adafruit GFX字体有很多优点,节省空间,可变宽度的字体,有容易使用的字体转换和生成工具。但是Adafruit GFX字体格式的定义比较复杂,下面我们详细讲述Adafruit GFX字体的格式规范。我们以Adafruit-GFX-Library中的字体为例。
3.1 Adafruit-GFX-Library中字体
我们在这里主要关心的是Adafruit GFX字体。
在Adafruit-GFX-Library中打开Fonts文件夹:
https://github.com/adafruit/Adafruit-GFX-Library
https://github.com/adafruit/Adafruit-GFX-Library/tree/master/Fonts
目前共有52种字体。下面我们看字体文件的构成。
3.2 字体文件的构成
打开一个字体文件,例如FreeMono18pt7b.h。
一个字体文件从ASCII码0x20 ' '开始到0x7E '~'结束,共95个字符。
字体文件由3部分组成:
3.2.1 位图数据Bitmaps
首先是位图定义字节数组:
先看看下一小节的内容,结合glyph信息就可以知道字节数组怎样使用。
例如,字符0x22 '"'的宽是11,高是10,字节长度为25-11=14。我们从11开始取14个字节:
0xF1, 0xFE, 0x3F, 0xC7, 0xF8, 0xFF, 0x1E, 0xC3, 0x98, 0x33, 0x06, 0x60, 0xCC, 0x18
将这14个字节展开成二进制,用.代表0,用X代表1,宽度为11,逐行排列如下:
高度正好是10,这就是双引号"的字模。最后多出1个bit就不用了。
我们看到字模并不完美,这是因为Adafruit GFX字体是从TTF字体转换过来的,TTF是矢量字体,转换成点阵字体的过程中会有误差。如果你要求很高,可以自己修改。
3.2.2 字形Glyphs
接下来是一个glyph信息数组:
类型GFXglyph是结构体,定义如下:
typedef struct {
uint16_t bitmapOffset; /// Pointer into GFXfont->bitmap
uint8_t width; /// Bitmap dimensions in pixels
uint8_t height; /// Bitmap dimensions in pixels
uint8_t xAdvance; /// Distance to advance cursor (x axis)
int8_t xOffset; /// X dist from cursor pos to UL corner
int8_t yOffset; /// Y dist from cursor pos to UL corner
} GFXglyph;
- 位图数组的索引
GFXglyph的第一项是位图索引bitmapOffset。
我们从第一个字符索引开始看。
字符' '空格没有数据,所以第二个字符'!'的索引仍然为0。
第三个字符'"'的索引为11,说明第二个字符的字节长度为11。
第四个字符'#'的索引为25,说明第三个字符的字节长度为25-11=14
依此类推。
- 字形的宽度和高度
GFXglyph第二和第三项是字形的宽度width和高度height。
例如:第四个字符0x23 '#'的宽度为14,高度为24。
- 显示优化
GFXglyph第四项xAdvance用来优化显示效果。
例如第四个字符0x23 '#'的宽度为14,xAdvance为21。21-14=7
这样在显示的时候在字符的左边多出三个像素右边多出4个像,这样的空白便于阅读。
如有需要,这个值可以自己调整。
- 字符的位置
GFXglyph的最后两个值xOffset和yOffset是像素便宜,用于定位字符。
通常显示器的坐标原点在左上角,如图左边的A。与之不同的是Adafruit GFX字体的原点坐标在左下角,如图右边的A。
所以如下图所示,xOffset和yOffset都会出现负值。
xOffset和yOffset是从光标位置到glyph位图左上角的像素偏移,在GFX坐标空间中,Y轴的原点在基线(Baseline)上,向上偏移是负值。xOffset的值多数情况下为正值,有时出现负值也是正常的。
如有需要,这两个值可以自己调整。
举前面的例子来说,字符双引号'"'的GFXglyph是{11, 11, 10, 21, 5, -20},其中宽是11,高是10,xOffset是5,yOffset是-20。我们用红色的.代表偏移,绘制出来是这样的:
xAdvance是21,21-11=10,左右各空5个像素,用绿色的.表示:
这是字符在显示器上的X方向占有26个像素,在Y方向占有20个像素,参考其他字符的高度最高有29,可以考虑将行高设置为30像素,这样我们在字符的上下分别再加5行像素,用蓝色的.表示:
这样就比较完美了。
关于行高在下一小节中有说明。
3.3.2 GFXfont
GFXfont是结构体,定义如下:
typedef struct {
uint8_t *bitmap; /// Glyph bitmaps, concatenated
GFXglyph *glyph; /// Glyph array
uint8_t first; /// ASCII extents (first char)
uint8_t last; /// ASCII extents (last char)
uint8_t yAdvance; /// Newline distance (y axis)
} GFXfont;
GFXfont是字体定义的最后一部分,是将所有内容连接在一起的结构。它包括指向位图数组的指针、指向glyph数据的指针和一些其他值。我们看看这三个其他值。
在我们的例子中,这三个值列为“0x20,0x7E,35”。0x20是第一个字符的ASCII码值,0x7E是最后个字符的ASCII码值。值“35”是字符显示时一行的参考垂直间距(也就是行高),这个值大于字符的高,而且大的比较多,所以一般不使用此值,而时根据字符的高在具体程序中自行定义一个行高。
3.3.4 PROGMEM关键字
PROGMEM关键字被Arduino和AVR编程使用,在ESP8266和ESP32的官方开发环境RTOS SDK和ESP-IDF中要删除。
参考文档
- Understanding the Font Specification
https://learn.adafruit.com/creating-custom-symbol-font-for-adafruit-gfx-library/understanding-the-font-specification - adafruit/Adafruit-GFX-Library
https://github.com/adafruit/Adafruit-GFX-Library