Fix floating point clip rectangle rounding in raster and opengl paint engine
Fixes: QTBUG-83229 Pick-to: 5.15 Change-Id: If94028f27c9085e391acb9c423cde1b7c12bca36 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
This commit is contained in:
parent
7e2fded55e
commit
d9cc149995
@ -1251,7 +1251,7 @@ void QRasterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
|
|||||||
#endif
|
#endif
|
||||||
const qreal *points = path.points();
|
const qreal *points = path.points();
|
||||||
QRectF r(points[0], points[1], points[4]-points[0], points[5]-points[1]);
|
QRectF r(points[0], points[1], points[4]-points[0], points[5]-points[1]);
|
||||||
if (setClipRectInDeviceCoords(s->matrix.mapRect(r).toRect(), op))
|
if (setClipRectInDeviceCoords(s->matrix.mapRect(r).toAlignedRect(), op))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2496,7 +2496,7 @@ void QOpenGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op)
|
|||||||
&& qFuzzyIsNull(state()->matrix.m11())
|
&& qFuzzyIsNull(state()->matrix.m11())
|
||||||
&& qFuzzyIsNull(state()->matrix.m22())))
|
&& qFuzzyIsNull(state()->matrix.m22())))
|
||||||
{
|
{
|
||||||
state()->rectangleClip = state()->rectangleClip.intersected(state()->matrix.mapRect(rect).toRect());
|
state()->rectangleClip = state()->rectangleClip.intersected(state()->matrix.mapRect(rect).toAlignedRect());
|
||||||
d->updateClipScissorTest();
|
d->updateClipScissorTest();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -138,6 +138,7 @@ private slots:
|
|||||||
|
|
||||||
void disableEnableClipping();
|
void disableEnableClipping();
|
||||||
void setClipRect();
|
void setClipRect();
|
||||||
|
void clipRect();
|
||||||
void setEqualClipRegionAndPath_data();
|
void setEqualClipRegionAndPath_data();
|
||||||
void setEqualClipRegionAndPath();
|
void setEqualClipRegionAndPath();
|
||||||
|
|
||||||
@ -1750,6 +1751,42 @@ void tst_QPainter::setClipRect()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Verify that the clipping works correctly.
|
||||||
|
The red outline should be covered by the blue rect on top and left,
|
||||||
|
while it should be clipped on the right and bottom and thus the red outline be visible
|
||||||
|
|
||||||
|
See: QTBUG-83229
|
||||||
|
*/
|
||||||
|
void tst_QPainter::clipRect()
|
||||||
|
{
|
||||||
|
int width = 654;
|
||||||
|
int height = 480;
|
||||||
|
QRect rect(0, 0, width, height);
|
||||||
|
|
||||||
|
QImage image(width, height, QImage::Format_ARGB32);
|
||||||
|
QPainter p(&image);
|
||||||
|
qreal halfWidth = width / 2.0;
|
||||||
|
qreal halfHeight = height / 2.0;
|
||||||
|
|
||||||
|
QRectF clipRect = QRectF(halfWidth - halfWidth / 2.0, halfHeight - halfHeight / 2.0,
|
||||||
|
halfWidth / 2.0, halfHeight / 2.0);
|
||||||
|
|
||||||
|
p.fillRect(rect, Qt::white);
|
||||||
|
p.setPen(Qt::red);
|
||||||
|
p.drawRect(clipRect);
|
||||||
|
|
||||||
|
p.setClipRect(clipRect, Qt::ReplaceClip);
|
||||||
|
p.fillRect(rect, Qt::blue);
|
||||||
|
|
||||||
|
p.end();
|
||||||
|
|
||||||
|
QCOMPARE(image.pixelColor(clipRect.left() + 1, clipRect.top()), QColor(Qt::blue));
|
||||||
|
QCOMPARE(image.pixelColor(clipRect.left(), clipRect.top() + 1), QColor(Qt::blue));
|
||||||
|
QCOMPARE(image.pixelColor(clipRect.left() + 1, clipRect.bottom()), QColor(Qt::red));
|
||||||
|
QCOMPARE(image.pixelColor(clipRect.right(), clipRect.top() + 1), QColor(Qt::red));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This tests the two different clipping approaches in QRasterPaintEngine,
|
This tests the two different clipping approaches in QRasterPaintEngine,
|
||||||
one when using a QRegion and one when using a QPainterPath. They should
|
one when using a QRegion and one when using a QPainterPath. They should
|
||||||
|
@ -93,6 +93,7 @@ private slots:
|
|||||||
void defaultSurfaceFormat();
|
void defaultSurfaceFormat();
|
||||||
void imageFormatPainting();
|
void imageFormatPainting();
|
||||||
void nullTextureInitializtion();
|
void nullTextureInitializtion();
|
||||||
|
void clipRect();
|
||||||
|
|
||||||
#ifdef USE_GLX
|
#ifdef USE_GLX
|
||||||
void glxContextWrap();
|
void glxContextWrap();
|
||||||
@ -1686,6 +1687,74 @@ void tst_QOpenGL::nullTextureInitializtion()
|
|||||||
QVERIFY(!t.isCreated());
|
QVERIFY(!t.isCreated());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Verify that the clipping works correctly.
|
||||||
|
The red outline should be covered by the blue rect on top and left,
|
||||||
|
while it should be clipped on the right and bottom and thus the red outline be visible
|
||||||
|
|
||||||
|
See: QTBUG-83229
|
||||||
|
*/
|
||||||
|
void tst_QOpenGL::clipRect()
|
||||||
|
{
|
||||||
|
#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(__x86_64__)
|
||||||
|
QSKIP("QTBUG-22617");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QScopedPointer<QSurface> surface(createSurface(int(QSurface::Window)));
|
||||||
|
|
||||||
|
QOpenGLContext ctx;
|
||||||
|
QVERIFY(ctx.create());
|
||||||
|
|
||||||
|
QVERIFY(ctx.makeCurrent(surface.data()));
|
||||||
|
|
||||||
|
if (!QOpenGLFramebufferObject::hasOpenGLFramebufferObjects())
|
||||||
|
QSKIP("QOpenGLFramebufferObject not supported on this platform");
|
||||||
|
|
||||||
|
// No multisample with combined depth/stencil attachment:
|
||||||
|
QOpenGLFramebufferObjectFormat fboFormat;
|
||||||
|
fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
|
||||||
|
|
||||||
|
// Uncomplicate things by using POT:
|
||||||
|
const QSize size(654, 480);
|
||||||
|
const QRect rect(QPoint(0, 0), size);
|
||||||
|
QOpenGLFramebufferObject fbo(size, fboFormat);
|
||||||
|
|
||||||
|
if (fbo.attachment() != QOpenGLFramebufferObject::CombinedDepthStencil)
|
||||||
|
QSKIP("FBOs missing combined depth~stencil support");
|
||||||
|
|
||||||
|
QVERIFY(fbo.bind());
|
||||||
|
|
||||||
|
QPainter fboPainter;
|
||||||
|
QOpenGLPaintDevice device(fbo.width(), fbo.height());
|
||||||
|
bool painterBegun = fboPainter.begin(&device);
|
||||||
|
QVERIFY(painterBegun);
|
||||||
|
|
||||||
|
qreal halfWidth = size.width() / 2.0;
|
||||||
|
qreal halfHeight = size.height() / 2.0;
|
||||||
|
|
||||||
|
QRectF clipRect = QRectF(halfWidth - halfWidth / 2.0, halfHeight - halfHeight / 2.0,
|
||||||
|
halfWidth / 2.0, halfHeight / 2.0);
|
||||||
|
|
||||||
|
fboPainter.fillRect(rect, Qt::white);
|
||||||
|
fboPainter.setPen(Qt::red);
|
||||||
|
fboPainter.drawRect(clipRect);
|
||||||
|
|
||||||
|
fboPainter.setClipRect(clipRect, Qt::ReplaceClip);
|
||||||
|
fboPainter.fillRect(rect, Qt::blue);
|
||||||
|
|
||||||
|
fboPainter.end();
|
||||||
|
|
||||||
|
const QImage fb = fbo.toImage().convertToFormat(QImage::Format_RGB32);
|
||||||
|
QCOMPARE(fb.size(), size);
|
||||||
|
|
||||||
|
QCOMPARE(fb.pixelColor(clipRect.left() + 1, clipRect.top()), QColor(Qt::blue));
|
||||||
|
QCOMPARE(fb.pixelColor(clipRect.left(), clipRect.top() + 1), QColor(Qt::blue));
|
||||||
|
QCOMPARE(fb.pixelColor(clipRect.left() + 1, clipRect.bottom()), QColor(Qt::red));
|
||||||
|
|
||||||
|
// Enable this once QTBUG-85286 is fixed
|
||||||
|
//QCOMPARE(fb.pixelColor(clipRect.right(), clipRect.top() + 1), QColor(Qt::red));
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_QOpenGL)
|
QTEST_MAIN(tst_QOpenGL)
|
||||||
|
|
||||||
#include "tst_qopengl.moc"
|
#include "tst_qopengl.moc"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user