GDI+ Text, Resolution Independence, and Rendering Methods.
Or - Why does my text look different in GDI+ and in GDI?
- Summary
- Resolution independent layout
-
Grid fitting and hinting, and their disproportionate effect on glyph widths
- How GDI+ compensates for Grid
Fitting.
- How to display adjacent text
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.
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, 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.
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:
- The line is allowed to contract by up to an em without any change of glyph spacing.
- Remaining contraction is made up by increasing the width of any spaces between words,
to a maximum of doubling.
- 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
- GDI+ is using design widths to layout the string, and so measures he whole string
longer than GDI.
- GDI+ has allowed the string to stop short of the far end by 1 em
- 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.
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:
- Always pass MeasureString and DrawString a StringFormat based on the typographic
StringFormat (GenericTypographic).
- 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.