3. フォントの管理

この章ではフォントの管理について説明し、アプリケーションでの文字描画については以降の章で説明します。

FONT ライブラリでは、基礎となる Font クラスをベースに、メモリ上にロードされたフォントリソースを操作する ResFont クラス、圧縮されているフォントリソースを操作する ArchiveFont クラスと PackedFont クラス、2 つのフォントを 1 つのフォントとして扱う PairFont クラスを用意しています。なお、フォントリソースの文字コードには、CTR-SDK のライブラリが文字列を扱う際に使用している、UTF16-LE を使用することを推奨します。

下図は、FONT ライブラリのクラスの階層図(左側が継承元)を示したものです。アプリケーションでは、図中で右端にあるクラスの中から、フォントリソースの利用形態によってインスタンスを作成するクラスを選択します。

図 3-1. クラス階層図(フォントの管理部分)

Font ResFontBase ResFont ArchiveFontBase ArchiveFont PackedFont PairFont

 

3.1. Font クラス

フォントリソースを扱うクラスのベースとなるクラスですが、このクラス自身のインスタンスを作成することはありません。文字の描画に FONT ライブラリのクラスを利用する場合、テクスチャ(グリフイメージが描画されているシート)のロードがメインメモリを直接参照する設定で行われるため、アプリケーションはデバイスメモリ上にフォント(イメージ)用のバッファを用意しなければなりません。このメモリ配置の制限については、このクラスを継承するそれぞれのクラスで説明します。

下表は、Font クラスで定義されているメンバ関数の一覧です。パラメータを取得する場合は、基本的にピクセル単位の値を返すことに注意してください。

表 3-1. Font クラスのメンバ関数一覧
カテゴリ 関数 説明
フォント情報取得







GetWidth() フォントの幅を返します。タブ幅の解決などに使用します。
GetHeight() フォントの高さを返します。
GetAscent() アセントを返します。文字の上端をそろえるために使用します。
GetDescent() ディセントを返します。文字の下端をそろえるために使用します。
GetMaxCharWidth() 含まれている文字の中で最大の文字幅を返します。
GetType() フォントの種別を返します。
GetTextureFormat() シートの(テクスチャ)フォーマットを返します。
GetLineFeed() 改行幅を返します。
GetDefaultCharWidths() デフォルトの文字幅情報を返します。フォントにない文字の文字幅などに使用します。
フォント情報設定

SetLineFeed() 改行幅を再設定します。
SetDefaultCharWidths() デフォルトの文字幅情報を再設定します。
SetAlternateChar() 代替文字を設定します。
文字情報取得


GetCharWidth() 文字の文字幅を返します。
GetCharWidths() 文字の文字幅情報を返します。
GetGlyph() グリフの情報。指定された文字のグリフがフォントに含まれていなければ、代替文字のグリフを返します。
HasGlyph() 指定された文字のグリフがフォントに含まれているかどうかを返します。

文字列

エンコーディング

GetCharacterCode() 文字コードを返します。
GetCharStrmReader() FONT ライブラリで文字を描画する際に、CharWriter クラスが利用します。
シート情報取得

GetBaselinePos() ベースラインを返します。
GetCellHeight() セルの高さを返します。
GetCellWidth() セルの幅を返します。
テクスチャ補間


EnableLinearFilter() FONT ライブラリで文字を描画する際、拡大縮小時に線形補間を行うかどうかを設定します。
IsLinearFilterEnableAtSmall() FONT ライブラリで文字を描画する際、縮小時に線形補間を行うかどうかを返します。
IsLinearFilterEnableAtLarge() FONT ライブラリで文字を描画する際、拡大時に線形補間を行うかどうかを返します。
GetTextureWrapFilterValue() FONT ライブラリで文字を描画する際の、ラッピングモードとフィルタ設定を返します。

3.2. ResFont クラス

フォントリソースを操作するためのクラスです。グループ化には対応していませんので、すべてのシートがメモリにロードされます。そのため、フォントリソース全体がメモリ上にロードされていなければなりません。

メモリ上にロードされたフォントリソース(bcfnt ファイル)は SetResource() で ResFont クラスに関連付けます。文字の描画に FONT ライブラリのクラスを利用する場合、フォントリソースに含まれているシートと同じ数のテクスチャオブジェクトが glGenTextures() で作成されます。作成されたテクスチャオブジェクトはテクスチャイメージに GPU が直接アクセスする設定のため、フォントリソースはデバイスメモリ上に 128 Byte のアライメント(nn::font::GlyphDataAlignment で定義)で読み込まなければなりません。関連付けの解除は RemoveResource() で行います。関連付けを解除するまで、フォントリソースを読み込んだバッファは解放しないでください。

文字の描画に FONT ライブラリのクラスを利用する場合、GetDrawBufferSize() で取得したサイズの描画用バッファを SetDrawBuffer() で設定する必要がありますが、描画用バッファはデバイスメモリ上に確保する必要はありません。描画用バッファは nn::font::ResFont::BUFFER_ALIGNMENT ( 4 Byte ) でアライメントする必要があります。

3.2.1. 内蔵フォント

3DS では、本体保存メモリ内に内蔵フォントと呼ばれるフォントリソースが格納されています。アプリケーションは PL ライブラリを使用して、この内蔵フォントを共有のフォントリソースとして利用することができます。

