HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Drawing multi-line text fast in C++, MLTextOut

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
fastmltextoutmultilinetextdrawing

Problem

I need to draw a lot of multi-line text to the screen so I first used DrawText but it was getting a bit slow... So I've been looking at a few alternatives: save the drawn text in memory DC's, use Direct3D/Direct2D, write my own function. I don't want my program to be a memory hog so using memory DC's wasn't too great. I don't want to be dependent on D3D either so I was left with one option.

Here is my routine to draw multi-line text using the standard Windows GDI. It splits up the text in lines (split by \r\n's) and then calculates the length of the full line and estimates where it should break.

Since speed is crucial, does anyone sees optimization I could perform to increase speed?

bool MLTextOut(HDC hDC, int x, int y, int cx, int cy, CString str, int nLineHeight = 0)
{
    if (!hDC || cx = rc.bottom)
            break;

        // calculate line length

        GetTextExtentPoint32(hDC, p1, p2 - p1, &sz);

        // if line fits

        if (sz.cx  p1; p3--)
                if (*p3 == _T(' '))
                    break;

            // if it's one word spanning this line, but it doesn't fit... let's clip it

            if (p3 == p1)
            {
                // find first space on line

                for (p3 = p1; p3  p1; p4--)
                        if (*p4 == _T(' '))
                            break;

                    // if it's one word spanning this line, but it doesn't fit... let's clip it

                    if (p4 == p1)
                    {
                        // find first space on line

                        for (p3 = p1; p3  cx);

                if (bContinue)
                    continue;

                ExtTextOut(hDC, x, y + yInc, ETO_CLIPPED, &rc, p1, p3 - p1, NULL);
                yInc += (nLineHeight ? nLineHeight : sz.cy);
                p1 = p3 + 1;
                continue;
            }
        }

        if (p2 == lpszEnd)
            break;
        p1 = p2 + 2;
    }
    return true;
}

Solution

I would split this function into two parts:

  • Text layout part - find positions of text runs / lines of text. You


can use GetTextExtentPoint32 as you did.

  • And drawing using single call of PolyTextOut



That will allow to skip #1 if text position is not changing between WM_PAINTs - in this case you will get just single PolyTextOut call.

Context

StackExchange Code Review Q#4741, answer score: 3

Revisions (0)

No revisions yet.