the Fiddler's picture

New text renderer

Project:The Open Toolkit library
Assigned:the Fiddler

I have just committed a WIP implementation of a new text renderer to the text branch. Improvements:

  1. Simpler to use.
  2. More modular. It is now possible to have different GL1/GL2/GL3-level output or text layout providers. It is also possible to specify your own implementations (for example if you wish to integrate this into your engine).
  3. More accurate rendering (better grid fitting).
  4. Improved speed and reduced GC pressure through caching.
  5. Lower texture memory consumption.

The new implementation is based on GdiPMeasureCharacterRanges, which provides better control over text layout, when compared to MeasureString (the old implementation). Text is now cached on two levels, rasterized glyphs (loaded in texture memory) and laid out text. The public API looks like this:

// No TextureFonts, TextHandles or anything.
TextPrinter text = new TextPrinter();
text.Print("Hello, World!", font);
text.Print(fps.ToString(), font, TextPrinterOptions.NoCache);
TextExtents extents = text.Measure("ABC", font);
RectangleF bbox = extents.BoundingBox;
RectangleF char_pos = extents[1];  // Returns the position of "B" - useful for e.g. drawing a caret or selecting text.

The implementation in SVN is still under heavy development. Caveats:

  • (Fixed) Single texture sheet limitation remains. This is proving more difficult than expected.
  • (Fixed) Sometimes binds the wrong texture for glyphs (funky results!)
  • Trying to draw / measure uncached strings with newlines will cause GC pressure. This is the unfortunate result of a bug in Mono's GdiPMeasureCharacterRanges implementation. Fortunately, this is unlikely to cause problems in real life (you don't usually create dynamic text with newlines in a tight loop).

Anyone still interested despite these problems, you can test the code from the text branch. Expect screenshots shortly.

Edit: Clarified GC-pressure caveat.


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture


This is an upstream bug in libgdiplus, which doesn't handle corner cases such as word wrapping.

A possible workaround it to use 0 for the width and height of the text, which should completely turn off word wrapping.

TextLocation = new RectangleF(100.0f, 100.0f, 0, 0);

Edit: It seems that Mono includes pango backend which handles these cases correctly. It is disabled by default, however.

Edit 2: Reported the bug upstream at

Mincus's picture


Thanks for the response.
Using 0 for the width and height doesn't seem to be working unfortunately, neither did TextLocation.Size = SizeF.Empty;
No matter for now, it's not integral to what I'm working on and it's reported.

the Fiddler's picture


Just to gather some data on this bug, which version of Mono are you using? IIRC, there was a bug with TextLocation.Size = SizeF.Empty in Mono <= 1.9.2.

objarni's picture


I experience a similar "feature" running the text example under Ubuntu 8.10, default mono version (1.2.6?).

the Fiddler's picture


The feature is still there with Mono 2.2 and I don't think 2.4 will fix that either.

One solution would be to add a different codepath that uses Mono.Pango for text layout - but I'm not the one who's going to do that (even though it should be a relatively simple job). Now, if there was some willing to implement this... ;)

Mincus's picture


Xubuntu 8.10 64-bit running Mono 1.9.1: Confirmed doesn't work even with SizeF.Empty.
Xubuntu 8.04 32-bit running Mono 1.2.6: Again confirmed doesn't work even with SizeF.Empty.

Looking on the Mono downloads page:
These are the expected versions.

Pango looks interesting, I'll have a play but won't promise anything. ;o)