summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2009-05-28 13:31:46 (GMT)
committerAndreas Aardal Hanssen <andreas.aardal.hanssen@nokia.com>2009-06-09 07:27:26 (GMT)
commit7c164da956c3b55b6b38df1c9e13dcd821b5062f (patch)
treefef86d6521c967704d4b97fb025352111e164154
parentf233dafed58b6429d693ae0248f596a0377cd547 (diff)
downloadQt-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.cpp114
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h28
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;