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

Bad clip region when using 175% High DPI scaling

    XMLWordPrintable

Details

    • Bug
    • Resolution: Duplicate
    • P2: Important
    • None
    • 6.2.4
    • GUI: High-DPI
    • None
    • Windows
    • 423b6509382c3bcc36eca78ced0254bfb463d017

    Description

      Please use this to reproduce:

      #include <QtWidgets/QApplication>
      #include <QtWidgets/QWidget>
      #include <QtGui/QPainter>
      
      int main(int argc, char** argv)
      {
          QApplication app(argc, argv);
      
          // Simulate calling QWidget::update(). Region in widget coordinate.
          QRegion dirtyRegion;
          dirtyRegion += QRect(0, 0, 1387, 4);
          dirtyRegion += QRect(246, 4, 5, 452);
          dirtyRegion += QRect(1163, 4, 5, 452);
          dirtyRegion += QRect(0, 456, 1387, 5);
          dirtyRegion += QRect(246, 461, 5, 100);
          dirtyRegion += QRect(1163, 461, 5, 100);
      
          // Simulate a widget at (31, 150). Region in tlw's widget coordinate.
          dirtyRegion = dirtyRegion.translated(31, 150);
      
          // Simulate 175% High DPI scaling.
          QTransform dpiScaling = QTransform::fromScale(1.75, 1.75);
          // QTransform dpiScaling = QTransform::fromScale(2.0, 2.0); // for reference image
      
          // Simulate final clip region in tlw's backing store in device coordinate.
          QRegion clipRegion = dpiScaling.map(dirtyRegion);
      
          printf("clipRegion = \n");
          for (QRect r : clipRegion)
              printf("  x=%d, y=%d, w=%d, h=%d\n", r.left(), r.top(), r.width(), r.height());
          printf("\n");
          /*
          clipRegion =
            [0] x=54, y=263, w=2427, h=7
            [1] x=485, y=270, w=9, h=791
            [2] x=2090, y=270, w=9, h=791
            [3] x=54, y=1061, w=2427, h=9
            [4] x=485, y=1069, w=9, h=175
            [5] x=2090, y=1069, w=9, h=175
          Bug: [3].y + [3].h > [4].y
      
          This breaks clip spans generation: https://github.com/qt/qtbase/blob/4af07d6e54091e7a9e413b92b943eee41cb67bb8/src/gui/painting/qpaintengine_raster.cpp#L3830
            while (lastInBand + 1 < numRects && rects[lastInBand+1].top() == y)
              ++lastInBand;
          The code expects ascending and non-overlapping y. lastInBand should be 5 but got 4.
          Result: [5] is ignored unexpectedly.
          */
      
          // Expect:
          // ------------
          //    |     |
          // ------------
          //    |     |
          //
          // Result:
          // ------------
          //    |     |
          // ------------
          //    |
          //
          QImage backstore(2500, 1500, QImage::Format_ARGB32_Premultiplied);
          backstore.fill(Qt::white);
          {
              QPainter p(&backstore);
              p.setClipRegion(clipRegion);
              p.fillRect(backstore.rect(), Qt::yellow);
          }
          backstore.save("C:/temp/cross.png");
      }
      

      QRegion contains 6 rects. After scaling, some rectangles overlap. This breaks clip span generation code, which expects ascending and non-overlapping rects.
      https://github.com/qt/qtbase/blob/4af07d6e54091e7a9e413b92b943eee41cb67bb8/src/gui/painting/qpaintengine_raster.cpp#L3830

      200%: 6 clip regions are filled.

      175%: the last clip region is ignored and not filled.

      Attachments

        Issue Links

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

          Activity

            People

              sorvig Morten Sørvig
              mingxiang Mingxiang Xu
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes