Text rendering methods comparison or GDI vs. GDI+ revised

In this post, hopefully the last on this subject1, I'm going to compare the different text rending methods available for Windows .NET application for standard resolution devices2.
 
I decided to revise my original findings (see: The wonders of text rendering and GDI) and do a comprehensive comparison for three reasons:

  1. In response to my earlier post (see: GDI text rendering to image ) Kris commented he uses GraphicsPath for text rendering to image to achieve better visual quality than standard GDI+ text rendering.
  2. My latest "revelation" (see: Blurry/Fuzzy GDI+ Text Rendering using anti-alias and floating-point Y coördinates ) on improving GDI+ text rendering visual quality.
  3. GDI+ typographic StringFormat can offer good text measurement for custom text layout.

 
I'm going to show comparison (visual and performance) between:

  1. GDI using native methods via PInvoke.
  2. GDI using .NET managed TextRenderer class.
  3. GDI+ using clear-type/Anti-Alias TextRenderingHints .
  4. GDI+ using Default/Typographic StringFormat .
  5. GraphicsPath using default/high quality SmoothingMode .

 
The scope of the comparison is to render text on display/bitmap devices and not high-resolution devices like printers2. This is due to GDI+ resolution independent rendering has better quality with high-resolution devices, also clear-type is not applicable for non-display devices.
 
For transparency and validation, I added a 12 with the code I used for the comparison, so if you think my results/tests are incorrect please point me to the errors.
 

Simple visual comparison

To get the idea how different text rendering method compares visually I start by rendering the same string ("Test-s.tri,ng m(g=j{}3)"), using the same font (Arial 11p regular), in two columns: the left has gradient background from grey to white and the right has transparent background, using eight rendering methods: (top to bottom)

  1. GDI using TextRenderer.
  2. Native GDI.
  3. GDI+ with clear-type hint.
  4. GDI+ with clear-type hint and typographic format.
  5. GDI+ with Anti-Alias hint.
  6. GDI+ with Anti-Alias hint and typographic format.
  7. GraphicsPath with default quality.
  8. GraphicsPath with high quality.

 
clip_image001.png
Figure 1-1: Visual comparison of 8 text rendering methods on gradient and transparent background.
 
See also samples using different fonts: Tahoma 10p, Segoe UI 9p and Sans Serif 8.25p (default font).
 

Findings:

  • GDI uses clear-type rendering. I didn’t find a way to change this behavior, so I'm assuming this is the way it is.
  • Clear-type rendering does not handle transparent background, the surrounding pixels that are affected by a clear-type algorithm become black.
  • TextRenderer doesn't handle gradient background. This is specific to image rendering. Native GDI has the same problem that is solved by buffer copying3.
  • Native GDI black rectangle is the result of buffer copying required for GDI image rendering, as already pointed GDI doesn't work with transparent background.
  • GDI+ with an anti-alias rendering hint adds a little width to the text, it looks a little blurry compared to clear-type rendering.
  • GDI+ using clear-type is almost identical to GDI rendering, the next section will show a deeper comparison to highlight the difference.
  • GDI+ with anti-alias rendering hint and typographic format provides the best result for text on a transparent background.
  • GraphicsPath visual quality is inferior to all other methods4 even when using high quality smoothing mode. Default quality is almost unreadable, while high quality is blurry and virtually bold like width, very different from the expected result.

 

Deep GDI / GDI+ visual comparison

As seen in the previous section, the difference between GDI and GDI+ text rendering can be subtle. This is because it is strongly affected by the font family, size, style and even the version of the operating system used. If you are interested in the fine details, there is an excellent MSDN article: Why text appears different when drawn with GDIPlus versus GDI.
 
To show a sample case where GDI+ text rendering fails visually I used a string containing 9 consecutive lowercase 'L' characters using "Sans Serif" 9p bold font:

 
clip_image002.png
Figure 2-1: Visual comparison with specific string and font combination.
 
Due to GDI+ resolution independent rendering it was forced to squash the l's together as in this font each 'l' character takes a little more pixel space than it should. Also note the "HtmlLabel" string is more spacious in GDI rendering than in GDI+ resulting in clearer text.
 
Beyond a specific sample, to see the effect of GDI+ rendering issues on different fonts I created a test to render test string with all available fonts on the system using GDI and 3 GDI+ methods. Showing selected samples:

  • Different 10p fonts, as indicated by rendering font name.
  • Top to bottom: Native GDI, GDI+ with clear-type hint and typographic format, GDI+ with Anti-Alias hint and typographic format, GDI+ with Anti-Alias hint and default format.
  • Two samples showing the difference between the measured and rendered text size (1.5,1.6).
  • Top samples rendered in Windows 7 (1.), bottom on Windows 8 (2.).

 
clip_image003.png
Figure 2-2: Visual comparison of 4 rendering methods using different fonts.
 

Findings:

  • GDI+ resolution independent rendering may result in letters "touch" each other resulting in less clear text rendering.
  • GDI+ with anti-alias is lighter and more blurry compared to clear-type rendering, darkening the rendered text by changing contrast can help.
  • GDI+ may return incorrect size measurements for rendered text resulting in bad multi text layout when two words are either too close or too far apart.
  • Windows 8 shows much better results for the same fonts than Windows 7, it seems Microsoft is working on improving common fonts rendering.

 

Performance comparison

To test the rendering performance of each method I have run a loop rendering a test string ("Test-s.tri,ng m(g=j{}3)") 30000 times in three iteration (10000 in each iteration) using three common fonts. For native GDI rendering the extra work required for rendering was done in each iteration and not for each string rendering.
 

Method Time in milliseconds X times slower than Native GDI X times slower than DrawString AA
Native GDI 947
DrawString AA (GDI+) 2819 3.0
DrawString AAT (GDI+) 2691 2.8
DrawString CT (GDI+) 3157 3.3 1.1
TextRenderer (GDI) 18375 19.4 6.5
GraphicsPath 10552 11.1 3.7
GraphicsPath HQ 15001 15.9 5.3

Figure 3-1: Performance comparison on HP Z800, Xeon 2.26 GHz, NVIDIA Quadro, Windows 8 machine.
 

Method Time in milliseconds X times slower than Native GDI X times slower than DrawString AA
Native GDI 525
DrawString AA (GDI+) 1494 2.8
DrawString AAT (GDI+) 1467 2.8
DrawString CT (GDI+) 2015 3.8 1.3
TextRenderer (GDI) 9169 17.5 6.1
GraphicsPath 7352 14.0 4.9
GraphicsPath HQ 10281 19.6 6.9

Figure 3-2: Performance comparison on HP EliteBook 8560w, i7 2.7GHz NVIDIA Quadro 1000M, Windows 8.1 machine.
 

Findings:

  • Native GDI is by far the fastest rendering method.
  • Managed GDI using TextRenderer performance is unbelievably slow, especially considering it’s a wrapper of native GDI.
  • GraphicsPath is on the same, horrible, performance level of TextRenderer. The variance of its result has no special interest as it doesn't come near the best performing methods.
  • Using typographic format, with GDI+, has no effect on performance.
  • There is a difference between machines but the relative performance difference between methods remains stable.

 
Text measurement performance
In addition to text rendering performance there is also a significant difference in text measurement performance as well. I have skipped it as it is similar to the differences in rendering performance and I covered it well in my previous post.
 
Native GDI+
It is possible that using native GDI+ method via PInvoke, in a similar way native GDI methods are used, can improve performance of GDI+ text rendering. I haven't tested this theory due to time constrains and the confidence it can't be faster than native GDI based on this performance test.
 

Conclusions

  • GDI text rendering provides the best visual quality but doesn't support transparent background.
  • Native GDI rendering provides the best performance.
  • GDI+ with anti-aliasing and typographic format provides the best performance and visual quality for transparent background rendering.
  • GraphicsPath rendering method visual quality4 and performance is disappointing.
  • Text rendered in each rendering method is visually different.
  • As Microsoft will improve their fonts and display resolution (DPI) will raise, GDI+ text rendering will improve to a point where GDI has no significant visual benefit.

 

Tips

 

Code

Too long to burden the post, see it on gist.
 


  1. Earlier posts: The wonders of text rendering and GDI, Using native GDI for text rendering in C#, Transparent text rendering with GDI, GDI text rendering to image, Blurry/Fuzzy GDI+ Text Rendering using AntiAlias and floating-point Y coördinates
  2. Display/Bitmap (96-150 DPI) and not printers (600-2400 DPI). 
  3. See GDI text rendering to image for my solution to this issue. 
  4. Not including comparing to transparent background rendering with methods that don't support it. 
Advertisement

4 comments on “Text rendering methods comparison or GDI vs. GDI+ revised

  1. […] Text rendering methods comparison or GDI vs. GDI+ revised. […]

  2. […] Text rendering methods comparison or GDI vs. GDI+ revised . […]

  3. […] built. If you have nothing better to do, read up on the differences on The Art of Dev, here and here. In nearly all respects GDI+ appears to be inferior, but it can do one thing that GDI cannot […]

  4. MV says:

    Very useful. Thanks!

Leave a Reply to Generate image from HTML using HTML Renderer « The Art of Dev Cancel reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s