跳轉到主要內容

點陣圖字型壓縮

TouchGFX 從版本 4.25 開始支援點陣圖字型壓縮。

點陣圖字型壓縮功能 允許將 4 BPP 的點陣圖字型壓縮。 目標是減少字型資料的大小, 同時保持渲染效能。

It is very simple to enable font compression in TouchGFX Designer. 只要選擇「4-壓縮」 作為 Designer 排版的「Bpp」即可。

選擇壓縮的 4 BPP

兩類應用程式可以受益於此: 包含數千種字元 (例如中文字) 的應用程式,或使用特大字體的應用程式。 這些應用程式可以獲得很大的效能提升。 相較之下,僅使用 20 號英文字的應用程式不會省下太多位元組空間, 因為字型資料本來就不大。

壓縮率取決於字的大小和字型大小。 小字型的壓縮效果比大字型差。 您可以預期壓縮率 從原先的 30% 提高到 70%。

在繪製之前,字元被解壓縮到快取緩衝區中。 如果字元不在快取中,我們在渲染前必須付出解壓縮的成本。 使用的壓縮演算法 (運行長度類型) 非常 易於解壓縮,因此通常不會出現問題。 如果字元已經在快取中,渲染的效能將會比正常情況好一點, 因為從 SRAM 渲染比從外部快閃記憶體快。 快取大小可以在 Designer 中設定, 詳見下文。

如果您多次繪製同一個字 (因為它在文字中重複,或因為文字為動畫或滾動的一部分而重新繪製),許多情況下快取會省去解壓縮的成本。

Note
快取大小必須足夠大, 以容納您正在繪製的文字。

如果快取不夠大,應用程式將停止運作。

請參閱 [此處] (#font-configuration) 的說明。

如果平台提供硬體加速繪圖, 也會使用使用壓縮字型。

壓縮字型的替代方案是向量字型。 使用超過一種大小時,這類字型通常比壓縮字型小, 但更加耗用效能。

點選此處進一步瞭解向量字型。

效能​

在本節中,我們將檢視使用大量中文字和包含大量數字的應用程式。

對於第一個範例,我們將使用 28 號的 NotoSansCJKsc-Black.otf 建立字型, 其中涵蓋 0x4E00 到 0x5E00 的字元範圍 (加上文中額外使用的字元)。 因此,我們共有 4165 個字元。 真正的中文應用程式 當然可能包括甚至更多字元。

應用程式顯示包含 24 個字元的文字:

28 號的中文字

第二個應用程式使用 40 號和 140 號的 Verdana 字型:

40 號和 140 號的 Verdana 字型

我們將檢查字型資料的大小和繪製字元的表現。

字型資料大小​

下表顯示字型資料大小 (以位元組為單位):

字型大小字元數未壓縮大小壓縮大小儲存壓縮率
NotoSansCJKsc-Black.otf284,1161,568,599917,170651,4291.7
Verdana.ttf409527,36912,78914,5802.1
Verdana.ttf1401140,4088,21132,1974.9

我們看到壓縮後的中文字元節省了 超過 0.5 MB 的資料。 這會足夠大,足以減少外部快閃記憶體大小, 進而降低 BOM 成本。

Verdana 字型的壓縮並沒有節省同樣多的位元組空間, 即使壓縮率較高。 主要是因為相較之下字元數量少太多。
兩種 Verdana 字型的資料總和低於 22Kb。 這表示字型資料 可以容納在極小型裝置的內部快閃記憶體中。

如果我們將 Noto 字型生成為向量字型, 則字型資料的大小為 1,509,236 位元組。 這比未壓縮的字型大小略小, 但大於壓縮的點陣圖字型。 當您使用多個字型大小的向量字型,向量字型可以省下許多空間, 因為所有字型大小都共享同樣的資料。

渲染​

我們現在要來檢查渲染壓縮字元的效能。 我們將瞭解到快取大小很重要。 如果應用程式重複繪製相同的字元,並且快取夠大足以容納它們, 效能會接近未壓縮的字型, 有時甚至更好。

我們將從中文應用程式和 10,000 位元組的快取大小開始。 這足以容納所有使用的字元。

我們測量重新繪製整個螢幕 (包括背景影像) 的渲染時間。

測試快取大小渲染時間/毫秒
背景影像-5.28 ms
未壓縮的 Noto-7.57 ms
壓縮的 Noto100007.55 ms
壓縮的 Noto50009.41 ms
壓縮的 Noto20009.42 ms

保存所有顯示字元的快取要求約為 8000 位元組。 如果快取大於此值, 且字元已經在第一個影格解壓縮, 渲染時就無需在所有未來影格中再次解壓縮。 當快取較小時 (5,000 或 2,000 位元組), 我們必須反覆解壓縮,因為快取不夠大, 無法保存所有字元。 效能雖然較低,但仍勘用。

我們現在來看看第二個應用程式。 這次只有大號字會在每一個影格都重新繪製。 大小大約為 4,000 位元組, 因此 10,000 位元組的快取 足以容納兩種字型大小。 舉例而言,5000 位元組的快取只能容納一個字元, 需要反覆解壓縮。

測試快取大小渲染時間/毫秒
背景影像-1.44 ms
未壓縮的 Verdana-2.46 ms
壓縮的 Verdana100002.45 ms
壓縮的 Verdana50003.57 ms

我們再次看到,如果快取夠大,效能就會維持不變, 但我們會有其他的效能折損。

最後一個範例,我們將使用一個更「人造」的應用程式,顯示很多「A」字元:

40 號 Verdana 文字

測試快取大小渲染時間/毫秒
背景影像-5.19 ms
未壓縮的 Verdana-16.51 ms
壓縮的 Verdana1000016.45 ms
壓縮的 Verdana100016.46 ms

所有設定下的效能都相同。 由於我們僅繪製單個字元「A」, 只需要非常小的快取就已足夠。

快取必須足夠大, 才能容納影格中繪製的唯一字元。 在此情況下,只有「A」。

結論​

綜上所述, 如果快取保存了影格中繪製的字元, 壓縮字型的效能與未壓縮的字型相同。 換言之,如果快取足夠大, 壓縮字型可以用於動畫和滾動文字。

如果快取不夠大, 解壓縮字元的效能損失不大。 也就是說,即使快取大小不大,壓縮字型可以用於處理靜態文字,不會有顯著的效能問題。

設定​

As mentioned in the introduction font compression is enabled by selecting it on the individual Typographies in TouchGFX Designer. 應用程式會自動包含必要的解壓縮程式碼。

快取大小​

The cache size can be configured in TouchGFX Designer. 選擇設定分頁中的 「文字設定」:

123

設定快取大小。

If the cache is smaller than required by the largest compressed letter TouchGFX Designer will report an error in the log:

當快取不夠大時的錯誤輸出。

將字型快取變更為大於報告的數字。

字型檔案顯示繪製字型中所有字元所需的最小快取大小。 詳細資訊請見 TouchGFX/generated/fonts/src/Table_xxx.cpp 檔案:

140 號 Verdana 壓縮大小和最小快取大小

我們看到,140 號的 Verdana 字型繪製所有字元所需的最小快取為 4025 位元組。

快取失敗​

如果快取不夠大,無法容納正在繪製的字元, 應用程式將會停止運作。 應用程式呼叫該函數 CompressedFontCache::unableToCache(const GlyphNode* glyphNode, int byteSize),但永遠不會回傳。

只有當您手動修改產生的檔案時才會發生這種情況。

限制​

不能在相同的字型同時使用壓縮的 4 Bpp 和未壓縮的 4 Bpp。