繁体   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