反鋸齒指南

Paul Lewis

簡介

消除鋸齒是網路圖像的無名英雄,所以畫面會顯示文字清楚且平滑的向量形狀。事實上,目前瀏覽器採用的幾種消除鋸齒技術,在文字顯示方面最為明顯。如果用於防毒功能的演算法切換,可能會導致非預期的影像結果。本文將說明消除鋸齒的方法,以及瞭解像素繪製方式。

我們所有螢幕都以像素為基礎,建構出我們所知的像素。這是一個巨大的塊狀格線,每個區塊都包含紅色、綠色和藍色 (RGB) 元件。遠處可以看到圖片、文字和圖示,但近距離可以看到 RGB 元件的格線以及所有項目的組成方式。

螢幕特寫。每個像素都有紅色、綠色和藍色元件
圖 1 - 特寫畫面的像素。每個像素都有紅色、綠色和藍色元件。

消除混疊

那麼,當我們繪製向量形狀並通過像素的「部分」時,會發生什麼事呢?假設我們要繪製的形狀是黑色,背景為白色。我們應該為像素著色嗎?如果有顏色,它應該是什麼顏色?黑色、灰色還是其他?

填色程序會決定填入像素時應使用哪種顏色。其中最簡單的版本稱為灰階消除鋸齒,而且會平均處理像素的三個元件。因此,如果像素已遮住一半,並且假定一秒以白色顯示黑色文字來維持簡單的流程,您應該以為每個元件的亮度設為一半 (我確定已經如此) 但其實只會比 Gamma 複雜。也就是說,您不一定要將 Gamma 值設為這個值。這當然會稍微複雜一點,但這是我本來不會深入探討的主題。重要的是,灰階消除疑慮是處理像素層級的問題,事實上我們還是可以做得更好。

圖 2:消除鋸齒與硬邊緣
圖 2 - 鋸齒狀與硬邊緣

在圖 2 中,您可以看到繪製中的同一個三角形,但左側的三角形啟用反鋸齒功能,在右側則已停用。如您所見,啟用消除鋸齒功能時,當三角形只能穿過部分像素時,像素就會變成灰色。不過,如果停用這個模式,像素就會填滿實心或純白色,而形狀看起來則有所不同。

文字轉譯

每當瀏覽器轉譯文字 (本質為向量形狀) 時,我們就會發生同樣的問題:文字字元只會填滿部分像素,因此我們會採用策略來瞭解如何填入這些像素。在理想情況下,我們希望文字經過消除鋸齒,以便閱讀起來更得心應手。

但事實證明,灰階消除原理只是處理其中一種方式。常見的做法是,以更嚴謹的方式,啟用像素的 RGB 元件。這個過程稱為子像素消除鋸齒,多年來,ClearType 團隊特別投注了大量的時間和精力來推動這個過程。如今這個領域獲得廣泛採用,所有主要瀏覽器都會放大或縮小這個數字。

首先,既然我們知道每個像素是由獨立的紅色、綠色和藍色元件組成,所以會偵測每個元件應該「開啟」多少像素的元件。因此,如果像素從左方「遮住一半」,我們可能會完全切換成紅色元件,將綠色元件完全關閉,然後保持藍色的關閉狀態。這項程序常常描述為「移除螢幕的水平解析度」,而且必須考量每個像素實際上都是並排的三個元件,而不是一個單元。

圖 3:使用灰階與子像素的反鋸齒技術
圖 3 - 使用灰階與子像素消除鋸齒

如上圖 3 所示,在左側圖 3 中,我們會對每個元件一視同仁,每個元件的啟用與關閉情形均相同 (灰階)。但右側的子像素方法則會根據元件與繪製形狀重疊的「程度」,以不同的方式啟用每個元件 (紅、綠、藍)。

不過,即使如此,人類視覺的重量也不會相等紅、綠光和藍光。我們對於綠色的重要性遠勝於紅色或藍色,也就是說,雖然使用灰階消除鋸齒還是明顯受益,如 Darel Rex Finley 指出,單單啟用每個元件不會使清晰度提升 3 倍。子像素消除鋸齒一定很有用,而且這意味著,比起使用灰階消除鋸齒,文字會顯得更清楚。

