Details
-
Bug
-
Resolution: Unresolved
-
P3: Somewhat important
-
None
-
5.12.3
-
None
Description
Currently, we are replacing the deprecated QFontMetrics::width method. Tthe use case is for example having a string and wanting to derive a minimum window width from it. The problem appears when the string has leading or trailing spaces (or the string is a single space). Those get sometimes ignored other times, they don't. The documentation has a note in boundingRect( QChar ) that a single space should return bounding rectangle with zero width, which kinda makes sense. This note is note in the method for QFontMetrics::boundingRect( QString ).
Attached is a small program to calculate some widths:
#include <QDebug> #include <QFontMetrics> #include <QApplication> #include <QStringList> int main( int argc, char** argv ) { QApplication app( argc, argv ); // without this, QFontMetrics segfaults! QStringList fontFamilies{ "Calibri", "Times", "Dejavu", "Courier" }; for ( const auto& fontFamily : fontFamilies ) { QFontMetrics metrics{ QFont( fontFamily ) }; qDebug() << "font family:" << fontFamily; qDebug() << "font height:" << metrics.height(); qDebug() << "text width horizontalAdvance boundingRect.width boundingRect"; qDebug() << "------------------------------------------------------------"; QStringList textSamples{ "M", " ", "MM", " ", "M ", " M", "M ", " M" }; for ( const auto& text : textSamples ) { qDebug() << text << metrics.width( text ) << metrics.horizontalAdvance( text ) << metrics.boundingRect( text ).width() << metrics.boundingRect( text ); } qDebug() << ""; } return 0; }
This is the output:
font family: "Calibri" font height: 16 text width horizontalAdvance boundingRect.width boundingRect ------------------------------------------------------------ "M" 14 14 12 QRect(1,-12 12x16) " " 4 4 0 QRect(0,-12 0x16) "MM" 27 27 26 QRect(1,-12 26x16) " " 7 7 4 QRect(0,-12 4x16) "M " 17 17 13 QRect(1,-12 13x16) " M" 17 17 17 QRect(0,-12 17x16) "M " 21 21 17 QRect(1,-12 17x16) " M" 21 21 21 QRect(0,-12 21x16)font family: "Times" font height: 22 text width horizontalAdvance boundingRect.width boundingRect ------------------------------------------------------------ "M" 14 14 14 QRect(0,-17 14x22) " " 4 4 0 QRect(0,-17 0x22) "MM" 28 28 28 QRect(0,-17 28x22) " " 8 8 4 QRect(0,-17 4x22) "M " 18 18 14 QRect(0,-17 14x22) " M" 18 18 18 QRect(0,-17 18x22) "M " 22 22 18 QRect(0,-17 18x22) " M" 22 22 22 QRect(0,-17 22x22)font family: "Dejavu" font height: 19 text width horizontalAdvance boundingRect.width boundingRect ------------------------------------------------------------ "M" 14 14 12 QRect(1,-15 12x19) " " 5 5 0 QRect(0,-15 0x19) "MM" 28 28 26 QRect(1,-15 26x19) " " 10 10 5 QRect(0,-15 5x19) "M " 19 19 13 QRect(1,-15 13x19) " M" 19 19 18 QRect(0,-15 18x19) "M " 24 24 18 QRect(1,-15 18x19) " M" 24 24 23 QRect(0,-15 23x19)font family: "Courier" font height: 19 text width horizontalAdvance boundingRect.width boundingRect ------------------------------------------------------------ "M" 10 10 10 QRect(0,-14 10x19) " " 10 10 0 QRect(0,-14 0x19) "MM" 19 19 20 QRect(0,-14 20x19) " " 19 19 10 QRect(0,-14 10x19) "M " 19 19 10 QRect(0,-14 10x19) " M" 19 19 20 QRect(0,-14 20x19) "M " 29 29 20 QRect(0,-14 20x19) " M" 29 29 30 QRect(0,-14 30x19)
Personally, I was a bit surprised to see " " (single space) having a bounding box width of 0. But if defined by the inked pixels, it makes sense. But then there is " " (two spaces), which suddenly has a nonzero width. And then there also is " M" which is larger than a single "M" because of the leading space.
In general, it looks like the algorithm only ignores the last single character trailing space and the rest adds to the width. This is very crude and looks almost like a bug?
P.S.: Some bounding boxes begin at x=1 instead of x=0, which I also find weird.