功能價格文件部落格
取得 mote
← 部落格
工程·2026年7月2日·閱讀時間 4 分鐘

不自行繪製文字,而是交給平台處理的理由

你是否曾遇過韓文字看起來很正常,只有漢字莫名顯得陌生?當我們決定不親自繪製文字,而是交給平台的文字引擎時,我們的工作就不再是「要畫什麼」,而是「該要求使用哪種字型」。

m
mote
使用 Noto Sans CJK 的 KR 子集與 JP 子集繪製相同字串的比較。韓文字相同,但「骨」與「直」等漢字的字形不同。
使用 Noto Sans CJK 的 KR 子集與 JP 子集繪製相同字串的比較。韓文字相同,但「骨」與「直」等漢字的字形不同。

文字要顯示在畫面上,需要經過許多處理。必須將字元轉換成形狀、進行換行,再繪製成像素。從韓文字組合到漢字、表情符號、阿拉伯文字,以及字型回退,全都必須處理。

我們沒有重新打造這套流程。我們把它交給了 Linux 的 Pango 與 HarfBuzz、Windows 的 DirectWrite,以及 macOS 的 TextKit 2。

因為這是作業系統長期以來持續打磨的領域。若由我們自行打造,在 CJK 字元或無障礙功能等棘手之處,品質反而很可能變差。我們也認為,產品的差異化並不在於渲染器本身,而在於排版與符合各平台習慣的使用體驗。

不過,何時建立則由我們決定

建立文字版面配置需要時間與記憶體。大型文件可能有數萬行,因此無法全部建立。

所以,我們只建立畫面上可見的行及其周邊內容。離開畫面較遠的行則立即丟棄。即使長時間捲動一份 1MB 的文件,仍然存活的版面配置也只有大約四十到六十個。

尚未建立的行會先預估高度。因為捲軸必須知道整份文件的總長度。

當然,預估有時也會出錯。若重新計算出的高度與預期不同,畫面就可能位移。這時會在同一影格內,依照差值修正捲動位置。在使用者眼中,應該像什麼事都沒發生一樣。

正在組合韓文字的行會不加任何樣式地繪製。因為如果輸入過程中插入粗體或隱藏等屬性,輸入法所知道的字元數可能會與畫面上的字元數不同。

最先遇到的問題,是漢字的面貌

交給平台處理,也就會連平台的預設值一起採用。

Ubuntu 的預設 UI 字型不包含韓文字。因此,系統改為選用的字型是 Noto Sans CJK JP。韓文字顯示正常,但部分漢字卻以日式字形呈現。這是因為即使是相同的 Unicode 字元,在韓國與日本也可能有不同的字形。

解決方法很簡單。我們在 UI 字型清單中把 Noto Sans CJK KR 放到前面。

但另有一點更為重要。如果我們不制定標準,平台就會以自身的預設值,而不是使用者的語言來作答。

透過字型順序呈現各語言的字形

字型堆疊會從前往後尋找字元。只有第一個字型中不存在的字元,才會交給下一個字型。

利用這項特性,就能讓英文以襯線體顯示、韓文字以無襯線體顯示。只需一行設定,即可為不同語言搭配合適的字型。

如果閱讀字型留空,就會直接使用內文字型。若另外指定,則只會在閱讀模式下變更。原始碼模式則使用程式碼字型。

字體大小會遵循作業系統的無障礙設定。在系統中放大文字的使用者,不需要在每個應用程式裡重新設定。

設定卡片的外觀分頁——字型欄位中直接填入以逗號分隔的字型堆疊,閱讀字型則留空,並以淡色文字標示「與內文相同」。
設定卡片的外觀分頁——字型欄位中直接填入以逗號分隔的字型堆疊,閱讀字型則留空,並以淡色文字標示「與內文相同」。

螢幕閱讀器也會利用相同的基礎。平台的文字層級已經連接無障礙功能,因此我們只需準確傳遞系統所要求之行的內容即可。

缺少翻譯時,建置就會失敗

UI 句子以英文撰寫,並將該句子用作翻譯表的鍵。如果沒有翻譯,畫面上就會直接顯示英文。

問題在於它不會發生錯誤。即使缺少翻譯,英文也只會悄悄混入其中。

因此,我們製作了檢查指令碼。它會收集程式碼中實際使用的句子,並與 12 種語言的翻譯表進行比較。如果只在某一種語言中新增句子,或漏掉翻譯,建置就會失敗。

每份翻譯表有 304 個鍵,程式碼中實際使用的句子則有 282 個。支援的語言包括 English、한국어、日本語、简体中文、繁體中文、Deutsch、Français、Español、Português (Brasil)、Русский、Italiano、Polski。

設定的「一般」分頁——最上方一列是語言下拉式選單,目前選擇了韓語,所以下方所有項目的名稱也都是韓語。
設定的「一般」分頁——最上方一列是語言下拉式選單,目前選擇了韓語,所以下方所有項目的名稱也都是韓語。

切換語言時,會以同一份文件開啟新視窗,再關閉原有視窗。如果逐一翻譯已經顯示的數百個小工具,很可能有所遺漏。我們判斷,與其維護一條幾乎不會使用的複雜路徑,不如在切換語言的瞬間重新開啟一次視窗,會更加安全。

交給平台處理,結果也會帶有平台的樣貌

即使是同一份文件,在不同作業系統上的像素也不會完全相同。因為文字的修飾方式與預設字型各不相同。

我們不會勉強讓它們變得一致。取而代之的是,維持字體大小比例、行高與留白等文件基準的一致性。

字型回退的結果也可能因已安裝的字型而異。因此,我們不承諾特定結果,而是公開顯示字型的請求順序。使用者也可以自行變更。

不親自繪製,並不代表責任也隨之消失。我們反而必須更精確地決定要委託哪些工作,以及應以何種順序提出要求。

← 較舊在單一 Rust 核心上搭配各平台外殼的理由較新 →文件再長,打字也不會變慢的原因
透過 RSS 持續關注。
只留下文字。
繁體中文
© 2026 mote