In Wpf (4.0) my listbox (using a VirtualizingStackPanel) contains 500 items. Each item is of a custom Type
class Page : FrameworkElement
...
protected over
A big contributor is the fact(based on my experience with GlyphRun which I think gets used behind the scenes) that it uses at least 2 dictionary look-ups per character to get the glyph index and width. One hack I used in my project was I figured out the offset between the ASCII value and the glyph index for alphanumeric characters for the font I was using. I then used that to calculate the glyph indexes for each character rather than doing the dictionary look up. That gave me a decent speed up. Also the fact that I could reuse the glyph run moving it around with a translate transform without recalculating everything or those dictionary lookups. The system can't do this hack on it's own because it is not generic enough to be used in every case. I imagine a similar hack could be done for other fonts. I only tested with Arial,other fonts could be indexed differently. May be able to go even faster with a mono-spaced font since you may be able to assume the glyph widths would all be the same and only do one look up rather than one per character, but I haven't tested this.
The other slow down contributor is this little code, I haven't figured out how to hack it yet. typeface.TryGetGlyphTypeface(out glyphTypeface);
Here is my code for my alphanumeric Arial hack(compatibility with other characters unknown)
public GlyphRun CreateGlyphRun(string text,double size)
{
Typeface typeface = new Typeface("Arial");
GlyphTypeface glyphTypeface;
if (!typeface.TryGetGlyphTypeface(out glyphTypeface))
throw new InvalidOperationException("No glyphtypeface found");
ushort[] glyphIndexes = new ushort[text.Length];
double[] advanceWidths = new double[text.Length];
for (int n = 0; n < text.Length; n++) {
ushort glyphIndex = (ushort)(text[n] - 29);
glyphIndexes[n] = glyphIndex;
advanceWidths[n] = glyphTypeface.AdvanceWidths[glyphIndex] * size;
}
Point origin = new Point(0, 0);
GlyphRun glyphRun = new GlyphRun(glyphTypeface, 0, false, size, glyphIndexes, origin, advanceWidths, null, null, null,
null, null, null);
return glyphRun;
}