视图框内的 TextBlock - 奇怪的渲染 [英] TextBlock inside a Viewbox - strange rendering

查看:27
本文介绍了视图框内的 TextBlock - 奇怪的渲染的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个关于一个非常简单的结构的问题 - 我有以下 XAML:

This is a question regarding a very simple construction - I have the following XAML:

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

这很容易理解.然而,当我启动程序时,我得到了奇怪的模糊文本(我的项目中的任何地方都没有位图效果).

This is quite simple to understand. Yet when I start the program I get strange blurry text (there are no bitmap effects anywhere in my project).

(左侧 - VS2010 中的设计器视图,右侧 - 正在运行的应用程序)

(left side - the designer view in VS2010, right side - the running application)

有人对为什么会发生这种情况有任何建议吗??

Does anyone have ANY suggestions about why this is happening??

推荐答案

虽然 Jefim 正确回答了他自己的问题,但我想解释一下为什么在使用这组特定功能时会出现这种行为.Jefim 认为这是 WPF 中的一个错误,但事实并非如此.问题是由于要求 WPF 做一些不可能的事情而产生的.当你要求这个不可能的事情时,它必须选择一个妥协,结果就是你在上面看到的.

While Jefim has correctly answered his own question, I wanted to explain why you get this behaviour when using this particular set of features. Jefim suggests that this is a bug in WPF, but it's not. The problem arises as a result of asking for WPF to do something impossible. It has to pick a compromise when you've asked for this impossible thing, and the result is what you see above.

评论的解释有点长,这就是为什么我把它放在一个单独的答案中.

The explanation is a bit long for a comment, which is why I'm putting it in a separate answer.

这个例子使用了 WPF 的两个相互矛盾的特性.这些功能是:

This example uses two mutually contradictory features of WPF. Those features are:

  1. 能够以任何比例一致地呈现视觉效果
  2. 能够以与 GDI32 呈现文本相同的方式呈现文本

您不能同时使用这两种功能.GDI32 以无法一致缩放的方式呈现文本:如果特定字体大小的特定文本片段恰好是 200 像素宽,如果将字体大小乘以 3,并在相同字体系列中呈现相同文本新的字体大小,在 GDI32 中可能不会是 600 像素 - 会很接近,但通常不太正确.

You can't use both features at once. GDI32 renders text in a way that cannot be scaled consistently: if a particular piece of text at a certain font size happens to be 200 pixels wide, if you multiply the font size by 3, and render the same text in the same font family at that new font size, in GDI32 it probably won't be 600 pixels - it'll be close, but it will typically not be quite right.

GDI32 对字符的形状和宽度进行了处理,以增强文本的清晰度和清晰度.具体来说,它会将字母弯曲变形,使其特征与屏幕上的像素更好地对齐.并且在必要时,它会将单个字符的宽度调整为精确的像素宽度.由于这种字母弯曲完全基于实际像素,因此它以不同的方式以不同的字体大小弯曲文本.

GDI32 messes with the shapes and widths of characters in order to enhance the clarity and sharpness of the text. Specifically, it bends letters out of shape so that their features align better with the pixels on your screen. And where necessary, it will adjust the width of individual characters to be an exact number of pixels wide. Since this letter bending is all based around actual pixels, it bends text in different ways at different font sizes.

虽然这给了你漂亮清晰的文字,但如果你试图逐渐改变比例,它看起来绝对可怕.如果您尝试为以这种方式呈现的某些文本的字体大小设置动画,则该内容看起来会闪烁并颤抖,因为以清晰度的名义进行的调整最终会在每个字体大小上略有不同.即使你不做动画,它仍然会产生糟糕的结果——如果你有一个以多种尺寸显示的单一字体,它在每种尺寸下看起来都可能大不相同;如果您的应用程序具有缩放功能,当您放大和缩小时,文本的字符似乎会发生显着变化.(布局也是如此.如果您使用 Microsoft Word,您可能已经注意到有时在某些单词之间会出现看起来很奇怪的超宽空格.这是 Word 与 GDI32 争斗的结果 - Word 试图保持屏幕上的布局尽可能接近打印时的外观,这意味着它有时会与 GDI32 的网格拟合发生冲突.)

While that gives you nice sharp looking text, it looks absolutely horrible if you try to change the scale gradually. If you try to animate the font size of some text rendered in this fashion, the thing will seem to shimmer and shudder, because the adjustments made in the name of clarity end up being slightly different at each font size. Even if you're not animating, it can still produce poor results - if you have a single typeface shown at a number of sizes, it can look quite different at each size; if your application has a zoom feature, the character of the text can seem to change significantly as you zoom in and out. (And so can the layout. If you use Microsoft Word, you may have noticed that you sometimes get odd-looking extra wide spaces between certain words. This is the result of Word fighting with GDI32 - Word attempts to keep the on-screen layout as close as possible to how things will look when printing, which means it sometimes clashes with GDI32's grid fitting.)

因此 WPF 提供了一种不同的文本渲染方法:它可以以尽可能忠实于字体原始设计的方式渲染文本.这会减少文本扭曲,这意味着您在缩放时不会出现不连续性.

So WPF offers a different approach to text rendering: it can render text in a way that is as faithful as possible to the original design of the font. This distorts the text less, and it means that you don't get discontinuities as you scale.

缺点是与 GDI32 呈现的文本相比,文本看起来模糊.(GDI32所做的扭曲都是为了提高清晰度.)

