diff options
Diffstat (limited to 'src/gui/graphicsview/qgraphicsscene.cpp')
-rw-r--r-- | src/gui/graphicsview/qgraphicsscene.cpp | 114 |
1 files changed, 74 insertions, 40 deletions
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 28dd3be..2f7ae04 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4060,14 +4060,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) @@ -4084,7 +4077,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * // Calculate the full transform for this item. bool wasDirtyParentSceneTransform = false; bool dontDrawItem = true; - QTransform transform; + QTransform transform(Qt::Uninitialized); if (item) { if (item->d_ptr->itemIsUntransformable()) { transform = item->deviceTransform(viewTransform); @@ -4207,7 +4200,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(); @@ -4291,6 +4288,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; @@ -4298,34 +4300,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; } @@ -4354,11 +4380,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) @@ -4366,7 +4393,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; @@ -4377,17 +4403,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(); } } } @@ -4400,12 +4428,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; @@ -4428,7 +4462,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(); |