diff options
author | Bjørn Erik Nilsen <bjorn.nilsen@nokia.com> | 2009-07-07 08:31:52 (GMT) |
---|---|---|
committer | Bjørn Erik Nilsen <bjorn.nilsen@nokia.com> | 2009-07-08 15:28:39 (GMT) |
commit | 1336f8268512a4ad29732acf75f2e6c4d41683ce (patch) | |
tree | f20c5e7f6c632adc1d0e5184a5bcabc0d8c68932 /src/gui/graphicsview/qgraphicsscene.cpp | |
parent | d228015c67614051df8ae0b2f0483572fd667b83 (diff) | |
download | Qt-1336f8268512a4ad29732acf75f2e6c4d41683ce.zip Qt-1336f8268512a4ad29732acf75f2e6c4d41683ce.tar.gz Qt-1336f8268512a4ad29732acf75f2e6c4d41683ce.tar.bz2 |
Reduce QTransform operations in Graphics View.
Use the item's cached scene transform directly instead of always making a copy
of it. Moreover, we don't have to use the transform at all if the scene
transform is a "translate only" transform :-). QTransform already use
the same cut-offs, but it must update the type() before it can find out.
We don't have to check the type() because that is already stored (and we
usually don't call type() when we store the value either).
All auto-tests pass.
Diffstat (limited to 'src/gui/graphicsview/qgraphicsscene.cpp')
-rw-r--r-- | src/gui/graphicsview/qgraphicsscene.cpp | 86 |
1 files changed, 58 insertions, 28 deletions
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index bae1afd..ae6c53c 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4228,6 +4228,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * QTransform transform(Qt::Uninitialized); QTransform *transformPtr = 0; + bool translateOnlyTransform = false; #define ENSURE_TRANSFORM_PTR \ if (!transformPtr) { \ Q_ASSERT(!itemIsUntransformable); \ @@ -4237,6 +4238,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * transformPtr = &transform; \ } else { \ transformPtr = &item->d_ptr->sceneTransform; \ + translateOnlyTransform = item->d_ptr->sceneTransformTranslateOnly; \ } \ } @@ -4248,10 +4250,8 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * transform = item->deviceTransform(viewTransform ? *viewTransform : QTransform()); transformPtr = &transform; } else if (item->d_ptr->dirtySceneTransform) { - 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; + item->d_ptr->updateSceneTransformFromParent(); + Q_ASSERT(!item->d_ptr->dirtySceneTransform); wasDirtyParentSceneTransform = true; } @@ -4260,7 +4260,8 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (drawItem) { const QRectF brect = adjustedItemBoundingRect(item); ENSURE_TRANSFORM_PTR - QRect viewBoundingRect = transformPtr->mapRect(brect).toRect(); + QRect viewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy()).toRect() + : transformPtr->mapRect(brect).toRect(); item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect); viewBoundingRect.adjust(-1, -1, 1, 1); drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect) : !viewBoundingRect.isEmpty(); @@ -4416,13 +4417,45 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b } static inline bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item, - const QRectF &rect, const QTransform &xform) + const QRectF &rect, bool itemIsUntransformable) { Q_ASSERT(view); Q_ASSERT(item); - if (item->hasBoundingRegionGranularity) + + QGraphicsItem *itemq = static_cast<QGraphicsItem *>(item->q_ptr); + QGraphicsView *viewq = static_cast<QGraphicsView *>(view->q_ptr); + + if (itemIsUntransformable) { + const QTransform xform = itemq->deviceTransform(viewq->viewportTransform()); + if (!item->hasBoundingRegionGranularity) + return view->updateRect(xform.mapRect(rect).toRect()); return view->updateRegion(xform.map(QRegion(rect.toRect()))); - return view->updateRect(xform.mapRect(rect).toRect()); + } + + if (item->sceneTransformTranslateOnly && view->identityMatrix) { + const qreal dx = item->sceneTransform.dx(); + const qreal dy = item->sceneTransform.dy(); + if (!item->hasBoundingRegionGranularity) { + QRectF r(rect); + r.translate(dx - view->horizontalScroll(), dy - view->verticalScroll()); + return view->updateRect(r.toRect()); + } + QRegion r(rect.toRect()); + r.translate(qRound(dx) - view->horizontalScroll(), qRound(dy) - view->verticalScroll()); + return view->updateRegion(r); + } + + if (!viewq->isTransformed()) { + if (!item->hasBoundingRegionGranularity) + return view->updateRect(item->sceneTransform.mapRect(rect).toRect()); + return view->updateRegion(item->sceneTransform.map(QRegion(rect.toRect()))); + } + + QTransform xform = item->sceneTransform; + xform *= viewq->viewportTransform(); + if (!item->hasBoundingRegionGranularity) + return view->updateRect(xform.mapRect(rect).toRect()); + return view->updateRegion(xform.map(QRegion(rect.toRect()))); } void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren, @@ -4460,11 +4493,8 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool bool wasDirtyParentSceneTransform = item->d_ptr->dirtySceneTransform; const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable(); if (wasDirtyParentSceneTransform && !itemIsUntransformable) { - // 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; + item->d_ptr->updateSceneTransformFromParent(); + Q_ASSERT(!item->d_ptr->dirtySceneTransform); } const bool wasDirtyParentViewBoundingRects = item->d_ptr->paintedViewBoundingRectsNeedRepaint; @@ -4479,8 +4509,14 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool if (item->d_ptr->geometryChanged) { // Update growingItemsBoundingRect. - if (!hasSceneRect) - growingItemsBoundingRect |= item->d_ptr->sceneTransform.mapRect(item->boundingRect()); + if (!hasSceneRect) { + if (item->d_ptr->sceneTransformTranslateOnly) { + growingItemsBoundingRect |= item->boundingRect().translated(item->d_ptr->sceneTransform.dx(), + item->d_ptr->sceneTransform.dy()); + } else { + growingItemsBoundingRect |= item->d_ptr->sceneTransform.mapRect(item->boundingRect()); + } + } item->d_ptr->geometryChanged = 0; } @@ -4493,7 +4529,12 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool // This block of code is kept for compatibility. Since 4.5, by default // QGraphicsView does not connect the signal and we use the below // method of delivering updates. - q->update(item->d_ptr->sceneTransform.mapRect(itemBoundingRect)); + if (item->d_ptr->sceneTransformTranslateOnly) { + q->update(itemBoundingRect.translated(item->d_ptr->sceneTransform.dx(), + item->d_ptr->sceneTransform.dy())); + } else { + q->update(item->d_ptr->sceneTransform.mapRect(itemBoundingRect)); + } } else { QRectF dirtyRect; bool uninitializedDirtyRect = true; @@ -4536,18 +4577,7 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool if (dirtyRect.isEmpty()) continue; // Discard updates outside the bounding rect. - bool valid = false; - if (itemIsUntransformable) { - 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 (!valid) + if (!updateHelper(viewPrivate, item->d_ptr, dirtyRect, itemIsUntransformable)) paintedViewBoundingRect = QRect(); } } |