JHubbard80
JHubbard80

Reputation: 2277

Strange behavior of graphics.MeasureString at different resolutions

I have noticed strange behavior of Graphics.MeasureString at different resolutions.

For the default resolution (96x96) there is a linear relationship across the different font sizes I tested.

However, if I raise it to 512 x 512, the linear relationship disappears and something really strange happens when using measure string. (See 4 plots below)

If I leave the resolution at the default size for a graphics object, and measure the font size, here is the relationship between font size and the width of a string:

Graphics object, Default Resolution (96):

Font size (X-Axis), WIDTH of a particular string (Y-Axis) Width96

Font size (X-Axis), HEIGHT of a particular string (Y-Axis) Height96

However, if I change the resolution

Graphics object, 512 resolution:

Font size (X-Axis), WIDTH of a particular string (Y-Axis) enter image description here

Font size (X-Axis), HEIGHT of a particular string (Y-Axis) enter image description here

Anyone know why this might be happening?

Thanks you.

It should noted that I am using .NET 4 (Full Profile)

Code used to generate graphs (Change resolution for each type):

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);
}

Upvotes: 3

Views: 1618

Answers (2)

Yuriy Guts
Yuriy Guts

Reputation: 2220

I believe this might be happening because of the hinting/grid fitting algorithms in GDI+. Font sizes in your tests are extremely small in terms of glyph legibility, and, because of that, the rendering engine tries to apply special transformations to each glyph to make it clearer. These transformations depend greatly on the target DPI.

It is also worth mentioning that major increase of the font size will lead to a more 'linear' dependency.

This article explains these mechanisms in more details with some examples.

Meanwhile, you can try to modify the Graphics.TextRenderingHint property and/or try TextRenderer instead of Graphics.DrawString if that will help you with your issue.

Upvotes: 1

Lasse V. Karlsen
Lasse V. Karlsen

Reputation: 391336

This answer is a guess, but the evidence fits it perfectly.

What you're seeing is the string being wrapped onto two lines.

Let's assume the following:

  1. The width of the text is linearly proportional to the fontsize
  2. The height of the text is linearly proportional to the fontsize

This fits the start of your 512-resolution graph, everything increases linearly.

At some point, the width is sharply reduced by a certain amount, and at the same time the height doubles.

This means that a word was moved onto line 2, which doubled the height (2 lines vs. 1 before), and the string got a certain amount less wide since the last word on the line is now on the start of line 2.

From there on, the width slowly increases again as the part of the string still on line 1 linearly gets wider as the font-size increases. At the same time the height increases linearly, but now at double the rate as before the break, since 2 lines now get higher, vs. 1 before.

At some point, again, the last word on line 1 breaks the maximum width and is moved down on line 2, before the word that was previously alone there, and at that point, the width is again sharply reduced by a certain amount.

If you were to continue your graph, I predict that the width will continue its current pattern. The exact amount it dips down each time is proportional to the width of the word being moved. At the same time, at some point the 2nd line will need to be broken, in which case you get a 3x height and the height will then increase at 3x the pace, and so on.

Upvotes: 1

Related Questions