nn::pl::InitializeSharedFont() の呼び出しで 3DS 本体のリージョンに対応した内蔵フォントのロードが開始され、nn::pl::GetSharedFontLoadState()nn::pl::SHARED_FONT_LOAD_STATE_LOADED を返した時点でロードが完了します。この手順でロードされたフォントリソースは、固定アドレス(アプリケーション管轄外の物理アドレス)にロードされるため、アプリケーションのメモリを消費しません。

3DS 本体のリージョンに対応してロードされた内蔵フォントの種類は、nn::pl::GetSharedFontType() で取得することができます。この関数で取得した種類ではない内蔵フォントを使用する場合は、nn::pl::MountSharedFont() で内蔵フォントのアーカイブをマウントし、フォントリソースのファイルをアプリケーションでロードしなければなりません。ファイルは LZ77 形式で圧縮されていますので、CX ライブラリを利用して解凍してください。また、内蔵フォントの種類ごとにマウントする必要があることと、FONT ライブラリで文字を描画する場合は解凍したフォントリソースをデバイスメモリ上に置かなければならないことに注意してください。フォントリソースのロードが完了したときは、nn::pl::UnmountSharedFont() でアーカイブをアンマウントしてください。

補足:

内蔵フォントのロードについては、「3DS プログラミングマニュアル - システム編」を参照してください。

3.3. ArchiveFont クラス

アーカイブフォントを操作するためのクラスです。フォントファイル内のグリフはグループで分けられており、指定したグループ(複数可)のグリフが含まれているシートが解凍されてメモリにロードされます。グループの指定には、すべてのグリフをロードする LOAD_GLYPH_ALL か、ロードするグループ名を "," 区切りでつなげた文字列を用います。

フォントの構築方法には、すでにメモリ上にロードされているアーカイブフォントのデータから構築する方法と、データを順次ロードすることでロード時に必要なメモリを節約する方法とがあります。前者は Construct()、後者は InitStreamingConstruct()StreamingConsturuct() を使用します。フォントのデータは圧縮されていますが、フォントイメージは解凍されてメモリ上に展開されます。フォントの構築に必要なバッファ(展開先のメモリ)のサイズは GetRequireBufferSize() で取得します。文字の描画に FONT ライブラリのクラスを利用する場合は、バッファをデバイスメモリ上に 128 Byte アライメントで確保する必要があります。

フォントの構築後は、アーカイブフォントのロードに使用したメモリを解放することができますが、フォントを破棄するまで、フォントの構築に使用したバッファは解放することができません。フォントの破棄は Destroy() で行います。その際、解放すべきバッファのポインタが返されます。

3.4. PackedFont クラス

ArchiveFont クラスと同様に、アーカイブフォントを操作するためのクラスですが、圧縮されたままのフォントリソースをメモリに持ち、必要なときに解凍して使用することができます。文字に対応するシートを解凍する処理のために負荷はかかりますが、キャッシュが実装されているため、ある程度の負荷は軽減されます。また、キャッシュに残す割合を調整することや、シートをロックすることでキャッシュ落ちを防ぐことができます。

フォントの構築方法は ArchiveFont クラスと同じです。バッファのサイズを計算する際に、キャッシュに残すシートの数や割合を指定します。キャッシュを管理する関数としては、キャッシュ可能なシート数を取得する GetNumCache()、あらかじめシートをキャッシュに読み込む PreloadSheet()、シートをロックする LockSheet()、シート単位でロックを解除する UnlockSheet()、すべてのシートのロックを解除する UnlockSheetAll() が用意されています。

フォントの構築後は、アーカイブフォントのロードに使用したメモリを解放することができますが、フォントを破棄するまで、フォントの構築に使用したバッファは解放することができません。フォントの破棄は Destroy() で行います。その際、解放すべきバッファのポインタが返されます。

3.5. PairFont クラス

Font クラスを継承したクラスで、同じ文字コード、同じテクスチャフォーマットの 2 つのフォントを 1 つのフォントとして利用するためのクラスです。ベースラインの位置が異なるフォントを組み合わせた場合、文字の表示位置に問題が発生する可能性があることに注意してください。

PairFont クラスのインスタンス構築時に指定するフォントの順番で、先に指定したものをプライマリフォント、次に指定したものをセカンダリフォントと呼びます。このクラスでパラメータを取得すると、下表の条件に従って、プライマリフォントかセカンダリフォントのパラメータを取得することになります。

表 3-2. PairFont クラスのパラメータ
パラメータ パラメータ取得の条件
フォントの幅 両者のうちで最大の値。
フォントの高さ
最大文字幅
アセント

フォントの高さの値が大きいフォントの値。

フォントの高さが同じならばプライマリフォントの値を取得します。

ディセント
ベースライン
セルの高さ
改行幅
セルの幅

フォントの幅の値が大きいフォントの値。

フォントの幅が同じならばプライマリフォントの値を取得します。

デフォルト文字幅
グリフの取得

プライマリフォント優先。

プライマリフォントになければセカンダリフォントから取得し、指定の文字がどちらにもなければプライマリフォントの代替文字を取得します。ただし、インスタンス構築後に代替文字を設定したときは、その文字がプライマリフォントになく、セカンダリフォントにあった場合はセカンダリフォントの代替文字を取得します。

代替文字

プライマリフォント優先。

ただし、インスタンス構築後に代替文字を設定したときは、その文字がプライマリフォントになく、セカンダリフォントにあった場合はセカンダリフォントの代替文字を取得します。