QPainter: fix assert when drawing bitmaps at very near to .5 coord

The code assumed that the rounding of a floating point value, and the
rounding of the sum of that value and an integer, would always snap in
the same direction. But because of accuracy limits (independently
of the rounding function employed), that is not always the case for
fractions very near to .5.

Fixes: QTBUG-122451
Pick-to: 6.6 6.5 6.2 5.15
Change-Id: I0825d42e6be7f6e3397760a5e9be5dddca42dcdc
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
(cherry picked from commit a43d86fe1c0bc9d352f67c134a9ee5f754aea5e6)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Eirik Aavitsland 2024-02-20 08:07:38 +01:00 committed by Qt Cherry-pick Bot
parent d251de904a
commit 824d293601
2 changed files with 19 additions and 6 deletions

View File

@ -3397,16 +3397,18 @@ void QRasterPaintEngine::drawBitmap(const QPointF &pos, const QImage &image, QSp
// Boundaries
int w = image.width();
int h = image.height();
int ymax = qMin(qRound(pos.y() + h), d->rasterBuffer->height());
int ymin = qMax(qRound(pos.y()), 0);
int xmax = qMin(qRound(pos.x() + w), d->rasterBuffer->width());
int xmin = qMax(qRound(pos.x()), 0);
int px = qRound(pos.x());
int py = qRound(pos.y());
int ymax = qMin(py + h, d->rasterBuffer->height());
int ymin = qMax(py, 0);
int xmax = qMin(px + w, d->rasterBuffer->width());
int xmin = qMax(px, 0);
int x_offset = xmin - qRound(pos.x());
int x_offset = xmin - px;
QImage::Format format = image.format();
for (int y = ymin; y < ymax; ++y) {
const uchar *src = image.scanLine(y - qRound(pos.y()));
const uchar *src = image.scanLine(y - py);
if (format == QImage::Format_MonoLSB) {
for (int x = 0; x < xmax - xmin; ++x) {
int src_x = x + x_offset;

View File

@ -61,6 +61,7 @@ private slots:
#endif
void drawPixmapFragments();
void drawPixmapNegativeScale();
void drawPixmapRounding();
void drawLine_data();
void drawLine();
@ -747,6 +748,16 @@ void tst_QPainter::drawPixmapNegativeScale()
QVERIFY(resultImage.pixel(12, 8) == qRgba(0, 0, 0, 255)); // and right strip is now black
}
void tst_QPainter::drawPixmapRounding()
{
// Just test that we don't assert
QBitmap bm(8, 8);
QImage out(64, 64, QImage::Format_RGB32);
QPainter p(&out);
qreal y = 26.499999999999996;
p.drawPixmap(QPointF(0, y), bm);
}
void tst_QPainter::drawLine_data()
{
QTest::addColumn<QLine>("line");