0

I'm using simple code to draw text inside specified rectangle. Everything works fine, except that sometimes text layout is different depending on graphics scale (set via Graphics.ScaleTransform method).

It's hard to describe the issue in words, so take a look at example image

  1. ScaleTransform set to something around 0.3 - text fits in one line within specified rectangle.
  2. ScaleTransform set to something around 0.6 - text is wrapped before last word.

In both cases it's the same font, text, layout rectangle, StringFormatting and so on. The only thing that changes is the scale. Note that I do not use "font scaling"! In both cases IT IS even the same font object. No StringFormatFlags set.

How can I fix that? I don't care if text will be wrapped or not - I just need the consistency. Always wrapped or not, no matter the scale. How to do that?

5
  • It isn't rendered the same. The first line was rendered with TextRenderingHint.ClearTypeGridFit, the second with TextRenderingHint.AntiAlias. Use a tool like SysInternal's ZoomIt to see that. TrueType hinting makes this stuff difficult, it stretches letters to make the stems coincide with the pixel grid. Turning it off makes it ugly. Leave some room for this. Commented Aug 17, 2011 at 17:46
  • Hans, in both cases TextRenderingHint is set to SystemDefault. Changing it for example to AntiAlias does not help - the difference is still there (although text looks much better). Commented Aug 17, 2011 at 18:12
  • However it seems that changing TextRenderingHint to SingleBitPerPixel or SingleBitPerPixelGridFit helps - text is never wrapped (but looks ugly as hell). Unfortunately, this does not solve the problem, because if I add text to the GraphicsPath (what in the end I do in my App), there is no way to emulate SingleBitPerPixelGridFit setting. Commented Aug 17, 2011 at 18:17
  • There isn't. You'll have to deal with the limitations, this problem won't go away until monitors get the kind of resolution that printers have so that true resolution independent text rendering becomes feasible. There is a long way to go. Consider WPF to get ahead. Commented Aug 17, 2011 at 18:21
  • @Hans right now I'm limited to .NET 2.0, so WPF is not an option. But even if I could use WPF, the amount of work to port the code would be massive. As an alternative, I thought of converting text to GraphicsPath and then drawing it... but there are some possible issues: path would be updated only when text changes, so overall overhead would be minimal. But would grow up drastically during text input as my UI is kind of WYSIWYG. So the GraphicsPath would have to be recreated on every keystroke during input. I'm afraid think that this might be a serious performance bottleneck :( Commented Aug 17, 2011 at 18:58

1 Answer 1

2

Thanks to clues from Hans, the possible solution is to set Graphics.TextRenderingHint to SingleBitPerPixel or SingleBitPerPixelGridFit - it helps and rendered text looks always like the first one. But there is no anti aliasing and text looks ugly (like in second example).

Unfortunately this does not solve my problem, because the text is later converted to GraphicsPath and the result is always like the second one shown on example image. However, there is an alternative solution for that problem: converting text to GraphicsPath first and then drawing it.

However there are some possible issues:

  1. Make sure that the GraphicsPath is updated only when text changes, so overall overhead would be minimal.
  2. Be aware that the overhead would grow up drastically during text change - but this is important only if you are continuously displaying text during user input like in WYSIWYG app. The GraphicsPath would have to be recreated on every keystroke during text input. This might be a serious performance bottleneck. Make sure you test for a target configuration as your mileage may vary.
  3. Graphics.SmoothingMode needs to be set to AntiAlias (or HighQuality which is the same) to get smooth curves - yet another thing that might affect performance.

The most interesting part is that the solution with text converted to GraphicsPath outperforms traditional Graphics.DrawString method. Also note that the font itself is an important factor - more complex fonts with fancy-shaped letters uses more curve points hence they need more CPU time to draw.

During my tests I've noticed visible slowdowns when strings were longer that few thousand chars (i5 760 CPU, only one large GraphicsPath to draw)

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.