From 72fb0f2637db401efd178b9d4139fc2b6ef59112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 23 Oct 2009 13:17:06 +0200 Subject: Wrong worldTransform() on the painter in QGraphicsScene::drawForeground. The painter's worldTransform() is updated for each item we draw, and when the DontSavePainterState optimization flag is set, this change is not protected by save() and restore(). After all the items are drawn, it means the painter is left with the last drawn item's transform. We therefore have to make sure it is reset back to whatever it was before the items were drawn. Auto-test included. Task-number: QTBUG-4973 Reviewed-by: alexis Reviewed-by: andreas --- src/gui/graphicsview/qgraphicsview.cpp | 8 +++++ tests/auto/qgraphicsview/tst_qgraphicsview.cpp | 49 ++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 32747cc..49348de 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -3306,6 +3306,14 @@ void QGraphicsView::paintEvent(QPaintEvent *event) if (!(d->optimizationFlags & IndirectPainting)) { d->scene->d_func()->drawItems(&painter, viewTransformed ? &viewTransform : 0, &d->exposedRegion, viewport()); + // Make sure the painter's world transform is restored correctly when + // drawing without painter state protection (DontSavePainterState). + // We only change the worldTransform() so there's no need to do a full-blown + // save() and restore(). Also note that we don't have to do this in case of + // IndirectPainting (the else branch), because in that case we always save() + // and restore() in QGraphicsScene::drawItems(). + if (!d->scene->d_func()->painterStateProtection) + painter.setWorldTransform(viewTransform); } else { // Find all exposed items bool allItems = false; diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp index dc08d0e..092f81d 100644 --- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp @@ -194,6 +194,8 @@ private slots: void acceptDrops(); void optimizationFlags(); void optimizationFlags_dontSavePainterState(); + void optimizationFlags_dontSavePainterState2_data(); + void optimizationFlags_dontSavePainterState2(); void levelOfDetail_data(); void levelOfDetail(); void scrollBarRanges_data(); @@ -2455,6 +2457,53 @@ void tst_QGraphicsView::optimizationFlags_dontSavePainterState() QTest::qWaitForWindowShown(&painter2); } +void tst_QGraphicsView::optimizationFlags_dontSavePainterState2_data() +{ + QTest::addColumn("savePainter"); + QTest::newRow("With painter state protection") << true; + QTest::newRow("Without painter state protection") << false; +} + +void tst_QGraphicsView::optimizationFlags_dontSavePainterState2() +{ + QFETCH(bool, savePainter); + + class MyScene : public QGraphicsScene + { + public: + void drawBackground(QPainter *p, const QRectF &) + { transformInDrawBackground = p->worldTransform(); } + + void drawForeground(QPainter *p, const QRectF &) + { transformInDrawForeground = p->worldTransform(); } + + QTransform transformInDrawBackground; + QTransform transformInDrawForeground; + }; + + MyScene scene; + // Add transformed dummy items to make sure the painter's worldTransform() is changed in drawItems. + scene.addRect(0, 0, 20, 20)->setTransform(QTransform::fromScale(2, 2)); + scene.addRect(50, 50, 20, 20)->setTransform(QTransform::fromTranslate(200, 200)); + + QGraphicsView view(&scene); + if (!savePainter) + view.setOptimizationFlag(QGraphicsView::DontSavePainterState); + view.rotate(45); + view.scale(1.5, 1.5); + view.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&view); +#endif + QTest::qWait(150); + + // Make sure the painter's world transform is preserved after drawItems. + const QTransform expectedTransform = view.viewportTransform(); + QVERIFY(!expectedTransform.isIdentity()); + QCOMPARE(scene.transformInDrawForeground, expectedTransform); + QCOMPARE(scene.transformInDrawBackground, expectedTransform); +} + class LodItem : public QGraphicsRectItem { public: -- cgit v0.12