Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-77648

boundingRect is inconsistent with strings with leading/trailing whitespaces

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • P3: Somewhat important
    • None
    • 5.12.3
    • GUI: Font handling
    • None
    • Linux/X11

    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.

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            esabraha Eskil Abrahamsen Blomfeldt
            uiohbgq uiohbgq
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes