Main Site Documentation

Text Rendering Performance


#1

This is a rather long question so if you make it to the end, thank you.
I’m looking for any suggestions that might help me, even if it’s a totally different solution.

With RLP removing all other speech issue,
the rendering of Text has become the biggest bottleneck in our application.

In the application I define the concept of a TextElement,
basically a string that will be rendered within a master bitmap
with additional properties such as width, height, alignment, scrolling, offset, etc…

Let’s say I have a master bitmap with a size of 64x16
and inside (or on top of, however you want to look at it) I
draw the various fields.

Since the fields have a certain width and an X/Y position in the master bitmap, if the text I’m drawing exceeds that width it should simply be truncated.

Previously I looked at the Bitmap.DrawTextInRect() methods,
but they do not behave as expected. For example, text is correctly
trimmed on the right side but not on the left side (negative values of X, although that’s not important for this discussion). In summary the
behaviour of those methods make it really hard to properly scroll text, etc…

So I had to fall back to drawing a bitmap within a bitmap.

Consider the following Render() method:

public void Render(Bitmap surface)
{
    using (var bitmap = new Bitmap(this.Width, this.Height))
    {
        bitmap.DrawText(Text, TextFont, Color.White, GetAlignedTextXOffset(), TextYOffset);
        surface.DrawImage(X, Y, bitmap, 0, 0, Width, Height);
    }
    UpdateTextXOffset();
}

This little construct allows me to display, scroll, align, flash, etc… text but is far from efficient.

If I only need to draw a few fields, there’s no problem,
but when the number of fields increases so does the time to render everything, really slowing things down.

Just to give you an idea of how fields are rendered:

var surface = new Bitmap(64,16);
for(int i = 0; i < fields.Length; i++)
{
    fields[i].Render(surface);
}

var surfaceBitmap = surface.GetBitmap();
var ledBitmap = new byte[size / 8];

rlp.Convert32BPPBitmapToLedBitmap(surfaceBitmap, ledBitmap, width, height);
rlp.SendData(null, ledBitmap);

My first idea to speed things up was to remove the inner bitmap in the Render() method and extract it somewhere else so a single bitmap could be passed into the Render() method of all field instances, but since nog every field has the same dimensions it would defeat the reason I introduced it in the first place (to correctly trim texts).

So I’m wondering if anybody has suggestions of how I could optimize this process.

Controllers like this have been developed for years by C developers (on the classic micro controllers) so I’m wondering what do they normally use to render text?

Is there a native way to render tinyfont text?

In any case, thnx for reading :slight_smile:


#2

Do you use different size fonts or it is always the same size?

If same size, then you can RLP the draw text routine to fit your exact needs and it will be very fast


#3

That depends on the demands of the customer.
The idea is we generate a font for them based on their requirements.
(Using the tiny font tool).

In 90% of the cases only one font will be used at a time,
but it’s quite possible a customer will use different fonts for different fields on the screen.


#4

Gus,

Can you explain why it would make things easy if they are the same size?
I know our chinese developers always hammered on the size as well (the height only in their case) but they never explained why.

And how exactly would you draw it then ?

Thnx.


#5

The internal NETMF code for drawing text is not simple. It renders fonts of all shapes and all sizes. This comes are performance price.

Now, you can tweak your own character writing algorithm to be very fast but then you can’t dynamically use any font you like.

This code shows how to draw text the VERY simple way http://www.tinyclr.com/downloads/Extension/FEZ_Extensions_Graphical128x64_UEXT_Display.cs


#6

I’ll have a look, thnx