QPainter::drawText, get bounding boxes for each character

sashoalm picture sashoalm · Nov 13, 2012 · Viewed 7.2k times · Source

I'm using QPainter to draw multiline text on QImage. However, I also need to display a colored rectangle around each character's bounding box.

So I need to know the bounding box that each character had when being drawn.

For example, for

painter.drawText(QRect(100, 100, 200, 200), Qt::TextWordWrap, "line\nline2", &r);

I would need to get 10 rectangles, taking into account newlines, word-wrap, tabs, etc.

For example, the rectangle of the second 'l' would be below the rectangle of the first 'l', instead of being to the right of 'e', because of the newline.

Something like the coordinates of the red rectangles in this picture (I've put them by hand so they're not really the correct positions):

enter image description here

Answer

Mark Stevens picture Mark Stevens · Nov 13, 2012

This may not be the best solution, but it's the best one I can think of.

I believe you will have to "do it yourself". That is, instead of drawing a block of text, draw each character one at a time. Then you can use QFontMetrics to get the bounding box of each character.

It's a little work, but not too bad. Something like (pseudo code, not code):

QFontMetrics fm(myFont, paintDevice);
int x = startX;
int y = startY;
for (unsigned int i = 0; i < numChars; i++)
{
    char myChar = mystr[i];  // get character to print/bound
    QRect rect = fm.boundingRect( myChar );   // get that char's bounding box
    painter.drawText(x, y, Qt::TextWordWrap, mystr[i], &r);  // output char
    painter.drawRect(...); // draw char's bounding box using 'rect'
    x += rect.width();     // advance current position horizontally

    // TODO:
    // if y > lineLen      // handle cr
    //     x = startX;
    //     y += line height

}

Check out QFontMetrics, it has a number of different methods for getting bounding boxes, minimum bounding boxes, etc.

QFontMetrics 4.7

Ahhh... I see now that the overload you're using returns the actual bounding rect. You can just use that and skip the QFontMetrics if you like - otherwise the overall algorithm is the same.