メイン・コンテンツまでスキップ

ベクタ・フォント

TouchGFXバージョン4.23から、ベクタ・フォーマットのフォントの使用がサポートされています。 ベクタ・フォーマットで格納されるフォントは、フォント・データがすべてのフォント・サイズで共有されるため、データ・サイズを小さくできる可能性があります。 これは、すべてのフォント・サイズにそのサイズのグリフ専用のビットマップを持つビットマップ・フォントとは対照的です。

ベクタ・フォントは、TextAreaやButtonWithLabelなどのウィジェットで使用する通常のビットマップ・フォントと同様に、ユーザ・インタフェースで使用されます。

ベクタ・フォント・フォーマットを使用するには、STM32CubeMXのプラットフォームでベクタ・フォント機能を有効にする必要があります。

ベクタ・フォントは、16bpp、24bpp、または32bppのフレームバッファのみでサポートされます。

ベクタ・フォントとは

ベクタ・フォントは、個々の文字が曲線と直線で表されるフォントです。 これらの曲線と直線は、さまざまなサイズのグリフを生成するために拡大 / 縮小できます。 TouchGFXで通常使用するフォントはすべてベクタ・フォント(TrueTypeやOpenTypeフォントなど)です。 TouchGFX Designerがアセットを生成すると、フォント記述で使用されている曲線と直線は、TouchGFX Font Converterによって多数の小さいビットマップに変換されます。

ベクタ・フォントのビットマップへの変換は、TouchGFX Designerで定義されているタイポグラフィに基づきます。 たとえば、あるアプリケーションでLargeとSmallの2種類のタイポグラフィを使用するとします。 Largeはサイズ30のVerdanaをベースに、Smallはサイズ20のVerdanaをベースにします。 アプリケーションでこれらのタイポグラフィのグリフA~Zとa~zを使用している場合、各タイポグラフィのグリフは52個ですが、アプリケーションには104個のビットマップが含まれます。文字ごとに2種類のビットマップがあるからです。 サイズ30とサイズ20の2種類のビットマップです。

グリフのベクタ定義を保持し、グリフのビットマップが作成されないという点で、ベクタ・フォントは異なります。 代わりに、このベクタ定義は1回だけターゲット・アプリケーションに組み込まれます。 2つのタイポグラフィの生成に必要な追加データは、2種類のスケーリング・ファクタのみです。 ベクタ定義をサイズ30にスケーリングするものと、サイズ20にスケーリングするものです。

その結果、別のタイポグラフィ・サイズ、たとえばサイズ40のVerdanaをサンプルのアプリケーションに追加しても、必要とするFlashサイズの増加はわずかです。

例を挙げると、TruetypeフォントVerdanaの[G]のベクタ定義は170バイトです。

グリフを表すビットマップのサイズは、使用されるbppとグリフのサイズに応じて異なります。 次の表では、4bppのさまざまなグリフ・サイズでの[G]のビットマップ・サイズを示しています。

フォント・サイズGのグリフ・サイズ(pixels)ビットマップ・サイズ(bytes)
2014 x 1498
3021 x 22242
4027 x 32448
合計788

フォント・サイズ20のビットマップ・サイズは[G]のベクタ定義よりも小さいですが、すでにサイズ30でベクタ定義がビットマップ・サイズよりも小さくなっています。 また、3種類のサイズのVerdanaを使用する場合、ビットマップでは788バイトを使用しますが、ベクタ定義では170バイトしか使用しません。 したがって、Flash使用量を78%節約できます。

このストレージの節約には、パフォーマンス上のデメリットがあります。 グリフを描画する必要がある場合、ベクタ定義をピクセルに変換する必要があります。 それには、グリフのベクタ定義をスケーリングおよび変換してから、フレームバッファに描画します。

Verdanaでは1つの[G]は20本のベジェ曲線と6本の直線で構成されます。 これらはすべてアウトラインに変換され、最終的に選択したテキストの色を使用して色付けされます。 このプロセスはがテキスト内のすべての文字について繰り返され、テキストが再描画されるたびに繰り返されます。

上記のプロセスは、それがうまく機能するGPU2Dを搭載したマイクロコントローラ(STM32U5G9など)でハードウェア・アクセラレーションされます。 STM32G0のような低速のマイクロコントローラでは、浮動小数点ハードウェアがなければ、ハードウェアがこうした動作を実行するには非常に大きな負荷となります。

