簡體   English   中英

Viewbox內的TextBlock - 奇怪的渲染

[英]TextBlock inside a Viewbox - strange rendering

這是一個關於非常簡單的構造的問題 - 我有以下XAML:

    <Viewbox Height="100" Stretch="Uniform">
        <TextBlock FontFamily="Georgia">My Cool Text</TextBlock>
    </Viewbox>

這很容易理解。 然而,當我啟動程序時,我得到了奇怪的模糊文本(我的項目中沒有任何位圖效果)。 替代文字

(左側 - VS2010中的設計器視圖,右側 - 正在運行的應用程序)

有沒有人有任何關於為什么會發生這種情況的建議?

雖然Jefim已正確回答了他自己的問題,但我想解釋為什么在使用這組特殊功能時會出現這種情況。 Jefim認為這是WPF中的一個錯誤,但事實並非如此。 由於要求WPF做一些不可能的事情,問題就出現了。 當你要求這個不可能的事情時,它必須選擇妥協,結果就是你在上面看到的。

對於評論,解釋有點長,這就是為什么我把它放在一個單獨的答案中。

此示例使用WPF的兩個相互矛盾的功能。 這些功能是:

  1. 能夠以任何比例一致地呈現視覺效果
  2. 以與GDI32呈現文本相同的方式呈現文本的能力

您不能同時使用這兩個功能。 GDI32以無法一致縮放的方式呈現文本:如果某個字體大小的特定文本塊恰好是200像素寬,如果將字體大小乘以3,則在同一字體系列中呈現相同的文本新的字體大小,在GDI32中它可能不會是600像素 - 它會很接近,但它通常不會很正確。

GDI32混淆了字符的形狀和寬度,以增強文本的清晰度和清晰度。 具體來說,它會使字母變形,使其特征與屏幕上的像素更好地對齊。 並且在必要時,它會將單個字符的寬度調整為精確的像素寬度。 由於此字母彎曲全部基於實際像素,因此它以不同的方式以不同的字體大小彎曲文本。

雖然這給你提供了漂亮的清晰文本,但如果你試圖逐漸改變比例,它看起來絕對可怕。 如果你嘗試以這種方式渲染某些文本的字體大小,那么這個東西會顯得微微顫抖,因為以清晰度名稱進行的調整最終會在每種字體大小上略有不同。 即使你沒有動畫,它仍然會產生不好的結果 - 如果你有一個以多種尺寸顯示的單一字體,它在每種尺寸上都會看起來很不一樣; 如果您的應用程序具有縮放功能,則放大和縮小時文本的字符似乎會發生顯着變化。 (布局也是如此。如果你使用Microsoft Word,你可能已經注意到你有時會在某些單詞之間看到奇怪的超寬空間。這是Word與GDI32戰斗的結果 - Word試圖保持屏幕上的布局盡可能接近打印時的外觀,這意味着它有時會與GDI32的網格配件發生沖突。)

因此,WPF提供了一種不同的文本呈現方法:它可以以盡可能忠實於字體原始設計的方式呈現文本。 這樣可以減少文本的扭曲,這意味着在縮放時不會出現不連續性。

缺點是,與GDI32呈現的文本外觀相比,文本看起來模糊。 (GDI32的扭曲都旨在提高清晰度。)

因此,在WPF 4.0中,Microsoft添加了以GDI32的方式呈現文本的功能。 這就是TextOptions.TextFormattingMode="Display"作用。

通過啟用該選項,您說“我不需要一致的縮放,我更喜歡清晰度,因此生成與您在GDI32中完成的像素相同的像素。” 如果你繼續應用擴展,告訴WPF你不需要可伸縮性,你會得到糟糕的結果。 WPF小心地根據您的規范生成了文本的位圖表示,然后您告訴它以不同的比例呈現該文本。 所以它看起來像是什么:為不同分辨率生成的某些文本的縮放位圖。

你可以說WPF可以在這里做一些不同的事情:如果你在GDI32中應用比例變換你會看到不同的行為 - 你會看到前面描述的不同比例的不一致。 如果您真的想在WPF中使用該效果,可以通過直接修改字體大小來獲得它。 但WPF沒有優先考慮同樣的效果 - 它的目標是在你真正需要的時候獲得GDI32風格的清晰文本,並默認提供一致的縮放。

而你在這里遇到的是“一致擴展”。 打開GDI32樣式的文本渲染不會破壞一致的縮放:應用縮放因子(直接,通過ScaleTransform或通過Viewbox間接)將改變視覺的尺寸,精確指定比例因子。 如果要通過網格擬合到新縮放的大小來重新生成文本視覺效果,則文本將以不同的寬度出現。 這實際上會導致Viewbox出現問題:它根據內容的自然大小應用比例因子,旨在使其適合可用空間。 但如果它在縮放后重新進行網格擬合,那實際上會改變寬度。 由於GDI32文本渲染的工作原理不一致, ViewBox甚至可能無法找到合適的比例 - 它可能會產生一段文字,當以特定字體呈現時,它永遠不會出現寬度為200像素。 對於某些字體大小,網格擬合中固有的圓角可能會將大小縮小到比如198,並且當你在字體大小上進行微小增量時它可能會堅持下去,直到你超過某個閾值,此時它可能會跳躍到202像素。

對於試圖強制文本恰好適合200像素的Viewbox ,這將是一個問題。 Viewbox不能以這種方式工作 - 它使用WPF的一致縮放,在您選擇GDI32樣式文本渲染工作的字體大小的下游。 因此, Viewbox將始終能夠完成它的設計目標,但這是與GDI32風格的文本渲染根本不兼容的任務。

簡而言之,WPF會為您請求的字體大小呈現文本,然后縮放結果。

所以你必須選擇一個功能 - 你不能同時擁有這兩個功能,因為這根本不可能。 要么不嘗試在可以應用任意比例因子的上下文中呈現文本(例如Viewbox ),要么不要打開GDI32樣式的文本呈現。 否則,你會得到你遇到過的奇怪的像素化文本。

好的,發現了bug。 我的窗口樣式具有以下setter:

    <Setter Property="TextOptions.TextFormattingMode" Value="Display"/>

如果我將其設置回“理想”(這是默認值),那么它會正確地呈現視圖框內的文本。 我會說這是WPF中的一個錯誤。 基本上,如果你試試這個:

<Viewbox Height="100" Stretch="Uniform" TextOptions.TextFormattingMode="Display">
    <TextBlock FontFamily="Georgia">My Cool Text</TextBlock>
</Viewbox>

您將得到與我的初始圖片相同的結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM