diff options
Diffstat (limited to 'src/gui/effects')
-rw-r--r-- | src/gui/effects/qgraphicseffect.cpp | 579 | ||||
-rw-r--r-- | src/gui/effects/qgraphicseffect.h | 114 | ||||
-rw-r--r-- | src/gui/effects/qgraphicseffect_p.h | 48 |
3 files changed, 91 insertions, 650 deletions
diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index 96d35b0..3815b60 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -65,9 +65,6 @@ \o QGraphicsDropShadowEffect - renders a dropshadow behind the item \o QGraphicsColorizeEffect - renders the item in shades of any given color \o QGraphicsOpacityEffect - renders the item with an opacity - \o QGraphicsPixelizeEffect - pixelizes the item with any pixel size - \o QGraphicsGrayscaleEffect - renders the item in shades of gray - \o QGraphicsBloomEffect - applies a blooming / glowing effect \endlist \img graphicseffect-effects.png @@ -100,9 +97,11 @@ */ #include "qgraphicseffect_p.h" +#include <QtGui/qgraphicsitem.h> #include <QtGui/qimage.h> #include <QtGui/qpainter.h> +#include <QtGui/qpaintengine.h> #include <QtCore/qrect.h> #include <QtCore/qdebug.h> #include <private/qdrawhelper_p.h> @@ -251,17 +250,24 @@ bool QGraphicsEffectSource::isPixmap() const \sa QGraphicsEffect::draw(), boundingRect(), deviceRect() */ -QPixmap QGraphicsEffectSource::pixmap(Qt::CoordinateSystem system, QPoint *offset) const +QPixmap QGraphicsEffectSource::pixmap(Qt::CoordinateSystem system, QPoint *offset, PixmapPadMode mode) const { Q_D(const QGraphicsEffectSource); + // Shortcut, no cache for childless pixmap items... + const QGraphicsItem *item = graphicsItem(); + if (system == Qt::LogicalCoordinates && mode == NoExpandPadMode && item && isPixmap()) { + return ((QGraphicsPixmapItem *) item)->pixmap(); + } + QPixmap pm; - if (d->m_cachedSystem == system) + if (d->m_cachedSystem == system && d->m_cachedMode == mode) QPixmapCache::find(d->m_cacheKey, &pm); if (pm.isNull()) { - pm = d->pixmap(system, &d->m_cachedOffset); + pm = d->pixmap(system, &d->m_cachedOffset, mode); d->m_cachedSystem = system; + d->m_cachedMode = mode; d->invalidateCache(); d->m_cacheKey = QPixmapCache::insert(pm); @@ -353,8 +359,10 @@ void QGraphicsEffect::setEnabled(bool enable) return; d->isEnabled = enable; - if (d->source) + if (d->source) { d->source->d_func()->effectBoundingRectChanged(); + d->source->d_func()->invalidateCache(); + } emit enabledChanged(enable); } @@ -408,8 +416,10 @@ QGraphicsEffectSource *QGraphicsEffect::source() const void QGraphicsEffect::updateBoundingRect() { Q_D(QGraphicsEffect); - if (d->source) + if (d->source) { d->source->d_func()->effectBoundingRectChanged(); + d->source->d_func()->invalidateCache(); + } } /*! @@ -458,96 +468,6 @@ void QGraphicsEffect::sourceChanged(ChangeFlags flags) } /*! - \class QGraphicsGrayscaleEffect - \brief The QGraphicsGrayscaleEffect class provides a grayscale effect. - \since 4.6 - - A grayscale effect renders the source in shades of gray. - - \img graphicseffect-grayscale.png - - \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsPixelizeEffect, - QGraphicsColorizeEffect, QGraphicsOpacityEffect -*/ - -/*! - Constructs a new QGraphicsGrayscale instance. - The \a parent parameter is passed to QGraphicsEffect's constructor. -*/ -QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect(QObject *parent) - : QGraphicsEffect(*new QGraphicsGrayscaleEffectPrivate, parent) -{ -} - -/*! - Destroys the effect. -*/ -QGraphicsGrayscaleEffect::~QGraphicsGrayscaleEffect() -{ -} - - -/*! - \property QGraphicsGrayscaleEffect::strength - \brief the strength of the effect. - - By default, the strength is 1.0. - A strength 0.0 equals to no effect, while 1.0 means full grayscale. -*/ -qreal QGraphicsGrayscaleEffect::strength() const -{ - Q_D(const QGraphicsGrayscaleEffect); - return d->filter->strength(); -} - -void QGraphicsGrayscaleEffect::setStrength(qreal strength) -{ - Q_D(QGraphicsGrayscaleEffect); - if (qFuzzyCompare(d->filter->strength(), strength)) - return; - - d->filter->setStrength(strength); - d->opaque = !qFuzzyIsNull(strength); - update(); - emit strengthChanged(strength); -} - -/*! \fn void QGraphicsGrayscaleEffect::strengthChanged(qreal strength) - This signal is emitted whenever setStrength() changes the grayscale - strength property. \a strength contains the new strength value of - the grayscale effect. - */ - -/*! - \reimp -*/ -void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *source) -{ - Q_D(QGraphicsGrayscaleEffect); - - if (!d->opaque) { - source->draw(painter); - return; - } - - 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); - d->filter->draw(painter, offset, pixmap); - return; - } - - // Draw pixmap in device coordinates to avoid pixmap scaling; - const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); - QTransform restoreTransform = painter->worldTransform(); - painter->setWorldTransform(QTransform()); - d->filter->draw(painter, offset, pixmap); - painter->setWorldTransform(restoreTransform); - -} - -/*! \class QGraphicsColorizeEffect \brief The QGraphicsColorizeEffect class provides a colorize effect. \since 4.6 @@ -559,8 +479,7 @@ void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *so \img graphicseffect-colorize.png - \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsPixelizeEffect, - QGraphicsGrayscaleEffect, QGraphicsOpacityEffect + \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsOpacityEffect */ /*! @@ -655,7 +574,8 @@ void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou 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); + const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset, + QGraphicsEffectSource::NoExpandPadMode); d->filter->draw(painter, offset, pixmap); return; } @@ -669,126 +589,6 @@ void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou } /*! - \class QGraphicsPixelizeEffect - \brief The QGraphicsPixelizeEffect class provides a pixelize effect. - \since 4.6 - - A pixelize effect renders the source in lower resolution. This effect is - useful for reducing details, like censorship. The resolution can be - modified using the setPixelSize() function. - - By default, the pixel size is 3. - - \img graphicseffect-pixelize.png - - \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsGrayscaleEffect, - QGraphicsColorizeEffect, QGraphicsOpacityEffect -*/ - -/*! - Constructs a new QGraphicsPixelizeEffect instance. - The \a parent parameter is passed to QGraphicsEffect's constructor. -*/ -QGraphicsPixelizeEffect::QGraphicsPixelizeEffect(QObject *parent) - : QGraphicsEffect(*new QGraphicsPixelizeEffectPrivate, parent) -{ -} - -/*! - Destroys the effect. -*/ -QGraphicsPixelizeEffect::~QGraphicsPixelizeEffect() -{ -} - -/*! - \property QGraphicsPixelizeEffect::pixelSize - \brief the size of a pixel in the effect. - - Setting the pixel size to 2 means two pixels in the source will be used to - represent one pixel. Using a bigger size results in lower resolution. - - By default, the pixel size is 3. -*/ -int QGraphicsPixelizeEffect::pixelSize() const -{ - Q_D(const QGraphicsPixelizeEffect); - return d->pixelSize; -} - -void QGraphicsPixelizeEffect::setPixelSize(int size) -{ - Q_D(QGraphicsPixelizeEffect); - if (d->pixelSize == size) - return; - - d->pixelSize = size; - update(); - emit pixelSizeChanged(size); -} - -/*! - \fn void QGraphicsPixelizeEffect::pixelSizeChanged(int size) - - This signal is emitted whenever the effect's pixel size changes. - The \a size parameter holds the effect's new pixel size. -*/ - -static inline void pixelize(QImage *image, int pixelSize) -{ - Q_ASSERT(pixelSize > 0); - Q_ASSERT(image); - int width = image->width(); - int height = image->height(); - for (int y = 0; y < height; y += pixelSize) { - int ys = qMin(height - 1, y + pixelSize / 2); - QRgb *sbuf = reinterpret_cast<QRgb*>(image->scanLine(ys)); - for (int x = 0; x < width; x += pixelSize) { - int xs = qMin(width - 1, x + pixelSize / 2); - QRgb color = sbuf[xs]; - for (int yi = 0; yi < qMin(pixelSize, height - y); ++yi) { - QRgb *buf = reinterpret_cast<QRgb*>(image->scanLine(y + yi)); - for (int xi = 0; xi < qMin(pixelSize, width - x); ++xi) - buf[x + xi] = color; - } - } - } -} - -/*! - \reimp -*/ -void QGraphicsPixelizeEffect::draw(QPainter *painter, QGraphicsEffectSource *source) -{ - Q_D(QGraphicsPixelizeEffect); - if (d->pixelSize <= 0) { - source->draw(painter); - return; - } - - QPoint offset; - if (source->isPixmap()) { - const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset); - QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); - pixelize(&image, d->pixelSize); - painter->drawImage(offset, image); - return; - } - - // Draw pixmap in device coordinates to avoid pixmap scaling. - const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); - - // pixelize routine - QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); - pixelize(&image, d->pixelSize); - - QTransform restoreTransform = painter->worldTransform(); - painter->setWorldTransform(QTransform()); - painter->drawImage(offset, image); - painter->setWorldTransform(restoreTransform); -} - -/*! \class QGraphicsBlurEffect \brief The QGraphicsBlurEffect class provides a blur effect. \since 4.6 @@ -802,8 +602,7 @@ void QGraphicsPixelizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou \img graphicseffect-blur.png - \sa QGraphicsDropShadowEffect, QGraphicsPixelizeEffect, QGraphicsGrayscaleEffect, - QGraphicsColorizeEffect, QGraphicsOpacityEffect + \sa QGraphicsDropShadowEffect, QGraphicsColorizeEffect, QGraphicsOpacityEffect */ /*! @@ -833,16 +632,16 @@ QGraphicsBlurEffect::~QGraphicsBlurEffect() By default, the blur radius is 5 pixels. */ -int QGraphicsBlurEffect::blurRadius() const +qreal QGraphicsBlurEffect::blurRadius() const { Q_D(const QGraphicsBlurEffect); return d->filter->radius(); } -void QGraphicsBlurEffect::setBlurRadius(int radius) +void QGraphicsBlurEffect::setBlurRadius(qreal radius) { Q_D(QGraphicsBlurEffect); - if (d->filter->radius() == radius) + if (qFuzzyCompare(d->filter->radius(), radius)) return; d->filter->setRadius(radius); @@ -851,7 +650,7 @@ void QGraphicsBlurEffect::setBlurRadius(int radius) } /*! - \fn void QGraphicsBlurEffect::blurRadiusChanged(int radius) + \fn void QGraphicsBlurEffect::blurRadiusChanged(qreal radius) This signal is emitted whenever the effect's blur radius changes. The \a radius parameter holds the effect's new blur radius. @@ -911,9 +710,13 @@ void QGraphicsBlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) return; } + QGraphicsEffectSource::PixmapPadMode mode = QGraphicsEffectSource::ExpandToEffectRectPadMode; + if (painter->paintEngine()->type() == QPaintEngine::OpenGL2) + mode = QGraphicsEffectSource::ExpandToTransparentBorderPadMode; + // Draw pixmap in device coordinates to avoid pixmap scaling. QPoint offset; - const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); + const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset, mode); QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); d->filter->draw(painter, offset, pixmap); @@ -937,8 +740,7 @@ void QGraphicsBlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) \img graphicseffect-drop-shadow.png - \sa QGraphicsBlurEffect, QGraphicsPixelizeEffect, QGraphicsGrayscaleEffect, - QGraphicsColorizeEffect, QGraphicsOpacityEffect + \sa QGraphicsBlurEffect, QGraphicsColorizeEffect, QGraphicsOpacityEffect */ /*! @@ -988,6 +790,8 @@ void QGraphicsDropShadowEffect::setOffset(const QPointF &offset) By default, the horizontal shadow offset is 8 pixels. + + \sa yOffset(), offset() */ @@ -1018,16 +822,16 @@ void QGraphicsDropShadowEffect::setOffset(const QPointF &offset) \sa color(), offset(). */ -int QGraphicsDropShadowEffect::blurRadius() const +qreal QGraphicsDropShadowEffect::blurRadius() const { Q_D(const QGraphicsDropShadowEffect); return d->filter->blurRadius(); } -void QGraphicsDropShadowEffect::setBlurRadius(int blurRadius) +void QGraphicsDropShadowEffect::setBlurRadius(qreal blurRadius) { Q_D(QGraphicsDropShadowEffect); - if (d->filter->blurRadius() == blurRadius) + if (qFuzzyCompare(d->filter->blurRadius(), blurRadius)) return; d->filter->setBlurRadius(blurRadius); @@ -1036,7 +840,7 @@ void QGraphicsDropShadowEffect::setBlurRadius(int blurRadius) } /*! - \fn void QGraphicsDropShadowEffect::blurRadiusChanged(int blurRadius) + \fn void QGraphicsDropShadowEffect::blurRadiusChanged(qreal blurRadius) This signal is emitted whenever the effect's blur radius changes. The \a blurRadius parameter holds the effect's new blur radius. @@ -1095,9 +899,13 @@ void QGraphicsDropShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *s return; } + QGraphicsEffectSource::PixmapPadMode mode = QGraphicsEffectSource::ExpandToEffectRectPadMode; + if (painter->paintEngine()->type() == QPaintEngine::OpenGL2) + mode = QGraphicsEffectSource::ExpandToTransparentBorderPadMode; + // Draw pixmap in device coordinates to avoid pixmap scaling. QPoint offset; - const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); + const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset, mode); QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); d->filter->draw(painter, offset, pixmap); @@ -1117,8 +925,7 @@ void QGraphicsDropShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *s \img graphicseffect-opacity.png - \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsPixelizeEffect, - QGraphicsGrayscaleEffect, QGraphicsColorizeEffect + \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsColorizeEffect */ /*! @@ -1235,295 +1042,39 @@ void QGraphicsOpacityEffect::draw(QPainter *painter, QGraphicsEffectSource *sour return; } - painter->save(); - painter->setOpacity(d->opacity); QPoint offset; - if (source->isPixmap()) { - // No point in drawing in device coordinates (pixmap will be scaled anyways). - if (!d->hasOpacityMask) { - const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset); - painter->drawPixmap(offset, pixmap); - } else { - QRect srcBrect = source->boundingRect().toAlignedRect(); - offset = srcBrect.topLeft(); - QPixmap pixmap(srcBrect.size()); - pixmap.fill(Qt::transparent); - - QPainter pixmapPainter(&pixmap); - pixmapPainter.setRenderHints(painter->renderHints()); - pixmapPainter.translate(-offset); - source->draw(&pixmapPainter); - pixmapPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn); - pixmapPainter.fillRect(srcBrect, d->opacityMask); - pixmapPainter.end(); - - painter->drawPixmap(offset, pixmap); - } - } else { - // Draw pixmap in device coordinates to avoid pixmap scaling; - 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(); + Qt::CoordinateSystem system = source->isPixmap() ? Qt::LogicalCoordinates : Qt::DeviceCoordinates; + QPixmap pixmap = source->pixmap(system, &offset, QGraphicsEffectSource::NoExpandPadMode); + if (pixmap.isNull()) + return; - offset = srcDeviceBrect.topLeft(); - worldTransform *= QTransform::fromTranslate(-srcDeviceBrect.x(), -srcDeviceBrect.y()); - QPixmap pixmap(srcDeviceBrect.size()); - pixmap.fill(Qt::transparent); + painter->save(); + painter->setOpacity(d->opacity); - QPainter pixmapPainter(&pixmap); - pixmapPainter.setRenderHints(painter->renderHints()); + if (d->hasOpacityMask) { + QPainter pixmapPainter(&pixmap); + pixmapPainter.setRenderHints(painter->renderHints()); + pixmapPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn); + if (system == Qt::DeviceCoordinates) { + QTransform worldTransform = painter->worldTransform(); + worldTransform *= QTransform::fromTranslate(-offset.x(), -offset.y()); 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); + pixmapPainter.fillRect(source->boundingRect(), d->opacityMask); + } else { + pixmapPainter.translate(-offset); + pixmapPainter.fillRect(pixmap.rect(), d->opacityMask); } } - painter->restore(); -} - -/*! - \class QGraphicsBloomEffect - \brief The QGraphicsBloomEffect class provides a bloom/glow effect. - \since 4.6 - - A bloom/glow effect adds fringes of light around bright areas in the source. - - \img graphicseffect-bloom.png - - \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsPixelizeEffect, - QGraphicsGrayscaleEffect, QGraphicsColorizeEffect -*/ - -/*! - Constructs a new QGraphicsBloomEffect instance. - The \a parent parameter is passed to QGraphicsEffect's constructor. -*/ -QGraphicsBloomEffect::QGraphicsBloomEffect(QObject *parent) - : QGraphicsEffect(*new QGraphicsBloomEffectPrivate, parent) -{ - Q_D(QGraphicsBloomEffect); - for (int i = 0; i < 256; ++i) - d->colorTable[i] = qMin(i + d->brightness, 255); -} - -/*! - Destroys the effect. -*/ -QGraphicsBloomEffect::~QGraphicsBloomEffect() -{ -} - -/*! - \reimp -*/ -QRectF QGraphicsBloomEffect::boundingRectFor(const QRectF &rect) const -{ - Q_D(const QGraphicsBloomEffect); - const qreal delta = d->blurFilter.radius() * 2; - return rect.adjusted(-delta, -delta, delta, delta); -} - -/*! - \property QGraphicsBloomEffect::blurRadius - \brief the blur radius in pixels of the effect. - - Using a smaller radius results in a sharper appearance, whereas a bigger - radius results in a more blurred appearance. - - By default, the blur radius is 5 pixels. - - \sa strength(), brightness() -*/ -int QGraphicsBloomEffect::blurRadius() const -{ - Q_D(const QGraphicsBloomEffect); - return d->blurFilter.radius(); -} - -void QGraphicsBloomEffect::setBlurRadius(int radius) -{ - Q_D(QGraphicsBloomEffect); - if (d->blurFilter.radius() == radius) - return; - - d->blurFilter.setRadius(radius); - updateBoundingRect(); - emit blurRadiusChanged(radius); -} - -/*! - \fn void QGraphicsBloomEffect::blurRadiusChanged(int blurRadius) - - This signal is emitted whenever the effect's blur radius changes. - The \a blurRadius parameter holds the effect's new blur radius. -*/ - -/*! - \property QGraphicsBloomEffect::blurHint - \brief the blur hint of the effect. - - Use the Qt::PerformanceHint hint to say that you want a faster blur, - and the Qt::QualityHint hint to say that you prefer a higher quality blur. - - When animating the blur radius it's recommended to use Qt::PerformanceHint. + if (system == Qt::DeviceCoordinates) + painter->setWorldTransform(QTransform()); - By default, the blur hint is Qt::PerformanceHint. -*/ -Qt::RenderHint QGraphicsBloomEffect::blurHint() const -{ - Q_D(const QGraphicsBloomEffect); - return d->blurFilter.blurHint(); -} - -void QGraphicsBloomEffect::setBlurHint(Qt::RenderHint hint) -{ - Q_D(QGraphicsBloomEffect); - if (d->blurFilter.blurHint() == hint) - return; - - d->blurFilter.setBlurHint(hint); - emit blurHintChanged(hint); -} - -/*! - \fn void QGraphicsBloomEffect::blurHintChanged(Qt::RenderHint hint) - - This signal is emitted whenever the effect's blur hint changes. - The \a hint parameter holds the effect's new blur hint. -*/ - -/*! - \property QGraphicsBloomEffect::brightness - \brief the brightness of the glow. - - The value should be in the range of 0 to 255, where 0 is dark - and 255 is bright. - - By default, the brightness is 70. - - \sa strength(), blurRadius() -*/ -int QGraphicsBloomEffect::brightness() const -{ - Q_D(const QGraphicsBloomEffect); - return d->brightness; -} - -void QGraphicsBloomEffect::setBrightness(int brightness) -{ - Q_D(QGraphicsBloomEffect); - brightness = qBound(0, brightness, 255); - if (d->brightness == brightness) - return; - - d->brightness = brightness; - for (int i = 0; i < 256; ++i) - d->colorTable[i] = qMin(i + brightness, 255); - - update(); - emit brightnessChanged(brightness); -} - -/*! - \fn void QGraphicsBloomEffect::brightnessChanged(int brightness) - - This signal is emitted whenever the effect's brightness changes. - The \a brightness parameter holds the effect's new brightness. -*/ - -/*! - \property QGraphicsBloomEffect::strength - \brief the strength of the effect. - - A strength 0.0 equals to no effect, while 1.0 means maximum glow. - - By default, the strength is 0.7. -*/ -qreal QGraphicsBloomEffect::strength() const -{ - Q_D(const QGraphicsBloomEffect); - return d->strength; -} - -void QGraphicsBloomEffect::setStrength(qreal strength) -{ - Q_D(QGraphicsBloomEffect); - strength = qBound(qreal(0.0), strength, qreal(1.0)); - if (qFuzzyCompare(d->strength, strength)) - return; - - d->strength = strength; - update(); - emit strengthChanged(strength); -} - -/*! - \fn void QGraphicsBloomEffect::strengthChanged(qreal strength) - - This signal is emitted whenever the effect's strength changes. - The \a strength parameter holds the effect's new strength. -*/ - -extern QPixmap qt_toRasterPixmap(const QPixmap &pixmap); - -/*! - \reimp -*/ -void QGraphicsBloomEffect::draw(QPainter *painter, QGraphicsEffectSource *source) -{ - Q_D(QGraphicsBloomEffect); - if (d->strength < 0.001) { - source->draw(painter); - return; - } - - QPoint offset; - QPixmap pixmap = qt_toRasterPixmap(source->pixmap(Qt::DeviceCoordinates, &offset)); - - // Blur. - QImage overlay(pixmap.size(), QImage::Format_ARGB32_Premultiplied); - overlay.fill(0); - - QPainter blurPainter(&overlay); - d->blurFilter.draw(&blurPainter, QPointF(), pixmap); - blurPainter.end(); - - // Brighten. - const int numBits = overlay.width() * overlay.height(); - QRgb *bits = reinterpret_cast<QRgb *>(overlay.bits()); - for (int i = 0; i < numBits; ++i) { - const QRgb pixel = INV_PREMUL(bits[i]); - bits[i] = PREMUL(qRgba(d->colorTable[qRed(pixel)], d->colorTable[qGreen(pixel)], - d->colorTable[qBlue(pixel)], qAlpha(pixel))); - } - - // Composite. - QPainter compPainter(&pixmap); - compPainter.setCompositionMode(QPainter::CompositionMode_Overlay); - compPainter.setOpacity(d->strength); - compPainter.drawImage(0, 0, overlay); - compPainter.end(); - - QTransform restoreTransform = painter->worldTransform(); - painter->setWorldTransform(QTransform()); painter->drawPixmap(offset, pixmap); - painter->setWorldTransform(restoreTransform); + painter->restore(); } + QT_END_NAMESPACE diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h index c89851e..bf18581 100644 --- a/src/gui/effects/qgraphicseffect.h +++ b/src/gui/effects/qgraphicseffect.h @@ -64,6 +64,12 @@ class Q_GUI_EXPORT QGraphicsEffectSource : public QObject { Q_OBJECT public: + enum PixmapPadMode { + NoExpandPadMode, + ExpandToTransparentBorderPadMode, + ExpandToEffectRectPadMode + }; + ~QGraphicsEffectSource(); const QGraphicsItem *graphicsItem() const; const QWidget *widget() const; @@ -75,7 +81,9 @@ public: QRectF boundingRect(Qt::CoordinateSystem coordinateSystem = Qt::LogicalCoordinates) const; QRect deviceRect() const; - QPixmap pixmap(Qt::CoordinateSystem system = Qt::LogicalCoordinates, QPoint *offset = 0) const; + QPixmap pixmap(Qt::CoordinateSystem system = Qt::LogicalCoordinates, + QPoint *offset = 0, + PixmapPadMode mode = ExpandToEffectRectPadMode) const; protected: QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, QObject *parent = 0); @@ -141,31 +149,6 @@ private: }; Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsEffect::ChangeFlags) -class QGraphicsGrayscaleEffectPrivate; -class Q_GUI_EXPORT QGraphicsGrayscaleEffect: public QGraphicsEffect -{ - Q_OBJECT - Q_PROPERTY(qreal strength READ strength WRITE setStrength NOTIFY strengthChanged) -public: - QGraphicsGrayscaleEffect(QObject *parent = 0); - ~QGraphicsGrayscaleEffect(); - - qreal strength() const; - -protected: - void draw(QPainter *painter, QGraphicsEffectSource *source); - -public Q_SLOTS: - void setStrength(qreal strength); - -Q_SIGNALS: - void strengthChanged(qreal strength); - -private: - Q_DECLARE_PRIVATE(QGraphicsGrayscaleEffect) - Q_DISABLE_COPY(QGraphicsGrayscaleEffect) -}; - class QGraphicsColorizeEffectPrivate; class Q_GUI_EXPORT QGraphicsColorizeEffect: public QGraphicsEffect { @@ -195,51 +178,26 @@ private: Q_DISABLE_COPY(QGraphicsColorizeEffect) }; -class QGraphicsPixelizeEffectPrivate; -class Q_GUI_EXPORT QGraphicsPixelizeEffect: public QGraphicsEffect -{ - Q_OBJECT - Q_PROPERTY(int pixelSize READ pixelSize WRITE setPixelSize NOTIFY pixelSizeChanged) -public: - QGraphicsPixelizeEffect(QObject *parent = 0); - ~QGraphicsPixelizeEffect(); - - int pixelSize() const; - -public Q_SLOTS: - void setPixelSize(int pixelSize); - -Q_SIGNALS: - void pixelSizeChanged(int pixelSize); - -protected: - void draw(QPainter *painter, QGraphicsEffectSource *source); - -private: - Q_DECLARE_PRIVATE(QGraphicsPixelizeEffect) - Q_DISABLE_COPY(QGraphicsPixelizeEffect) -}; - class QGraphicsBlurEffectPrivate; class Q_GUI_EXPORT QGraphicsBlurEffect: public QGraphicsEffect { Q_OBJECT - Q_PROPERTY(int blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) + Q_PROPERTY(qreal blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) Q_PROPERTY(Qt::RenderHint blurHint READ blurHint WRITE setBlurHint NOTIFY blurHintChanged) public: QGraphicsBlurEffect(QObject *parent = 0); ~QGraphicsBlurEffect(); QRectF boundingRectFor(const QRectF &rect) const; - int blurRadius() const; + qreal blurRadius() const; Qt::RenderHint blurHint() const; public Q_SLOTS: - void setBlurRadius(int blurRadius); + void setBlurRadius(qreal blurRadius); void setBlurHint(Qt::RenderHint hint); Q_SIGNALS: - void blurRadiusChanged(int blurRadius); + void blurRadiusChanged(qreal blurRadius); void blurHintChanged(Qt::RenderHint hint); protected: @@ -257,7 +215,7 @@ class Q_GUI_EXPORT QGraphicsDropShadowEffect: public QGraphicsEffect Q_PROPERTY(QPointF offset READ offset WRITE setOffset NOTIFY offsetChanged) Q_PROPERTY(qreal xOffset READ xOffset WRITE setXOffset NOTIFY offsetChanged) Q_PROPERTY(qreal yOffset READ yOffset WRITE setYOffset NOTIFY offsetChanged) - Q_PROPERTY(int blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) + Q_PROPERTY(qreal blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) public: QGraphicsDropShadowEffect(QObject *parent = 0); @@ -272,7 +230,7 @@ public: inline qreal yOffset() const { return offset().y(); } - int blurRadius() const; + qreal blurRadius() const; QColor color() const; public Q_SLOTS: @@ -290,12 +248,12 @@ public Q_SLOTS: inline void setYOffset(qreal dy) { setOffset(QPointF(xOffset(), dy)); } - void setBlurRadius(int blurRadius); + void setBlurRadius(qreal blurRadius); void setColor(const QColor &color); Q_SIGNALS: void offsetChanged(const QPointF &offset); - void blurRadiusChanged(int blurRadius); + void blurRadiusChanged(qreal blurRadius); void colorChanged(const QColor &color); protected: @@ -335,44 +293,6 @@ private: Q_DISABLE_COPY(QGraphicsOpacityEffect) }; -class QGraphicsBloomEffectPrivate; -class Q_GUI_EXPORT QGraphicsBloomEffect: public QGraphicsEffect -{ - Q_OBJECT - Q_PROPERTY(int blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) - Q_PROPERTY(Qt::RenderHint blurHint READ blurHint WRITE setBlurHint NOTIFY blurHintChanged) - Q_PROPERTY(int brightness READ brightness WRITE setBrightness NOTIFY brightnessChanged) - Q_PROPERTY(qreal strength READ strength WRITE setStrength NOTIFY strengthChanged) -public: - QGraphicsBloomEffect(QObject *parent = 0); - ~QGraphicsBloomEffect(); - - QRectF boundingRectFor(const QRectF &rect) const; - int blurRadius() const; - Qt::RenderHint blurHint() const; - int brightness() const; - qreal strength() const; - -public Q_SLOTS: - void setBlurRadius(int blurRadius); - void setBlurHint(Qt::RenderHint hint); - void setBrightness(int brightness); - void setStrength(qreal strength); - -Q_SIGNALS: - void blurRadiusChanged(int blurRadius); - void blurHintChanged(Qt::RenderHint hint); - void brightnessChanged(int brightness); - void strengthChanged(qreal strength); - -protected: - void draw(QPainter *painter, QGraphicsEffectSource *source); - -private: - Q_DECLARE_PRIVATE(QGraphicsBloomEffect) - Q_DISABLE_COPY(QGraphicsBloomEffect) -}; - QT_END_NAMESPACE QT_END_HEADER diff --git a/src/gui/effects/qgraphicseffect_p.h b/src/gui/effects/qgraphicseffect_p.h index fc925f2..1ed7103 100644 --- a/src/gui/effects/qgraphicseffect_p.h +++ b/src/gui/effects/qgraphicseffect_p.h @@ -66,7 +66,12 @@ class QGraphicsEffectSourcePrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QGraphicsEffectSource) public: - QGraphicsEffectSourcePrivate() : QObjectPrivate() {} + QGraphicsEffectSourcePrivate() + : QObjectPrivate() + , m_cachedSystem(Qt::DeviceCoordinates) + , m_cachedMode(QGraphicsEffectSource::ExpandToTransparentBorderPadMode) + {} + virtual ~QGraphicsEffectSourcePrivate() { invalidateCache(); } virtual void detach() = 0; virtual QRectF boundingRect(Qt::CoordinateSystem system) const = 0; @@ -77,7 +82,8 @@ public: virtual void draw(QPainter *p) = 0; virtual void update() = 0; virtual bool isPixmap() const = 0; - virtual QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset = 0) const = 0; + virtual QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset = 0, + QGraphicsEffectSource::PixmapPadMode mode = QGraphicsEffectSource::ExpandToTransparentBorderPadMode) const = 0; virtual void effectBoundingRectChanged() = 0; void invalidateCache() const { QPixmapCache::remove(m_cacheKey); } @@ -87,6 +93,7 @@ public: private: mutable Qt::CoordinateSystem m_cachedSystem; + mutable QGraphicsEffectSource::PixmapPadMode m_cachedMode; mutable QPoint m_cachedOffset; mutable QPixmapCache::Key m_cacheKey; }; @@ -118,22 +125,6 @@ public: quint32 padding : 31; // feel free to use }; -class QGraphicsGrayscaleEffectPrivate : public QGraphicsEffectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsGrayscaleEffect) -public: - QGraphicsGrayscaleEffectPrivate() - : opaque(true) - { - filter = new QPixmapColorizeFilter; - filter->setColor(Qt::black); - } - ~QGraphicsGrayscaleEffectPrivate() { delete filter; } - - QPixmapColorizeFilter *filter; - quint32 opaque : 1; - quint32 padding : 31; -}; class QGraphicsColorizeEffectPrivate : public QGraphicsEffectPrivate { @@ -151,15 +142,6 @@ public: quint32 padding : 31; }; -class QGraphicsPixelizeEffectPrivate : public QGraphicsEffectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsPixelizeEffect) -public: - QGraphicsPixelizeEffectPrivate() : pixelSize(3) {} - - int pixelSize; -}; - class QGraphicsBlurEffectPrivate : public QGraphicsEffectPrivate { Q_DECLARE_PUBLIC(QGraphicsBlurEffect) @@ -195,18 +177,6 @@ public: uint hasOpacityMask : 1; }; -class QGraphicsBloomEffectPrivate : public QGraphicsEffectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsBlurEffect) -public: - QGraphicsBloomEffectPrivate() : brightness(70), strength(qreal(0.7)) {} - - QPixmapBlurFilter blurFilter; - int colorTable[256]; - int brightness; - qreal strength; -}; - QT_END_NAMESPACE #endif // QGRAPHICSEFFECT_P_H |