そのような場合、ビットマップ・フォントが使用されていると、描画時間が短くなります。 したがって、Flashの節約が必要な場合はベクタ・フォントを使用し、それ以外の場合はビットマップ・フォントを使用することをお勧めします。
テキストがアニメーション(スクロール、移動またはフェード)になっている場合は、ビットマップ・フォントの使用をお勧めします。

設定

ベクタ・フォントの使用には、追加のフレームワーク機能であるVector RenderingVector Fontsが必要です。 これらはSTM32CubeMXで有効になっています。 詳細については、Generator User Guideを参照してください。

タイポグラフィはTouchGFX Designerで設定します。 ここで、プロジェクトのタイポグラフィにビットマップ・フォント・フォーマットまたはベクタ・フォント・フォーマットのどちらを使用するのか選択できます。 デフォルトはビットマップ・フォント・フォーマットです。

ベクタ・フォントの使用

TouchGFXでは、ベクタ・フォントはビットマップ・フォントと同じように使用されます。 テキストを名前付きリソースまたはシングル・ユース・テキストとして作成します。 そのテキストをウィジェットの1つ、たとえばTextAreaに表示します。 ベクタ・フォントとビットマップ・フォントとの違いは、描画コードに隠されています。

タイポグラフィ

ベクタ・フォントは、TouchGFX Designerでタイポグラフィがベクタ・ベースに設定されている場合に生成されます。 Designer User Guideを参照してください。

複数のタイポグラフィで同じフォント(Verdanaなど)を使用している場合は、タイポグラフィはプロジェクト内でベクタ定義を共有しますが、異なるサイズのグリフを生成するために異なるスケーリング・ファクタを使用します。

つまり、タイポグラフィ属性Fallback CharacterおよびEllipsis Characterもタイポグラフィ間で同じである必要があるということです。

タイポグラフィで使用される文字(ワイルドカード文字を含む)はまとめられ、同じフォントを使用するプロジェクトのすべてのタイポグラフィで使用可能になります。

アーキテクチャ

ベクタ・フォントの描画は、新しいコンポーネントVectorFontRendererに基づいています。 このコンポーネントは、VectorRendererコンポーネントを使用してグリフを描画します。

ベクタ・フォントを使用するプロジェクトでは、これら2つのコンポーネントを使用可能にする必要があります。 これらのコンポーネントが有効な場合は、これはSTM32CubeMXによって自動的に実行されます。 STM32CubeMXを使用していない場合は、手動で実行する必要があります。

次のSTM32CubeMXで生成されたコードでは、関連する行がハイライト表示されています。

static STM32TouchController tc;
static STM32DMA dma;
static TouchGFXDataReader dataReader;
static LCD16bppSerialFlash display(dataReader);
static VectorFontRendererImpl vectorFontRenderer;
static ApplicationFontProvider fontProvider;
static Texts texts;
static TouchGFXHAL hal(dma, display, tc, 240, 320);

