跳轉到主要內容

點陣圖字型壓縮

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

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

在 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」。

結論

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

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

設定

正如前言所提到,若要啟用字型壓縮, 需要從 Designer 中的個別排版進行選擇。 應用程式會自動包含必要的解壓縮程式碼。

快取大小

快取大小可以在 Designer 中設定, 選擇設定分頁中的 「文字設定」:

123

設定快取大小。

如果快取小於最大壓縮字元所需的快取,TouchGFX Designer 將在日誌中報告錯誤:

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

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

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

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

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

快取失敗

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

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

限制

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