圖 4 - Subpixel 反鋸齒文字。系統會啟用個別像素的個別元件,藉此產生整體效果
圖 4 - Subpixel 反鋸齒文字。系統會啟用個別像素的個別元件,藉此產生整體效果

躍上追逐隊伍

這對我們身為開發人員的意義為何?從 Chrome 的角度來看,至少混合使用灰階和子像素反鋸齒技術,並根據幾項條件決定套用方式。不過,我們必須先大致瞭解圖層,因為這是遊戲的主要準則,如果你還不說過分層結構,且 Chrome 內部的使用方式,Tom Wiltzius 已針對這類問題撰寫了很棒的簡介,建議你優先閱讀。

假設您熟悉圖層,或剛剛看過這些圖層,我們就繼續講解。如果網頁已啟用硬體合成功能,但如果您所在圖層的文字內容「不是」根層,則根據預設會使用灰階消除鋸齒進行轉譯。開發人員經常注意到,如果開發人員對元素套用駭客攻擊,使這些元素進入自己的 (非根) 層 (例如使用 translateZ),就會發現文字顯示方式不同。開發人員常常透過 JavaScript 或 CSS 套用「新圖層」觸發條件,導致文字轉譯結果從子像素變為灰階。如果您不清楚導致轉譯變更的因素,可能會感到困惑。不過,如果文字位於根層,則應透過子像素消除鋸齒的方式轉譯,因此使用者會更清楚地閱讀文字。

不過,如同所有網路功能,體驗也不斷在改變。只要圖層符合三個條件,系統就會在 Chrome 中為非根層中的文字啟用子像素消除鋸齒功能。值得一提的是,這些條件今天仍然適用,但可能會有所變動,因此日後會持續納入更多案例。目前適用的條件如下:

  1. 圖層的背景顏色不透明。請特別注意,如果使用 border-radius 或非預設的 background-clip 值,系統會將圖層視為非不透明,而文字算繪則會還原為灰階消除鋸齒。
  2. 圖層只能套用「身分轉換」或「完整性翻譯」。整數是指四捨五入的值,因此,以 translate(20.2px, 30px) 為例,由於 x 元件 20.2px 並非內建,因此會導致灰階消除鋸齒。身分轉換僅代表除了其預設值之外,不會有額外的旋轉、平移或縮放功能。
  3. 圖層的不透明度為 1.0。任何不透明度變更都會從子像素變為灰階。
圖 5 - 使用前後:灰階與子像素。請注意右側文字上的顏色標示
圖 5 - 前後對照:灰階與子像素。請注意右側文字的色階

最後請注意,套用 CSS 動畫可能會導致系統建立新圖層,使用 requestAnimationFrame 則不會。對部分開發人員來說,使用 CSS 動畫時容易隱含的文字顯示差異。因此,如果您因為文字轉譯不同而一直使用 JavaScript 來為元素製作動畫,不妨檢查這次更新是否能幫助您解決問題!

以上就是 Chrome 的課程內容至於其他瀏覽器,Opera 會隨著 Chrome 運作而與 Chrome 的運作密切吻合。Internet Explorer 似乎會對所有文字 (當然,如果您已啟用 ClearType) 使用子像素消除鋸齒,但似乎不是使用 Windows 8 的 Metro 模式。Safari 是 WebKit 與 Blink 相近,運作方式與 Chrome 非常類似,儘管沒有這些較新的改善項目,也能支援更多子像素消除鋸齒。Firefox 的運作方式與 Internet Explorer insofar 大致相同,差別在於 Firefox 會使用子像素消除鋸齒功能,處理幾乎所有文字。當然,這份清單並未列出所有瀏覽器。在所有瀏覽器中,可能都會使用灰階消除鋸齒技術,而非子像素,不過別忘了,子像素反鋸齒功能已廣泛運用於瀏覽器。

結論

現在,您已瞭解消除鋸齒的運作方式,以及目前在網站和應用程式 (尤其是低 DPI 裝置) 中可能會出現文字呈現差異的原因。如果您想瞭解 Chrome 的文字轉譯實作方式,請為下列錯誤加上星號:

資源與參考資料