ビットマップフォントとUnicodeとcairo
ビットマップフォントを使いたい。
- pros
- たぶん速い
- グラデーションや縁取りで飾り付けできる
- 複数のフォントの合成、あるいはsubstitutionがしやすい
- オリジナル文字とか、絵文字も使いやすいかも
- 依存ライブラリがほとんど不要
- cons
- 漢字を含めるとテクスチャサイズがすごくデカい
- フォントサイズを綺麗に自由に変えられない
- 多少汚くて良いなら拡大縮小で対応可能ではある
ビットマップフォントを作るプログラムはすでにいくつか存在するのだが、 以下のような条件を満たす良い感じのが見つけられなかったので自分で作ろうかな…。
- substitution や合成ができる
- SMP (Supplementary Multilingual Plane) の Unicode を扱える
- 4096x4096 以上のサイズに対応
- グリフ数が多くても平気
- グラデーション、アウトラインその他の飾り付けが可能
- コマンドラインで操作できる
- FOSS
参考:ビットマップフォントを作るプログラム
テクスチャサイズについて
JIS X 0208 に6879グリフが含まれている。 ユニコードとの対応 も参照。
これとASCIIやいくつかの記号をあわせて7000グリフとして、32pxのフォントでレンダリングすると、 32×32×7000=7,168,000px
となる。
テクスチャサイズ 4096x4096 であれば、 32×32×7000 / 4096^2 ≒ 0.43
というわけで四割強程度の占有率に収まる、はず。
参考: JIS X 0208の漢字リスト
レンダリング
FreeType
FreeType を直接使うのは、飾り付け等を考えると結構大変そうである。
絵文字の場合分けをして、アウトラインは FT_Glyph_Stroke
で作って FT_Render_Glyph
でレンダリングして、
あとはグラデーションをなんとかして…という感じであろうか。
SDL_ttf
SDL_ttf は version2.0.14 で確認したとこ、以下二点が厳しい。
- フォントによってはレンダリング結果がクロップされた状態になる
- 4バイト使う Supplementary な領域のグリフを扱えない
(1)については、例えば “ᾆ” (U+1F86
) のようなダイアクリティカルマーク盛り盛りのグリフなんかで上下が切れてしまう場合がある。
以下は Miguフォント をレンダリングしたもの。
上は macOSのレンダリング結果、下は SDL_ttf を使ったもので、ダイアクリティカルマークが結構途切れてしまっている。
(2)は例えば “👺” (U+1F47A
) のようなカラー絵文字だとか、ヒエログリフだとかを表示できない。
cairo
というわけで FreeTypeのフロントエンドとして cairo を使ってみる。
以下は mplusフォント をレンダリングしたもの。
cairo_pattern_t
を使ったグラデーションと cairo_stroke
を使ったアウトライン入り。
以下は Notoフォント の Noto Color Emoji を cairo_show_glyphs
でレンダリングした結果。
cairoを使うとbdfフォントなんかもほぼ透過的にハンドリングしてくれる。 Gohufont をレンダリングしたのが以下。
素晴らしい結果なのだが、cairoは標準の配布用バイナリ(*.framework とか *.dll とか)が用意されておらず、 実行ファイルを作って配布しようと思うとそこが少々めんどくさそうである。 最低限 FreeType, libpng, libz, libbz2, pixman, cairo が必要そうかな…?
レンダリングするにあたっては、テキストから UTF-8 の文字を一文字ずつとりだす必要があり、これも自分で実装するとちょっとめんどくさい。 レンダリングするだけなので Overlong encodings なんかは無視しても良いと思う。SDL_ttfは無視してた。