From c563cff78b9606bf5869707fcbe6183198508d60 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Fri, 29 May 2009 08:54:31 +0200 Subject: Introduce QGraphicsItem::ItemHasNoContents. This flag helps optimize the case where an item is used only as a transformation node in a scene graph, and where the item itself doesn't paint anything. This is the default for FxItem (the subclasses that do paint enable the HasContents flag). This lets Graphics View know whether there's any point in setting up the world transform, opacity and other things. Reviewed-by: Lars --- src/gui/graphicsview/qgraphicsitem.cpp | 8 ++++++++ src/gui/graphicsview/qgraphicsitem.h | 3 ++- src/gui/graphicsview/qgraphicsitem_p.h | 4 ++-- src/gui/graphicsview/qgraphicsscene.cpp | 30 ++++++++++++++++++++---------- 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 486e0b5..12aaba5 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -309,6 +309,11 @@ and is always initialized to 1. Use QStyleOptionGraphicsItem::levelOfDetailFromTransform for a more fine-grained value. + + \value ItemHasNoContents The item does not paint anything (i.e., calling + paint() on the item has no effect). You should set this flag on items that + do not need to be painted to ensure that Graphics View avoids unnecessary + painting preparations. */ /*! @@ -9108,6 +9113,9 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag) case QGraphicsItem::ItemUsesExtendedStyleOption: str = "ItemUsesExtendedStyleOption"; break; + case QGraphicsItem::ItemHasNoContents: + str = "ItemHasNoContents"; + break; } debug << str; return debug; diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index def773e..737ea80 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -95,7 +95,8 @@ public: ItemIgnoresParentOpacity = 0x40, ItemDoesntPropagateOpacityToChildren = 0x80, ItemStacksBehindParent = 0x100, - ItemUsesExtendedStyleOption = 0x200 + ItemUsesExtendedStyleOption = 0x200, + ItemHasNoContents = 0x400 // NB! Don't forget to increase the d_ptr->flags bit field by 1 when adding a new flag. }; Q_DECLARE_FLAGS(GraphicsItemFlags, GraphicsItemFlag) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index acd2fcc..9d5b58a 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -350,11 +350,11 @@ public: quint32 unused : 3; // New 32 bits - quint32 flags : 10; + quint32 flags : 11; quint32 dirtyChildrenBoundingRect : 1; quint32 inDirtyList : 1; quint32 paintedViewBoundingRectsNeedRepaint : 1; - quint32 padding : 19; // feel free to use + quint32 padding : 18; // feel free to use // Optional stacking order int globalStackingOrder; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index b105c9c..eaebd1a 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -295,9 +295,13 @@ static inline bool QRectF_intersects(const QRectF &s, const QRectF &r) static inline void _q_adjustRect(QRectF *rect) { Q_ASSERT(rect); - if (!rect->width()) + bool nullWidth = !rect->width(); + bool nullHeight = !rect->height(); + if (nullWidth && nullHeight) + return; + if (nullWidth) rect->adjust(-0.00001, 0, 0.00001, 0); - if (!rect->height()) + else if (nullHeight) rect->adjust(0, -0.00001, 0, 0.00001); } @@ -5079,22 +5083,23 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * } } QRectF brect = item->boundingRect(); - _q_adjustRect(&brect); - const QRect paintedViewBoundingRect = transform.mapRect(brect).toRect().adjusted(-1, -1, 1, 1); - item->d_ptr->paintedViewBoundingRects.insert(widget, paintedViewBoundingRect); - viewBoundingRect = paintedViewBoundingRect & exposedRegion.boundingRect(); + if (!brect.size().isNull()) { + // ### This does not take the clip into account. + _q_adjustRect(&brect); + const QRect paintedViewBoundingRect = transform.mapRect(brect).toRect().adjusted(-1, -1, 1, 1); + item->d_ptr->paintedViewBoundingRects.insert(widget, paintedViewBoundingRect); + viewBoundingRect = paintedViewBoundingRect & exposedRegion.boundingRect(); + } } else { transform = parentTransform; } - // Find and sort children. - QList children = item ? item->d_ptr->children : topLevelItems; - qSort(children.begin(), children.end(), qt_notclosestLeaf); - bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)); bool dontDrawItem = !item || viewBoundingRect.isEmpty(); bool dontDrawChildren = item && dontDrawItem && childClip; childClip &= !dontDrawChildren & !children.isEmpty(); + if (item && item->d_ptr->flags & QGraphicsItem::ItemHasNoContents) + dontDrawItem = true; // Clip children. if (childClip) { @@ -5103,6 +5108,11 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * painter->setClipPath(item->shape(), Qt::IntersectClip); } + // Find and sort children. + QList children = item ? item->d_ptr->children : topLevelItems; + if (!dontDrawChildren) + qSort(children.begin(), children.end(), qt_notclosestLeaf); + // Draw children behind int i; if (!dontDrawChildren) { -- cgit v0.12