diff options
author | Bradley T. Hughes <bradley.hughes@nokia.com> | 2009-06-18 11:33:26 (GMT) |
---|---|---|
committer | Bradley T. Hughes <bradley.hughes@nokia.com> | 2009-06-18 11:33:26 (GMT) |
commit | e6e60b096bb8b5e5073e32220c74810e80bf2d25 (patch) | |
tree | ca247002a4193d0deeee3b4be369e830c7b4f778 /src/gui/graphicsview | |
parent | 5a350be913139e2b994878c62ce06eb88604abbe (diff) | |
parent | c23d4d6644bff2195fbb6aa84d3425dc2d31491a (diff) | |
download | Qt-e6e60b096bb8b5e5073e32220c74810e80bf2d25.zip Qt-e6e60b096bb8b5e5073e32220c74810e80bf2d25.tar.gz Qt-e6e60b096bb8b5e5073e32220c74810e80bf2d25.tar.bz2 |
Merge branch 'master' of git@scm.dev.nokia.troll.no:qt/qt
Conflicts:
src/gui/graphicsview/qgraphicsitem_p.h
Diffstat (limited to 'src/gui/graphicsview')
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem_p.h | 26 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsscene.cpp | 112 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsscene_p.h | 5 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsview.cpp | 61 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsview_p.h | 4 |
5 files changed, 135 insertions, 73 deletions
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 688130b..a0d061b 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -56,6 +56,7 @@ #include "qgraphicsitem.h" #include "qset.h" #include "qpixmapcache.h" +#include "qgraphicsview_p.h" #include <QtCore/qpoint.h> @@ -158,6 +159,8 @@ public: geometryChanged(0), inDestructor(0), isObject(0), + ignoreVisible(0), + ignoreOpacity(0), acceptTouchEvents(0), acceptedTouchBeginEvent(0), globalStackingOrder(-1), @@ -181,7 +184,7 @@ public: void combineTransformToParent(QTransform *x, const QTransform *viewTransform = 0) const; void combineTransformFromParent(QTransform *x, const QTransform *viewTransform = 0) const; - + // ### Qt 5: Remove. Workaround for reimplementation added after Qt 4.4. virtual QVariant inputMethodQueryHelper(Qt::InputMethodQuery query) const; static bool movableAncestorIsSelected(const QGraphicsItem *item); @@ -250,7 +253,7 @@ public: } } } - + struct ExtraStruct { ExtraStruct(Extra type, QVariant value) : type(type), value(value) @@ -262,7 +265,7 @@ public: bool operator<(Extra extra) const { return type < extra; } }; - + QList<ExtraStruct> extras; QGraphicsItemCache *maybeExtraItemCache() const; @@ -337,6 +340,15 @@ public: return calcEffectiveOpacity(); } + inline qreal combineOpacityFromParent(qreal parentOpacity) const + { + if (parent && !(flags & QGraphicsItem::ItemIgnoresParentOpacity) + && !(parent->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) { + return parentOpacity * opacity; + } + return opacity; + } + inline bool childrenCombineOpacity() const { if (!children.size()) @@ -423,8 +435,8 @@ public: quint32 cacheMode : 2; quint32 hasBoundingRegionGranularity : 1; quint32 isWidget : 1; - quint32 dirty : 1; - quint32 dirtyChildren : 1; + quint32 dirty : 1; + quint32 dirtyChildren : 1; quint32 localCollisionHack : 1; quint32 dirtyClipPath : 1; quint32 emptyClipPath : 1; @@ -441,9 +453,11 @@ public: quint32 geometryChanged : 1; quint32 inDestructor : 1; quint32 isObject : 1; + quint32 ignoreVisible : 1; + quint32 ignoreOpacity : 1; quint32 acceptTouchEvents : 1; quint32 acceptedTouchBeginEvent : 1; - quint32 unused : 12; // feel free to use + quint32 unused : 10; // feel free to use // Optional stacking order int globalStackingOrder; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 13b1b5a..7428d79 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5180,14 +5180,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (item) { if (!item->d_ptr->visible) return; - QGraphicsItem *p = item->d_ptr->parent; - bool itemIgnoresParentOpacity = item->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity; - bool parentDoesntPropagateOpacity = (p && (p->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)); - if (!itemIgnoresParentOpacity && !parentDoesntPropagateOpacity) { - opacity = parentOpacity * item->opacity(); - } else { - opacity = item->d_ptr->opacity; - } + opacity = item->d_ptr->combineOpacityFromParent(parentOpacity); if (opacity == 0.0 && !(item->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) { invisibleButChildIgnoresParentOpacity = !item->d_ptr->childrenCombineOpacity(); if (!invisibleButChildIgnoresParentOpacity) @@ -5337,7 +5330,11 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (clipsToShape) painter->setClipPath(item->shape(), Qt::IntersectClip); painter->setOpacity(opacity); - drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection); + + if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget) + item->paint(painter, &styleOptionTmp, widget); + else + drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection); if (savePainter) painter->restore(); @@ -5421,6 +5418,11 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b item->d_ptr->dirtyChildren = 1; } + if (force) + item->d_ptr->ignoreVisible = 1; + if (ignoreOpacity) + item->d_ptr->ignoreOpacity = 1; + QGraphicsItem *p = item->d_ptr->parent; while (p && !p->d_ptr->dirtyChildren) { p->d_ptr->dirtyChildren = 1; @@ -5428,34 +5430,58 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b } } -void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren) +static inline bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item, + const QRectF &rect, const QTransform &xform) +{ + Q_ASSERT(view); + Q_ASSERT(item); + if (item->hasBoundingRegionGranularity) + return view->updateRegion(xform.map(QRegion(rect.toRect()))); + return view->updateRect(xform.mapRect(rect).toRect()); +} + +void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren, + qreal parentOpacity) { Q_Q(QGraphicsScene); - // Calculate the full scene transform for this item. + bool wasDirtyParentViewBoundingRects = false; bool wasDirtyParentSceneTransform = false; - if (item && item->d_ptr->dirtySceneTransform && !item->d_ptr->itemIsUntransformable()) { - item->d_ptr->sceneTransform = item->d_ptr->parent ? item->d_ptr->parent->d_ptr->sceneTransform - : QTransform(); - item->d_ptr->combineTransformFromParent(&item->d_ptr->sceneTransform); - item->d_ptr->dirtySceneTransform = 0; - wasDirtyParentSceneTransform = true; + qreal opacity = parentOpacity; + + if (item) { + wasDirtyParentViewBoundingRects = item->d_ptr->paintedViewBoundingRectsNeedRepaint; + opacity = item->d_ptr->combineOpacityFromParent(parentOpacity); + const bool itemIsHidden = !item->d_ptr->ignoreVisible && !item->d_ptr->visible; + const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity && opacity == 0.0; + + if (item->d_ptr->dirtySceneTransform && !itemIsHidden && !item->d_ptr->itemIsUntransformable() + && !(itemIsFullyTransparent && item->d_ptr->childrenCombineOpacity())) { + // Calculate the full scene transform for this item. + item->d_ptr->sceneTransform = item->d_ptr->parent ? item->d_ptr->parent->d_ptr->sceneTransform + : QTransform(); + item->d_ptr->combineTransformFromParent(&item->d_ptr->sceneTransform); + item->d_ptr->dirtySceneTransform = 0; + wasDirtyParentSceneTransform = true; + } + + if (itemIsHidden || itemIsFullyTransparent || (item->d_ptr->flags & QGraphicsItem::ItemHasNoContents)) { + // Make sure we don't process invisible items or items with no content. + item->d_ptr->dirty = 0; + item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0; + } } // Process item. - bool wasDirtyParentViewBoundingRects = false; if (item && (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint)) { const bool useCompatUpdate = views.isEmpty() || (connectedSignals & changedSignalMask); const bool untransformableItem = item->d_ptr->itemIsUntransformable(); - const QRectF itemBoundingRect = item->boundingRect(); + const QRectF itemBoundingRect = adjustedItemBoundingRect(item); if (item->d_ptr->geometryChanged) { // Update growingItemsBoundingRect. - if (!hasSceneRect) { - QRectF itemSceneBoundingRect = item->d_ptr->sceneTransform.mapRect(itemBoundingRect); - _q_adjustRect(&itemSceneBoundingRect); - growingItemsBoundingRect |= itemSceneBoundingRect; - } + if (!hasSceneRect) + growingItemsBoundingRect |= item->d_ptr->sceneTransform.mapRect(itemBoundingRect); item->d_ptr->geometryChanged = 0; } @@ -5484,11 +5510,12 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool break; } + QRect &paintedViewBoundingRect = item->d_ptr->paintedViewBoundingRects[viewPrivate->viewport]; if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) { wasDirtyParentViewBoundingRects = true; - QRect rect = item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport); - rect.translate(viewPrivate->dirtyScrollOffset); - viewPrivate->updateRect(rect); + paintedViewBoundingRect.translate(viewPrivate->dirtyScrollOffset); + if (!viewPrivate->updateRect(paintedViewBoundingRect)) + paintedViewBoundingRect = QRect(); } if (!item->d_ptr->dirty) @@ -5496,7 +5523,6 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool if (uninitializedDirtyRect) { dirtyRect = itemBoundingRect; - _q_adjustRect(&dirtyRect); if (!item->d_ptr->fullUpdatePending) { _q_adjustRect(&item->d_ptr->needsRepaint); dirtyRect &= item->d_ptr->needsRepaint; @@ -5507,17 +5533,19 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool if (dirtyRect.isEmpty()) continue; // Discard updates outside the bounding rect. - QTransform deviceTransform = item->d_ptr->sceneTransform; - if (view->isTransformed()) { - if (!untransformableItem) - deviceTransform *= view->viewportTransform(); - else - deviceTransform = item->deviceTransform(view->viewportTransform()); + bool valid = false; + if (untransformableItem) { + valid = updateHelper(viewPrivate, item->d_ptr, dirtyRect, + item->deviceTransform(view->viewportTransform())); + } else if (!view->isTransformed()) { + valid = updateHelper(viewPrivate, item->d_ptr, dirtyRect, item->d_ptr->sceneTransform); + } else { + QTransform deviceTransform = item->d_ptr->sceneTransform; + deviceTransform *= view->viewportTransform(); + valid = updateHelper(viewPrivate, item->d_ptr, dirtyRect, deviceTransform); } - if (item->d_ptr->hasBoundingRegionGranularity) - viewPrivate->updateRegion(deviceTransform.map(QRegion(dirtyRect.toRect()))); - else - viewPrivate->updateRect(deviceTransform.mapRect(dirtyRect).toRect()); + if (!valid) + paintedViewBoundingRect = QRect(); } } } @@ -5530,12 +5558,18 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren = item && item->d_ptr->fullUpdatePending && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape); } + const bool parentIgnoresVisible = item && item->d_ptr->ignoreVisible; + const bool parentIgnoresOpacity = item && item->d_ptr->ignoreOpacity; for (int i = 0; i < children->size(); ++i) { QGraphicsItem *child = children->at(i); if (wasDirtyParentSceneTransform) child->d_ptr->dirtySceneTransform = 1; if (wasDirtyParentViewBoundingRects) child->d_ptr->paintedViewBoundingRectsNeedRepaint = 1; + if (parentIgnoresVisible) + child->d_ptr->ignoreVisible = 1; + if (parentIgnoresOpacity) + child->d_ptr->ignoreOpacity = 1; if (allChildrenDirty) { child->d_ptr->dirty = 1; @@ -5558,7 +5592,7 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool child->d_ptr->paintedViewBoundingRectsNeedRepaint = 0; } - processDirtyItemsRecursive(child, dirtyAncestorContainsChildren); + processDirtyItemsRecursive(child, dirtyAncestorContainsChildren, opacity); } } else if (wasDirtyParentSceneTransform) { item->d_ptr->invalidateChildrenSceneTransform(); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index b3f168c..983486f 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -271,7 +271,8 @@ public: void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false, bool maybeDirtyClipPath = false, bool force = false, bool ignoreOpacity = false, bool removingItemFromScene = false); - void processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren = false); + void processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren = false, + qreal parentOpacity = qreal(1.0)); inline void resetDirtyItem(QGraphicsItem *item) { @@ -283,6 +284,8 @@ public: item->d_ptr->needsRepaint = QRectF(); item->d_ptr->allChildrenDirty = 0; item->d_ptr->fullUpdatePending = 0; + item->d_ptr->ignoreVisible = 0; + item->d_ptr->ignoreOpacity = 0; } QStyle *style; diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 47a492b..6ac2914 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -846,19 +846,22 @@ void QGraphicsViewPrivate::processPendingUpdates() dirtyRegion = QRegion(); } -void QGraphicsViewPrivate::updateRegion(const QRegion &r) +bool QGraphicsViewPrivate::updateRegion(const QRegion &r) { - if (r.isEmpty() || fullUpdatePending) - return; + if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate || r.isEmpty()) + return false; + + const QRect boundingRect = r.boundingRect(); + if (!boundingRect.intersects(viewport->rect())) + return false; // Update region outside viewport. - // Rect intersects viewport - update everything? switch (viewportUpdateMode) { case QGraphicsView::FullViewportUpdate: fullUpdatePending = true; viewport->update(); break; case QGraphicsView::BoundingRectViewportUpdate: - dirtyBoundingRect |= r.boundingRect(); + dirtyBoundingRect |= boundingRect; if (dirtyBoundingRect.contains(viewport->rect())) { fullUpdatePending = true; viewport->update(); @@ -876,18 +879,20 @@ void QGraphicsViewPrivate::updateRegion(const QRegion &r) } break; } - case QGraphicsView::NoViewportUpdate: - // Unreachable + default: break; } + + return true; } -void QGraphicsViewPrivate::updateRect(const QRect &r) +bool QGraphicsViewPrivate::updateRect(const QRect &r) { - if (r.isEmpty() || fullUpdatePending) - return; + if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate + || !r.intersects(viewport->rect())) { + return false; + } - // Rect intersects viewport - update everything? switch (viewportUpdateMode) { case QGraphicsView::FullViewportUpdate: fullUpdatePending = true; @@ -907,10 +912,11 @@ void QGraphicsViewPrivate::updateRect(const QRect &r) else dirtyRegion += r.adjusted(-2, -2, 2, 2); break; - case QGraphicsView::NoViewportUpdate: - // Unreachable + default: break; } + + return true; } QStyleOptionGraphicsItem *QGraphicsViewPrivate::allocStyleOptionsArray(int numItems) @@ -3288,10 +3294,6 @@ void QGraphicsView::paintEvent(QPaintEvent *event) // Determine the exposed region d->exposedRegion = event->region(); - if (!d->accelerateScrolling) - d->exposedRegion = viewport()->rect(); - else if (d->viewportUpdateMode == BoundingRectViewportUpdate) - d->exposedRegion = event->rect(); QRectF exposedSceneRect = mapToScene(d->exposedRegion.boundingRect()).boundingRect(); // Set up the painter @@ -3305,8 +3307,10 @@ void QGraphicsView::paintEvent(QPaintEvent *event) painter.setRenderHints(d->renderHints, true); // Set up viewport transform - const QTransform viewTransform = viewportTransform(); - painter.setWorldTransform(viewTransform); + const bool viewTransformed = isTransformed(); + if (viewTransformed) + painter.setWorldTransform(viewportTransform()); + const QTransform viewTransform = painter.worldTransform(); // Draw background if ((d->cacheMode & CacheBackground) @@ -3331,16 +3335,21 @@ void QGraphicsView::paintEvent(QPaintEvent *event) if (!d->backgroundPixmapExposed.isEmpty()) { QPainter backgroundPainter(&d->backgroundPixmap); backgroundPainter.setClipRegion(d->backgroundPixmapExposed, Qt::ReplaceClip); - backgroundPainter.setTransform(viewportTransform()); + if (viewTransformed) + backgroundPainter.setTransform(viewTransform); backgroundPainter.setCompositionMode(QPainter::CompositionMode_Source); drawBackground(&backgroundPainter, exposedSceneRect); d->backgroundPixmapExposed = QRegion(); } // Blit the background from the background pixmap - painter.setWorldTransform(QTransform()); - painter.drawPixmap(QPoint(), d->backgroundPixmap); - painter.setWorldTransform(viewTransform); + if (viewTransformed) { + painter.setWorldTransform(QTransform()); + painter.drawPixmap(QPoint(), d->backgroundPixmap); + painter.setWorldTransform(viewTransform); + } else { + painter.drawPixmap(QPoint(), d->backgroundPixmap); + } } else { if (!(d->optimizationFlags & DontSavePainterState)) painter.save(); @@ -3363,8 +3372,10 @@ void QGraphicsView::paintEvent(QPaintEvent *event) const int numItems = itemList.size(); QGraphicsItem **itemArray = &itemList[0]; // Relies on QList internals, but is perfectly valid. QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems); - for (int i = 0; i < numItems; ++i) - itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], viewTransform, d->exposedRegion, allItems); + for (int i = 0; i < numItems; ++i) { + itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], viewTransform, + d->exposedRegion, allItems); + } // Draw the items. drawItems(&painter, numItems, itemArray, styleOptionArray); d->freeStyleOptionsArray(styleOptionArray); diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h index 903ca2b..5682138 100644 --- a/src/gui/graphicsview/qgraphicsview_p.h +++ b/src/gui/graphicsview/qgraphicsview_p.h @@ -171,8 +171,8 @@ public: dirtyBoundingRect = QRect(); dirtyRegion = QRegion(); } - void updateRect(const QRect &rect); - void updateRegion(const QRegion ®ion); + bool updateRect(const QRect &rect); + bool updateRegion(const QRegion ®ion); bool updateSceneSlotReimplementedChecked; QRegion exposedRegion; |