NSTextField 文本模糊的解決辦法 canDrawSubviewsIntoLayer

在開發落格輸入法 macOS 的過程當中,我一直被一個奇怪的問題所困擾——文本模糊。

次像素

無論我怎樣調試,落格輸入法的候選文字都無法達到原生文字的那樣清晰和銳利。在請教了大神之後,得到的活久見經驗是——上游次像素渲染 錯誤。

在很多平台都有類似問題,macOS 底層渲染也有這樣的錯誤,一旦你的佈局出現了小數點或者不是整數,就會導致文本渲染模糊。

那麼怎麼解決呢?只要把位置和大小“對正”就可以了,不要直接使用 Int(XXX) 來轉換你的數值,使用 roundf() ,不過,對於 Swift 來說,我們有更方便的方式,比如這樣:

() 方法就是我們常說的“四捨五入”,如果你直接轉換數據類型到整形,那麼小數點後的內容會被直接拋棄,哪怕是 0.99999 ,也會變成 0 ,顯然這並不是我們想要的,如果用這個函數來轉換,那麼你得到的還是 CGFloat的 ,但值卻變成了原本的四捨五入“整數”。

確實好了很多,不會那麼模糊了,但如果你仔細看,總感覺還是有哪裡不太一樣。

實際上,這個 bug 在最新的 macOS 10.14 Mojave 中已經修復了。

canDrawSubviewsIntoLayer

還有的人說,是因為你用了 layer,這樣就會導致性能底下,如果把 wantsLayer 關閉,或者給一個非透明的背景,就會好很多。但這終究不是個辦法,如果必須要透明呢?總之,我經過查詢找到了這個方法 canDrawSubviewsIntoLayer

蘋果官方的文檔對它是這麼描述的:

當這個屬性的值是 true ,任何任何子視圖隱式創建的 layer——也就是說,那些你沒有通過設置 wantsLayer 屬性為 true 創建的 layer,都會把自己繪製在當前視圖的 layer上。換句話說就是子視圖不再擁有自己的layer。相反,他們把自身的內容繪製在父視圖的 layer中。所有受影響的視圖都使用 (_:) 方法來繪製內容。它們不再使用 updateLayer() 方法更新 layer 內容,就算 wantsUpdateLayer 屬性設置為 true

使用這個屬性來為基於 layer 的視圖和子視圖扁平化 layer 繼承。扁平化 layer 集成減少了你試圖繼承中的 layer 數量(並且還可能減少內存的使用)。減少 layer 數量可以在大量視圖和子視圖內容不明顯變化的情況下更加高效。比如說,扁平化繼承降低了組合視圖時使用的時間。不要扁平化視圖繼承如果你準備給子視圖添加動畫的話。

當改變這個屬性的值時,當前視圖必須擁有一個 layer 對象。該屬性默認值為

我把英文翻譯過來了,實際上,就可以理解為是 Photoshop 裡的“合併圖層”,如果你的視圖組合不做大的改變,那麼就可以把它們合併繪製,不需要去管什麼透明度和漸變了,直接把最終的效果繪製在同一個圖層上。大大降低了渲染成本,這樣文本也就不再模糊,變得清晰銳利。

由...出版 R0uter

如非聲明,本人所著文章均為原創手打,轉載請註明本頁面鏈接和我的名字。

發表評論

您的電子郵件地址不會被公開. 必填字段標 *