2012-03-02 49 views
3

我注意到Graphics.MeasureString在不同分辨率下的奇怪行为。graphics.MeasureString在不同分辨率下的奇怪行为

对于默认分辨率(96x96),我测试的不同字体大小之间存在线性关系。

但是,如果我将它提升到512 x 512,则使用度量字符串时,线性关系将消失,并且会发生一些真正奇怪的事情。 (参见下面的4绘出)

如果我离开分辨率在用于图形对象的默认大小,并测量字体大小,这里是字体大小和字符串的宽度之间的关系:

图形对象,默认分辨率(96):

字体尺寸(X轴),一个特定的字符串的宽度(Y轴) Width96

字体尺寸(X轴),一个特定的字符串的HEIGHT(Y -AXIS) Height96

但是,如果我改变分辨率

图形对象,512分辨率:

字体尺寸(X轴),一个特定的字符串的宽度(Y轴) enter image description here

字体大小(X轴),特定字符串的高度(Y轴) enter image description here

任何人都知道为什么会发生这种情况?

谢谢你。

它应该指出的是,我使用的.NET 4(全部档案)

代码用于生成图表(针对每种类型更改分辨率):

string str = "6 CN-3 Tie EomgVeo405- 2ss>era09rni IBne 20iopv Atdrsn - Ng72"; 
SizeF sizef = new SizeF(855, 14.000001f); 
StringFormat stringFormat = new StringFormat() 
{ 
    Alignment = StringAlignment.Center, 
    LineAlignment = StringAlignment.Near, 
    Trimming = StringTrimming.None, 
    FormatFlags = StringFormatFlags.NoClip, 
}; 

Bitmap b = new Bitmap(901, 401); 
//b.SetResolution(512, 512); 
Graphics g = Graphics.FromImage(b); 

for (float x = origFont.Size; x >= 0.5; x -= 0.1f) 
{ 
    var data = g.MeasureString(str, new Font("Microsoft Sans Serif", x), sizef, stringFormat); 
    Console.WriteLine(x + "\t" + data.Width + "\t" + data.Height); 
} 
+0

Graphics.MeasureString()很糟糕,用.NET版本2中的TextRenderer.MeasureText()取代。否则,您可以从TrueType提示算法中预期的模式种类。在点或像素大小小于8的情况下渲染文本是没有意义的。 – 2012-03-02 00:29:53

+0

当宽度达到850时,它开始'口吃'。这是我给Graphics.MeasureString提供的最大允许宽度。正如Lasse V. Karlsen指出的那样,织物的包装物正在缠绕。我未能添加“无包裹”标志。感谢大家! – JHubbard80 2012-03-02 00:49:46

回答

1

这个答案是猜测,但证据非常符合它。

你所看到的是将字符串缠绕成两行。

假设如下:

  1. 文本的宽度是线性正比于字号
  2. 文本的高度是线性正比于字号

这符合启动你的512分辨率图表,一切都会线性增加。

在某一点上,宽度急剧减少一定量,同时高度加倍。

这意味着一个单词被移动到第2行上,该第2行将高度加倍(2行比1之前),并且由于行上的最后一个单词现在在第2行。

从那里开始,随着字体大小的增加,宽度仍然在线1上的部分线性变宽,宽度再次缓慢增加。与此同时,高度线性增加,但现在是休息前的两倍,因为现在有两条线变高,而之前为1条。

在某些时候,第1行的最后一个字再次打破了最大宽度,并在第2行上向下移动,之前单词在此之前,此时,宽度再次急剧减少一定数量。

如果你要继续你的图形,我预测宽度将继续其当前模式。它每次减少的确切数量与正在移动的单词的宽度成正比。同时,在某些时候,第二条线将需要被打破,在这种情况下,您将获得3倍的高度,然后高度将以3倍的速度增加,等等。

+0

虽然我还没有证实这一点 - 看看我的情节,这似乎是合乎逻辑的,因为当字符串宽度达到850时发生'口吃' - 这正好在我给Graphics.MeasureString的允许宽度的宽度。谢谢!我应该抓住了这个,我责怪阅读直到凌晨3点:D – JHubbard80 2012-03-02 00:45:48

+0

那么,请确认这一点然后:)其他答案在这里告诉我,我不知道文本渲染和.NET的一半,因为我想,所以我在这里可能错过了一些东西。尽管如此,它似乎适合:) – 2012-03-02 00:50:26

+0

这是由于缺少NoWrap标志。口吃总是在850发生的事实是一支冒烟的枪。我确实证实了这一点。谢谢! – JHubbard80 2012-03-02 04:16:10

1

我相信这可能是因为GDI +中的提示/网格拟合算法而发生的。测试中的字体大小在字形可读性方面非常小,因此,渲染引擎会尝试对每个字形应用特殊转换以使其更清晰。这些转变很大程度上取决于目标新闻部。

还值得一提的是,字体大小的增加会导致更多的“线性”依赖。

这个article用一些例子更详细地解释了这些机制。

同时,您可以尝试修改Graphics.TextRenderingHint媒体资源和/或尝试TextRenderer而不是Graphics.DrawString,如果这可以帮助解决您的问题。

+0

感谢您的提示。我将在未来继续关注这一点。 – JHubbard80 2012-03-02 04:17:13