summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Aardal Hanssen <andreas@hanssen.name>2013-07-29 23:11:14 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-08-05 17:03:28 +0200
commit7bf4381a95bb4812f5a74419099a1a18f7a536a7 (patch)
tree643b19ca58244904cf650198f1fd29f1aa92ffdd
parent78b4162a352ddac398b8af7f8be33b009c333244 (diff)
downloadqt4-tools-7bf4381a95bb4812f5a74419099a1a18f7a536a7.tar.gz
Fix double transform for items ignoring parent transformations.
Previously, the topmost untransformable's scene transform, which includes the item's position and local transformation, was used to determine the item's anchoring position. This position was then passed on to be multiplied by the item's transform again. This works fine for toplevel untransformable items that don't have any transform set at all, but those who do would have their transforms applied twice - one to determine the anchoring position, and again to transform the item itself. Since only translation transformations can affect the first operation (the anchoring pos), this bug only applies to items that set ItemIgnoresTransformations and use a local transform that includes translation. Task-number: QTBUG-21618 Change-Id: I3f3c4f2357e2ca6cd0c75cb5b7e428c0803d9e73 Reviewed-by: Alexis Menard <alexis@webkit.org> Reviewed-by: Jan Arve Sæther <jan-arve.saether@digia.com>
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp11
-rw-r--r--tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp61
2 files changed, 69 insertions, 3 deletions
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 4f31793768..fccd706031 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -4217,9 +4217,14 @@ QTransform QGraphicsItem::deviceTransform(const QTransform &viewportTransform) c
return QTransform();
}
- // First translate the base untransformable item.
- untransformedAncestor->d_ptr->ensureSceneTransform();
- QPointF mappedPoint = (untransformedAncestor->d_ptr->sceneTransform * viewportTransform).map(QPointF(0, 0));
+ // Determine the inherited origin. Find the parent of the topmost untransformable.
+ // Use its scene transform to map the position of the untransformable. Then use
+ // that viewport position as the anchoring point for the untransformable subtree.
+ QGraphicsItem *parentOfUntransformedAncestor = untransformedAncestor->parentItem();
+ QTransform inheritedMatrix;
+ if (parentOfUntransformedAncestor)
+ inheritedMatrix = parentOfUntransformedAncestor->sceneTransform();
+ QPointF mappedPoint = (inheritedMatrix * viewportTransform).map(untransformedAncestor->pos());
// COMBINE
QTransform matrix = QTransform::fromTranslate(mappedPoint.x(), mappedPoint.y());
diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
index 2637106953..8f54f3a9b2 100644
--- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
+++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
@@ -479,6 +479,7 @@ private slots:
void QTBUG_16374_crashInDestructor();
void QTBUG_20699_focusScopeCrash();
void QTBUG_30990_rightClickSelection();
+ void QTBUG_21618_untransformable_sceneTransform();
private:
QList<QGraphicsItem *> paintedItems;
@@ -11525,5 +11526,65 @@ void tst_QGraphicsItem::QTBUG_30990_rightClickSelection()
QVERIFY(!item2->isSelected());
}
+void tst_QGraphicsItem::QTBUG_21618_untransformable_sceneTransform()
+{
+ QGraphicsScene scene(0, 0, 150, 150);
+ scene.addRect(-2, -2, 4, 4);
+
+ QGraphicsItem *item1 = scene.addRect(0, 0, 100, 100, QPen(), Qt::red);
+ item1->setPos(50, 50);
+ item1->translate(50, 50);
+ item1->rotate(90);
+ QGraphicsItem *item2 = scene.addRect(0, 0, 100, 100, QPen(), Qt::green);
+ item2->setPos(50, 50);
+ item2->translate(50, 50);
+ item2->rotate(90);
+ item2->setFlags(QGraphicsItem::ItemIgnoresTransformations);
+
+ QGraphicsRectItem *item1_topleft = new QGraphicsRectItem(QRectF(-2, -2, 4, 4));
+ item1_topleft->setParentItem(item1);
+ item1_topleft->setBrush(Qt::black);
+ QGraphicsRectItem *item1_bottomright = new QGraphicsRectItem(QRectF(-2, -2, 4, 4));
+ item1_bottomright->setParentItem(item1);
+ item1_bottomright->setPos(100, 100);
+ item1_bottomright->setBrush(Qt::yellow);
+
+ QGraphicsRectItem *item2_topleft = new QGraphicsRectItem(QRectF(-2, -2, 4, 4));
+ item2_topleft->setParentItem(item2);
+ item2_topleft->setBrush(Qt::black);
+ QGraphicsRectItem *item2_bottomright = new QGraphicsRectItem(QRectF(-2, -2, 4, 4));
+ item2_bottomright->setParentItem(item2);
+ item2_bottomright->setPos(100, 100);
+ item2_bottomright->setBrush(Qt::yellow);
+
+ QCOMPARE(item1->sceneTransform(), item2->sceneTransform());
+ QCOMPARE(item1_topleft->sceneTransform(), item2_topleft->sceneTransform());
+ QCOMPARE(item1_bottomright->sceneTransform(), item2_bottomright->sceneTransform());
+ QCOMPARE(item1->deviceTransform(QTransform()), item2->deviceTransform(QTransform()));
+ QCOMPARE(item1->deviceTransform(QTransform()).map(QPointF()), QPointF(100, 100));
+ QCOMPARE(item2->deviceTransform(QTransform()).map(QPointF()), QPointF(100, 100));
+ QCOMPARE(item1->deviceTransform(QTransform()).map(QPointF(100, 100)), QPointF(0, 200));
+ QCOMPARE(item2->deviceTransform(QTransform()).map(QPointF(100, 100)), QPointF(0, 200));
+ QCOMPARE(item1_topleft->deviceTransform(QTransform()).map(QPointF()), QPointF(100, 100));
+ QCOMPARE(item2_topleft->deviceTransform(QTransform()).map(QPointF()), QPointF(100, 100));
+ QCOMPARE(item1_bottomright->deviceTransform(QTransform()).map(QPointF()), QPointF(0, 200));
+ QCOMPARE(item2_bottomright->deviceTransform(QTransform()).map(QPointF()), QPointF(0, 200));
+
+ item2->setParentItem(item1);
+
+ QCOMPARE(item2->deviceTransform(QTransform()).map(QPointF()), QPointF(100, 200));
+ QCOMPARE(item2->deviceTransform(QTransform()).map(QPointF(100, 100)), QPointF(0, 300));
+ QCOMPARE(item2_topleft->deviceTransform(QTransform()).map(QPointF()), QPointF(100, 200));
+ QCOMPARE(item2_bottomright->deviceTransform(QTransform()).map(QPointF()), QPointF(0, 300));
+
+ QTransform tx = QTransform::fromTranslate(100, 0);
+ QCOMPARE(item1->deviceTransform(tx).map(QPointF()), QPointF(200, 100));
+ QCOMPARE(item1->deviceTransform(tx).map(QPointF(100, 100)), QPointF(100, 200));
+ QCOMPARE(item2->deviceTransform(tx).map(QPointF()), QPointF(200, 200));
+ QCOMPARE(item2->deviceTransform(tx).map(QPointF(100, 100)), QPointF(100, 300));
+ QCOMPARE(item2_topleft->deviceTransform(tx).map(QPointF()), QPointF(200, 200));
+ QCOMPARE(item2_bottomright->deviceTransform(tx).map(QPointF()), QPointF(100, 300));
+}
+
QTEST_MAIN(tst_QGraphicsItem)
#include "tst_qgraphicsitem.moc"