はじめに
Arduinoで使える手軽に使えるグラフィックライブラリにAdafruit GFX Libraryがあります。
このライブラリのテキスト表示に初期フォントではなく任意のフォントを使いたい場合がありました。
Adafruit-GFX-LibraryのGitHubにはfontconvertというツールがあり、TrueTypeフォントファイルからヘッダファイルに変換できます。
fontconvertのコンパイル
GitHubにはfontconvertのソースコードがあるので各自でコンパイル作業が必要です。
以下はWSLのUbuntu環境で作業したときの流れです。
- Ubuntu 22.04.3 LTS(WSL2)
- git version 2.34.1
- gcc version 11.4.0
$ git clone https://github.com/adafruit/Adafruit-GFX-Library.git
$ cd Adafruit-GFX-Library/fontconvert/
$ make
FreeTypeというフォント関連のライブラリが必要なので、メイクに失敗するは以下をインストールしてみる。
$ sudo apt install libfreetype6-dev
使い方
fontconvertの引数にフォントファイルとフォントサイズを渡してやると、フォントデータを変換してヘッダファイルの形式で出力されます。
出力をファイルにリダイレクトしてやればヘッダファイルとしてそのまま使用できます。
$ ./fontconvert fontfile size [first] [last]
コマンド引数について
- fontfile : TrueTypeフォントファイル
- size : フォントサイズ
- first : 変換を開始するASCIIコード(オプション)
- last : 変換を終了するASCIIコード(オプション)
first、lastを指定しない場合はASCIIコードの文字の範囲(0x20~0x7E)のみ出力されるようです。
例えば数字フォントのみ利用したい場合は0x30~0x39を指定してやればメモリ消費を抑えられそうです。
実際に変換してみる
今回はGoogle FontsのHenny Pennyで試してみます。
Google Fontsからダウンロードして解凍したフォントファイル(HennyPenny-Regular.ttf)を適当な場所にコピーしてからfontconvertを実行します。
$ ./fontconvert HennyPenny-Regular.ttf 16 > HennyPenny-Regular_16.h
例ではサイズを16に設定して、出力をヘッダファイルとしてリダイレクトしています。
完了すると以下のようなヘッダファイルになります。
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()で使用できます。
以下のような感じで任意のフォントを利用できます。
#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()
{
}