テキストとフォント
テキストとフォントは、現代のグラフィカル・ユーザ・インタフェースの非常に重要な要素です。 アプリケーションがサポートするすべての言語で、高品質でなめらかなテキストを表示できるようにすることはとても重要です。
TouchGFXでは、TouchGFX DesignerのTexts Viewによって、テキストとタイポグラフィの作成および変更をサポートしています。 TouchGFX Designerは、テキストとタイポグラフィの設定をassets/texts/texts.xml
にあるデータベースに出力します。 このデータベースはフォント・ファイルと一緒に、フォントおよびテキスト・コンバータ・ツールに供給され、これによって生成済みのC++コード・ファイルが作成され、TouchGFXが描画できるようになります。
この記事では、テキストおよびフォント変換ツールを紹介し、コードとTouchGFX Designerを通じてアプリケーション内で生成済みテキストを使用する方法について説明します。
テキストとタイポグラフィ
TouchGFXアプリケーションのテキストとタイポグラフィは、assets/texts/texts.xml
にあるデータベースに保存されます。 このデータベースには、翻訳のテキストと、アプリケーション内で使用されるタイポグラフィが含まれています。 このデータベースは一般には「テキスト・データベース」と呼ばれます。
テキストとタイポグラフィはTouchGFX Designerで、Texts Viewを使用して編集できます。これにより編集を簡単かつ便利に行えます。
ただし、texts.xml内でタイポグラフィとテキストを直接編集することもできます。この編集を支援するために、検証用のXMLスキーマassets/texts/texts.xsd
が提供されています。 多くの既知のテキスト・エディタには、XMLスキーマ検証をサポートするためにXMLプラグインが含まれています(VS code、Notepad++またはEmacs、Visual Studioなど)。 一般的には、テキストとタイポグラフィを編集する際には、タイポグラフィ内の不整合や翻訳の欠落を防ぐために、TouchGFX Designerを使用することをお勧めします。XMLスキーマではこれらを検証できないからです。
TouchGFX Designer以外でのテキスト翻訳(外部トランスレータを使用した翻訳など)の操作をサポートするために、テキスト・データベースからExcelスプレッドシートにテキスト翻訳をエクスポートできる新しいスタンドアロンのツールがテキスト・コンバータに装備されました。 さらに、このExcelスプレッドシートを外部トランスレータと共有できます。 翻訳が更新された場合には、同じツールを使用して、Excelスプレッドシートをテキスト・データベースにインポートできます。 詳細については、「Translations(翻訳)」を参照してください。
Further reading
テキスト・コンバータ
テキスト・コンバータは、テキスト・データベース内の情報を、TouchGFXアプリケーションで使用される内部C++フォーマットに変換するツールです。 このツールは、ビルド・ツールチェーンの統合パートで、アプリケーションの構築時に自動的に実行されます。 テキスト・コンバータは、テキスト・データベース内の翻訳またはテキスト・プロパティが変更された場合、あるいは新しいテキストまたは翻訳が追加された場合に、新しいC++コードのみを生成します。
Note
テキスト・コンバータは、テキスト・データベース内の指定されたすべてのテキストを、TouchGFXで使用されるテキスト・フォーマットに変換します。 このフォーマットはTypedText
と呼ばれるオブジェクトでラップされます。 TouchGFXのTypedText
は、テキスト・コンテンツそのものとテキストのタイポグラフィを組み合わせた実態です。 タイポグラフィには、テキストのフォントとフォント・サイズ、およびフォントのグリフのアンチエイリアシング(なめらか処理)で使用されるピクセルあたりビット数(bpp)が含まれます。
テキスト・コンバータは、generated/texts/include/texts/TextKeysAndLanguages.hpp
というファイルを生成します。 このファイルには、テキスト・データベース内のすべてのテキストを参照するenum(列挙型)のTEXTS
が含まれています。
enum内のすべてのエントリは、テキスト・データベース内の各テキスト・ノードに示されたIDから生成されますが、先頭にT_が付き、大文字に変換されます。 これらの列挙値は、アプリケーション内でTypedTextを初期化するために使用されます。
TextKeysAndLanguages.hpp
には、テキスト・データベース内に存在するすべての言語を指定するenumのLANGUAGES
も含まれています。 命名方法はテキスト・データベース内の言語の列と同じです。
generated/texts/include/texts/TextKeysAndLanguages.hpp
/* DO NOT EDIT THIS FILE */
/* This file is autogenerated by the text-database code generator */
#ifndef TEXT_KEYS_AND_LANGUAGES_HPP
#define TEXT_KEYS_AND_LANGUAGES_HPP
typedef enum {
GB,
DE,
NUMBER_OF_LANGUAGES
} LANGUAGES;
typedef enum {
T_TEMPERATURE_READOUT,
T_TEMPERATURE_HEADLINE,
NUMBER_OF_TEXT_KEYS
} TEXTS;
#endif /* TEXT_KEYS_AND_LANGUAGES_HPP */
Translations(翻訳)
このセクションでは、テキスト翻訳をエクスポートおよびインポートするときのワークフローについて簡単に説明します。
ここでは、開発者がテキストを含むアプリケーションを作成し、そのテキストを複数の異なる言語に翻訳する必要があるというシナリオについて考えてみます。 開発者は外部のトランスレータを使用するので、テキストをエクスポートして、トランスレータに送信できるようにする必要があります。
テキストをエクスポートするために開発者は、touchgfx/framework/tools/textconvert/translations.rb
にある新しいツールを使用します。 このツールはTouchGFX環境で実行できます。 引数なしでツールを実行すると、以下のヘルプ・テキストが出力されます。
$ translations.rb
Export and import the text database for translation using e.g. Excel
Usage: translations.rb {export|import} assets/texts/texts.xml translations.xlsx [language]*
Export: Will create the "translations.xlsx" by extracting the texts for
all languages from the given assets/texts/texts.xml
Import: Will merge the text translations from "translations.xlsx" into
the given assets/texts/texts.xml. Only the actual texts are
imported, not alignment and text direction.
If no languages are specified, all languages will be handled,
otherwise only the specified languages are imported/exported.
すべての言語をエクスポートするには、以下を実行します。
$ translations.rb export assets/texts/texts.xml translations.xlsx
特定の言語(英語、フランス語、アラビア語など)をエクスポートするには、以下を実行します。
$ translations.rb export assets/texts/texts.xml translations.xlsx English French Arabic
次に、Excelスプレッドシートtouchgfx/framework/tools/textconvert/translations.xlsx
をトランスレータと共有できます。次の例を参照してください。
Note
TouchGFX Designer内の対応するTexts View。
翻訳が完了して開発者に戻されたら、その翻訳をテキスト・データベースにインポートできます。
すべての言語をインポートするには、以下を実行します。
$ translations.rb import assets/texts/texts.xml translations.xlsx
特定の言語(フランス語、アラビア語など)をインポートするには、以下を実行します。
$ translations.rb import assets/texts/texts.xml translations.xlsx French Arabic
テキスト・データベースがこれらの翻訳に更新されます。
推奨事項
翻訳用テキストのエクスポートと再インポートは、テキスト・データベースの同じベースライン上で実行する必要があります。この方法により、インポート・プロセスで発生する可能性がある競合を回避できます。 Gitなどのバージョン管理システムを使用する場合は、エクスポートする前に"branch"を作成し、翻訳完了後にそのテキスト翻訳でこの"branch"を更新して、最終的にこの"branch"をメインの"branch"にマージします。
下の図は、アラビア語とフランス語の翻訳が翻訳"branch"にインポートされ、メイン"branch"にマージして戻された例を示しています。 ここでは、翻訳"branch"での作業の実行中に、メイン"branch"のテキスト・データベースに変更を加える場合には、細心の注意が必要であることが示されています。マージ競合が発生するからです。
マージ競合が発生するのは、以下のような場合です。
- メイン"branch"でテキスト・データベース内のテキストIDを削除
- メイン"branch"でテキスト・データベースにテキストIDを追加
- メイン"branch"でテキスト・データベース内のテキストIDの名前を変更
フォント・コンバータ
フォント・コンバータは、フォント・ファイル内の情報とテキスト・データベース内の情報を結合し、アプリケーションで必要とされる文字を生成するツールです。 出力フォーマットは、TouchGFXアプリケーションで使用される内部C++フォーマットです。 このツールは、ビルド・ツールチェーンの統合パートで、シミュレータの構築時に自動的に実行されます。
フォント・コンバータは以下のフォーマットが利用できます。
- TrueType(.ttf)
- OpenType(.otf)
- Glyph Bitmap Distribution Format(.bdf)
Note
フォントは単純にassets/fonts/
フォルダ内に配置され、TouchGFX Designerで参照できるようになります(TouchGFX Designerの実行中にフォントが追加された場合、再起動して使用可能なフォントを更新する必要があります)。
TouchGFX Designerでは、Windowsにインストールされたフォントも使用することができます。これらのフォントを選択すると、自動的にassets/fonts/
フォルダに追加されます。
フォント・コンバータは、提供されたフォント内のカーニング情報を使用することでカーンニングをサポートします。
Note
文字メモリ最適化
TouchGFXはメモリ消費量を少なくするために最適化されています。 特定のタイポグラフィに使用される文字の解析によって、生成される文字数(内部C++フォーマット)は、アプリケーションで実際に使用される文字数まで最小化されます。
テキストのメモリ消費量も、共通の接尾文字を使用するテキストを圧縮することで最適化されます。このためには、Text Configurationでテキストの再配置を行うオプション(Remap texts)を有効にします。
ワイルドカード
実行時の値をテキストの一部として使用できます。 これはテキスト内でワイルドカードを使用することで可能になります。 これらは<*>
という所定のフォーマットで指定され、*は変換結果のテキストには含まれないオプションの補助テキストを表しています。 1つのテキスト内で最大2つのワイルドカードを使用できます。
特定のテキストのすべての翻訳に、同じ数のワイルドカードを含める必要があります。 ワイルドカードの値は、実行時にアプリケーションのC++コードで挿入されます。
ワイルドカードの使用例: The temperature is <insert_temperature>°
注意すべき詳細事項の1つとして、文字メモリ最適化(前のセクションを参照)のために、特定のタイポグラフィを持つテキスト内では、そのタイポグラフィ用に生成された文字のみが使用されることがあります。 フォント・ジェネレータに特定の文字を強制的に含めるには、各タイポグラフィで"Wildcard Characters"および"Character Ranges"を使用します。
ワイルドカードのフォーマット<*>
は、\<not a wildcard\>のように、バックスラッシュ表記を使用することでエスケープできます。 この例の結果として、アプリケーション内では"<not a wildcard><not a wildcard>"という文字テキストが使用されることになります。
TouchGFX Designerでのワイルドカードの使用
TouchGFX Designerでは、ワイルドカードを通常のテキスト・エリアに追加できます。 事実上、これによってTextAreaウィジェットが、これまでTextAreaWithOneWildcard / TextAreaWithTwoWildcardsウィジェットが対応していた機能を網羅することになりますが、TouchGFXでのコード生成方法に変更はありません。
TouchGFX Designerでは、選択したTextAreaのプロパティで[+]ボタン(Add Wildcard)を単純にクリックすることで、ワイルドカードをテキスト・エリアに追加できます。 対応する[-]ボタンをクリックすると、ワイルドカードを削除できます。 よく使用される例として、The temperature is °と表示されているテキスト・エリアに、読み取った温度を追加することがあります。 この例では、屋外温度の読取りに使用できます。 ここでは、静的な数値を表示するだけでなく、読み取った温度に応じて更新されるようにワイルドカードを挿入してみます。 ワイルドカードは、テキスト内のキャレット(挿入記号)の現在の位置に追加されます。
これでプロパティ内のテキスト表示はThe temperature is <value>°になり、キャンバス上のテキスト表示はThe temperature is °になります。
特定のワイルドカードを設定するには、対応するWildcardボタン(この例ではWildcard 1)をクリックします。これにより、追加したワイルドカードの編集が可能になります。
ここでワイルドカードの更新方法を選択できます。 このためには、事前定義されたリソース・テキストを使用するか、実行時に動的に作成されたテキストを使用します。 どちらの場合も、実行時にテキストを更新できます。 自動生成のテキストを使用するには、[+](Create auto-generated text)をクリックするか、既存のテキストを選択します。 ダイナミック・テキストが必要な場合は、ワイルドカード・バッファを使用します。 このバッファを作成するには、Use wildcard Bufferのチェック・マークをオンにします。 この例では、バッファのサイズ(文字数)を指定する必要もあります。 メモリを効率化するには、指定するサイズを、実際に必要なテキスト・サイズとできる限り近づける必要があります。 文字列の終了を示すために、余分なスペースを1つ追加することを忘れないでください(‘\0’)。
ワイルドカードの初期値を設定することもできます。これにより、温度の読取りによって最終的にテキスト・エリアがどのような表示になるのか確認できます。
ユーザ・コードでのワイルドカードの使用
以下の例に示すように、ワイルドカードはユーザ・コードを使用して追加および更新することもできます。この例ではUnicode::UnicodeChar
配列が管理され更新されています。
gui/include/gui/some_screen/SomeView.hpp
#include <touchgfx/widgets/TextAreaWithWildcard.hpp>
...
class SomeView : public View<SomePresenter>
{
TextAreaWithOneWildcard txt;
Unicode::UnicodeChar txtBuffer[10];
}
gui/src/some_screen/SomeView.cpp
#include <texts/TextKeysAndLanguages.hpp>
void SomeView::setupScreen()
{
txt.setTypedText(TypedText(T_TEMPERATURE_READOUT));
txt.setXY(10, 20);
txt.setWildcard(txtBuffer);
add(txt);
updateTxt(5);
}
void SomeView::updateTxt(int newValue)
{
Unicode::snprintf(txtBuffer, 10, "%d", newValue);
txt.invalidate();
}
テキストの配置
TouchGFXのすべてのウィジェットと同様に、スクリーン上にテキスト・エリアを配置するには、位置(XおよびY)と寸法(幅および高さ)を指定します。 これはTouchGFX Designerのウィジェットのプロパティで簡単に実行できますが、TouchGFX Designerにおけるテキストの描画は、TouchGFXでテキストを描画する方法と比べると、必ずしも100%正確ではありません。
さらに、テキストを処理するときには、このセクションで説明するような注意すべき詳細事項やその可能性がいくつかあります。
アラインメント
テキスト・エリア内のテキストは、テキスト・データベース内の選択したテキスト・エントリに対して指定されているアラインメントに従って配置されます。 テキストはテキスト・エリアの領域を基準にして配置されます。 次のスクリーンショットでは、テキスト・エリアの領域が青色でハイライト表示されています。
これらの設定はTouchGFX DesignerのTexts Viewで行うことができます。
テキスト・エリアの正しい幅と高さの設定
テキスト・エリアでは、現在選択されているテキストに応じて幅と高さを調整することができます。 このためには、TextArea::resizeToCurrentText()
メソッドを読み出して実行します。
Note
中央揃え / 右詰めのテキストを使用する場合は、固定領域内でテキストを中央揃え / 右詰めにする必要があるので、幅や高さのサイズ変更をしないことがほとんどです。 この場合は、幅と高さを手動で設定します。 このためには、TextArea::setPosition(x, y, width, height)
、TextArea::setWidth(width)
およびTextArea::setHeight(height)
を呼び出して実行します。
幅または高さ(あるいは両方)が小さすぎてテキストに適合しない場合には、下に示すように領域に合わせてテキストが切り取られます。
テキスト・エリアの正しいXおよびYの設定
テキスト・エリアを正しいXY位置に配置するには、大きな文字の表示を可能にするために、使用するフォントには文字の上に少し余白が設けられることに注意する必要があります。 このために、左上隅のY位置に従ってテキスト・エリアを配置することが少し難しくなります。テキスト上部のスペースの正確な大きさがわからないからです。 テキストを配置する1つの方法は、ほぼ間違いないと思われる位置を指定し、その後シミュレータで配置を調べて位置を微調整することです。 ほとんどの場合この方法は非常に単純な作業ですが、フォントまたはフォント・サイズを後で変更する場合には再実行の必要があります。
もっと堅実な方法として、テキスト・ベースラインの使用があります。 ベースラインとは、ほとんどの文字の「お尻が揃う」位置を示すラインで、その下にディセンダ(pやjなどの文字)が延びます。
ベースラインを設定するには、TextArea::setBaselineY(y)
またはTextArea::setXBaselineY(x, y)
を使用します。 これらのメソッドでは、テキスト・エリアの左上隅を指定するのではなく、最初のテキスト行のベースラインを指定します。 これによりフォント・サイズとスペースの大きさが考慮され、それに応じてテキスト・エリアのY位置が設定されます。
ベースライン機能はTouchGFX Designerでは使用できません。TextAreaウィジェットの配置はTouchGFX Designerのキャンバスで簡単に実行できるからです。このため、ベースライン機能はユーザ・コードでのみ使用されます。
Note
長いテキスト行の自動ラップ
場合によっては、テキスト・エリアに非常に長いテキストを含むことがあります。 デフォルトでは、こうしたテキストは単純に1行で記述され、テキスト・エリア内に収まらないテキストはすべて単純に切り取られます。 テキストを単語間でラップして(折り返して)リフローさせ、複数の行で表示する必要がある場合は、単純に次のコマンドをコールして、Wide Text Actionを設定します。
myTextArea.setWideTextAction(WIDE_TEXT_WORDWRAP); // Default is WIDE_TEXT_NONE
文字列全体を出力するための十分な領域がない場合には、TouchGFXで特殊文字(…など)を追加することもできます。 これは省略記号と呼ばれます。
使用可能なWide Text Action
多様なWide Text Actionを使用できます。
WIDE_TEXT_NONE
: 何も実行せず、テキスト・エリアの幅を越えて延びる文字の半ばで単純にテキストを切ります。 これはデフォルトのアクションです。WIDE_TEXT_WORDWRAP
: 単語間で次の行にラップします。省略記号は追加しません。WIDE_TEXT_WORDWRAP_ELLIPSIS
: 単語間で次の行にラップし、任意の場所に省略記号を表示します("Very long t...")。WIDE_TEXT_WORDWRAP_ELLIPSIS_AFTER_SPACE
: 単語間で次の行にラップし、スペースの後の任意の場所に省略記号を表示します("Very long ...")。WIDE_TEXT_CHARWRAP
: 任意の2文字間で次の行にラップします。省略記号は追加しません。WIDE_TEXT_CHARWRAP_ELLIPSIS
: 任意の2文字間で次の行にラップし、任意の場所に省略記号を表示します(中国語で使用)。WIDE_TEXT_CHARWRAP_DOUBLE_ELLIPSIS
: 任意の2文字の間でラップし、任意の場所に省略記号を二重に表示します(中国語で使用)。
Further reading
おそらくこれによってテキスト・エリアには縦方向のスペースが多く必要になります。 縦方向のスペースを増やすには、Designerでテキスト・エリアの高さを増すか、次のようなユーザ・コードを使用します。
myTextArea.setWidth(200);
myTextArea.resizeHeightToCurrentText(); // Will set height by wrapping text at 200px long lines
myTextArea.invalidate();
テキスト・エリアのサイズを小さくする場合には、myTextArea
のサイズを変更する前にmyTextArea.invalidate()
を呼び出すことを忘れないでください。 そうしないと、新しい小さくなったテキスト・エリアではカバーされない古いテキスト・エリアの一部が表示されたままになるからです。
省略記号の設定
WIDE_TEXT_NONE
とは異なるWide Text Actionを選択し、省略記号を表示したい場合には、選択した文字またはUnicode番号をDesignerで指定して、その省略記号をフォントに含める必要もあります。
Unicode 0x2026は、標準の横方向の省略記号です。
言語の切替え
TouchGFXは多言語インタフェースをサポートしています。 インタフェースで使用されている現在の言語は、スタティック・メソッドTexts::setLanguage
を呼び出すことで変更できます。
Texts::setLanguage(GB);
GB値は、The Text Converterセクションの例に示すように、TextKeysAndLanguages.hpp
のLANGUAGES
enum(列挙型)の中にあります。
この呼出しの後、テキストを表示するすべてのウィジェットを無効化(または単純にスクリーン全体を無効化)すると、新しく選択した言語でテキストが表示されます。
TouchGFX Designerでの操作
言語間を切り替えて、すべての翻訳をテストできます。 この操作はConfig ViewのGeneralセクションで行います。 ここでは単純に、Selected Languageを変更してアプリケーションの起動言語を変更します。