The downside is that the text looks blurry, compared to how text rendered by GDI32 looks. (The distortions made by GDI32 are all aimed at improving clarity.)

因此,在 WPF 4.0 中,Microsoft 添加了以 GDI32 的方式呈现文本的功能.这就是 TextOptions.TextFormattingMode="Display" 所做的.

So in WPF 4.0, Microsoft added the ability to render text in the way GDI32 would. That's what TextOptions.TextFormattingMode="Display" does.

通过启用该选项,您是在说我不需要一致的缩放比例,我更喜欢清晰度,因此生成与您在 GDI32 中所做的相同的像素."如果你继续应用缩放,告诉 WPF 你不需要可扩展性,你会得到糟糕的结果.WPF 根据您的规范仔细地生成文本的位图表示,然后您告诉它以不同的比例呈现该文本.所以它看起来像这样:为不同分辨率生成的某些文本的缩放位图.

By turning on that option, you are saying "I don't need consistent scaling, and I'd prefer clarity, so generate the same pixels you would have done in GDI32." If you then go on to apply scaling, having told WPF you didn't need scalability, you get crappy results. WPF carefully generated a bitmap representation of the text exactly to your specifications, and you then told it to render that text at a different scale. And so it looks like what it is: a scaled bitmap of some text that was generated for a different resolution.

您可能会争辩说 WPF 可以在这里做一些不同的事情:如果您在 GDI32 中应用比例变换,您会看到不同的行为 - 您会看到前面描述的不同比例的不一致.如果你真的想在 WPF 中实现这种效果,你可以通过直接修改字体大小来获得它.但是 WPF 并没有优先考虑获得相同的效果 - 它的目标是在您真正需要时获得 GDI32 样式的清晰文本,并在默认情况下提供一致的缩放.

You could argue that WPF could do something different here: if you apply a scale transform in GDI32 you'd see different behaviour - you'd see the inconsistency at different scales described earlier. If you really want that effect in WPF you can get it by modifying the font size directly. But WPF doesn't prioritise getting that same effect - its goals are to make it possible to get GDI32-style crisp text when you really need it, and to provide consistent scaling by default.

您在这里遇到的是一致缩放".打开 GDI32 样式的文本渲染不会破坏一致的缩放:应用缩放因子(直接通过 ScaleTransform 或间接通过 Viewbox)将改变尺寸视觉效果完全按照指定的比例因子.如果要通过网格拟合到新缩放的大小来重新生成文本视觉效果,则文本将以不同的宽度出现.这实际上会导致 Viewbox 问题:它根据内容的自然大小应用比例因子,旨在使其适合可用空间.但是如果它在缩放后重新调整网格,那实际上会改变宽度.由于 GDI32 文本渲染工作方式固有的不一致,ViewBox 甚至可能无法找到合适的比例 - 有可能想出一段文本,当以特定的字体,永远不会出现在 200 像素宽.对于某些字体大小,网格拟合中固有的舍入可能会将大小降低到 198,并且当您对字体大小进行微小增量时,它可能会坚持下去,直到您超过某个阈值,此时它可能会跳跃到 202 像素.

And what you're running into here is the "consistent scaling". Turning on GDI32-style text rendering doesn't break consistent scaling: applying a scale factor (either directly, via a ScaleTransform or indirectly via a Viewbox) will change the dimensions of the visual by exactly the specified scale factor. If it were to re-generate the text visuals by grid fitting to the newly scaled size, the text would come out at a different width. That would actually cause the Viewbox problems: it applies a scale factor based on the content's natural size, designed to make it fit the available space. But if it re-did the grid fit after scaling, that would actually change the width. Because of the inconsistencies inherent in how GDI32 text rendering works, it might not even be possible for the ViewBox to find a suitable scale - it's possible to come up with a piece of text which, when rendered in a particular font, will never come out at 200 pixels wide. For some font sizes, the rounding inherent in grid fitting might bump the size down to, say, 198, and it might stick at that as you make tiny increments in the font size, until you go past some threshold at which point it might jump to 202 pixels.

对于 Viewbox 试图强制文本恰好适合 200 像素,这将是一个问题.但是 Viewbox 不是这样工作的 - 它使用 WPF 的一致缩放,在您选择 GDI32 样式文本呈现工作的字体大小的点的下游.因此,Viewbox 将始终能够执行它设计的任务,但这是从根本上与 GDI32 样式文本渲染不兼容的任务.

For a Viewbox attempting to force the text to fit into exactly 200 pixels, that would be a problem. But Viewbox doesn't work that way - it uses WPF's consistent scaling, downstream of the point at which you chose the font size to which GDI32-style text rendering is working. So Viewbox will always be able to do what it is designed to do, but that is task that's fundamentally incompatible with GDI32-style text rendering.

简而言之,WPF 根据您请求的字体大小呈现文本,然后缩放结果.

So in short, WPF renders the text for the font size you requested, and then scales the result.

因此您必须只选择一个功能 - 您不能同时拥有这两个功能,因为那是不可能的.要么不要尝试在可以应用任意比例因子的上下文中渲染文本(例如 Viewbox),要么不要打开 GDI32 样式的文本渲染.否则,你会得到你遇到过的奇怪的像素化文本.

So you have to pick just one feature - you can't have both because that's simply impossible. Either don't attempt to render text in a context in which an arbitrary scale factor may be applied (e.g. Viewbox) or don't turn on GDI32-style text rendering. Otherwise, you get that weird pixelated text that you've encountered.

这篇关于视图框内的 TextBlock - 奇怪的渲染的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