void touchgfx_init()
{
Bitmap::registerBitmapDatabase(BitmapDatabase::getInstance(), BitmapDatabase::getInstanceSize());
TypedText::registerTexts(&texts);
Texts::setLanguage(0);

hal.setDataReader(&dataReader);
fontProvider.setFlashReader(&dataReader);

display.setVectorFontRenderer(&vectorFontRenderer);
...

VectorRendererコンポーネントも(TouchGFXGeneratedHAL.cppから)指定する必要があります。

namespace touchgfx
{
VectorRenderer* VectorRenderer::getInstance()
{
static CWRVectorRendererRGB565 renderer;

return &renderer;
}
} // namespace touchgfx

GPU2Dアクセラレータを搭載したプラットフォームでは、CWRVectorRendererRGB565ではなく、CPU2DVectorRendererを使用する必要があります。 これにより、ハードウェア・アクセラレーションが可能になります。

制限

ワインディング・ルール

TouchGFXアプリケーションで使用されるベクタ・フォント・タイポグラフィは、グリフを適切に描画するために一定のルールに従う必要があります。 特に、オーバーラップしたアウトラインがあるグリフは、ベクタ・フォントを描画する際に、TouchGFXで採用されているワインディング・ルールが原因で、適切に描画されないことがあります。 オーバーラップしたアウトラインをカスタムのタイポグラフィから削除するには、無償のFontForgeツールを使用することを推奨します。

FontForgeの使用

FontForgeインストール・フォルダ(通常はc:/Program Files (x86)/FontForgeBuilds)に移動し、.exeを起動します。

FontForgeの起動ビュー。

プロジェクトのassets/fonts/フォルダ(たとえば、c:/TouchGFXProjects/MyApplication/TouchGFX/assets/fonts/)に移動します。 FontForgeにより、アプリケーション内のすべてのTrueTypeフォントが検出されます。 この例では、Cairo-Bold.ttf TrueTypeフォントに、適切に描画されないオーバーラップしたアウトラインが含まれています。

FontForgeのTrueTypeフォント・ビューを開く。

[OK]をクリックすると、タイポグラフィにあるすべてのグリフのフォント・ビューが開きます。

FontForgeフォント・ビュー。

オーバーラップした輪郭をグリフから削除するには、 Ctrl + Aをキーインして、フォント・ビューのすべてのグリフを選択します。. 次に、選択したすべてのグリフで、ショートカット Ctrl + u、 次いで Ctrl + Shift + Oをキーインして、 オーバーラップした輪郭を選択したグリフから削除します。 変更されたことを示す青色のマークが、すべてのグリフの上に表示されます。 個々のグリフをダブルクリックすると、効果を確認できます。 例として、$グリフのオーバーラップした輪郭を削除した前後を次に示します。

オーバーラップした輪郭がある$グリフ(左)とオーバーラップした輪郭がない$グリフ(右)

グリフのアウトラインは影響を受けないままですが、オーバーラップした輪郭がマージされたことがわかります。 TouchGFXアプリケーションでオーバーラップのないタイポグラフィを使用するために、FontForgeを使用して、新しいフォントをエクスポートします。 FontForgeのフォント・ビューで、ショートカット Ctrl + Shift + G をキーインしてフォントをエクスポートします。 これにより、[Generate Fonts]ビューが開きます。 タイポグラフィの名前を、接尾辞としてたとえば「-no-overlap」を付けて変更し、誤って元のフォントが上書きされないようにすることを推奨します。 [TrueType]を出力フォーマットとして選択します。 以下のとおりに設定します。

FontForgeのフォント設定を生成。

[Generate]を押してフォントをエクスポートします。 警告が表示された場合は、[Yes]を押します。 プロジェクトのassets/fonts/フォルダの元のTrueTypeフォントの横に、エクスポートされたタイポグラフィが表示されます。 元のフォントをこのフォルダから削除して、ディスク上のいずれかの場所に移し、TouchGFX Designerで同じ名前のタイポグラフィが複数表示されないようにします。 TouchGFX Designerを再起動し、新しいフォントをフォント・セレクタに表示します。 フォントの変更前にTouchGFX Designerでコードを生成した場合は、コードを再度生成する前に、generated/fonts/フォルダを削除してください。

ストレージ

ベクタ・フォント・データは、メモリ・マップド領域に格納する必要があります。 内部Flash、メモリ・マップド・モードの外部QSPI / OSPI Flash、RAM、またはその他の類似メモリなどに格納できます。

プラットフォームで他のフォント・データが非メモリ・マップド・データに格納される場合は、リンカ・スクリプトを変更して、すべてのベクタ・フォント・データを内部Flashなどに移動する必要があります。 次に、ARM gccを使用してこれを実行する方法を示します。

  /* Constant data into "FLASH" Rom type memory */
.FontFlashSection :
{
. = ALIGN(4);
*/Vector_*.o(FontFlashSection) /* Vector font data */
. = ALIGN(4);
} >FLASH

FontFlashSection :
{
*(FontFlashSection FontFlashSection.*)
*(.gnu.linkonce.r.*)
. = ALIGN(0x4);
} >SPI_FLASH

これにより、フォント・データが */Vector_*.o/に一致するファイルからFLASH領域に格納され、その他のフォント・データがSPI_FLASH領域に格納されます。

ベクタ・フォント・データはgenerated/fonts/src/Vector_Font_Verdana.cppや類似のファイルに生成されます。

タイ語

タイ語がベクタ・フォントでは正確に描画できないことは既知の問題です。 対応策として、タイ語にはビットマップ・フォントを使用します。