tags:

views:

152

answers:

3

I have a MFC application that displays annotated maps, which can include a large amount of text. While the size and font of the text does not tend to change much, the rotation of the text varies considerably, in order to be aligned with the surrounding line work. This basically means that I have to do create and select a new font into the display context each time the rotation changes. Something like;

if (TextRotationChanges)
{
    m_pFont = new CFont;
    m_lf.lfEscapement = NewRotation;
    m_pFont->CreateFontIndirect(&m_lf);
}
CFont *OldFont = m_pDC->SelectObject(m_pFont);
m_pDC->TextOut(x,y,text,strlen(text));
m_pDC->SelectObject(OldFont);

This is obviously slow when dealing with large amounts of text. Is there any way of speeding this up without going to a different display engine such as D3D or OpenGL? Put another way, can I change the text rotation in the existing selected font?

n.b. I'm already carrying out other obvious optimizations, like ensuring text is on screen at a visible size prior to attempting to draw it.

A: 

You should first draw it on the invisible DC and than copy to your DC.

Oleg
+1  A: 

Are you sure that the problem is the font and not the TextOut?
Oleg's idea of using a back buffer isn't bad if you want to avoid flickering.

If I was going to use a graphic engine I'd try Cairo because it's designed specifically for that kind of jobs.
(it can render directly on win32 DC surfaces)

Nick D
+1  A: 

Creating and destroying many GDI object can be slow. What you can do is create 360 fonts at the startup of your program so that you can SelectObject() from a lookup table with pre-made fonts at the correct rotation, rather than creating them on-demand. Or you can rotate your text by not using lfEscapement but by using SetWorldTransform() with the appropriate rotation matrix (again, you could cache rotation matrices for speed). You'd have to test if it will actually give you a speed gain.

See my question here http://stackoverflow.com/questions/2014757/setworldtransform-and-font-rotation for an issue I had/have with that approach, though (haven't had time to go back and look into it).

Roel
+1 for pre-creating an array of fonts at each degree of rotation, hadn't thought of that one at all, but will give it a go. Any idea if I'm going to fall foul of GDI resource limitations if I use this type of approach?
Shane MacLaughlin
If you're hitting the GDI handle limit I don't see any ways around that really - the default is 10k, 360 is a small percentage of that, I think it would be doable. I guess you could write a cache object that would store the X most often used rotations (where X would always be < 360) and replace the least-often used ones when a rotation that is not in the cache is requested, but this much bookkeeping may give too much of a speed hit to make it worthwhile.I guess you could clip all your rotations to multiples of 2, or 3 or 5, dependng on mem reqs; I doubt it'd be an issue, visually.
Roel