Adafruit GFX Libraryにフォントを追加

## はじめに
Arduinoで使える手軽に使えるグラフィックライブラリにAdafruit GFX Libraryがあります。
このライブラリのテキスト表示に初期フォントではなく任意のフォントを使いたい場合がありました。

[Adafruit-GFX-LibraryのGitHub](https://github.com/adafruit/Adafruit-GFX-Library)にはfontconvertというツールがあり、TrueTypeフォントファイルからヘッダファイルに変換できます。

https://github.com/adafruit/Adafruit-GFX-Library

## fontconvertのコンパイル
GitHubにはfontconvertのソースコードがあるので各自でコンパイル作業が必要です。
以下はWSLのUbuntu環境で作業したときの流れです。

- Ubuntu 22.04.3 LTS（WSL2）
- git version 2.34.1
- gcc version 11.4.0

```bash:リポジトリのクローン
$ git clone https://github.com/adafruit/Adafruit-GFX-Library.git
$ cd Adafruit-GFX-Library/fontconvert/
```

```bash:メイク
$ make
```

FreeTypeというフォント関連のライブラリが必要なので、メイクに失敗するは以下をインストールしてみる。
```bash:FreeTypeのインストール
$ sudo apt install libfreetype6-dev
```

## 使い方
fontconvertの引数にフォントファイルとフォントサイズを渡してやると、フォントデータを変換してヘッダファイルの形式で出力されます。
出力をファイルにリダイレクトしてやればヘッダファイルとしてそのまま使用できます。
```bash:使用例
$ ./fontconvert fontfile size [first] [last]
```
コマンド引数について
- fontfile : TrueTypeフォントファイル
- size : フォントサイズ
- first : 変換を開始するASCIIコード（オプション）
- last : 変換を終了するASCIIコード（オプション）

first、lastを指定しない場合はASCIIコードの文字の範囲（0x20～0x7E）のみ出力されるようです。
例えば数字フォントのみ利用したい場合は0x30～0x39を指定してやればメモリ消費を抑えられそうです。

## 実際に変換してみる

今回は[Google Fonts](https://fonts.google.com)の[Henny Penny](https://fonts.google.com/specimen/Henny+Penny)で試してみます。

https://fonts.google.com/specimen/Henny+Penny

Google Fontsからダウンロードして解凍したフォントファイル（HennyPenny-Regular.ttf）を適当な場所にコピーしてからfontconvertを実行します。

```bash:フォントの変換
$ ./fontconvert HennyPenny-Regular.ttf 16 > HennyPenny-Regular_16.h
```

例ではサイズを16に設定して、出力をヘッダファイルとしてリダイレクトしています。
完了すると以下のようなヘッダファイルになります。

```c:HennyPenny-Regular_16.h
const uint8_t HennyPenny_Regular16pt7bBitmaps[] PROGMEM = {
  0x00, 0x6F, 0xFF, 0xFF, 0xF7, 0x77, 0x77, 0x77, 0x73, 0x22, 0x22, 0x22,
  0x40, 0x00, 0x6F, 0xF6, 0x0F, 0x3C, 0xF3, 0xCF, 0x3C, 0xD3, 0x4D, 0x34,
...
  0x83, 0x21, 0xFF, 0xE8, 0x0F, 0xF9, 0x00, 0x7C, 0x00 };

const GFXglyph HennyPenny_Regular16pt7bGlyphs[] PROGMEM = {
  {     0,   1,   1,   8,    0,    0 },   // 0x20 ' '
  {     1,   4,  30,   8,    2,  -28 },   // 0x21 '!'
...
  {  5250,  19,   6,  23,    2,  -10 } }; // 0x7E '~'

const GFXfont HennyPenny_Regular16pt7b PROGMEM = {
  (uint8_t  *)HennyPenny_Regular16pt7bBitmaps,
  (GFXglyph *)HennyPenny_Regular16pt7bGlyphs,
  0x20, 0x7E, 56 };
```

このヘッダファイルをインクルードすればsetFont()で使用できます。
以下のような感じで任意のフォントを利用できます。

```c:サンプルコード
#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <HennyPenny-Regular_16.h>

#define SCREEN_WIDTH    128     // OLED display width, in pixels
#define SCREEN_HEIGHT   64      // OLED display height, in pixels

#define OLED_RESET      -1      // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS  0x3C    // See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32

Adafruit_SSD1306 display( SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET );

void setup()
{
    Serial.begin( 115200 );

    if( !display.begin( SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS ) )
    {
        Serial.println( F("SSD1306 allocation failed") );
        for(;;);
    }

    display.clearDisplay();

    display.setFont( &HennyPenny_Regular16pt7b );
    display.setTextColor( SSD1306_WHITE );

    display.setCursor( 1, 30 );
    display.println( F("Hello") );

    display.setCursor( 30, 60 );
    display.println( F("World") );

    display.display(); 
}

void loop()
{
}
```
表示画面
![hello_world](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3695082/0eee9553-5c95-fd90-2cb0-29ce2859387d.jpeg "表示画面")