跳轉到主要內容

文字和字體

文字和字體是新式圖形化使用者介面的一個十分重要的方面。 必須能夠以應用支援的所有語言顯示高品質抗鋸齒文字。

TouchGFX支援通過TouchGFX Designer的文字視圖創建和修改文字和字體排印。 TouchGFX Designer將文字和字體排印配置輸出到資料庫(位於assets/texts/texts.xml)。 將此資料庫與字體檔一起輸入字體和文字轉換器工具,輸出生成的TouchGFX可渲染的C++程式碼檔。

本文介紹文字和字體轉換器工具,並說明如何通過程式碼和TouchGFX Designer使用在應用中生成的文字。

文字和字體排印

TouchGFX應用中的文字和字體排印存儲在assets/texts/texts.xml資料庫中。 該資料庫包含應用中使用的帶有翻譯的文字和字體排印。 此資料庫通常被稱為“文字資料庫”。

文字和排版可以在TouchGFX Designer中通過文字視圖進行編輯,這使編輯變得簡單和方便。

但是,可以在texts.xml中直接編輯字體排印和文字;為了輔助編輯,為validation assets/text /text.xsd提供了一個XML模式。 許多已知的文字編輯器都通過XML外掛程式支援XML模式驗證,例如VS code、notepad++、或Emacs、Visual Studio。 通常建議在編輯文字和字體排印時使用TouchGFX Designer,以避免字體排印的不一致和翻譯缺失,這是XML模式無法驗證的。

為了支援在TouchGFX Designer之外進行文字翻譯(例如使用外部翻譯工具進行翻譯),文字轉換器現在配有新的獨立式工具,允許從文字資料庫匯出文字翻譯到Excel試算表。 該Excel表格可以與外部翻譯工具共用。 當翻譯更新後,可以使用相同的工具將Excel試算表重新導入文字資料庫。 詳細瞭解翻譯相關事宜。

Further reading
如需獲取關於如何創建和編輯字體排印、文字、翻譯檔和語言的更多資訊,請轉至文字視圖

文字轉換器

文字轉換器是將文字資料庫中的文字資訊轉換為TouchGFX應用使用的內部C++格式的工具。 該工具是構建工具鏈不可或缺的一部分,將在構建應用時自動執行。 只有在文字資料庫中的翻譯或文字屬性被修改或添加了新的文字或翻譯之後,文字轉換器才會生成新的C++程式碼。

Note
文字轉換器的輸出目錄為generated/texts/。

文字轉換器將文字資料庫中的所有指定文字轉換為TouchGFX使用的文字格式。 格式被封裝成名為TypedText的對象。 TouchGFX中的TypedText是文字內容本身與文字字體排印的組合實體。 字體排印包含文字的字體和字型大小,以及字體字形抗鋸齒時使用的每一像素位元數(bpp)。

文字轉換器生成名為generated/texts/include/texts/TextKeysAndLanguages.hpp的文件。 此檔包含引用文字資料庫中所有文字的枚舉TEXTS

請注意,枚舉中的所有條目均生成自文字資料庫每個文字節點中規定的ID,但具有前置的T_並轉換成大寫字母。 應用中使用這些枚舉值初始化TypedText。

TextKeysAndLanguages.hpp還包含枚舉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 */

翻譯

本節簡要介紹匯出和導入文字翻譯時的工作流程。

考慮這樣一個場景:開發人員創建了一個包含文字的應用程式,這些文字需要翻譯成多種不同的語言。 開發人員使用外部翻譯工具,需要匯出文字,然後發送給翻譯工具。

為了匯出文字,開發人員使用位於touchgfx/framework/tools/textconvert/translations.rb的新工具。 該工具可以在TouchGFX環境中運行。 運行不帶任何參數的工具,將列印以下説明文字:

$ translations.rb
使用Excel等工具匯出和導入文字資料庫,以進行翻譯

用法:translations.rb {export|import} assets/texts/texts.xml translations.xlsx [language]*

