summaryrefslogtreecommitdiffstats
path: root/tests/auto/widgets/graphicsview
diff options
context:
space:
mode:
authorDimitar Asenov <dimitar.asenov@gmail.com>2014-03-12 14:11:45 -0700
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-31 22:54:14 +0200
commit3270b4490bc420359483cb00ae48e91e261b30e8 (patch)
treed6e18a39fd0d21d36d10abe6edbfdb68084780ca /tests/auto/widgets/graphicsview
parentd13d03f012b9c0516fa027f4e1ea18c12f1491ca (diff)
Add a new optimization flag to QGraphicsItem.
The new flag ItemContainsChildrenInShape is similar to the existing flag ItemClipsChildrenToShape. Setting the new flag makes QGraphicsScene assume that children are drawn within the shape of the current item but this is not enforced by clipping. When an application manually ensures this clipping boundary, setting the new flag removes the overhead of enforcing the clip with ItemClipsChildrenToShape, while still allowing other routines to behave more optimially by assuming children are within the shape of the current item. [ChangeLog][QtWidgets][QGraphicsItem] Added the ItemContainsChildrenInShape flag that enables using optimizations of ItemClipsChildrenToShape without the overhead of enforcing the clip. Change-Id: I5496fe1ca331b77fd51e0df8a3ace2b8e939eaf2 Reviewed-by: Andreas Aardal Hanssen <andreas@hanssen.name>
Diffstat (limited to 'tests/auto/widgets/graphicsview')
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp124
1 files changed, 119 insertions, 5 deletions
diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
index 84466b92d1..f686b5854c 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
@@ -377,6 +377,8 @@ private slots:
void itemClipsChildrenToShape5();
void itemClipsTextChildToShape();
void itemClippingDiscovery();
+ void itemContainsChildrenInShape();
+ void itemContainsChildrenInShape2();
void ancestorFlags();
void untransformable();
void contextMenuEventPropagation();
@@ -5845,6 +5847,102 @@ void tst_QGraphicsItem::itemClippingDiscovery()
QCOMPARE(scene.itemAt(90, 90), (QGraphicsItem *)0);
}
+class ItemCountsBoundingRectCalls : public QGraphicsRectItem
+{
+public:
+ ItemCountsBoundingRectCalls(const QRectF & rect, QGraphicsItem *parent = 0)
+ : QGraphicsRectItem(rect, parent), boundingRectCalls(0) {}
+ QRectF boundingRect () const {
+ ++boundingRectCalls;
+ return QGraphicsRectItem::boundingRect();
+ }
+ mutable int boundingRectCalls;
+};
+
+void tst_QGraphicsItem::itemContainsChildrenInShape()
+{
+ ItemCountsBoundingRectCalls *parent = new ItemCountsBoundingRectCalls(QRectF(0,0, 10, 10));
+ ItemCountsBoundingRectCalls *childOutsideShape = new ItemCountsBoundingRectCalls(QRectF(0,0, 10, 10), parent);
+ childOutsideShape->setPos(20,0);
+
+ QGraphicsScene scene;
+ scene.setItemIndexMethod(QGraphicsScene::NoIndex);
+ scene.addItem(parent);
+
+ QVERIFY(parent->boundingRectCalls == childOutsideShape->boundingRectCalls);
+
+ int oldParentBoundingRectCalls = parent->boundingRectCalls;
+ int oldChildBoundingRectCalls = childOutsideShape->boundingRectCalls;
+
+ // First test that both items are searched if no optimization flags are set
+ QGraphicsItem* item = scene.itemAt(25,5);
+
+ QVERIFY(item == childOutsideShape);
+ QVERIFY(parent->boundingRectCalls > oldParentBoundingRectCalls);
+ QVERIFY(childOutsideShape->boundingRectCalls > oldChildBoundingRectCalls);
+ QVERIFY(parent->boundingRectCalls == childOutsideShape->boundingRectCalls);
+
+ oldParentBoundingRectCalls = parent->boundingRectCalls;
+ oldChildBoundingRectCalls = childOutsideShape->boundingRectCalls;
+
+ // Repeat the test to make sure that no caching/indexing is in effect
+ item = scene.itemAt(25,5);
+
+ QVERIFY(item == childOutsideShape);
+ QVERIFY(parent->boundingRectCalls > oldParentBoundingRectCalls);
+ QVERIFY(childOutsideShape->boundingRectCalls > oldChildBoundingRectCalls);
+ QVERIFY(parent->boundingRectCalls == childOutsideShape->boundingRectCalls);
+
+ oldParentBoundingRectCalls = parent->boundingRectCalls;
+ oldChildBoundingRectCalls = childOutsideShape->boundingRectCalls;
+
+ // Set the optimization flag and make sure that the child is not returned
+ // and that the child's boundingRect() method is never called.
+ parent->setFlag(QGraphicsItem::ItemContainsChildrenInShape);
+ item = scene.itemAt(25,5);
+
+ QVERIFY(!(item));
+ QVERIFY(parent->boundingRectCalls > oldParentBoundingRectCalls);
+ QVERIFY(childOutsideShape->boundingRectCalls == oldChildBoundingRectCalls);
+ QVERIFY(parent->boundingRectCalls > childOutsideShape->boundingRectCalls);
+}
+
+void tst_QGraphicsItem::itemContainsChildrenInShape2()
+{
+ //The tested flag behaves almost identically to ItemClipsChildrenToShape
+ //in terms of optimizations but does not enforce the clip.
+ //This test makes sure there is no clip.
+ QGraphicsScene scene;
+ QGraphicsItem *rect = scene.addRect(0, 0, 50, 50, QPen(Qt::NoPen), QBrush(Qt::yellow));
+
+ QGraphicsItem *ellipse = scene.addEllipse(0, 0, 100, 100, QPen(Qt::NoPen), QBrush(Qt::green));
+ ellipse->setParentItem(rect);
+
+ QGraphicsItem *clippedEllipse = scene.addEllipse(0, 0, 50, 50, QPen(Qt::NoPen), QBrush(Qt::blue));
+ clippedEllipse->setParentItem(ellipse);
+
+ QGraphicsItem *clippedEllipse2 = scene.addEllipse(0, 0, 25, 25, QPen(Qt::NoPen), QBrush(Qt::red));
+ clippedEllipse2->setParentItem(clippedEllipse);
+
+ QVERIFY(!(ellipse->flags() & QGraphicsItem::ItemClipsChildrenToShape));
+ QVERIFY(!(ellipse->flags() & QGraphicsItem::ItemContainsChildrenInShape));
+ ellipse->setFlags(QGraphicsItem::ItemContainsChildrenInShape);
+ QVERIFY(!(ellipse->flags() & QGraphicsItem::ItemClipsChildrenToShape));
+ QVERIFY((ellipse->flags() & QGraphicsItem::ItemContainsChildrenInShape));
+
+ QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
+ image.fill(0);
+ QPainter painter(&image);
+ painter.setRenderHint(QPainter::Antialiasing);
+ scene.render(&painter);
+ painter.end();
+
+ QCOMPARE(image.pixel(2, 2), QColor(Qt::yellow).rgba());
+ QCOMPARE(image.pixel(12, 12), QColor(Qt::red).rgba());
+ QCOMPARE(image.pixel(2, 25), QColor(Qt::blue).rgba());
+ QCOMPARE(image.pixel(2, 50), QColor(Qt::green).rgba());
+}
+
void tst_QGraphicsItem::ancestorFlags()
{
QGraphicsItem *level1 = new QGraphicsRectItem;
@@ -5965,11 +6063,27 @@ void tst_QGraphicsItem::ancestorFlags()
// Nobody handles child events
level21->setHandlesChildEvents(false);
- for (int i = 0; i < 2; ++i) {
- QGraphicsItem::GraphicsItemFlag flag = !i ? QGraphicsItem::ItemClipsChildrenToShape
- : QGraphicsItem::ItemIgnoresTransformations;
- int ancestorFlag = !i ? QGraphicsItemPrivate::AncestorClipsChildren
- : QGraphicsItemPrivate::AncestorIgnoresTransformations;
+ for (int i = 0; i < 3; ++i) {
+ QGraphicsItem::GraphicsItemFlag flag;
+ int ancestorFlag;
+
+ switch (i) {
+ case(0):
+ flag = QGraphicsItem::ItemClipsChildrenToShape;
+ ancestorFlag = QGraphicsItemPrivate::AncestorClipsChildren;
+ break;
+ case(1):
+ flag = QGraphicsItem::ItemIgnoresTransformations;
+ ancestorFlag = QGraphicsItemPrivate::AncestorIgnoresTransformations;
+ break;
+ case(2):
+ flag = QGraphicsItem::ItemContainsChildrenInShape;
+ ancestorFlag = QGraphicsItemPrivate::AncestorContainsChildren;
+ break;
+ default:
+ qFatal("Unknown ancestor flag, please fix!");
+ break;
+ }
QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);