Welcome to WindowsClient.net | Sign in | Join

GDI+ Text, Resolution Independence, and Rendering Methods.

Or - Why does my text look different in GDI+ and in GDI?

  1. Summary
  2. Resolution independent layout
  3. Grid fitting and hinting, and their disproportionate effect on glyph widths
  4. How GDI+ compensates for Grid Fitting.
  5. How to display adjacent text

Summary

GDI+ text layout is resolution independent, and thus different from GDI.

Forms built with GDI+ text look the same at all resolutions and when printed.

In grid-fitted rendering (the default), font hinting usually changes the width of glyphs. When a sequence of glyphs all increase significantly in width GDI+ may have to close up the text to remain resolution independent. In pathological cases (such as a long run of bold lower case 'l's in 8 pt Microsoft Sans Serif on a 96 dpi display), the space between some letters can disappear completely.

Resolution independent layout

The GDI+ APIs DrawString and MeasureString lay out text independent of device resolution, thus a paragraph of text takes the same number of lines, no matter what device it is displayed on. There are many benefits:

  • If a form field is sized to fit some static text on one developers machine, it will fit that text on all machines the application runs on, regardless of screen resolution, or accessibility settings.
  • When the form is printed, it will layout the same as it looks on the screen.
  • A form recorded in a metafile retains its layout.

Consider the forms designer working with resolution dependant layout. A box is defined on the form for some text - a title maybe. The title is typed, and the box adjusted to fit. Sadly, unlike the lines, the text will not scale linearly with resolution, so the box will only fit correctly at the resolution the designer was working in.

For graphical objects, such as lines and pictures, a different device resolution simply means a different scale factor at display time. A line 100 pixels long on a 96 dot per inch (dpi) display, will be drawn 125 pixels long on a 120 dpi display, and 625 pixels long on a 600 dpi printer.

For text, the font height will be scaled appropriately for the device resolution: a font that is 20 pixels high on a 96 dpi screen will be rendered 25 pixels high on a 125 dpi screen and 125 pixels high on a 600dpi printer. However the width of individual glyphs will scale only approximately with the height. The exact width is also dependant on hinting (or grid fitting) that has been included in the font to adjust glyphs for legibility.

Grid fitting and hinting, and their disproportionate effect on glyph widths

Grid Fitting, also known as hinting, is the process of adjusting the position of pixels in a rendered glyph to make the glyph easily legible at smaller sizes. Techniques include aligning glyph stems on whole pixels and ensuring similar features of a glyph are affected equally. Font designers spend many hours per glyph defining hinting.

For example, consider the letters 'elsw' from Times New Roman, rendered at 8 points on various resolutions, using GDIs standard grid fitting.

In this chart, each glyph is drawn at high resolution in gray, then the actual pixels representing it at a given size and dpi are drawn on top as black circles. 96 dpi is the most widely used display resolution, also known as 'small fonts' in control panel/display/settings/advanced/general. 120 dpi corresponds to 'large fonts'. 150dpi is becoming a common laptop LCD screen resolution. 600dpi is a current low end laser printers resolution.

Notice how at 96 dpi (standard screen resolution) there are very few pixels in an 8pt glyph. The 8pt 96dpi lower-case 's' for example has almost none of the character of the glyph it is intended to portray.

The figures below each glyph show the difference between the designed width of the glyph, and the width after grid fitting.  The left hand figure is the difference as a positive or negative percent. The right hand figure is the difference in pixels at the display resolution. For example, the top left glyph, the 8pt 96dpi lower-case 'e' is about 11% or .61 pixels narrower after grid fitting.

If there were no grid fitting, we would expect the only difference between designed and displayed width would be the effect of rounding to the nearest pixel. In this case we would never see a width difference of more than 1/2 a pixel.  At the highest resolution (2400dpi) this is indeed the case, the biggest difference seen here amounting to 0.37 pixels.

However at lower resolutions the effect of grid fitting can exceed or swamp simple rounding.

How GDI+ compensates for Grid Fitting.

When grid fitting generates glyphs narrower than designed