匯出:將創建“translations.xlsx” ,方法是
從給定的assets/texts/texts.xml提取所有語言的文字

導入: 將文字翻譯從“translations.xlsx” 合併到給定的assets/texts/texts.xml。 只導入實際文字
不導入對齊和文字方向。

如果未指定語言,將處理所有語言,否則只導入/匯出指定的語言

如需匯出所有語言:

$ 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 可以與翻譯工具共用,請參見下面的範例。

Excel試算表 - 空白的翻譯

Note
  • 語言必須添加在TouchGFX設計器中,而不是Excel試算表中。
  • 字體排印、對齊和方向必須在TouchGFX Designer(而不是Excel試算表)中設置。
  • 只有包含翻譯的儲存格才會解鎖,以便在Excel試算表中進行編輯。
  • TouchGFX Designer中對應的文字視圖。

    文字視圖 - 空白的翻譯

    當翻譯完成並返回給開發人員時,可以將它們導入文字資料庫。

    Excel試算表 - 更新後的翻譯

    如需導入所有語言:

    $ translations.rb import assets/texts/texts.xml translations.xlsx

    如需導入指定語言,例如法語和阿拉伯語:

    $ translations.rb import assets/texts/texts.xml translations.xlsx French Arabic

    現在,文字資料庫中的翻譯已經更新。

    文字視圖 - 更新後的翻譯

    建議

    匯出文字用於翻譯,然後再次導入,應該在文字資料庫的同一基線上進行,這樣可以避免導入過程中的潛在衝突。 如果你使用版本控制系統(例如Git),建議在匯出之前創建一個分支,然後在匯出完成後用文字翻譯更新該分支,最後將該分支合併回主枝。

    下圖顯示了一個範例,範例中將阿拉伯語和法語翻譯導入到翻譯分支,然後合併回主枝。 範例還展示了:在翻譯分支上進行工作的同時,對主枝上的文字資料庫進行更改時應該小心,因為會出現合併衝突。

    分支範例

    合併衝突會在這些情況下出現:

    • 刪除主枝上文字資料庫中的文字ID時
    • 在主枝上的文字資料庫中添加文字ID時
    • 對主枝上文字資料庫中的文字ID進行重命名時

    文字轉換器

    文字轉換器是將字體檔中的資訊與文字資料庫中的資訊進行組合並生成應用需要的字元的工具。 輸出格式是TouchGFX應用使用的內部C++格式。 該工具是構建工具鏈不可或缺的一部分,將在構建模擬器時自動執行。

    文字轉換器接受

    • TrueType (.ttf)
    • OpenType (.otf)

    只需將字體放在assets/fonts/資料夾中,TouchGFX Designer就可以引用該字體(如果在TouchGFX Designer運行時添加字體,必須重啟軟體才能更新可用字體)

    在TouchGFX Designer中,還可以使用Windows作業系統中安裝的字體,選擇這些字體中的任何字體,它們就會被自動添加到assets/fonts/資料夾

    字體轉換器使用提供的字體中的字距調整資訊進行字距調整。

    Note
  • 使用TouchGFX並不以任何形式提供任何TrueType、OpenType或Bitmap字體的商業使用許可。
  • 字體轉換器的輸出目錄為generated/fonts/。
  • 字元存儲空間優化

    TouchGFX為減少存儲空間消耗而進行了優化。 通過分析對特定字體排印使用的字元,將生成的字元(內部C++格式)數量最大限度壓縮至應用實際使用的字元。

    另外,通過在文字配置中啟用重新映射文字的選項,壓縮使用常用尾碼的文字,從而優化文字存儲空間消耗量。

    萬用字元

    可將執行時間值作為文字的一部分來使用。 這可以通過在文字中使用萬用字元來實現。 按給定格式<*>指定萬用字元,其中的*表示不會包含在結果文字中的可選輔助文字。 一個文字中可以有至多2個萬用字元。

    給定文字的所有翻譯檔必須包含相同數量的萬用字元。 在執行時間在應用C++程式碼中插入萬用字元值。

    萬用字元使用範例:溫度為 <insert_temperature>°

    要注意的一個細節是,由於字元存儲空間優化(參見上一節),只為特定字體排印生成了採用此字體排印的文字中使用的字元。 為強制字體生成器包含特定字元,您可以對每種字體排印使用“萬用字元字元”和“字元範圍”。

    像下面這樣使用反斜線記號可以避免萬用字元格式<*>\<not a wildcard\>。 這會導致應用中使用原義文字"<not a wildcard>" 。

    在TouchGFX Designer中使用萬用字元

    在TouchGFX Designer中,可以將萬用字元添加到常規TextArea。 現在,儘管TouchGFX中生成程式碼的方式並無變化,但有效地讓TextArea小部件覆蓋了之前被TextAreaWithOneWildcard/TextAreaWithTwoWildcards小部件覆蓋的功能。

    在TouchGFX Designer中,只需點擊“+”按鈕為所選文字區域的屬性添加萬用字元,即可將萬用字元添加到文字區域。 點擊相應的“-”按鈕以刪除萬用字元。 一個熟悉的範例是將溫度讀數添加到TextArea,可顯示為溫度為 °。 這種情況下可能是室外溫度讀數。 下面我們要插入一個萬用字元,不僅顯示靜態數值,還將根據溫度讀數進行更新。 萬用字元會被添加到文字中插入點游標的當前位置:

    將萬用字元添加到Text Area小部件

    現在,屬性中的文字將顯示“溫度為<value>°”,而畫布上的文字顯示“溫度為°”:

    TouchGFX Designer中帶萬用字元的Text Area小部件

    為了設置特定的萬用字元,您可以點擊相應的“萬用字元”按鈕(本例中為萬用字元1),就可以編輯剛才添加的萬用字元。

    在這裡,您可以選擇如何更新萬用字元。 要麼通過預定義資源文字,要麼通過動態執行時間創建的文字。 在兩種情況下,都可以在執行時間更新文字。 要使用自動生成的文字,請點擊“+”創建自動生成文字或選擇現有文字。 如需要動態文字,請使用萬用字元緩衝區。 這樣的緩衝區可通過選中使用萬用字元緩衝區核取方塊來創建。 在這種情況下,還需要指定緩衝區大小(字元數)。 如果想要高效地利用存儲空間,需使指定大小盡可能接近實際需要的文字大小。 記住,為字串結束符(“\0”)增加一個額外空格。

    在TouchGFX Designer中將自動生成的文字添加到萬用字元

    另外,還可以為萬用字元設置初始值,這樣可以看到包含溫度讀數的TextArea的最終外觀:

    TouchGFX Designer中的萬用字元設置

    在用戶程式碼中使用萬用字元

    還可通過用戶程式碼添加和更新萬用字元,如下面的程式碼範例所示,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)和尺寸(寬和高)將TextArea放置到螢幕上。 可以在TouchGFX Designer的小部件屬性中輕鬆做到這一點,但是與TouchGFX渲染文字相比,TouchGFX Designer中的文字渲染並非總是100%準確。

    本節還描述了在處理文字時要注意的更多細節和可能性。

    對齊

    按照為文字資料庫中選中文字條目指定的對齊方式對齊TextArea中的文字。 文字對齊是就TextArea的區域而言。 在下面的螢幕截圖中,TextArea的區域highlighte顯示為藍色。

    左對齊文字

    中心對齊文字

    右對齊文字

    這些設置可以在TouchGFX Designer的文字視圖中進行設置。

    字型大小

    如前所示,TouchGFX僅包含應用程式所需字型的字元。 依據此項選擇,TouchGFX會計算字元的字型高度及放置(稱為基準線)。 字型高度是使用字型文字行的像素高度, 基準線是在該行的字母放置。

    如果在執行階段有需要,以下屬性可透過Font(字型)類別提供使用:

    個別字元(字符)大小可使用GlyphNode結構體的方法找到:

    字符高度是指繪製字符時使用的像素列數。 頂端是指基準線上方行數,應在此處繪製字符。 請注意字符可能在基準線上方(例如「^」)或下方(例如「g」)。

    以下是我們在TouchGFX Designer以大小100px使用Verdana的範例。 應用程式只在螢幕上寫出文字「Ac」:

    以大小100使用Verdana寫出Ac。

    綠線顯示基準線的位置。 字型高度為101像素。 基準線位置為100。 「A」的大小為 73. 頂端也是73, 因此「A」會靠在基準線上。 「c」的高度為57,頂端為56, 因此「c」的繪製位置會比「A」再低一行。 以上數值是Verdana字型設計的一部分。

    以下是另一個範例,我們使用了相同字型,但應用程式現在於螢幕寫出「Acg」文字:

    以大小100使用Verdana寫出Acg。

    在應用程式納入「g」改變字型。 字型高度目前為121,但基準線位置仍為100。 因此行的範圍擴大,以便有空間可以容納「g」(垂吊在行下方),但「A」和「c」則與之前一樣以垂直方式放置。 「g」的高度為77,但頂端僅為56,因此有21行像素落在基準線下方。

    我們已經發現TouchGFX之中的字型高度,需視其中包含的字母而定。 個別字元是以相對於字型基準線的方式放置。

    設置TextArea的正確寬度和高度

    TextArea能夠根據目前選擇的文字調整其寬度和高度。 這是通過呼叫TextArea::resizeToCurrentText()方法來完成的。

    Note
    `resizeToCurrentText()`會被自動呼叫,前提是在產生實體具有新TypedText的TextArea時沒有設置寬度和高度。

    在使用中心/右對齊文字時,通常不希望調整寬度和高度,因為文字需要在固定區域內實現中心/右對齊。 在這種情況下,可以手動設置寬度和高度。 這可以通過呼叫TextArea::setPosition(x, y, width, height)TextArea::setWidth(width)TextArea::setHeight(height)來完成。

    如果寬度或高度過小,無法容納文字,將按照區域剪切文字,如下圖所示。

    被TextArea小部件邊界框剪切掉的文字

    為TextArea設置正確的X和Y值

    為了將TextArea放在正確的X和Y位置,需注意使用的字體的字元上方會有一些額外的間隔,可以容納大字元。 由於不知道文字上方的具體間隔,使得根據左上角的Y位置放置TextArea變得有點困難。 放置文字的一種方式是指定您認為它應當處於的位置,然後通過在模擬器中檢查放置效果來進行微調。 這通常是一項十分簡單的任務,但如果之後更改字體或字型大小,則需要重新執行。

    一種更穩健的方式是使用文字基線。 基線是一條線,大多數字母“坐”在基線上,而下行字母(像p和j這樣的字元)會延伸到基線之下。

    文字基線

    為了設置文字基線,可使用TextArea::setBaselineY(y)TextArea::setXBaselineY(x, y)。 對於這些方法,不指定TextArea的左上角,而是指定第一個文字行的基線。 這會考慮字型大小和間距,並相應地設置TextArea的Y位置。

    由於通過TouchGFX Designer畫布可以輕鬆地放置TextArea小部件,因此TouchGFX Designer中沒有基線功能,只能在用戶程式碼中使用。

    Note
    由於setBaselineY依賴於字體,TextArea需在呼叫setBaselineY之前設置其TypedText。 另外還要注意,如果將TextAreas TypedText修改為採用其他字體或字型大小,則需要再次呼叫setBaselineY。

    長文字的自動換行

    TextArea有時需要包含極長的文字。 預設情況下,只需將此類文字寫成一行,並直接將超出TextArea的所有文字剪切掉。 如果文字應在空格處自動換行並回流以便形成多行,只需呼叫:

    myTextArea.setWideTextAction(WIDE_TEXT_WORDWRAP); // Default is WIDE_TEXT_NONE

    如果沒有足夠的可用空間列印完整字串,TouchGFX也可新增特殊字元(例如)。 這稱為省略符號字元。

    可用寬文字操作

    • WIDE_TEXT_NONE:非自動,只需從超出TextArea寬度的任何字元的中間切割文字。
    • WIDE_TEXT_WORDWRAP:在字之間換行,無省略號字元。
    • WIDE_TEXT_WORDWRAP_ELLIPSIS:在字之間換行,於最後一個可見字母之後插入省略號字元,例如「Very long t...」。
    • WIDE_TEXT_WORDWRAP_ELLIPSIS_AFTER_SPACE:在字之間換行,只在空格後插入省略號「Very long ...」。
    • WIDE_TEXT_CHARWRAP:在任意兩個字元之間換行,無省略號(如中文用法)。
    • WIDE_TEXT_CHARWRAP_ELLIPSIS:在任何兩個字元之間換行,於最後一個可見字母之後插入省略號字元(如中文用法)。
    • WIDE_TEXT_CHARWRAP_DOUBLE_ELLIPSIS:在任意兩個字元之間換行,在最後一個可見字母之後插入雙省略號(如中文用法)。

    以下圖像顯示不同的換行模式:

    WORDWRAP - WORDWRAP_ELLIPSIS - WORDWRAP_ELLIPSIS_AFTER_SPACE.

    CHARWRAP - CHARWRAP_ELLIPSIS - CHARWRAP_DOUBLE_ELLIPSIS

    這可能會使TextArea需要更多垂直空間。 您可在Designer中增加TextArea高度,或是在使用者程式碼中處理,方法如下:

    myTextArea.setWideTextAction(WIDE_TEXT_WORDWRAP);
    myTextArea.setWidth(200);
    myTextArea.resizeHeightToCurrentText(); // Will set height by wrapping text at 200px long lines
    myTextArea.invalidate();

    如果您準備縮小文字區的尺寸,記得在調整 myTextArea 尺寸之前呼叫myTextArea.invalidate()。 如果沒有,由於原文字區未被更小的新文字區覆蓋,因此您會看到它的一部分。

    設定省略符號字元

    如果您選擇的寬文字動作與WIDE_TEXT_NONE不同,且您想要使用省略符號字元,就必須在字型中納入省略符號字元,方法是在Designer中指定選定字元或Unicode數字:

    為字型設定省略符號字元

    Unicode 0x2026為標準的水平省略符號。

    Text Indentation

    The TextArea widget supports indentation of a text. The amount of indentation can be set by calling TextArea::setIndentation.

    The image below shows two TextAreas showing the same text. The second TextArea uses an indentation of 20 pixels.

    TextArea with indentation of 20 pixels

    The code below shows how to set the indentation. The setting is unfortunately not available in the Designer.

    void Screen1View::setupScreen()
    {
    Screen1ViewBase::setupScreen();
    textArea2.setIndentation(20);
    }

    手動換行

    您也可以在文字中插入手動換行(ASCII/Unicode字元10)。 此字元可讓TextArea變更至下一行,不受WideTextAction設定影響。

    在XML之中請編寫新行為「&#10;」。 例如:

    <Text Id="__SingleUse_1VW7" Alignment="Left" TypographyId="Default">
    <Translation Language="GB">New&#10;Text&#10;On 3 lines.</Translation>
    </Text>

    這樣會產生:

    New
    Text
    On 3 lines.

    切換語言

    TouchGFX支援多語言介面。 可以更改介面當前使用的語言,方法是呼叫靜態函數Texts::setLanguage:

    Texts::setLanguage(GB)

    GB位於LANGUAGES枚舉(位於TextKeysAndLanguages.hpp中)中,如“文字轉換器”一節中的範例所示。

    此次呼叫後,使所有顯示文字的小部件無效(或簡單地使整個螢幕無效),它們將以新選擇的語言顯示文字。

    TouchGFX Designer中

    您可以在不同語言之間切換,以便測試所有翻譯檔。 可從配置視圖的常規部分執行此操作。 這裡只需更改應用的啟動語言,方法是更改選中語言