PDA

View Full Version : QFontMetrics boundingRect vs horizontalAdvance with monospaced fonts



tuli
5th May 2021, 10:01
Hi,

I am trying to understand the differences between

fontmetrics.horizontalAdvance(str) and fontmetrics.boundingRect(str).width().

I understand it's related to kerning, but with my experiments, the bounding rect just doesnt "bound" the string.
Also, with monospaced fonts kerning should not be a concern, right?

Consider this code:


{
QFont fixedfont = QFontDatabase::systemFont(QFontDatabase::FixedFont );
fixedfont.setPointSize(9);
QFontMetrics fontmetrics = QFontMetrics(fixedfont);
QString str = "abcdefghijk 0123456789";

int a = fontmetrics.horizontalAdvance(str);
int b = fontmetrics.boundingRect(str).width();
int c = fontmetrics.averageCharWidth() * str.length();
assert(b == c);

QPixmap pixmap(QSize(b, fontmetrics.height()));
pixmap.fill(Qt::white);
QPainter painter(&pixmap);
painter.setFont(fixedfont);
painter.drawText(QPoint(0,fontmetrics.height()), str);
pixmap.save("fontm.bmp", "bmp");

}


Whereas horizontalAdvance gives the correct result:

13636


boundingRect.width() truncates the text:

13637



I would understand if HA had some extra space at the end. But as is, BR just doesnt bound the text. Why not?

In other words, I dont understand why with a fixed-width font, averageCharWidth * str.length() doesnt equal the pixels the string occupies when drawn at (0,0).

ChrisW67
6th May 2021, 10:02
QFontMetrics::boundingRect() is returning a rectangle width from the leftmost black pixel to the rightmost black pixel (Assuming a black pen).

The horizontalAdvance includes the whitespace that precedes/follows the end characters when rendered.
If you use QPainter::boundingRect() you will get a rectangle that contains the string neatly

The averageCharWidth() is that of all the glyphs in the font (not just the ones in your string), looks to be the rendered pixels only, and may be subject to rounding.