Details
-
Bug
-
Resolution: Done
-
P2: Important
-
5.6.0
-
None
-
Windows 10
Description
Using QPainter::drawTiledPixmap with a pixmap width > 2048 causes the image to repeat after 2048 pixel instead of after the actual width. The following sample triggers this (you need a big enough screen to stretch to the window to over 2048 pixel width in logical space. See also the attached image.
#include <QtGui> #include <QWidget> #include <QApplication> class QTestWidget : public QWidget { virtual void paintEvent(QPaintEvent* event) override { QPainter painter(this); const QRect rect = contentsRect(); QImage img(rect.width(), 1, QImage::Format_ARGB32); for (int x = 0; x < img.width(); ++x) { QColor color = QColor::fromHslF((double)x / img.width(), 1, 0.5); img.setPixel(x, 0, color.rgba()); } QImage img565 = img.convertToFormat(QImage::Format_RGB16); { QPainter painter565(&img565); QBrush brush(img565); // Triggers blend_tiled_rgb565 opague bug painter565.fillRect(rect.adjusted(0, 0, 0, -rect.width() / 2), brush); } painter.drawTiledPixmap(rect.adjusted(0, rect.height() / 2, 0, 0), QPixmap::fromImage(img565)); // Triggers blend_tiled_argb bug painter.drawTiledPixmap(rect.adjusted(0, 0, 0, -rect.height() / 2), QPixmap::fromImage(img)); } }; int main(int argc, char *argv[]) { QApplication app(argc, argv); QTestWidget test; test.show(); return qApp->exec(); }
The error is in the function blend_tiled_argb in qdrawhelper.cpp:
while (length) { int l = qMin(image_width - sx, length); if (buffer_size < l) l = buffer_size; const uint *src = (const uint *)data->texture.scanLine(sy) + sx; uint *dest = ((uint *)data->rasterBuffer->scanLine(spans->y)) + x; op.func(dest, src, l, coverage); x += l; length -= l; sx = 0; }
Should be replaced with:
while (length) { int l = qMin(image_width - sx, length); if (buffer_size < l) l = buffer_size; const uint *src = (const uint *)data->texture.scanLine(sy) + sx; uint *dest = ((uint *)data->rasterBuffer->scanLine(spans->y)) + x; op.func(dest, src, l, coverage); x += l; sx += l; length -= l; if (sx >= image_width) sx = 0; }
This way it would function the same as e.g. blend_tiled_generic_rgb64 above it in the same file. The same pattern is also used incorrectly in blend_tiled_rgb565. I've tested both on the current dev branch and the problem exists there as well.