The worst case above is the 96dpi lower-case 'w'. 'w' is a particularly difficult glyph to hint well: the stems must appear symmetrical, evenly spaced and equally thick. Careful hinting has resulted in a good appearance, but the hinted glyph is over 2 pixels narrower than its design width. A string composed only of 8pt 96dpi 'w's will be 23% shorter when grid fitted.

When GDI+ displays a line of grid fitted glyphs that are shorter than their design width, it follows these general rules:

  1. The line is allowed to contract by up to an em without any change of glyph spacing.
  2. Remaining contraction is made up by increasing the width of any spaces between words, to a maximum of doubling.
  3. Remaining contraction is made up by introducing blanks pixels between glyphs.

The following example shows how GDI and GDI+ display the string 'wwwww wwwww wwwww wwwww wwwww' in 8pt Times New Roman at 96dpi with grid fitting.

GDI (resolution dependant) display
GDI+ (resolution independent) display

This shows

  1. GDI+ is using design widths to layout the string, and so measures he whole string longer than GDI.
  2. GDI+ has allowed the string to stop short of the far end by 1 em
  3. GDI+ has placed remaining expansion in the spaces.

The following example takes the same strings with the spaces removed. Now GDI+ cannot use the spaces to compensate for the contractions caused by grid fitting and instead inserts an extra pixel between some of the glyphs.

GDI (resolution dependant) display
GDI+ (resolution independent) display

When grid fitting generates glyphs wider than designed

Now consider the following chart of Microsoft Sans Serif Bold 8pt. Microsoft Sans Serif is the default user interface font for Windows 2000 and higher.

 

In this case most of the glyphs are wider than design at 96 and 120dpi. Although many are not much larger, there are some particularly difficult cases.

Consider a string of 96dpi lower-case 'l's. Although each 'l' is only .16 pixels wider than its design width, a run of just 7 'l's is enough to exceed the runs design width by a whole pixel. In this case we need to compress the string by one pixel. Unfortunately the shape of the lower case 'l' behaves very poorly when a pair are overlapped by one pixel: since there is only one blank pixel column, overlapping causes the adjacent glyphs to become solid.

The following example shows a run of 19 'l's displayed by GDI and by GDI+

GDI (resolution dependant) display
GDI+ (resolution independent) display

Notice how in GDI+ the last two 'l's are touching.

You can also see in this example that GDI+ adds a small amount (1/6 em) to each end of every string displayed. This 1/6 em allows for glyphs with overhanging ends (such as italic 'f'), and also gives GDI+ a small amount of leeway to help with grid fitting expansion.

How to display adjacent text

Maybe you would like to display two strings side by side such that they appear as one string. You might do this if you are writing an editor, or are displaying text with a formatting change inside the paragraph.

Warning: Building lines of text with multiple DrawString calls is inherently unable to display general International text. In particular, In Arabic, Hebrew, Farsi and other right-to-left languages, strings advance generally from right to left, with localized order reversal around numbers and around western phrases. DrawString handles within one output, using bidirectional behaviour defined by Unicode. The rules are complex. See The Unicode Standard Version 3.0 section 3.12.

The default action of DrawString will work against you in displaying adjacent runs: Firstly the default StringFormat adds an extra 1/6 em at each end of each output; Secondly, when grid fitted widths are less than designed, the string is allowed to contract by up to an em.

To avoid these problems:

  1. Always pass MeasureString and DrawString a StringFormat based on the typographic StringFormat (GenericTypographic).
  2. Set the Graphics TextRenderingHint to TextRenderingHintAntiAlias. This rendering method uses anti-aliasing and sub-pixel glyph positioning to avoid the need for grid-fitting, and is thus inherently resolution independent.

The following table compares GDI, GDI+ GridFitted and GDI+ anti-alias text for the examples considered above.

GDI (resolution dependant) display
GDI+ (resolution independent) grid fitted display
GDI+ (resolution independent) anti alias display

While Anti-alias text can look a little gray at very small sizes (this is 8pt), it shows the shape of the glyphs far more accurately than grid fitted text, and does not suffer from the glyph position adjustment described above for grid fitting.