diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2009-05-28 13:31:46 (GMT) |
---|---|---|
committer | Andreas Aardal Hanssen <andreas.aardal.hanssen@nokia.com> | 2009-06-09 07:27:26 (GMT) |
commit | 7c164da956c3b55b6b38df1c9e13dcd821b5062f (patch) | |
tree | fef86d6521c967704d4b97fb025352111e164154 | |
parent | f233dafed58b6429d693ae0248f596a0377cd547 (diff) | |
download | Qt-7c164da956c3b55b6b38df1c9e13dcd821b5062f.zip Qt-7c164da956c3b55b6b38df1c9e13dcd821b5062f.tar.gz Qt-7c164da956c3b55b6b38df1c9e13dcd821b5062f.tar.bz2 |
simplify opacity handling in QGraphicsItem
Greatly simplify how we handle opacity and store it as a member in
QGraphicsItemPrivate. Remove the caching of effectiveOpacity. It's
faster to calculate it on the fly, and the recursive painting algorithm
will make even that need go away.
Reviewed-by: Andreas
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem.cpp | 114 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem_p.h | 28 |
2 files changed, 31 insertions, 111 deletions
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 26da858..3f6b83c 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -912,9 +912,6 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de scene->d_func()->invalidateSortCache(); } - // Resolve opacity. - updateEffectiveOpacity(); - // Resolve depth. resolveDepth(parent ? parent->d_ptr->depth : -1); @@ -1372,11 +1369,6 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) // Update flags. d_ptr->flags = flags; - // Reresolve effective opacity if the opacity flags change. - static const quint32 opacityFlagsMask = ItemIgnoresParentOpacity | ItemDoesntPropagateOpacityToChildren; - if ((flags & opacityFlagsMask) != (oldFlags & opacityFlagsMask)) - d_ptr->updateEffectiveOpacity(); - if (!(d_ptr->flags & ItemIsFocusable) && hasFocus()) { // Clear focus on the item if it has focus when the focusable flag // is unset. @@ -1981,12 +1973,7 @@ void QGraphicsItem::setSelected(bool selected) */ qreal QGraphicsItem::opacity() const { - if (d_ptr->hasOpacity) { - QVariant o = d_ptr->extra(QGraphicsItemPrivate::ExtraOpacity); - if (!o.isNull()) - return o.toDouble(); - } - return qreal(1.0); + return d_ptr->opacity; } /*! @@ -2002,11 +1989,20 @@ qreal QGraphicsItem::opacity() const */ qreal QGraphicsItem::effectiveOpacity() const { - if (!d_ptr->hasEffectiveOpacity) - return qreal(1.0); + if (!d_ptr->parent) + return d_ptr->opacity; + + QGraphicsItem::GraphicsItemFlags myFlags = flags(); + QGraphicsItem::GraphicsItemFlags parentFlags = d_ptr->parent ? d_ptr->parent->flags() : QGraphicsItem::GraphicsItemFlags(0); + + // If I have a parent, and I don't ignore my parent's opacity, and my + // parent propagates to me, then combine my local opacity with my parent's + // effective opacity into my effective opacity. + if (!(myFlags & QGraphicsItem::ItemIgnoresParentOpacity) + && !(parentFlags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) + return d_ptr->opacity * d_ptr->parent->effectiveOpacity(); - QVariant effectiveOpacity = d_ptr->extra(QGraphicsItemPrivate::ExtraEffectiveOpacity); - return effectiveOpacity.isNull() ? qreal(1.0) : qreal(effectiveOpacity.toDouble()); + return d_ptr->opacity; } /*! @@ -2041,24 +2037,10 @@ void QGraphicsItem::setOpacity(qreal opacity) newOpacity = qBound<qreal>(0.0, newOpacity, 1.0); // No change? Done. - if (qFuzzyIsNull(newOpacity - this->opacity())) + if (newOpacity == d_ptr->opacity) return; - // Assign local opacity. - if (qFuzzyIsNull(newOpacity - 1)) { - // Opaque, unset opacity. - d_ptr->hasOpacity = 0; - d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraOpacity); - } else { - d_ptr->hasOpacity = 1; - d_ptr->setExtra(QGraphicsItemPrivate::ExtraOpacity, double(newOpacity)); - } - - // Resolve effective opacity. - if (QGraphicsItem *p = d_ptr->parent) - d_ptr->resolveEffectiveOpacity(p->effectiveOpacity()); - else - d_ptr->resolveEffectiveOpacity(1.0); + d_ptr->opacity = newOpacity; // Notify change. itemChange(ItemOpacityHasChanged, newOpacity); @@ -3793,70 +3775,6 @@ bool QGraphicsItemPrivate::discardUpdateRequest(bool ignoreClipping, bool ignore || (!ignoreOpacity && childrenCombineOpacity() && isFullyTransparent()); } -static inline bool allChildrenCombineOpacityHelper(QGraphicsItem *parent) -{ - Q_ASSERT(parent); - if (parent->flags() & QGraphicsItem::ItemDoesntPropagateOpacityToChildren) - return false; - - const QList<QGraphicsItem *> children(parent->childItems()); - for (int i = 0; i < children.size(); ++i) { - if (children.at(i)->flags() & QGraphicsItem::ItemIgnoresParentOpacity) - return false; - } - return true; -} - -void QGraphicsItemPrivate::updateEffectiveOpacity() -{ - Q_Q(QGraphicsItem); - if (parent) { - resolveEffectiveOpacity(parent->effectiveOpacity()); - parent->d_ptr->allChildrenCombineOpacity = allChildrenCombineOpacityHelper(parent); - } else { - resolveEffectiveOpacity(1.0); - } - allChildrenCombineOpacity = allChildrenCombineOpacityHelper(q); -} - -/*! - \internal - - Resolves and propagates this item's effective opacity to its children. -*/ -void QGraphicsItemPrivate::resolveEffectiveOpacity(qreal parentEffectiveOpacity) -{ - Q_Q(QGraphicsItem); - QGraphicsItem::GraphicsItemFlags myFlags = q->flags(); - QGraphicsItem::GraphicsItemFlags parentFlags = parent ? parent->flags() : QGraphicsItem::GraphicsItemFlags(0); - - // My local opacity is always part of my effective opacity. - qreal myEffectiveOpacity = q->opacity(); - - // If I have a parent, and I don't ignore my parent's opacity, and my - // parent propagates to me, then combine my local opacity with my parent's - // effective opacity into my effective opacity. - if (parent - && !(myFlags & QGraphicsItem::ItemIgnoresParentOpacity) - && !(parentFlags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) { - myEffectiveOpacity *= parentEffectiveOpacity; - } - - // Set this item's resolved opacity. - if (qFuzzyIsNull(myEffectiveOpacity - 1)) { - // Opaque, unset effective opacity. - hasEffectiveOpacity = 0; - unsetExtra(ExtraEffectiveOpacity); - } else { - hasEffectiveOpacity = 1; - setExtra(ExtraEffectiveOpacity, myEffectiveOpacity); - } - - // Resolve children always. - for (int i = 0; i < children.size(); ++i) - children.at(i)->d_ptr->resolveEffectiveOpacity(myEffectiveOpacity); -} - /*! \internal diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 35305b4..c999378 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -100,10 +100,7 @@ public: ExtraCursor, ExtraCacheData, ExtraMaxDeviceCoordCacheSize, - ExtraBoundingRegionGranularity, - ExtraOpacity, - ExtraEffectiveOpacity, - ExtraDecomposedTransform + ExtraBoundingRegionGranularity }; enum AncestorFlag { @@ -115,6 +112,7 @@ public: inline QGraphicsItemPrivate() : z(0), + opacity(1.), scene(0), parent(0), transform(0), @@ -136,8 +134,6 @@ public: ancestorFlags(0), cacheMode(0), hasBoundingRegionGranularity(0), - hasOpacity(0), - hasEffectiveOpacity(0), isWidget(0), dirty(0), dirtyChildren(0), @@ -177,8 +173,6 @@ public: void setEnabledHelper(bool newEnabled, bool explicitly, bool update = true); bool discardUpdateRequest(bool ignoreClipping = false, bool ignoreVisibleBit = false, bool ignoreDirtyBit = false, bool ignoreOpacity = false) const; - void updateEffectiveOpacity(); - void resolveEffectiveOpacity(qreal effectiveParentOpacity); void resolveDepth(int parentDepth); void addChild(QGraphicsItem *child); void removeChild(QGraphicsItem *child); @@ -278,10 +272,19 @@ public: void updateCachedClipPathFromSetPosHelper(const QPointF &newPos); inline bool isFullyTransparent() const - { return hasEffectiveOpacity && qFuzzyIsNull(q_func()->effectiveOpacity()); } + { return q_func()->effectiveOpacity() < .001; } inline bool childrenCombineOpacity() const - { return allChildrenCombineOpacity || children.isEmpty(); } + { + if (!children.size() || flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren) + return false; + + for (int i = 0; i < children.size(); ++i) { + if (children.at(i)->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity) + return false; + } + return true; + } inline bool isClippedAway() const { return !dirtyClipPath && q_func()->isClipped() && (emptyClipPath || cachedClipPath.isEmpty()); } @@ -314,6 +317,7 @@ public: QMap<QWidget *, QRect> paintedViewBoundingRects; QPointF pos; qreal z; + qreal opacity; QGraphicsScene *scene; QGraphicsItem *parent; QList<QGraphicsItem *> children; @@ -338,8 +342,6 @@ public: quint32 ancestorFlags : 3; quint32 cacheMode : 2; quint32 hasBoundingRegionGranularity : 1; - quint32 hasOpacity : 1; - quint32 hasEffectiveOpacity : 1; quint32 isWidget : 1; quint32 dirty : 1; quint32 dirtyChildren : 1; @@ -347,7 +349,7 @@ public: quint32 dirtyClipPath : 1; quint32 emptyClipPath : 1; quint32 inSetPosHelper : 1; - quint32 unused : 1; + quint32 unused : 3; // New 32 bits quint32 flags : 10; |