From d6d49aa56750359012cdf722df27b0a1c3e5b2aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 28 Aug 2009 10:31:31 +0200 Subject: Add support for setting an opacity mask on QGraphicsOpacityEffect. Opacity masks enable you to make portions of an element transparent. More information about opacity masks here: http://msdn.microsoft.com/en-us/library/ms743320.aspx Reviewed-by: Samuel --- .../code/src_gui_effects_qgraphicseffect.cpp | 10 +++ src/gui/effects/qgraphicseffect.cpp | 93 ++++++++++++++++++++-- src/gui/effects/qgraphicseffect.h | 5 ++ src/gui/effects/qgraphicseffect_p.h | 4 +- 4 files changed, 106 insertions(+), 6 deletions(-) diff --git a/doc/src/snippets/code/src_gui_effects_qgraphicseffect.cpp b/doc/src/snippets/code/src_gui_effects_qgraphicseffect.cpp index 6265c80..152b04f 100644 --- a/doc/src/snippets/code/src_gui_effects_qgraphicseffect.cpp +++ b/doc/src/snippets/code/src_gui_effects_qgraphicseffect.cpp @@ -31,3 +31,13 @@ MyGraphicsEffect::draw(QPainter *painter, QGraphicsEffectSource *source) } //! [1] +//! [2] +... +QLinearGradient alphaGradient(rect.topLeft(), rect.bottomLeft()); +alphaGradient.setColorAt(0.0, Qt::transparent); +alphaGradient.setColorAt(0.5, Qt::black); +alphaGradient.setColorAt(1.0, Qt::transparent); +QGraphicsOpacityEffect *effect = new QGraphicsOpacityEffect; +effect->setOpacityMask(alphaGradient); +... +//! [2] diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index 5f64698..62ad44d 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -990,6 +990,8 @@ QGraphicsOpacityEffect::~QGraphicsOpacityEffect() fully transparent and 1.0 is fully opaque. By default, the opacity is 0.7. + + \sa setOpacityMask() */ qreal QGraphicsOpacityEffect::opacity() const { @@ -1017,6 +1019,45 @@ void QGraphicsOpacityEffect::setOpacity(qreal opacity) */ /*! + \property QGraphicsOpacityEffect::opacityMask + \brief the opacity mask of the effect. + + An opacity mask allows you apply opacity to portions of an element. + + For example: + + \snippet doc/src/snippets/code/src_gui_effects_qgraphicseffect.cpp 2 + + There is no opacity mask by default. + + \sa setOpacity() +*/ +QBrush QGraphicsOpacityEffect::opacityMask() const +{ + Q_D(const QGraphicsOpacityEffect); + return d->opacityMask; +} + +void QGraphicsOpacityEffect::setOpacityMask(const QBrush &mask) +{ + Q_D(QGraphicsOpacityEffect); + if (d->opacityMask == mask) + return; + + d->opacityMask = mask; + d->hasOpacityMask = (mask.style() != Qt::NoBrush); + + emit opacityMaskChanged(mask); +} + +/*! + \fn void QGraphicsOpacityEffect::opacityMaskChanged(const QBrush &mask) + + This signal is emitted whenever the effect's opacity mask changes. + The \a mask parameter holds the effect's new opacity mask. +*/ + +/*! \reimp */ void QGraphicsOpacityEffect::draw(QPainter *painter, QGraphicsEffectSource *source) @@ -1039,13 +1080,55 @@ void QGraphicsOpacityEffect::draw(QPainter *painter, QGraphicsEffectSource *sour QPoint offset; if (source->isPixmap()) { // No point in drawing in device coordinates (pixmap will be scaled anyways). - const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset); - painter->drawPixmap(offset, pixmap); + if (!d->hasOpacityMask) { + const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset); + painter->drawPixmap(offset, pixmap); + } else { + QRectF srcBrect = source->boundingRect(); + QPixmap pixmap(srcBrect.size().toSize()); + pixmap.fill(Qt::transparent); + + QPainter pixmapPainter(&pixmap); + pixmapPainter.setRenderHints(painter->renderHints()); + pixmapPainter.translate(-srcBrect.topLeft()); + source->draw(&pixmapPainter); + pixmapPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn); + pixmapPainter.fillRect(srcBrect, d->opacityMask); + pixmapPainter.end(); + + painter->drawPixmap(srcBrect.topLeft(), pixmap); + } } else { // Draw pixmap in device coordinates to avoid pixmap scaling; - const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); - painter->setWorldTransform(QTransform()); - painter->drawPixmap(offset, pixmap); + if (!d->hasOpacityMask) { + const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); + painter->setWorldTransform(QTransform()); + painter->drawPixmap(offset, pixmap); + } else { + QTransform worldTransform = painter->worldTransform(); + + // Calculate source bounding rect in logical and device coordinates. + QRectF srcBrect = source->boundingRect(); + QRect srcDeviceBrect = worldTransform.mapRect(srcBrect).toAlignedRect(); + srcDeviceBrect &= source->deviceRect(); + + offset = srcDeviceBrect.topLeft(); + worldTransform *= QTransform::fromTranslate(-srcDeviceBrect.x(), -srcDeviceBrect.y()); + + QPixmap pixmap(srcDeviceBrect.size()); + pixmap.fill(Qt::transparent); + + QPainter pixmapPainter(&pixmap); + pixmapPainter.setRenderHints(painter->renderHints()); + pixmapPainter.setWorldTransform(worldTransform); + source->draw(&pixmapPainter); + pixmapPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn); + pixmapPainter.fillRect(srcBrect, d->opacityMask); + pixmapPainter.end(); + + painter->setWorldTransform(QTransform()); + painter->drawPixmap(offset, pixmap); + } } painter->restore(); diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h index fef6531..a53357b 100644 --- a/src/gui/effects/qgraphicseffect.h +++ b/src/gui/effects/qgraphicseffect.h @@ -46,6 +46,7 @@ #include #include #include +#include QT_BEGIN_HEADER @@ -274,17 +275,21 @@ class Q_GUI_EXPORT QGraphicsOpacityEffect: public QGraphicsEffect { Q_OBJECT Q_PROPERTY(int opacity READ opacity WRITE setOpacity NOTIFY opacityChanged) + Q_PROPERTY(QBrush opacityMask READ opacityMask WRITE setOpacityMask NOTIFY opacityMaskChanged) public: QGraphicsOpacityEffect(QObject *parent = 0); ~QGraphicsOpacityEffect(); qreal opacity() const; + QBrush opacityMask() const; public Q_SLOTS: void setOpacity(qreal opacity); + void setOpacityMask(const QBrush &mask); Q_SIGNALS: void opacityChanged(qreal opacity); + void opacityMaskChanged(const QBrush &mask); protected: void draw(QPainter *painter, QGraphicsEffectSource *source); diff --git a/src/gui/effects/qgraphicseffect_p.h b/src/gui/effects/qgraphicseffect_p.h index 6ce5cda..e0a77e7 100644 --- a/src/gui/effects/qgraphicseffect_p.h +++ b/src/gui/effects/qgraphicseffect_p.h @@ -164,10 +164,12 @@ class QGraphicsOpacityEffectPrivate : public QGraphicsEffectPrivate { Q_DECLARE_PUBLIC(QGraphicsOpacityEffect) public: - QGraphicsOpacityEffectPrivate() : opacity(qreal(0.7)) {} + QGraphicsOpacityEffectPrivate() : opacity(qreal(0.7)), hasOpacityMask(0) {} ~QGraphicsOpacityEffectPrivate() {} qreal opacity; + QBrush opacityMask; + uint hasOpacityMask : 1; }; QT_END_NAMESPACE -- cgit v0.12