src/gui/effects/qgraphicseffect.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 /*!
       
    43     \class QGraphicsEffect
       
    44     \brief The QGraphicsEffect class is the base class for all graphics
       
    45            effects.
       
    46     \since 4.6
       
    47     \ingroup multimedia
       
    48     \ingroup graphicsview-api
       
    49 
       
    50     Effects alter the appearance of elements by hooking into the rendering
       
    51     pipeline and operating between the source (e.g., a QGraphicsPixmapItem)
       
    52     and the destination device (e.g., QGraphicsView's viewport). Effects can be
       
    53     disabled by calling setEnabled(false). If effects are disabled, the source
       
    54     is rendered directly.
       
    55 
       
    56     To add a visual effect to a QGraphicsItem, for example, you can use one of
       
    57     the standard effects, or alternately, create your own effect by creating a
       
    58     subclass of QGraphicsEffect. The effect can then be installed on the item
       
    59     using QGraphicsItem::setGraphicsEffect().
       
    60 
       
    61     Qt provides the following standard effects:
       
    62 
       
    63     \list
       
    64     \o QGraphicsBlurEffect - blurs the item by a given radius
       
    65     \o QGraphicsDropShadowEffect - renders a dropshadow behind the item
       
    66     \o QGraphicsColorizeEffect - renders the item in shades of any given color
       
    67     \o QGraphicsOpacityEffect - renders the item with an opacity
       
    68     \o QGraphicsPixelizeEffect - pixelizes the item with any pixel size
       
    69     \o QGraphicsGrayscaleEffect - renders the item in shades of gray
       
    70     \o QGraphicsBloomEffect - applies a blooming / glowing effect
       
    71     \endlist
       
    72 
       
    73     \img graphicseffect-effects.png
       
    74     \img graphicseffect-widget.png
       
    75 
       
    76     For more information on how to use each effect, refer to the specific
       
    77     effect's documentation.
       
    78 
       
    79     To create your own custom effect, create a subclass of QGraphicsEffect (or
       
    80     any other existing effects) and reimplement the virtual function draw().
       
    81     This function is called whenever the effect needs to redraw. The draw()
       
    82     function accepts two arguments: the painter and a pointer to the source
       
    83     (QGraphicsEffectSource). The source provides extra context information,
       
    84     such as a pointer to the item that is rendering the effect, any cached
       
    85     pixmap data, or the device rectangle bounds. For more information, refer to
       
    86     the documenation for draw(). To obtain a pointer to the current source,
       
    87     simply call source().
       
    88 
       
    89     If your effect changes, use update() to request for a redraw. If your
       
    90     custom effect changes the bounding rectangle of the source, e.g., a radial
       
    91     glow effect may need to apply an extra margin, you can reimplement the
       
    92     virtual boundingRectFor() function, and call updateBoundingRect() to notify
       
    93     the framework whenever this rectangle changes. The virtual
       
    94     sourceBoundingRectChanged() function is called to notify the effects that
       
    95     the source's bounding rectangle has changed - e.g., if the source is a
       
    96     QGraphicsRectItem and its rectangle parameters have changed.
       
    97 
       
    98     \sa QGraphicsItem::setGraphicsEffect(), QWidget::setGraphicsEffect(),
       
    99     QGraphicsEffectSource
       
   100 */
       
   101 
       
   102 #include "qgraphicseffect_p.h"
       
   103 
       
   104 #include <QtGui/qimage.h>
       
   105 #include <QtGui/qpainter.h>
       
   106 #include <QtCore/qrect.h>
       
   107 #include <QtCore/qdebug.h>
       
   108 #include <private/qdrawhelper_p.h>
       
   109 
       
   110 QT_BEGIN_NAMESPACE
       
   111 
       
   112 /*!
       
   113     \class QGraphicsEffectSource
       
   114     \brief The QGraphicsEffectSource class represents the source on which a
       
   115            QGraphicsEffect is installed on.
       
   116     \since 4.6
       
   117 
       
   118     When a QGraphicsEffect is installed on a QGraphicsItem, for example, this
       
   119     class will act as a wrapper around QGraphicsItem. Then, calling update() is
       
   120     effectively the same as calling QGraphicsItem::update().
       
   121 
       
   122     QGraphicsEffectSource also provides a pixmap() function which creates a
       
   123     pixmap with the source painted into it.
       
   124 
       
   125     \sa QGraphicsItem::setGraphicsEffect(), QWidget::setGraphicsEffect().
       
   126 */
       
   127 
       
   128 /*!
       
   129     \internal
       
   130 */
       
   131 QGraphicsEffectSource::QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, QObject *parent)
       
   132     : QObject(dd, parent)
       
   133 {}
       
   134 
       
   135 /*!
       
   136     Destroys the effect source.
       
   137 */
       
   138 QGraphicsEffectSource::~QGraphicsEffectSource()
       
   139 {}
       
   140 
       
   141 /*!
       
   142     Returns the bounds of the current painter's device.
       
   143 
       
   144     This function is useful when you want to draw something in device
       
   145     coordinates and ensure the size of the pixmap is not bigger than the size
       
   146     of the device.
       
   147 
       
   148     Calling QGraphicsEffectSource::pixmap(Qt::DeviceCoordinates) always returns
       
   149     a pixmap which is bound to the device's size.
       
   150 
       
   151     \sa pixmap()
       
   152 */
       
   153 QRect QGraphicsEffectSource::deviceRect() const
       
   154 {
       
   155     return d_func()->deviceRect();
       
   156 }
       
   157 
       
   158 /*!
       
   159     Returns the bounding rectangle of the source mapped to the given \a system.
       
   160 
       
   161     \sa draw()
       
   162 */
       
   163 QRectF QGraphicsEffectSource::boundingRect(Qt::CoordinateSystem system) const
       
   164 {
       
   165     return d_func()->boundingRect(system);
       
   166 }
       
   167 
       
   168 /*!
       
   169     Returns a pointer to the item if this source is a QGraphicsItem; otherwise
       
   170     returns 0.
       
   171 
       
   172     \sa widget()
       
   173 */
       
   174 const QGraphicsItem *QGraphicsEffectSource::graphicsItem() const
       
   175 {
       
   176     return d_func()->graphicsItem();
       
   177 }
       
   178 
       
   179 /*!
       
   180     Returns a pointer to the widget if this source is a QWidget; otherwise
       
   181     returns 0.
       
   182 
       
   183     \sa graphicsItem()
       
   184 */
       
   185 const QWidget *QGraphicsEffectSource::widget() const
       
   186 {
       
   187     return d_func()->widget();
       
   188 }
       
   189 
       
   190 /*!
       
   191     Returns a pointer to the style options (used when drawing the source) if
       
   192     available; otherwise returns 0.
       
   193 
       
   194     \sa graphicsItem(), widget()
       
   195 */
       
   196 const QStyleOption *QGraphicsEffectSource::styleOption() const
       
   197 {
       
   198     return d_func()->styleOption();
       
   199 }
       
   200 
       
   201 /*!
       
   202     Draws the source using the given \a painter.
       
   203 
       
   204     This function should only be called from QGraphicsEffect::draw().
       
   205 
       
   206     For example:
       
   207 
       
   208     \snippet doc/src/snippets/code/src_gui_effects_qgraphicseffect.cpp 0
       
   209 
       
   210     \sa QGraphicsEffect::draw()
       
   211 */
       
   212 void QGraphicsEffectSource::draw(QPainter *painter)
       
   213 {
       
   214     d_func()->draw(painter);
       
   215 }
       
   216 
       
   217 /*!
       
   218     Schedules a redraw of the source. Call this function whenever the source
       
   219     needs to be redrawn.
       
   220 
       
   221     \sa QGraphicsEffect::updateBoundingRect(), QWidget::update(),
       
   222         QGraphicsItem::update(),
       
   223 */
       
   224 void QGraphicsEffectSource::update()
       
   225 {
       
   226     d_func()->update();
       
   227 }
       
   228 
       
   229 /*!
       
   230     Returns true if the source effectively is a pixmap, e.g., a
       
   231     QGraphicsPixmapItem.
       
   232 
       
   233     This function is useful for optimization purposes. For instance, there's no
       
   234     point in drawing the source in device coordinates to avoid pixmap scaling
       
   235     if this function returns true - the source pixmap will be scaled anyways.
       
   236 */
       
   237 bool QGraphicsEffectSource::isPixmap() const
       
   238 {
       
   239     return d_func()->isPixmap();
       
   240 }
       
   241 
       
   242 /*!
       
   243     Returns a pixmap with the source painted into it.
       
   244 
       
   245     The \a system specifies which coordinate system to be used for the source.
       
   246     The optional \a offset parameter returns the offset where the pixmap should
       
   247     be painted at using the current painter.
       
   248 
       
   249     The returned pixmap is bound to the current painter's device rectangle when
       
   250     \a system is Qt::DeviceCoordinates.
       
   251 
       
   252     \sa QGraphicsEffect::draw(), boundingRect(), deviceRect()
       
   253 */
       
   254 QPixmap QGraphicsEffectSource::pixmap(Qt::CoordinateSystem system, QPoint *offset) const
       
   255 {
       
   256     Q_D(const QGraphicsEffectSource);
       
   257 
       
   258     QPixmap pm;
       
   259     if (d->m_cachedSystem == system)
       
   260         QPixmapCache::find(d->m_cacheKey, &pm);
       
   261 
       
   262     if (pm.isNull()) {
       
   263         pm = d->pixmap(system, &d->m_cachedOffset);
       
   264         d->m_cachedSystem = system;
       
   265 
       
   266         d->invalidateCache();
       
   267         d->m_cacheKey = QPixmapCache::insert(pm);
       
   268     }
       
   269 
       
   270     if (offset)
       
   271         *offset = d->m_cachedOffset;
       
   272 
       
   273     return pm;
       
   274 }
       
   275 
       
   276 /*!
       
   277     Constructs a new QGraphicsEffect instance having the
       
   278     specified \a parent.
       
   279 */
       
   280 QGraphicsEffect::QGraphicsEffect(QObject *parent)
       
   281     : QObject(*new QGraphicsEffectPrivate, parent)
       
   282 {
       
   283 }
       
   284 
       
   285 /*!
       
   286     \internal
       
   287 */
       
   288 QGraphicsEffect::QGraphicsEffect(QGraphicsEffectPrivate &dd, QObject *parent)
       
   289     : QObject(dd, parent)
       
   290 {
       
   291 }
       
   292 
       
   293 /*!
       
   294     Removes the effect from the source, and destroys the graphics effect.
       
   295 */
       
   296 QGraphicsEffect::~QGraphicsEffect()
       
   297 {
       
   298     Q_D(QGraphicsEffect);
       
   299     d->setGraphicsEffectSource(0);
       
   300 }
       
   301 
       
   302 /*!
       
   303     Returns the bounding rectangle for this effect, i.e., the bounding
       
   304     rectangle of the source, adjusted by any margins applied by the effect
       
   305     itself.
       
   306 
       
   307     \sa boundingRectFor(), updateBoundingRect()
       
   308 */
       
   309 QRectF QGraphicsEffect::boundingRect() const
       
   310 {
       
   311     Q_D(const QGraphicsEffect);
       
   312     if (d->source)
       
   313         return boundingRectFor(d->source->boundingRect());
       
   314     return QRectF();
       
   315 }
       
   316 
       
   317 /*!
       
   318     Returns the bounding rectangle for this effect, given the provided source
       
   319     \a rect. When writing you own custom effect, you must call
       
   320     updateBoundingRect() whenever any parameters are changed that may cause
       
   321     this this function to return a different value.
       
   322 
       
   323     \sa boundingRect()
       
   324 */
       
   325 QRectF QGraphicsEffect::boundingRectFor(const QRectF &rect) const
       
   326 {
       
   327     return rect;
       
   328 }
       
   329 
       
   330 /*!
       
   331     \property QGraphicsEffect::enabled
       
   332     \brief whether the effect is enabled or not.
       
   333 
       
   334     If an effect is disabled, the source will be rendered with as normal, with
       
   335     no interference from the effect. If the effect is enabled, the source will
       
   336     be rendered with the effect applied.
       
   337 
       
   338     This property is enabled by default.
       
   339 
       
   340     Using this property, you can disable certain effects on slow platforms, in
       
   341     order to ensure that the user interface is responsive.
       
   342 */
       
   343 bool QGraphicsEffect::isEnabled() const
       
   344 {
       
   345     Q_D(const QGraphicsEffect);
       
   346     return d->isEnabled;
       
   347 }
       
   348 
       
   349 void QGraphicsEffect::setEnabled(bool enable)
       
   350 {
       
   351     Q_D(QGraphicsEffect);
       
   352     if (d->isEnabled == enable)
       
   353         return;
       
   354 
       
   355     d->isEnabled = enable;
       
   356     if (d->source)
       
   357         d->source->d_func()->effectBoundingRectChanged();
       
   358     emit enabledChanged(enable);
       
   359 }
       
   360 
       
   361 /*!
       
   362     \fn void QGraphicsEffect::enabledChanged(bool enabled)
       
   363 
       
   364     This signal is emitted whenever the effect is enabled or disabled.
       
   365     The \a enabled parameter holds the effects's new enabled state.
       
   366 
       
   367     \sa isEnabled()
       
   368 */
       
   369 
       
   370 /*!
       
   371     Schedules a redraw of the source. Call this function whenever the source
       
   372     needs to be redrawn.
       
   373 
       
   374     This convenience function is equivalent to calling
       
   375     QGraphicsEffectSource::update().
       
   376 
       
   377     \sa updateBoundingRect(), QGraphicsEffectSource::update()
       
   378 */
       
   379 void QGraphicsEffect::update()
       
   380 {
       
   381     Q_D(QGraphicsEffect);
       
   382     if (d->source)
       
   383         d->source->update();
       
   384 }
       
   385 
       
   386 /*!
       
   387     Returns a pointer to the source, which provides extra context information
       
   388     that can be useful for the effect.
       
   389 
       
   390     \sa draw()
       
   391 */
       
   392 QGraphicsEffectSource *QGraphicsEffect::source() const
       
   393 {
       
   394     Q_D(const QGraphicsEffect);
       
   395     return d->source;
       
   396 }
       
   397 
       
   398 /*!
       
   399     This function notifies the effect framework when the effect's bounding
       
   400     rectangle has changed. As a custom effect author, you must call this
       
   401     function whenever you change any parameters that will cause the virtual
       
   402     boundingRectFor() function to return a different value.
       
   403 
       
   404     This function will call update() if this is necessary.
       
   405 
       
   406     \sa boundingRectFor(), boundingRect()
       
   407 */
       
   408 void QGraphicsEffect::updateBoundingRect()
       
   409 {
       
   410     Q_D(QGraphicsEffect);
       
   411     if (d->source)
       
   412         d->source->d_func()->effectBoundingRectChanged();
       
   413 }
       
   414 
       
   415 /*!
       
   416     \fn virtual void QGraphicsEffect::draw(QPainter *painter,
       
   417     QGraphicsEffectSource *source) = 0
       
   418 
       
   419     This pure virtual function draws the effect and is called whenever the
       
   420     source() needs to be drawn.
       
   421 
       
   422     Reimplement this function in a QGraphicsEffect subclass to provide the
       
   423     effect's drawing implementation, using \a painter. The \a source parameter
       
   424     is provided for convenience; its value is the same as source().
       
   425 
       
   426     For example:
       
   427 
       
   428     \snippet doc/src/snippets/code/src_gui_effects_qgraphicseffect.cpp 1
       
   429 
       
   430     This function should not be called explicitly by the user, since it is
       
   431     meant for reimplementation purposes only.
       
   432 
       
   433     \sa QGraphicsEffectSource
       
   434 */
       
   435 
       
   436 /*!
       
   437     \enum QGraphicsEffect::ChangeFlag
       
   438 
       
   439     This enum describes what has changed in QGraphicsEffectSource.
       
   440 
       
   441     \value SourceAttached The effect is installed on a source.
       
   442     \value SourceDetached The effect is uninstalled on a source.
       
   443     \value SourceBoundingRectChanged The bounding rect of the source has
       
   444            changed.
       
   445     \value SourceInvalidated The visual appearance of the source has changed.
       
   446 */
       
   447 
       
   448 /*!
       
   449     This virtual function is called by QGraphicsEffect to notify the effect
       
   450     that the source has changed. If the effect applies any cache, then this
       
   451     cache must be purged in order to reflect the new appearance of the source.
       
   452 
       
   453     The \a flags describes what has changed.
       
   454 */
       
   455 void QGraphicsEffect::sourceChanged(ChangeFlags flags)
       
   456 {
       
   457     Q_UNUSED(flags);
       
   458 }
       
   459 
       
   460 /*!
       
   461     \class QGraphicsGrayscaleEffect
       
   462     \brief The QGraphicsGrayscaleEffect class provides a grayscale effect.
       
   463     \since 4.6
       
   464 
       
   465     A grayscale effect renders the source in shades of gray.
       
   466 
       
   467     \img graphicseffect-grayscale.png
       
   468 
       
   469     \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsPixelizeEffect,
       
   470         QGraphicsColorizeEffect, QGraphicsOpacityEffect
       
   471 */
       
   472 
       
   473 /*!
       
   474     Constructs a new QGraphicsGrayscale instance.
       
   475     The \a parent parameter is passed to QGraphicsEffect's constructor.
       
   476 */
       
   477 QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect(QObject *parent)
       
   478     : QGraphicsEffect(*new QGraphicsGrayscaleEffectPrivate, parent)
       
   479 {
       
   480 }
       
   481 
       
   482 /*!
       
   483     Destroys the effect.
       
   484 */
       
   485 QGraphicsGrayscaleEffect::~QGraphicsGrayscaleEffect()
       
   486 {
       
   487 }
       
   488 
       
   489 
       
   490 /*!
       
   491     \property QGraphicsGrayscaleEffect::strength
       
   492     \brief the strength of the effect.
       
   493 
       
   494     By default, the strength is 1.0.
       
   495     A strength 0.0 equals to no effect, while 1.0 means full grayscale.
       
   496 */
       
   497 qreal QGraphicsGrayscaleEffect::strength() const
       
   498 {
       
   499     Q_D(const QGraphicsGrayscaleEffect);
       
   500     return d->filter->strength();
       
   501 }
       
   502 
       
   503 void QGraphicsGrayscaleEffect::setStrength(qreal strength)
       
   504 {
       
   505     Q_D(QGraphicsGrayscaleEffect);
       
   506     if (qFuzzyCompare(d->filter->strength(), strength))
       
   507         return;
       
   508 
       
   509     d->filter->setStrength(strength);
       
   510     d->opaque = !qFuzzyIsNull(strength);
       
   511     update();
       
   512     emit strengthChanged(strength);
       
   513 }
       
   514 
       
   515 /*! \fn void QGraphicsGrayscaleEffect::strengthChanged(qreal strength)
       
   516   This signal is emitted whenever setStrength() changes the grayscale
       
   517   strength property. \a strength contains the new strength value of
       
   518   the grayscale effect.
       
   519  */
       
   520 
       
   521 /*!
       
   522     \reimp
       
   523 */
       
   524 void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *source)
       
   525 {
       
   526     Q_D(QGraphicsGrayscaleEffect);
       
   527 
       
   528     if (!d->opaque) {
       
   529         source->draw(painter);
       
   530         return;
       
   531     }
       
   532 
       
   533     QPoint offset;
       
   534     if (source->isPixmap()) {
       
   535         // No point in drawing in device coordinates (pixmap will be scaled anyways).
       
   536         const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset);
       
   537         d->filter->draw(painter, offset, pixmap);
       
   538         return;
       
   539     }
       
   540 
       
   541     // Draw pixmap in device coordinates to avoid pixmap scaling;
       
   542     const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset);
       
   543     QTransform restoreTransform = painter->worldTransform();
       
   544     painter->setWorldTransform(QTransform());
       
   545     d->filter->draw(painter, offset, pixmap);
       
   546     painter->setWorldTransform(restoreTransform);
       
   547 
       
   548 }
       
   549 
       
   550 /*!
       
   551     \class QGraphicsColorizeEffect
       
   552     \brief The QGraphicsColorizeEffect class provides a colorize effect.
       
   553     \since 4.6
       
   554 
       
   555     A colorize effect renders the source with a tint of its color(). The color
       
   556     can be modified using the setColor() function.
       
   557 
       
   558     By default, the color is light blue (QColor(0, 0, 192)).
       
   559 
       
   560     \img graphicseffect-colorize.png
       
   561 
       
   562     \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsPixelizeEffect,
       
   563         QGraphicsGrayscaleEffect, QGraphicsOpacityEffect
       
   564 */
       
   565 
       
   566 /*!
       
   567     Constructs a new QGraphicsColorizeEffect instance.
       
   568     The \a parent parameter is passed to QGraphicsEffect's constructor.
       
   569 */
       
   570 QGraphicsColorizeEffect::QGraphicsColorizeEffect(QObject *parent)
       
   571     : QGraphicsEffect(*new QGraphicsColorizeEffectPrivate, parent)
       
   572 {
       
   573 }
       
   574 
       
   575 /*!
       
   576     Destroys the effect.
       
   577 */
       
   578 QGraphicsColorizeEffect::~QGraphicsColorizeEffect()
       
   579 {
       
   580 }
       
   581 
       
   582 /*!
       
   583     \property QGraphicsColorizeEffect::color
       
   584     \brief the color of the effect.
       
   585 
       
   586     By default, the color is light blue (QColor(0, 0, 192)).
       
   587 */
       
   588 QColor QGraphicsColorizeEffect::color() const
       
   589 {
       
   590     Q_D(const QGraphicsColorizeEffect);
       
   591     return d->filter->color();
       
   592 }
       
   593 
       
   594 void QGraphicsColorizeEffect::setColor(const QColor &color)
       
   595 {
       
   596     Q_D(QGraphicsColorizeEffect);
       
   597     if (d->filter->color() == color)
       
   598         return;
       
   599 
       
   600     d->filter->setColor(color);
       
   601     update();
       
   602     emit colorChanged(color);
       
   603 }
       
   604 
       
   605 /*!
       
   606     \property QGraphicsColorizeEffect::strength
       
   607     \brief the strength of the effect.
       
   608 
       
   609     By default, the strength is 1.0.
       
   610     A strength 0.0 equals to no effect, while 1.0 means full colorization.
       
   611 */
       
   612 qreal QGraphicsColorizeEffect::strength() const
       
   613 {
       
   614     Q_D(const QGraphicsColorizeEffect);
       
   615     return d->filter->strength();
       
   616 }
       
   617 
       
   618 void QGraphicsColorizeEffect::setStrength(qreal strength)
       
   619 {
       
   620     Q_D(QGraphicsColorizeEffect);
       
   621     if (qFuzzyCompare(d->filter->strength(), strength))
       
   622         return;
       
   623 
       
   624     d->filter->setStrength(strength);
       
   625     d->opaque = !qFuzzyIsNull(strength);
       
   626     update();
       
   627     emit strengthChanged(strength);
       
   628 }
       
   629 
       
   630 /*! \fn void QGraphicsColorizeEffect::strengthChanged(qreal strength)
       
   631   This signal is emitted whenever setStrength() changes the colorize
       
   632   strength property. \a strength contains the new strength value of
       
   633   the colorize effect.
       
   634  */
       
   635 
       
   636 /*!
       
   637     \fn void QGraphicsColorizeEffect::colorChanged(const QColor &color)
       
   638 
       
   639     This signal is emitted whenever the effect's color changes.
       
   640     The \a color parameter holds the effect's new color.
       
   641 */
       
   642 
       
   643 /*!
       
   644     \reimp
       
   645 */
       
   646 void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *source)
       
   647 {
       
   648     Q_D(QGraphicsColorizeEffect);
       
   649 
       
   650     if (!d->opaque) {
       
   651         source->draw(painter);
       
   652         return;
       
   653     }
       
   654 
       
   655     QPoint offset;
       
   656     if (source->isPixmap()) {
       
   657         // No point in drawing in device coordinates (pixmap will be scaled anyways).
       
   658         const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset);
       
   659         d->filter->draw(painter, offset, pixmap);
       
   660         return;
       
   661     }
       
   662 
       
   663     // Draw pixmap in deviceCoordinates to avoid pixmap scaling.
       
   664     const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset);
       
   665     QTransform restoreTransform = painter->worldTransform();
       
   666     painter->setWorldTransform(QTransform());
       
   667     d->filter->draw(painter, offset, pixmap);
       
   668     painter->setWorldTransform(restoreTransform);
       
   669 }
       
   670 
       
   671 /*!
       
   672     \class QGraphicsPixelizeEffect
       
   673     \brief The QGraphicsPixelizeEffect class provides a pixelize effect.
       
   674     \since 4.6
       
   675 
       
   676     A pixelize effect renders the source in lower resolution. This effect is
       
   677     useful for reducing details, like censorship. The resolution can be
       
   678     modified using the setPixelSize() function.
       
   679 
       
   680     By default, the pixel size is 3.
       
   681 
       
   682     \img graphicseffect-pixelize.png
       
   683 
       
   684     \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsGrayscaleEffect,
       
   685         QGraphicsColorizeEffect, QGraphicsOpacityEffect
       
   686 */
       
   687 
       
   688 /*!
       
   689     Constructs a new QGraphicsPixelizeEffect instance.
       
   690     The \a parent parameter is passed to QGraphicsEffect's constructor.
       
   691 */
       
   692 QGraphicsPixelizeEffect::QGraphicsPixelizeEffect(QObject *parent)
       
   693     : QGraphicsEffect(*new QGraphicsPixelizeEffectPrivate, parent)
       
   694 {
       
   695 }
       
   696 
       
   697 /*!
       
   698     Destroys the effect.
       
   699 */
       
   700 QGraphicsPixelizeEffect::~QGraphicsPixelizeEffect()
       
   701 {
       
   702 }
       
   703 
       
   704 /*!
       
   705     \property QGraphicsPixelizeEffect::pixelSize
       
   706     \brief the size of a pixel in the effect.
       
   707 
       
   708     Setting the pixel size to 2 means two pixels in the source will be used to
       
   709     represent one pixel. Using a bigger size results in lower resolution.
       
   710 
       
   711     By default, the pixel size is 3.
       
   712 */
       
   713 int QGraphicsPixelizeEffect::pixelSize() const
       
   714 {
       
   715     Q_D(const QGraphicsPixelizeEffect);
       
   716     return d->pixelSize;
       
   717 }
       
   718 
       
   719 void QGraphicsPixelizeEffect::setPixelSize(int size)
       
   720 {
       
   721     Q_D(QGraphicsPixelizeEffect);
       
   722     if (d->pixelSize == size)
       
   723         return;
       
   724 
       
   725     d->pixelSize = size;
       
   726     update();
       
   727     emit pixelSizeChanged(size);
       
   728 }
       
   729 
       
   730 /*!
       
   731     \fn void QGraphicsPixelizeEffect::pixelSizeChanged(int size)
       
   732 
       
   733     This signal is emitted whenever the effect's pixel size changes.
       
   734     The \a size parameter holds the effect's new pixel size.
       
   735 */
       
   736 
       
   737 static inline void pixelize(QImage *image, int pixelSize)
       
   738 {
       
   739     Q_ASSERT(pixelSize > 0);
       
   740     Q_ASSERT(image);
       
   741     int width = image->width();
       
   742     int height = image->height();
       
   743     for (int y = 0; y < height; y += pixelSize) {
       
   744         int ys = qMin(height - 1, y + pixelSize / 2);
       
   745         QRgb *sbuf = reinterpret_cast<QRgb*>(image->scanLine(ys));
       
   746         for (int x = 0; x < width; x += pixelSize) {
       
   747             int xs = qMin(width - 1, x + pixelSize / 2);
       
   748             QRgb color = sbuf[xs];
       
   749             for (int yi = 0; yi < qMin(pixelSize, height - y); ++yi) {
       
   750                 QRgb *buf = reinterpret_cast<QRgb*>(image->scanLine(y + yi));
       
   751                 for (int xi = 0; xi < qMin(pixelSize, width - x); ++xi)
       
   752                     buf[x + xi] = color;
       
   753             }
       
   754         }
       
   755     }
       
   756 }
       
   757 
       
   758 /*!
       
   759     \reimp
       
   760 */
       
   761 void QGraphicsPixelizeEffect::draw(QPainter *painter, QGraphicsEffectSource *source)
       
   762 {
       
   763     Q_D(QGraphicsPixelizeEffect);
       
   764     if (d->pixelSize <= 0) {
       
   765         source->draw(painter);
       
   766         return;
       
   767     }
       
   768 
       
   769     QPoint offset;
       
   770     if (source->isPixmap()) {
       
   771         const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset);
       
   772         QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
       
   773         pixelize(&image, d->pixelSize);
       
   774         painter->drawImage(offset, image);
       
   775         return;
       
   776     }
       
   777 
       
   778     // Draw pixmap in device coordinates to avoid pixmap scaling.
       
   779     const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset);
       
   780 
       
   781     // pixelize routine
       
   782     QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
       
   783     pixelize(&image, d->pixelSize);
       
   784 
       
   785     QTransform restoreTransform = painter->worldTransform();
       
   786     painter->setWorldTransform(QTransform());
       
   787     painter->drawImage(offset, image);
       
   788     painter->setWorldTransform(restoreTransform);
       
   789 }
       
   790 
       
   791 /*!
       
   792     \class QGraphicsBlurEffect
       
   793     \brief The QGraphicsBlurEffect class provides a blur effect.
       
   794     \since 4.6
       
   795 
       
   796     A blur effect blurs the source. This effect is useful for reducing details,
       
   797     such as when the source loses focus and you want to draw attention to other
       
   798     elements. The level of detail can be modified using the setBlurRadius()
       
   799     function. Use setBlurHint() to choose the quality or performance blur hints.
       
   800 
       
   801     By default, the blur radius is 5 pixels.
       
   802 
       
   803     \img graphicseffect-blur.png
       
   804 
       
   805     \sa QGraphicsDropShadowEffect, QGraphicsPixelizeEffect, QGraphicsGrayscaleEffect,
       
   806         QGraphicsColorizeEffect, QGraphicsOpacityEffect
       
   807 */
       
   808 
       
   809 /*!
       
   810     Constructs a new QGraphicsBlurEffect instance.
       
   811     The \a parent parameter is passed to QGraphicsEffect's constructor.
       
   812 */
       
   813 QGraphicsBlurEffect::QGraphicsBlurEffect(QObject *parent)
       
   814     : QGraphicsEffect(*new QGraphicsBlurEffectPrivate, parent)
       
   815 {
       
   816     Q_D(QGraphicsBlurEffect);
       
   817     d->filter->setBlurHint(Qt::PerformanceHint);
       
   818 }
       
   819 
       
   820 /*!
       
   821     Destroys the effect.
       
   822 */
       
   823 QGraphicsBlurEffect::~QGraphicsBlurEffect()
       
   824 {
       
   825 }
       
   826 
       
   827 /*!
       
   828     \property QGraphicsBlurEffect::blurRadius
       
   829     \brief the blur radius of the effect.
       
   830 
       
   831     Using a smaller radius results in a sharper appearance, whereas a bigger
       
   832     radius results in a more blurred appearance.
       
   833 
       
   834     By default, the blur radius is 5 pixels.
       
   835 */
       
   836 int QGraphicsBlurEffect::blurRadius() const
       
   837 {
       
   838     Q_D(const QGraphicsBlurEffect);
       
   839     return d->filter->radius();
       
   840 }
       
   841 
       
   842 void QGraphicsBlurEffect::setBlurRadius(int radius)
       
   843 {
       
   844     Q_D(QGraphicsBlurEffect);
       
   845     if (d->filter->radius() == radius)
       
   846         return;
       
   847 
       
   848     d->filter->setRadius(radius);
       
   849     updateBoundingRect();
       
   850     emit blurRadiusChanged(radius);
       
   851 }
       
   852 
       
   853 /*!
       
   854     \fn void QGraphicsBlurEffect::blurRadiusChanged(int radius)
       
   855 
       
   856     This signal is emitted whenever the effect's blur radius changes.
       
   857     The \a radius parameter holds the effect's new blur radius.
       
   858 */
       
   859 
       
   860 /*!
       
   861     \property QGraphicsBlurEffect::blurHint
       
   862     \brief the blur hint of the effect.
       
   863 
       
   864     Use the Qt::PerformanceHint hint to say that you want a faster blur,
       
   865     and the Qt::QualityHint hint to say that you prefer a higher quality blur.
       
   866 
       
   867     When animating the blur radius it's recommended to use Qt::PerformanceHint.
       
   868 
       
   869     By default, the blur hint is Qt::PerformanceHint.
       
   870 */
       
   871 Qt::RenderHint QGraphicsBlurEffect::blurHint() const
       
   872 {
       
   873     Q_D(const QGraphicsBlurEffect);
       
   874     return d->filter->blurHint();
       
   875 }
       
   876 
       
   877 void QGraphicsBlurEffect::setBlurHint(Qt::RenderHint hint)
       
   878 {
       
   879     Q_D(QGraphicsBlurEffect);
       
   880     if (d->filter->blurHint() == hint)
       
   881         return;
       
   882 
       
   883     d->filter->setBlurHint(hint);
       
   884     emit blurHintChanged(hint);
       
   885 }
       
   886 
       
   887 /*!
       
   888     \fn void QGraphicsBlurEffect::blurHintChanged(Qt::RenderHint hint)
       
   889 
       
   890     This signal is emitted whenever the effect's blur hint changes.
       
   891     The \a hint parameter holds the effect's new blur hint.
       
   892 */
       
   893 
       
   894 /*!
       
   895     \reimp
       
   896 */
       
   897 QRectF QGraphicsBlurEffect::boundingRectFor(const QRectF &rect) const
       
   898 {
       
   899     Q_D(const QGraphicsBlurEffect);
       
   900     return d->filter->boundingRectFor(rect);
       
   901 }
       
   902 
       
   903 /*!
       
   904     \reimp
       
   905 */
       
   906 void QGraphicsBlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source)
       
   907 {
       
   908     Q_D(QGraphicsBlurEffect);
       
   909     if (d->filter->radius() <= 0) {
       
   910         source->draw(painter);
       
   911         return;
       
   912     }
       
   913 
       
   914     // Draw pixmap in device coordinates to avoid pixmap scaling.
       
   915     QPoint offset;
       
   916     const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset);
       
   917     QTransform restoreTransform = painter->worldTransform();
       
   918     painter->setWorldTransform(QTransform());
       
   919     d->filter->draw(painter, offset, pixmap);
       
   920     painter->setWorldTransform(restoreTransform);
       
   921 }
       
   922 
       
   923 /*!
       
   924     \class QGraphicsDropShadowEffect
       
   925     \brief The QGraphicsDropShadowEffect class provides a drop shadow effect.
       
   926     \since 4.6
       
   927 
       
   928     A drop shadow effect renders the source with a drop shadow. The color of
       
   929     the drop shadow can be modified using the setColor() function. The drop
       
   930     shadow offset can be modified using the setOffset() function and the blur
       
   931     radius of the drop shadow can be changed with the setBlurRadius()
       
   932     function.
       
   933 
       
   934     By default, the drop shadow is a semi-transparent dark gray
       
   935     (QColor(63, 63, 63, 180)) shadow, blurred with a radius of 1 at an offset
       
   936     of 8 pixels towards the lower right.
       
   937 
       
   938     \img graphicseffect-drop-shadow.png
       
   939 
       
   940     \sa QGraphicsBlurEffect, QGraphicsPixelizeEffect, QGraphicsGrayscaleEffect,
       
   941         QGraphicsColorizeEffect, QGraphicsOpacityEffect
       
   942 */
       
   943 
       
   944 /*!
       
   945     Constructs a new QGraphicsDropShadowEffect instance.
       
   946     The \a parent parameter is passed to QGraphicsEffect's constructor.
       
   947 */
       
   948 QGraphicsDropShadowEffect::QGraphicsDropShadowEffect(QObject *parent)
       
   949     : QGraphicsEffect(*new QGraphicsDropShadowEffectPrivate, parent)
       
   950 {
       
   951 }
       
   952 
       
   953 /*!
       
   954     Destroys the effect.
       
   955 */
       
   956 QGraphicsDropShadowEffect::~QGraphicsDropShadowEffect()
       
   957 {
       
   958 }
       
   959 
       
   960 /*!
       
   961     \property QGraphicsDropShadowEffect::offset
       
   962     \brief the shadow offset in pixels.
       
   963 
       
   964     By default, the offset is 8 pixels towards the lower right.
       
   965 
       
   966     \sa xOffset(), yOffset(), blurRadius(), color()
       
   967 */
       
   968 QPointF QGraphicsDropShadowEffect::offset() const
       
   969 {
       
   970     Q_D(const QGraphicsDropShadowEffect);
       
   971     return d->filter->offset();
       
   972 }
       
   973 
       
   974 void QGraphicsDropShadowEffect::setOffset(const QPointF &offset)
       
   975 {
       
   976     Q_D(QGraphicsDropShadowEffect);
       
   977     if (d->filter->offset() == offset)
       
   978         return;
       
   979 
       
   980     d->filter->setOffset(offset);
       
   981     updateBoundingRect();
       
   982     emit offsetChanged(offset);
       
   983 }
       
   984 
       
   985 /*!
       
   986     \property QGraphicsDropShadowEffect::xOffset
       
   987     \brief the horizontal shadow offset in pixels.
       
   988 
       
   989     By default, the horizontal shadow offset is 8 pixels.
       
   990 
       
   991     \sa yOffset(), offset()
       
   992 */
       
   993 
       
   994 /*!
       
   995     \property QGraphicsDropShadowEffect::yOffset
       
   996     \brief the vertical shadow offset in pixels.
       
   997 
       
   998     By default, the vertical shadow offset is 8 pixels.
       
   999 
       
  1000     \sa xOffset(), offset()
       
  1001 */
       
  1002 
       
  1003 /*!
       
  1004     \fn void QGraphicsDropShadowEffect::offsetChanged(const QPointF &offset)
       
  1005 
       
  1006     This signal is emitted whenever the effect's shadow offset changes.
       
  1007     The \a offset parameter holds the effect's new shadow offset.
       
  1008 */
       
  1009 
       
  1010 /*!
       
  1011     \property QGraphicsDropShadowEffect::blurRadius
       
  1012     \brief the blur radius in pixels of the drop shadow.
       
  1013 
       
  1014     Using a smaller radius results in a sharper shadow, whereas using a bigger
       
  1015     radius results in a more blurred shadow.
       
  1016 
       
  1017     By default, the blur radius is 1 pixel.
       
  1018 
       
  1019     \sa color(), offset().
       
  1020 */
       
  1021 int QGraphicsDropShadowEffect::blurRadius() const
       
  1022 {
       
  1023     Q_D(const QGraphicsDropShadowEffect);
       
  1024     return d->filter->blurRadius();
       
  1025 }
       
  1026 
       
  1027 void QGraphicsDropShadowEffect::setBlurRadius(int blurRadius)
       
  1028 {
       
  1029     Q_D(QGraphicsDropShadowEffect);
       
  1030     if (d->filter->blurRadius() == blurRadius)
       
  1031         return;
       
  1032 
       
  1033     d->filter->setBlurRadius(blurRadius);
       
  1034     updateBoundingRect();
       
  1035     emit blurRadiusChanged(blurRadius);
       
  1036 }
       
  1037 
       
  1038 /*!
       
  1039     \fn void QGraphicsDropShadowEffect::blurRadiusChanged(int blurRadius)
       
  1040 
       
  1041     This signal is emitted whenever the effect's blur radius changes.
       
  1042     The \a blurRadius parameter holds the effect's new blur radius.
       
  1043 */
       
  1044 
       
  1045 /*!
       
  1046     \property QGraphicsDropShadowEffect::color
       
  1047     \brief the color of the drop shadow.
       
  1048 
       
  1049     By default, the drop color is a semi-transparent dark gray
       
  1050     (QColor(63, 63, 63, 180)).
       
  1051 
       
  1052     \sa offset(), blurRadius()
       
  1053 */
       
  1054 QColor QGraphicsDropShadowEffect::color() const
       
  1055 {
       
  1056     Q_D(const QGraphicsDropShadowEffect);
       
  1057     return d->filter->color();
       
  1058 }
       
  1059 
       
  1060 void QGraphicsDropShadowEffect::setColor(const QColor &color)
       
  1061 {
       
  1062     Q_D(QGraphicsDropShadowEffect);
       
  1063     if (d->filter->color() == color)
       
  1064         return;
       
  1065 
       
  1066     d->filter->setColor(color);
       
  1067     update();
       
  1068     emit colorChanged(color);
       
  1069 }
       
  1070 
       
  1071 /*!
       
  1072     \fn void QGraphicsDropShadowEffect::colorChanged(const QColor &color)
       
  1073 
       
  1074     This signal is emitted whenever the effect's color changes.
       
  1075     The \a color parameter holds the effect's new color.
       
  1076 */
       
  1077 
       
  1078 /*!
       
  1079     \reimp
       
  1080 */
       
  1081 QRectF QGraphicsDropShadowEffect::boundingRectFor(const QRectF &rect) const
       
  1082 {
       
  1083     Q_D(const QGraphicsDropShadowEffect);
       
  1084     return d->filter->boundingRectFor(rect);
       
  1085 }
       
  1086 
       
  1087 /*!
       
  1088     \reimp
       
  1089 */
       
  1090 void QGraphicsDropShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *source)
       
  1091 {
       
  1092     Q_D(QGraphicsDropShadowEffect);
       
  1093     if (d->filter->blurRadius() <= 0 && d->filter->offset().isNull()) {
       
  1094         source->draw(painter);
       
  1095         return;
       
  1096     }
       
  1097 
       
  1098     // Draw pixmap in device coordinates to avoid pixmap scaling.
       
  1099     QPoint offset;
       
  1100     const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset);
       
  1101     QTransform restoreTransform = painter->worldTransform();
       
  1102     painter->setWorldTransform(QTransform());
       
  1103     d->filter->draw(painter, offset, pixmap);
       
  1104     painter->setWorldTransform(restoreTransform);
       
  1105 }
       
  1106 
       
  1107 /*!
       
  1108     \class QGraphicsOpacityEffect
       
  1109     \brief The QGraphicsOpacityEffect class provides an opacity effect.
       
  1110     \since 4.6
       
  1111 
       
  1112     An opacity effect renders the source with an opacity. This effect is useful
       
  1113     for making the source semi-transparent, similar to a fade-in/fade-out
       
  1114     sequence. The opacity can be modified using the setOpacity() function.
       
  1115 
       
  1116     By default, the opacity is 0.7.
       
  1117 
       
  1118     \img graphicseffect-opacity.png
       
  1119 
       
  1120     \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsPixelizeEffect,
       
  1121         QGraphicsGrayscaleEffect, QGraphicsColorizeEffect
       
  1122 */
       
  1123 
       
  1124 /*!
       
  1125     Constructs a new QGraphicsOpacityEffect instance.
       
  1126     The \a parent parameter is passed to QGraphicsEffect's constructor.
       
  1127 */
       
  1128 QGraphicsOpacityEffect::QGraphicsOpacityEffect(QObject *parent)
       
  1129     : QGraphicsEffect(*new QGraphicsOpacityEffectPrivate, parent)
       
  1130 {
       
  1131 }
       
  1132 
       
  1133 /*!
       
  1134     Destroys the effect.
       
  1135 */
       
  1136 QGraphicsOpacityEffect::~QGraphicsOpacityEffect()
       
  1137 {
       
  1138 }
       
  1139 
       
  1140 /*!
       
  1141     \property QGraphicsOpacityEffect::opacity
       
  1142     \brief the opacity of the effect.
       
  1143 
       
  1144     The value should be in the range of 0.0 to 1.0, where 0.0 is
       
  1145     fully transparent and 1.0 is fully opaque.
       
  1146 
       
  1147     By default, the opacity is 0.7.
       
  1148 
       
  1149     \sa setOpacityMask()
       
  1150 */
       
  1151 qreal QGraphicsOpacityEffect::opacity() const
       
  1152 {
       
  1153     Q_D(const QGraphicsOpacityEffect);
       
  1154     return d->opacity;
       
  1155 }
       
  1156 
       
  1157 void QGraphicsOpacityEffect::setOpacity(qreal opacity)
       
  1158 {
       
  1159     Q_D(QGraphicsOpacityEffect);
       
  1160     opacity = qBound(qreal(0.0), opacity, qreal(1.0));
       
  1161 
       
  1162     if (qFuzzyCompare(d->opacity, opacity))
       
  1163         return;
       
  1164 
       
  1165     d->opacity = opacity;
       
  1166     if ((d->isFullyTransparent = qFuzzyIsNull(d->opacity)))
       
  1167         d->isFullyOpaque = 0;
       
  1168     else
       
  1169         d->isFullyOpaque = qFuzzyIsNull(d->opacity - 1);
       
  1170     update();
       
  1171     emit opacityChanged(opacity);
       
  1172 }
       
  1173 
       
  1174 /*!
       
  1175     \fn void QGraphicsOpacityEffect::opacityChanged(qreal opacity)
       
  1176 
       
  1177     This signal is emitted whenever the effect's opacity changes.
       
  1178     The \a opacity parameter holds the effect's new opacity.
       
  1179 */
       
  1180 
       
  1181 /*!
       
  1182     \property QGraphicsOpacityEffect::opacityMask
       
  1183     \brief the opacity mask of the effect.
       
  1184 
       
  1185     An opacity mask allows you apply opacity to portions of an element.
       
  1186 
       
  1187     For example:
       
  1188 
       
  1189     \snippet doc/src/snippets/code/src_gui_effects_qgraphicseffect.cpp 2
       
  1190 
       
  1191     There is no opacity mask by default.
       
  1192 
       
  1193     \sa setOpacity()
       
  1194 */
       
  1195 QBrush QGraphicsOpacityEffect::opacityMask() const
       
  1196 {
       
  1197     Q_D(const QGraphicsOpacityEffect);
       
  1198     return d->opacityMask;
       
  1199 }
       
  1200 
       
  1201 void QGraphicsOpacityEffect::setOpacityMask(const QBrush &mask)
       
  1202 {
       
  1203     Q_D(QGraphicsOpacityEffect);
       
  1204     if (d->opacityMask == mask)
       
  1205         return;
       
  1206 
       
  1207     d->opacityMask = mask;
       
  1208     d->hasOpacityMask = (mask.style() != Qt::NoBrush);
       
  1209     update();
       
  1210 
       
  1211     emit opacityMaskChanged(mask);
       
  1212 }
       
  1213 
       
  1214 /*!
       
  1215     \fn void QGraphicsOpacityEffect::opacityMaskChanged(const QBrush &mask)
       
  1216 
       
  1217     This signal is emitted whenever the effect's opacity mask changes.
       
  1218     The \a mask parameter holds the effect's new opacity mask.
       
  1219 */
       
  1220 
       
  1221 /*!
       
  1222     \reimp
       
  1223 */
       
  1224 void QGraphicsOpacityEffect::draw(QPainter *painter, QGraphicsEffectSource *source)
       
  1225 {
       
  1226     Q_D(QGraphicsOpacityEffect);
       
  1227 
       
  1228     // Transparent; nothing to draw.
       
  1229     if (d->isFullyTransparent)
       
  1230         return;
       
  1231 
       
  1232     // Opaque; draw directly without going through a pixmap.
       
  1233     if (d->isFullyOpaque && !d->hasOpacityMask) {
       
  1234         source->draw(painter);
       
  1235         return;
       
  1236     }
       
  1237 
       
  1238     painter->save();
       
  1239     painter->setOpacity(d->opacity);
       
  1240 
       
  1241     QPoint offset;
       
  1242     if (source->isPixmap()) {
       
  1243         // No point in drawing in device coordinates (pixmap will be scaled anyways).
       
  1244         if (!d->hasOpacityMask) {
       
  1245             const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset);
       
  1246             painter->drawPixmap(offset, pixmap);
       
  1247         } else {
       
  1248             QRect srcBrect = source->boundingRect().toAlignedRect();
       
  1249             offset = srcBrect.topLeft();
       
  1250             QPixmap pixmap(srcBrect.size());
       
  1251             pixmap.fill(Qt::transparent);
       
  1252 
       
  1253             QPainter pixmapPainter(&pixmap);
       
  1254             pixmapPainter.setRenderHints(painter->renderHints());
       
  1255             pixmapPainter.translate(-offset);
       
  1256             source->draw(&pixmapPainter);
       
  1257             pixmapPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
       
  1258             pixmapPainter.fillRect(srcBrect, d->opacityMask);
       
  1259             pixmapPainter.end();
       
  1260 
       
  1261             painter->drawPixmap(offset, pixmap);
       
  1262         }
       
  1263     } else {
       
  1264         // Draw pixmap in device coordinates to avoid pixmap scaling;
       
  1265         if (!d->hasOpacityMask) {
       
  1266             const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset);
       
  1267             painter->setWorldTransform(QTransform());
       
  1268             painter->drawPixmap(offset, pixmap);
       
  1269         } else {
       
  1270             QTransform worldTransform = painter->worldTransform();
       
  1271 
       
  1272             // Calculate source bounding rect in logical and device coordinates.
       
  1273             QRectF srcBrect = source->boundingRect();
       
  1274             QRect srcDeviceBrect = worldTransform.mapRect(srcBrect).toAlignedRect();
       
  1275             srcDeviceBrect &= source->deviceRect();
       
  1276 
       
  1277             offset = srcDeviceBrect.topLeft();
       
  1278             worldTransform *= QTransform::fromTranslate(-srcDeviceBrect.x(), -srcDeviceBrect.y());
       
  1279 
       
  1280             QPixmap pixmap(srcDeviceBrect.size());
       
  1281             pixmap.fill(Qt::transparent);
       
  1282 
       
  1283             QPainter pixmapPainter(&pixmap);
       
  1284             pixmapPainter.setRenderHints(painter->renderHints());
       
  1285             pixmapPainter.setWorldTransform(worldTransform);
       
  1286             source->draw(&pixmapPainter);
       
  1287             pixmapPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
       
  1288             pixmapPainter.fillRect(srcBrect, d->opacityMask);
       
  1289             pixmapPainter.end();
       
  1290 
       
  1291             painter->setWorldTransform(QTransform());
       
  1292             painter->drawPixmap(offset, pixmap);
       
  1293         }
       
  1294     }
       
  1295 
       
  1296     painter->restore();
       
  1297 }
       
  1298 
       
  1299 /*!
       
  1300     \class QGraphicsBloomEffect
       
  1301     \brief The QGraphicsBloomEffect class provides a bloom/glow effect.
       
  1302     \since 4.6
       
  1303 
       
  1304     A bloom/glow effect adds fringes of light around bright areas in the source.
       
  1305 
       
  1306     \img graphicseffect-bloom.png
       
  1307 
       
  1308     \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsPixelizeEffect,
       
  1309         QGraphicsGrayscaleEffect, QGraphicsColorizeEffect
       
  1310 */
       
  1311 
       
  1312 /*!
       
  1313     Constructs a new QGraphicsBloomEffect instance.
       
  1314     The \a parent parameter is passed to QGraphicsEffect's constructor.
       
  1315 */
       
  1316 QGraphicsBloomEffect::QGraphicsBloomEffect(QObject *parent)
       
  1317     : QGraphicsEffect(*new QGraphicsBloomEffectPrivate, parent)
       
  1318 {
       
  1319     Q_D(QGraphicsBloomEffect);
       
  1320     for (int i = 0; i < 256; ++i)
       
  1321         d->colorTable[i] = qMin(i + d->brightness, 255);
       
  1322 }
       
  1323 
       
  1324 /*!
       
  1325     Destroys the effect.
       
  1326 */
       
  1327 QGraphicsBloomEffect::~QGraphicsBloomEffect()
       
  1328 {
       
  1329 }
       
  1330 
       
  1331 /*!
       
  1332     \reimp
       
  1333 */
       
  1334 QRectF QGraphicsBloomEffect::boundingRectFor(const QRectF &rect) const
       
  1335 {
       
  1336     Q_D(const QGraphicsBloomEffect);
       
  1337     const qreal delta = d->blurFilter.radius() * 2;
       
  1338     return rect.adjusted(-delta, -delta, delta, delta);
       
  1339 }
       
  1340 
       
  1341 /*!
       
  1342     \property QGraphicsBloomEffect::blurRadius
       
  1343     \brief the blur radius in pixels of the effect.
       
  1344 
       
  1345     Using a smaller radius results in a sharper appearance, whereas a bigger
       
  1346     radius results in a more blurred appearance.
       
  1347 
       
  1348     By default, the blur radius is 5 pixels.
       
  1349 
       
  1350     \sa strength(), brightness()
       
  1351 */
       
  1352 int QGraphicsBloomEffect::blurRadius() const
       
  1353 {
       
  1354     Q_D(const QGraphicsBloomEffect);
       
  1355     return d->blurFilter.radius();
       
  1356 }
       
  1357 
       
  1358 void QGraphicsBloomEffect::setBlurRadius(int radius)
       
  1359 {
       
  1360     Q_D(QGraphicsBloomEffect);
       
  1361     if (d->blurFilter.radius() == radius)
       
  1362         return;
       
  1363 
       
  1364     d->blurFilter.setRadius(radius);
       
  1365     updateBoundingRect();
       
  1366     emit blurRadiusChanged(radius);
       
  1367 }
       
  1368 
       
  1369 /*!
       
  1370     \fn void QGraphicsBloomEffect::blurRadiusChanged(int blurRadius)
       
  1371 
       
  1372     This signal is emitted whenever the effect's blur radius changes.
       
  1373     The \a blurRadius parameter holds the effect's new blur radius.
       
  1374 */
       
  1375 
       
  1376 /*!
       
  1377     \property QGraphicsBloomEffect::blurHint
       
  1378     \brief the blur hint of the effect.
       
  1379 
       
  1380     Use the Qt::PerformanceHint hint to say that you want a faster blur,
       
  1381     and the Qt::QualityHint hint to say that you prefer a higher quality blur.
       
  1382 
       
  1383     When animating the blur radius it's recommended to use Qt::PerformanceHint.
       
  1384 
       
  1385     By default, the blur hint is Qt::PerformanceHint.
       
  1386 */
       
  1387 Qt::RenderHint QGraphicsBloomEffect::blurHint() const
       
  1388 {
       
  1389     Q_D(const QGraphicsBloomEffect);
       
  1390     return d->blurFilter.blurHint();
       
  1391 }
       
  1392 
       
  1393 void QGraphicsBloomEffect::setBlurHint(Qt::RenderHint hint)
       
  1394 {
       
  1395     Q_D(QGraphicsBloomEffect);
       
  1396     if (d->blurFilter.blurHint() == hint)
       
  1397         return;
       
  1398 
       
  1399     d->blurFilter.setBlurHint(hint);
       
  1400     emit blurHintChanged(hint);
       
  1401 }
       
  1402 
       
  1403 /*!
       
  1404     \fn void QGraphicsBloomEffect::blurHintChanged(Qt::RenderHint hint)
       
  1405 
       
  1406     This signal is emitted whenever the effect's blur hint changes.
       
  1407     The \a hint parameter holds the effect's new blur hint.
       
  1408 */
       
  1409 
       
  1410 /*!
       
  1411     \property QGraphicsBloomEffect::brightness
       
  1412     \brief the brightness of the glow.
       
  1413 
       
  1414     The value should be in the range of 0 to 255, where 0 is dark
       
  1415     and 255 is bright.
       
  1416 
       
  1417     By default, the brightness is 70.
       
  1418 
       
  1419     \sa strength(), blurRadius()
       
  1420 */
       
  1421 int QGraphicsBloomEffect::brightness() const
       
  1422 {
       
  1423     Q_D(const QGraphicsBloomEffect);
       
  1424     return d->brightness;
       
  1425 }
       
  1426 
       
  1427 void QGraphicsBloomEffect::setBrightness(int brightness)
       
  1428 {
       
  1429     Q_D(QGraphicsBloomEffect);
       
  1430     brightness = qBound(0, brightness, 255);
       
  1431     if (d->brightness == brightness)
       
  1432         return;
       
  1433 
       
  1434     d->brightness = brightness;
       
  1435     for (int i = 0; i < 256; ++i)
       
  1436         d->colorTable[i] = qMin(i + brightness, 255);
       
  1437 
       
  1438     update();
       
  1439     emit brightnessChanged(brightness);
       
  1440 }
       
  1441 
       
  1442 /*!
       
  1443     \fn void QGraphicsBloomEffect::brightnessChanged(int brightness)
       
  1444 
       
  1445     This signal is emitted whenever the effect's brightness changes.
       
  1446     The \a brightness parameter holds the effect's new brightness.
       
  1447 */
       
  1448 
       
  1449 /*!
       
  1450     \property QGraphicsBloomEffect::strength
       
  1451     \brief the strength of the effect.
       
  1452 
       
  1453     A strength 0.0 equals to no effect, while 1.0 means maximum glow.
       
  1454 
       
  1455     By default, the strength is 0.7.
       
  1456 */
       
  1457 qreal QGraphicsBloomEffect::strength() const
       
  1458 {
       
  1459     Q_D(const QGraphicsBloomEffect);
       
  1460     return d->strength;
       
  1461 }
       
  1462 
       
  1463 void QGraphicsBloomEffect::setStrength(qreal strength)
       
  1464 {
       
  1465     Q_D(QGraphicsBloomEffect);
       
  1466     strength = qBound(qreal(0.0), strength, qreal(1.0));
       
  1467     if (qFuzzyCompare(d->strength, strength))
       
  1468         return;
       
  1469 
       
  1470     d->strength = strength;
       
  1471     update();
       
  1472     emit strengthChanged(strength);
       
  1473 }
       
  1474 
       
  1475 /*!
       
  1476     \fn void QGraphicsBloomEffect::strengthChanged(qreal strength)
       
  1477 
       
  1478     This signal is emitted whenever the effect's strength changes.
       
  1479     The \a strength parameter holds the effect's new strength.
       
  1480 */
       
  1481 
       
  1482 extern QPixmap qt_toRasterPixmap(const QPixmap &pixmap);
       
  1483 
       
  1484 /*!
       
  1485     \reimp
       
  1486 */
       
  1487 void QGraphicsBloomEffect::draw(QPainter *painter, QGraphicsEffectSource *source)
       
  1488 {
       
  1489     Q_D(QGraphicsBloomEffect);
       
  1490     if (d->strength < 0.001) {
       
  1491         source->draw(painter);
       
  1492         return;
       
  1493     }
       
  1494 
       
  1495     QPoint offset;
       
  1496     QPixmap pixmap = qt_toRasterPixmap(source->pixmap(Qt::DeviceCoordinates, &offset));
       
  1497 
       
  1498     // Blur.
       
  1499     QImage overlay(pixmap.size(), QImage::Format_ARGB32_Premultiplied);
       
  1500     overlay.fill(0);
       
  1501 
       
  1502     QPainter blurPainter(&overlay);
       
  1503     d->blurFilter.draw(&blurPainter, QPointF(), pixmap);
       
  1504     blurPainter.end();
       
  1505 
       
  1506     // Brighten.
       
  1507     const int numBits = overlay.width() * overlay.height();
       
  1508     QRgb *bits = reinterpret_cast<QRgb *>(overlay.bits());
       
  1509     for (int i = 0; i < numBits; ++i) {
       
  1510         const QRgb pixel = INV_PREMUL(bits[i]);
       
  1511         bits[i] = PREMUL(qRgba(d->colorTable[qRed(pixel)], d->colorTable[qGreen(pixel)],
       
  1512                                d->colorTable[qBlue(pixel)], qAlpha(pixel)));
       
  1513     }
       
  1514 
       
  1515     // Composite.
       
  1516     QPainter compPainter(&pixmap);
       
  1517     compPainter.setCompositionMode(QPainter::CompositionMode_Overlay);
       
  1518     compPainter.setOpacity(d->strength);
       
  1519     compPainter.drawImage(0, 0, overlay);
       
  1520     compPainter.end();
       
  1521 
       
  1522     QTransform restoreTransform = painter->worldTransform();
       
  1523     painter->setWorldTransform(QTransform());
       
  1524     painter->drawPixmap(offset, pixmap);
       
  1525     painter->setWorldTransform(restoreTransform);
       
  1526 }
       
  1527 
       
  1528 QT_END_NAMESPACE
       
  1529