ラスタライズフォント生成ツール
Contents
ラスタライズフォント生成ツール#
概要#
ラスタライズフォントは画像化された文字の集合体です。実装が容易で高速に扱える特徴があり、文字の使用範囲が限定されているゲームプログラミングにおいては広く用いられている手法です。一方で、リサイズや回転などの変形で劣化しやすいというデメリットがあります。
本項では、フォントデータとして広く用いられているアウトラインフォントからラスタライズフォントを生成するツールと、その出力データをMGLで扱うためのエクステンションについて解説します。
重要
本ツールの利用にあたって、変換元となるアウトラインフォントのライセンスは必ず確認してください。本ツールが出力するデータの利用は複製・改変・再配布にあたる可能性があり、ライセンスによっては禁止または制限が課せられている場合があります。
ツールの導入#
アウトラインフォントをラスタライズするためにはmgl-font2texというツールを用います。このツールはコマンドラインツールであり、コンソール(Windowsのコマンドプロンプト、macOSのターミナル等)から利用します。
ツールの導入方法は次の通りです。
Windows#
MGLのダウンロードページにアクセスし、「ツール」からmgl-font2texのWindows向けの実行可能バイナリをダウンロードしてください。ダウンロードしたアーカイブ内にある「mgl-font2tex.exe」がツール本体になります。このファイルを必要に応じてパスの通ったディレクトリにコピーしてください。
macOS#
macOSではHomebrewを用いて導入します。Homebrewについては次のリンク先を参照してください。
MGL関連のツールは公式パッケージとして登録されていないため、最初にtapコマンドを用いてパッケージの追加を行う必要があります。
$ brew tap AcerolaSoftware/tap
このコマンドにより、MGLの配布元が提供しているツール類をHomebrewから導入できるようになります。
tapコマンド実行後、installコマンドによりmgl-font2texをインストールします。
$ brew install mgl-font2tex
実行後、mgl-font2tex -v
と入力してバージョン情報が表示されていれば成功です。
その他の環境#
一般的なPOSIX準拠のシステムであれば、ソースコードからビルドすることで利用可能です。
mgl-font2texはビルドに次のソフトウェアを利用します。
C++17に対応したコンパイラ(clang推奨)
SCons (バージョン4.0.0以降)
pkg-config
依存ライブラリは次の通りです。これらはpkg-configで参照できる必要があります。
libpng
FreeType
JsonCpp
ビルド方法は次の通りです。
$ scons
正常にビルドが完了した場合、そのディレクトリにmgl-font2texが生成されます。
ツールの使用方法#
設定ファイルの新規作成#
mgl-font2texはあらかじめ設定を記述したファイルを用意し、その設定ファイルを読み込むことで動作します。この設定ファイルのテンプレートはinit
コマンドを用いることで生成します。
まず初めに、次のように入力して設定ファイルを新規に作成してください。
$ mgl-font2tex init
成功するとカレントディレクトリにfont2tex.config
という設定ファイルが生成されます。
次のようにinit
の後にファイル名を指定する事も可能です。
$ mgl-font2tex init uifont.config
この場合、uifont.config
という名前で設定ファイルが作成されます。用途に応じて複数のフォントリソースを使い分ける場合に利用してください。
ラスタライズ#
init
コマンドで作成した設定ファイルには、設定可能なパラメータとその説明のコメントが記述されています。まずは設定ファイルをテキストエディタで開き、コメントに従い内容を記述してください。
ここでは例として、MGLのロゴにも使用されている「自家製Rounded M+」を用いる場合を想定して編集します。自家製Rounded M+は次のサイトにて配布されており、無償で利用可能です。
まず、利用したいアウトラインフォントのファイルを設定ファイルと同じディレクトリにコピーするか、システムにインストールしてください。ここではrounded-mplus-1p-regular.ttf
を利用するものと想定します。
次に、設定ファイルをテキストエディタで開いてください。設定ファイルの先頭にFontPath
というパラメータがありますので、ここにアウトラインフォントのファイル名を記述します。
FontPath = rounded-mplus-1p-regular.ttf
一旦この状態で保存し、コンソール上から設定ファイルと同じディレクトリで次のように実行してください。
$ mgl-font2tex
ヒント
設定ファイルの名前を変更した場合は、次のように引数に設定ファイル名を指定してください。
$ mgl-font2tex uifont.config
引数を省略した場合はfont2tex.config
が指定されます。
設定ファイルは初期状態でフォントサイズ32、画像サイズ256x256、印字可能なASCII文字のみを出力する設定になっています。設定が正しければ、font_00.png
という名前の次のような画像が生成されます。
- 出力画像
注釈
背景は本来は透過していますが、ここでは黒で塗りつぶしています。
画像ファイルの他にfont_metrics.bin
とfont_metrics.json
というファイルも同時に出力されています。これらはメトリクス情報と呼ばれ、文字ごとのレンダリングに必要な情報が格納されています。両者の内容は同じですが、拡張子.bin
はバイナリ形式で、拡張子.json
はJSON形式です。出力結果をゲーム内で利用するには、これらのどちらかを用いることになります。
文字の追加#
設定ファイルのデフォルト設定はASCII文字のみを出力しますが、パラメータを変更することでより多くの文字を扱うことが可能です。
使用する文字を追加する一般的な方法は、追加したい文字が記述されたテキストファイルをTextFiles
のパラメータに指定することです。実際のゲーム開発においては、ここにゲームが使用するメッセージデータを指定し、そのゲームが使用する文字のみをラスタライズするようにします。
ここでは仮として、設定ファイルをメッセージデータの代わりに指定します。
TextFiles = font2tex.config
ついでに、出力する画像サイズが256x256では収まりきらなくなるため、画像サイズを512x512に拡張します。全ての文字が1枚の画像に収まらなかった場合は複数枚に分割して出力されますが、描画パフォーマンスの観点から全ての文字が1枚に収まっている状態が理想的です。
PalletWidth = 512
PalletHeight = 512
この設定でのラスタライズ結果は次の通りです。
- 出力画像
書体の追加#
フォントリソースには複数の書体に対応しており、このツールではボールド体とルビ用の書体を追加で収録できます。これらの書体はタグによるテキスト装飾を行う際に使用されます。
ボールド体およびルビ用の書体の設定は生成された設定ファイルの最下段にあります。これらの設定パラメータを記述することによって、出力されるフォントリソースに書体が追加されます。
# ボールド体の出力設定
# この設定を有効にするとボールド体用のグリフを同時に出力します。
# 各パラメータの内容は先述の同名パラメータと同様です。
[bold]
Enable = No
FontPath = __PLEASE_SET_TTY_FONT_PATH__
TextFiles =
AppendAsciiCharacter = Yes
AppendHiragana = No
AppendKatakana = No
FontSize = 32
AlignmentSize = 2
# ルビの出力設定
# この設定を有効にするとルビ用のグリフを同時に出力します。
# 各パラメータの内容は先述の同名パラメータと同様です。
[ruby]
Enable = No
FontPath = __PLEASE_SET_TTY_FONT_PATH__
TextFiles =
AppendAsciiCharacter = Yes
AppendHiragana = Yes
AppendKatakana = Yes
FontSize = 14
AlignmentSize = 2
有効にしたい書体のパラメータEnable
にYes
を設定し、FontPath
に有効な変換元フォントファイルへのパスを指定してください。その他のパラメータの意味はデフォルトの書体と同じとなるため、設定ファイル内の同名パラメータのコメントまたは設定パラメータの詳細を参考にしながら設定してください。
これらの利用例を次に示します。
- 設定ファイル(変更箇所のみ)
PalletWidth = 1024 PalletHeight = 1024 [bold] Enable = Yes FontPath = rounded-mplus-2p-heavy.ttf TextFiles = font2tex.config [ruby] Enable = Yes FontPath = rounded-mplus-1p-regular.ttf
- 出力画像
出力した書体の利用方法については、フォントの利用方法のタグによるテキスト装飾を参照してください。
メッセージコンバータとの連動#
メッセージコンバータにはメッセージデータを最適化する機能があり、mgl-font2texはこの最適化に対応したフォントリソースを生成する機能を備えています。この機能はメッセージの描画負荷の軽減だけでなく、文字の選定を自動化する目的も兼ねています。
メッセージコンバータが最適化されたデータを生成する場合、同時にJSON形式に使用文字リストを出力します。mgl-font2tex側はこの使用文字リストを使用してラスタライズすることで、このメッセージデータに対応したフォントリソースを生成します。メッセージコンバータ側の最適化の詳細についてはインデックス化してバイナリ出力を参照してください。
注意
使用文字リストを使用してラスタライズを行う場合、TextFiles
と全てのAppend*
のパラメータは無視されます。任意の文字を追加したい場合、メッセージデータ側にその文字を追加してください。
使用文字リストを使用してラスタライズを行うには、UsingCharacterList
オプションにメッセージコンバータが出力したJSONファイルを指定します。
UsingCharacterList = msg_using_all.json
使用文字リストには全ての書体の情報が含まれています。もしリストが特定の書体を要求しており、その設定が有効になっていない場合はエラーとなります。その場合は各書体のパラメータを適切に設定してください。
その他の設定#
その他の設定については設定パラメータの詳細を参照してください。
MGLでの利用方法#
ライセンス#
ここで紹介するエクステンションはMGL本体と同じzlibライセンスに基づいて配布されています。もしMGLと併用する場合、このエクステンションはMGLの一部として扱って問題ありません。zlibライセンスの詳細はMGLのライセンスを参照してください。
利用方法#
MGLのダウンロードページではmgl-font2texの出力結果をMGLで扱うためのエクステンションも提供しています。このエクステンションはMGLのフォントリソースとして実装されており、MGL::Render::FontのAPIを通して利用可能になります。
エクステンションはソースコードとして配布されています。まず、ダウンロードページの「エクステンション」からmglext-rasterized-fontをダウンロードしてください。アーカイブ内のmglext
ディレクトリ内にソースコードが含まれていますので、これをアプリケーション側のプロジェクトへと追加してください。
ここでは、導入方法の各プラットフォーム共通で示したディレクトリ構成に追加し、次のような構成になることを想定します。
src
├── app_main.cc
├── app_main.h
└── mglext
├── rasterized_font.cc
└── rasterized_font.h
また、mgl-font2texの出力結果をリソースとして扱う必要があります。workdir
に全てのPNGファイルとfont_metrics.bin
をコピーします。Xcodeの場合はプロジェクトへの追加も忘れないでください。
結果、次のような構成になることを想定します。
workdir
├── font_00.png
└── font_metrics.bin
注釈
ディレクトリ構成は一例です。作成するゲームに合わせ適宜変更してください。
最後に、このフォントリソースをプログラム側から扱うための例を示します。導入方法の各プラットフォーム共通の例を元に、今回追加したフォントリソースで文字の描画する例は次の通りです。
- app_main.cc
#include "app_main.h" // ラスタライズフォント用のエクステンションをインクルード #include "mglext/rasterized_font.h" namespace { // フォントキーを定義 constexpr auto kFontKey = MGL::Render::MakeFontKey("font"); } namespace YourApp { /* ------------------------------------------------------------------------- */ /*! * \brief コンストラクタ */ /* ------------------------------------------------------------------------- */ Application::Application() noexcept { } /* ------------------------------------------------------------------------- */ /*! * \brief 初期化処理 * \retval true 成功 * \retval false 失敗 */ /* ------------------------------------------------------------------------- */ bool Application::OnInitialize() noexcept { // ラスタライズフォントを登録 auto font = MGL::Render::Font::Create<MGLExt::RasterizedFont>( kFontKey, // 登録するフォントキー "$resource/", // フォントファイル一式が格納されているディレクトリ "font"); // フォント名。NamePrefixに指定した文字を指定する if (!font) { MGL_TRACE("フォントの登録に失敗"); } return true; } /* ------------------------------------------------------------------------- */ /*! * \brief フレーム更新処理 */ /* ------------------------------------------------------------------------- */ void Application::OnFrameUpdate() noexcept { MGL::Render::Renderer2D renderer; // 黒色で画面をクリア renderer.Clear(MGL::kColorBlue); // 登録したフォントを用いて描画 MGL::Render::Font font(kFontKey); if (font) { font.SetPosition(MGL::Vector2(100.0f, 100.0f)); font.Print("Rounded M+ フォント"); } } /* ------------------------------------------------------------------------- */ /*! * \brief 終了処理 */ /* ------------------------------------------------------------------------- */ void Application::OnExit() noexcept { } } // namespace YourApp
フォントキーや描画方法についてはフォントの利用方法で解説している内容と共通しているため省略します。ラスタライズフォントを扱うための重要な部分は、Application::OnInitialize()
内の次の部分です。
// ラスタライズフォントを登録
auto font = MGL::Render::Font::Create<MGLExt::RasterizedFont>(
kFontKey, // 登録するフォントキー
"$resource/", // フォントファイル一式が格納されているディレクトリ
"font"); // フォント名。NamePrefixに指定した文字を指定する
MGLExt::RasterizedFont
というクラスがラスタライズフォントを扱うためのフォントリソースクラスです。第2引数にフォントファイル一式が格納されているディレクトリを、第3引数にフォント名を指定しています。フォント名は設定ファイルのNamePrefix
に指定した文字をそのまま指定してください。
戻り値に有効なフォントが返っている場合、フォントの登録に成功しています。
このサンプルの実行結果は次の通りです。
- 実行結果(640x480)
設定パラメータの詳細#
FontPath#
変換元のフォントファイルのパスを指定します。相対パスを指定した場合、フォントファイルを次の順で検索します。
カレントディレクトリ
環境変数
MGL_FONT_PATH
に設定されたパスシステムのフォントディレクトリ(Windows、macOSのみ)
WindowsとmacOSにおいては、システムのフォントディレクトリを検索する際にユーザー毎にインストールされたフォントを優先的に参照します。
このパラメータは省略できません。
- 例
FontPath = use-outline-font.ttf
OutputPath#
変換したファイルの保存先ディレクトリを指定します。
省略時は./
(カレントディレクトリ)が指定されます。
- 例
OutputPath = ./
NamePrefix#
生成するファイルの先頭に付ける名前を指定します。
省略時はfont
が指定されます。
- 例
NamePrefix = font
TextFiles#
使用する文字が記述されたテキストファイルのパスを指定します。複数指定する場合はtext1.txt:text2.txt
のように:
で区切ります。
このファイルはいずれかのUnicode形式で保存されていなければなりません。BOMがあればそれを利用して自動認識し、なければUTF-8として読み取ります。
ファイル名の先頭に!
を付与した場合、そのファイルに含まれる文字がアウトラインフォントに含まれていなくても警告を表示しません。
後述するUsingCharacterList
を使用せず、Append**
のオプションの全てがNo
の場合、このパラメータは省略できません。
- 例
TextFiles = text1.txt:!text2.txt
UsingCharacterList#
メッセージコンバータが出力するJSON形式の使用文字リストのパスを指定します。
このパラメータを指定した場合、全てのTextFiles
およびAppend*
オプションは無視されます。
- 例
UsingCharacterList = msg_using_all.json
OutputJSONMetrics#
文字のメトリクス情報をJSON形式で出力するかを指定します。
出力パスはOutputPath
+ NamePrefix
+ "_metrics.json"
(デフォルト設定では./font_metrics.json
)です。
省略時はYes
が指定されます。
- 例
OutputJSONMetrics = Yes
OutputBinaryMetrics#
文字のメトリクス情報をバイナリ形式で出力するかを指定します。
出力パスはOutputPath
+ NamePrefix
+ "_metrics.bin"
(デフォルト設定では./font_metrics.bin
)です。
省略時はYes
が指定されます。
- 例
OutputBinaryMetrics = Yes
AppendAsciiCharacter#
ASCIIコードのうち印字可能な文字を追加します。省略時はYes
が指定されます。
UsingCharacterList
を指定している場合、このパラメータは無視されます。
- 例
AppendAsciiCharacter = Yes
AppendHiragana#
日本語の平仮名といくつかの記号を追加します。省略時はNo
が指定されます。
UsingCharacterList
を指定している場合、このパラメータは無視されます。
- 例
AppendHiragana = No
AppendKatakana#
日本語の片仮名といくつかの記号を追加します。省略時はNo
が指定されます。
UsingCharacterList
を指定している場合、このパラメータは無視されます。
- 例
AppendKatakana = No
FontSize#
フォントサイズを指定します。
生成される文字のピクセル数はここで指定したサイズにおおよそ収まりますが、アウトラインフォントの仕様により若干オーバーする可能性もあります。
省略時は32
が指定されます。
- 例
FontSize = 32
PalletWidth#
生成されるテクスチャの幅を指定します。
省略時は256
が指定されます。
- 例
PalletWidth = 256
PalletHeight#
生成されるテクスチャの高さを指定します。
省略時は256
が指定されます。
- 例
PalletHeight = 256
AlignmentSize#
テクスチャ上の座標の幅と高さのアライメントを指定します。奇数サイズのテクスチャが描画品質に影響する場合などに指定してください。
指定可能な値は0, 2, 4, 8, 16, 32, 64のいずれかです。
省略時は2
が指定されます。
- 例
AlignmentSize = 2
PixelMode#
生成されるテクスチャのピクセルフォーマットを指定します。
指定可能な文字とその内容は次の通りです。
Monochrome: 1ビットのモノクロ
GrayScale: 8ビットのグレースケール
省略時はGrayScale
が指定されます。
- 例
PixelMode = GrayScale
ConfigVersion#
この設定データのフォーマットバージョンです。将来の後方互換のためのものですので、変更は行わないでください。
- 例
ConfigFormatVersion = 10000
Enable#
書体を有効にするかをYes
またはNo
で設定します。このオプションは追加の書体の設定でのみ有効であり、デフォルトの書体は設定に関わらず有効となります。
省略時にはNo
が指定されます。
- 例
[bold] Enable = Yes [Ruby] Enable = No
メトリクス情報のフォーマット#
mgl-font2texが出力するメトリクス情報の内容を次に示します。
バイナリフォーマット#
バイナリファイルは先頭にバイナリデータのヘッダが配置され、以降はチャンク単位でデータが格納されています。全てのチャンクには共通のヘッダが付与されており、アプリケーション側が未対応のチャンクは読み飛ばすことが可能となっています。
現時点でのデータフォーマットは次の通りです。型のunit32_t
は符号なしの32ビット値、uint16_t
は符号なしの16ビット値、int16_t
は符号付きの16ビット値、char32_t
はUTF-32エンコーディングされた文字を表しています。全ての値のバイトオーダーはリトルエンディアンです。
- バイナリヘッダ
名前
型
内容
identifier
uint32_t
識別子:
0x3BA5E2D0
(MGL::Hash::FNV1a("FontMetrics")
で算出)revision
uint32_t
リビジョン番号(予約)
faceCount
uint32_t
フォントフェイス(書体)の数
textureCount
uint32_t
テクスチャの数
maxHeight
uint32_t
全ての文字の高さの最大値
flags
uint32_t
フラグ情報(予約)
- チャンクヘッダ
名前
型
内容
identifier
uint32_t
チャンクの種類を表す識別子
chunkSize
uint32_t
チャンクのデータサイズ
- フェイスチャンク(識別子:
0x79337DCC MGL::Hash::FNV1a("FaceChunk")
で算出) 名前
型
内容
faceType
uint32_t
書体の識別子(書体名をMGL::Hash::FNV1aでハッシュ化した値)
fontSize
uint32_t
フォントサイズ(設定ファイルでの指定値)
glyphCount
uint32_t
グリフの数
alignmentSize
uint32_t
アライメントサイズ
maxHeight
uint32_t
この書体が持つグリフの高さの最大値
glyphs
後述
グリフ情報のテーブル。要素数は
glyphCount
と同値。- フェイスチャンク内のグリフ情報
名前
型
内容
code
char32_t
文字を表す値(UTF-32)
useCount
uint32_t
使用回数
width
uint16_t
幅
height
uint16_t
高さ
advance
uint16_t
送り幅
bearingX
int16_t
X方向のベアリング値
bearingY
int16_t
Y方向のベアリング値
textureX
uint16_t
テクスチャ上のX座標
textureY
uint16_t
テクスチャ上のY座標
textureWidth
uint16_t
テクスチャ上の幅
textureHeight
uint16_t
テクスチャ上の高さ
texturePage
uint16_t
文字が収録されているテクスチャの番号
flags
uint32_t
フラグ情報(予約)
これらを構造体で表すと次のようになります。なお、メモリアライメントによるパティングは発生しないものとします。
//! バイナリファイルのヘッダ
struct BinaryHeader
{
uint32_t identifier; //!< 識別子
uint32_t revision; //!< リビジョン番号
uint32_t faceCount; //!< フォントフェイスの数
uint32_t textureCount; //!< テクスチャの数
uint32_t maxHeight; //!< 全ての文字の高さの最大値
uint32_t flags; //!< フラグ情報
};
//! チャンクヘッダ
struct BinaryChunkHeader
{
uint32_t identifier; //!< 識別子
uint32_t chunkSize; //!< チャンクサイズ
};
//! フェイスチャンク
struct FaceInfo
{
uint32_t faceType; //!< 書体の識別子
uint32_t fontSize; //!< フォントサイズ
uint32_t glyphCount; //!< グリフの数
uint32_t alignmentSize; //!< アライメントサイズ
uint32_t maxHeight; //!< 高さの最大値
// 以降、glyphCountの数だけGlyphInfoが続く
};
//! フェイスチャンク内のグリフ情報
struct GlyphInfo
{
char32_t code; //!< 文字コード(UTF-32)
uint32_t useCount; //!< 使用回数
uint16_t width; //!< 幅
uint16_t height; //!< 高さ
uint16_t advance; //!< 送り幅
int16_t bearingX; //!< X方向のベアリング
int16_t bearingY; //!< Y方向のベアリング
uint16_t textureX; //!< テクスチャのX座標
uint16_t textureY; //!< テクスチャのY座標
uint16_t textureWidth; //!< テクスチャ上の幅
uint16_t textureHeight; //!< テクスチャ上の高さ
uint16_t texturePage; //!< 文字が収録されているテクスチャの番号
uint32_t flags; //!< フラグ情報(予約)
};
JSONフォーマット#
バイナリフォーマットの出力がゲーム側で利用することを想定しているのに対し、JSONフォーマットの出力は他のツールと連携することを想定しています。このため、JSONフォーマットにはバイナリフォーマットに含まれていない情報が追加されています。
JSONフォーマットの内容は次の通りです。なお、要素の並び順は前後している可能性があります。
fontMetrics
├── <書体名>
│ ├── fontInfo フォント情報
│ │ ├── familyName フォントファミリ名
│ │ ├── styleName スタイル名
│ │ ├── size 設定ファイルで指定されたフォントサイズ
│ │ ├── maxHeight 文字の高さの最大値
│ │ ├── texturePageCount テクスチャの最大数
│ │ └── alignmentSize 幅と高さのアライメントサイズ
│ └── glyphs[] グリフ情報(配列)
│ ├── code 文字を表す値(Unicode符号位置)
│ ├── width 文字の幅
│ ├── height 文字の高さ
│ ├── advance 文字の送り幅
│ ├── bearingX 文字のX方向のベアリング値
│ ├── bearingY 文字のY方向のベアリング値
│ ├── useCount 文字の使用回数
│ ├── textureX テクスチャ上のX座標
│ ├── textureY テクスチャ上のY座標
│ ├── textureWidth テクスチャ上の幅
│ ├── textureHeight テクスチャ上の高さ
│ └── texturePage 文字が収録されているテクスチャの番号
├── <書体名>
…
└─ texturePageCount テクスチャの最大数