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