跳轉到主要內容

字體快取

本節描述如何使用字體快取處理TouchGFX中的二進位字體。

請先閱讀二進位字體的相關內容。

字體快取

注意,使用二進位字體需要將整個字體載入到記憶體。 在某些情況下,如果字體很大,如大字型中文字體,則這樣做可能不可行。

字體快取使應用能夠只從外部記憶體載入顯示字串所需的字母。 這意味著整個字體無需駐留在可定址快閃記憶體或RAM上,而是可以保存在更大的檔案系統上。

在下圖中,內編譯字體Font2已被字體快取替代。 當TouchGFX使用Font2繪製文字時, TouchGFX會找到指向字體表中CachedFont的指標。 此特殊字體將查找FontCache物件中的字母。

使用快取字體

CachedFont設置了指向內連字體(上面的Font2)的指針。 當TouchGFX要求CachedFont提供特殊字母時,cachedFont將首先查找它替代的普通字體(Font2)。 該字體可能是空字體,但也可能是包含一些常用字母的“普通”字體。 如果字體不包含需要的字母,FontCache將查找FontCache,以便確定是否已從檔案系統載入了字母。

由於無需快取正常字體中已有的字母,此原則限制了必須快取的字母數量。

在應用程式碼中使用字體快取

必須先創建FontCache、記憶體緩衝區和檔案系統閱讀器物件,然後應用才能安裝CachedFont:

Screen1View.cpp
uint8_t fontdata[5120]; //Memory buffer for the font cache, 5Kb
FontCache fontCache;
CachedFont cachedFont; //Cached Font object
FileDataReader reader; //Filesystem reader object

FontCache必須連結到緩衝區和閱讀器:

Screen1View.cpp
//setup the font cache with buffer and size; and file reader object
fontCache.setMemory(fontdata, 5120);
fontCache.setReader(&reader);

現在,應用可以設置字體快取,初始化CachedFont並將它傳遞給TouchGFX。

字體快取需要用TextId來初始化CachedFont物件。 TextId用於查找CachedFont必須指向的字體。 這確保您替換的是顯示器上的文字使用的字體:

Screen1View.cpp
//initialize the cachedFont object to the font used by T_SINGLEUSEID1
TypedText text = TypedText(T_SINGLEUSEID1);
fontCache.initializeCachedFont(text, &cachedFont);

//replace the linked in font in TouchGFX with cachedFont
TypedTextDatabase::setFont(DEFAULT, &cachedFont);

以上程式碼可以放在應用中的任何位置。 如果快取字體只用在特定視圖中,此視圖可能是插入程式碼的理想位置。

快取字母

字體快取仍然為空。 必須先從字體快取讀取字母,然後才能顯示字母。 這是通過將unicodes(字串)陣列傳遞到字體快取來完成的。 在本例中,我們只從T_SINGLEUSEID1傳遞文字。

Screen1View.cpp
//cache the glyphs used by the text T_SINGLEUSEID1
Unicode::UnicodeChar* str = const_cast<Unicode::UnicodeChar*>(text.getText());
bool b = fontCache.cacheString(text, str);

字體緩存將通過閱讀器對象載入在str陣列中找到的字母。 讀取的unicodes將連結到TextId text參數使用的字體。

此應用負責配置要從正確的檔案載入的閱讀器物件。

緩存連字

對於在顯示前將unicodes序列轉換為其他unicodes的語言(如阿拉伯語),以上方法不適合。 它快取原始unicodes 而不是轉換後顯示的unicodes 。 此方法將轉換給定unicodes 並快取需要的unicodes (轉換後):

Screen1View.cpp
//cache the glyphs used by the text T_SINGLEUSEID1 after conversion
Unicode::UnicodeChar* str = const_cast<Unicode::UnicodeChar*>(text.getText());
bool b = fontCache.cacheLigatures(cachedFont, text, str);

記憶體使用

字體快取可以計算當前記憶體使用量:

Screen1View.cpp
touchgfx_printf("Memory usage %d\n", fontCache.getMemoryUsage());

快取GSUB表

在渲染時,一些字體使用GSUB表。 這只是東方語言的幾種字體,如天城體字體。 GSUB表使字體系統能夠重新排列字元並用字元序列代替其他“組合”字元。

字體快取可以從檔案系統載入此GSUB表。 如未載入,則文字渲染系統無GSUB表可用,將無法正確顯示字體。

在初始化快取字體時,通過提供額外參數載入GSUB表:

Screen1View.cpp
//initialize the cachedFont and load the GSUB table
text = TypedText(T_SINGLEUSEID1);
fontCache.initializeCachedFont(text, &cachedFont, true);

實現字體檔閱讀器

TouchGFX不包含以上範例程式碼中使用的FileDataReader類,它取決於使用的作業系統。

下面是普通“stdio”相容檔案系統的一個範例。

Screen1View.cpp
class FileDataReader : public FontDataReader
{
public:
virtual ~FileDataReader() { }
virtual void open()
{
fp = fopen("Font_verdana_20_4bpp.bin", "rb");
if (!fp)
{
touchgfx_printf("Unable to open font file!!!\n");
}
}
virtual void close()
{
fclose(fp);
}
virtual void setPosition(uint32_t position)
{
fseek(fp, position, SEEK_SET);
}
virtual void readData(void* out, uint32_t numberOfBytes)
{
fread(out, numberOfBytes, 1, fp);
}
private:
FILE* fp;
};

FileDataReader類從FontCache.hpp實現FontDataReader介面:

FontCache.hpp
class FontDataReader
{
public:
virtual ~FontDataReader() { }
virtual void open() = 0;
virtual void close() = 0;
virtual void setPosition(uint32_t position) = 0;
virtual void readData(void* out, uint32_t numberOfBytes) = 0;
};