上一篇文章 TFT_eSPI 字库格式分析(一) 我们主要分析了TFT_eSPI 字库的RLE格式
我们接着分析第三种格式GFX格式
GFX格式
GFX格式以位图的形式保存每个字符的字模信息的有效部分,省略每个字符的空白部分。
拿上一篇Font16.c
字库中的!
字模为例,字模是如下点阵:
00000000 //第1行
00000000 //第2行
00000000 //第3行
01000000 //第4行
01000000
01000000
01000000
01000000 // ...
01000000
01000000
01000000
00000000
01000000 //第13行
00000000 //第14行
00000000 //第15行
00000000 //第16行
有效点阵就是第4行第1列到第13行第1列,共1x10个点阵信息,原本16个字节的数据,现在2个字节即可存储。
GFX字库保存在Fonts/FGXFF
目录中,Fonts/gfxfont.h
中有GFX格式的数据结构定义
typedef struct { // Data stored PER GLYPH
uint32_t bitmapOffset; // Pointer into GFXfont->bitmap
uint8_t width, height; // Bitmap dimensions in pixels
uint8_t xAdvance; // Distance to advance cursor (x axis)
int8_t xOffset, yOffset; // Dist from cursor pos to UL corner
} GFXglyph;
typedef struct { // Data stored for FONT AS A WHOLE:
uint8_t *bitmap; // Glyph bitmaps, concatenated
GFXglyph *glyph; // Glyph array
uint16_t first, last; // ASCII extents
uint8_t yAdvance; // Newline distance (y axis)
} GFXfont;
GFXglyph
是每一个字符的数据结构
我们拿字库FreeMono9pt7b.h
为例分析,
const GFXglyph FreeMono9pt7bGlyphs[] PROGMEM = {
{ 0, 0, 0, 11, 0, 1 }, // 0x20 ' '
{ 0, 2, 11, 11, 4, -10 }, // 0x21 '!'
每个字符对应的字段在头文件结构体中都有注释
空白符
的数据为:
0, //位图指针
0, //字符宽度
0, //字符高度
11, //到光标的水平距离(程序中好像没用到)
0, //位图相对左上角的x偏移
1 //位图相对左上角的y偏移(以基线baseline为准)
!
的数据为:
0, //位图指针
2, //字符宽度
11, //字符高度
11, //到光标的水平距离(程序中好像没用到)
4, //位图相对左上角的x偏移
-10 //位图相对左上角的y偏移(以基线baseline为准)
空白符
我们略过,只看!
位图指针为0
,指向位图的第一个数据:
const uint8_t FreeMono9pt7bBitmaps[] PROGMEM = {
0xAA, 0xA8, 0x0C, 0xED, 0x24, 0x92, 0x48, 0x24, 0x48, 0x91, 0x2F, 0xE4,
0x89, 0x7F, 0x28, 0x51, 0x22, 0x40, 0x08, 0x3E, 0x62, 0x40, 0x30, 0x0E,
...
也就是0xAA
,字符宽度为2
,高度为11
,总共2x11=22
个点,占用3
个字节。所以0xAA,0xA8,0x0C
这3
个字节是字符!
的数据。
这3
个字节按位拆开就是10101010 10101000 00001100
,按照2x11的矩阵排列就成了下面的样子:
10 //第1行
10
10
10
10
10
10
00
00
00
11 //第11行
是不是差不多明白了?
自定义字库
这部分内容站内其他博主有介绍,我就不罗嗦了。
结束语
其实TFT_eSPI
应该还打算支持TueType
字体的,或许出于某些原因,目前并没实现,可能用处不大吧!