From 96773d4b21ce288b26857159dfbb553a81ae3a94 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Tue, 2 Jun 2009 13:57:45 +0200 Subject: Another n-th attempt at making an API for the effect framework. The implementation is not efficient, it serves as the proof-of-concept only. Check the notes in qgraphicseffect.cpp for details. --- src/gui/graphicsview/graphicsview.pri | 2 + src/gui/graphicsview/qgraphicseffect.cpp | 556 +++++++++++++++++++++++++++++++ src/gui/graphicsview/qgraphicseffect.h | 258 ++++++++++++++ src/gui/graphicsview/qgraphicsitem.cpp | 119 +++++++ src/gui/graphicsview/qgraphicsitem.h | 9 + src/gui/graphicsview/qgraphicsitem_p.h | 8 +- src/gui/graphicsview/qgraphicsscene.cpp | 97 +++++- src/gui/graphicsview/qgraphicsscene.h | 6 + src/gui/graphicsview/qgraphicsview.cpp | 21 +- 9 files changed, 1063 insertions(+), 13 deletions(-) create mode 100644 src/gui/graphicsview/qgraphicseffect.cpp create mode 100644 src/gui/graphicsview/qgraphicseffect.h diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri index 02d9bb1..f18bafc 100644 --- a/src/gui/graphicsview/graphicsview.pri +++ b/src/gui/graphicsview/graphicsview.pri @@ -2,6 +2,7 @@ HEADERS += \ graphicsview/qgraphicsitem.h \ + graphicsview/qgraphicseffect.h \ graphicsview/qgraphicsitem_p.h \ graphicsview/qgraphicsitemanimation.h \ graphicsview/qgraphicsscene.h \ @@ -13,6 +14,7 @@ HEADERS += \ SOURCES += \ graphicsview/qgraphicsitem.cpp \ + graphicsview/qgraphicseffect.cpp \ graphicsview/qgraphicsitemanimation.cpp \ graphicsview/qgraphicsscene.cpp \ graphicsview/qgraphicsscene_bsp.cpp \ diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp new file mode 100644 index 0000000..1d0e485 --- /dev/null +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -0,0 +1,556 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgraphicseffect.h" + +#ifndef QT_NO_GRAPHICSVIEW + +#include +#include +#include +#include + +#include + +/* + + List of known drawbacks which are being discussed: + + * No d-pointer yet. + + * No auto test yet. + + * No API documentation yet. + + * The API is far from being finalized. + + * Most of the effect implementation is not efficient, + as this is still a proof of concept only. + + * Painting artifacts occasionally occur when e.g. moving + an item over another item that has a large effective + bounding rect. + + * Item transformation is not taken into account. + For example, the effective bounding rect is calculated at + item coordinate (fast), but the painting is mostly + done at device coordinate. + + * Coordinate mode: item vs device. Most effects make sense only + in device coordinate. Should we keep both options open? + See also above transformation issue. + + * Right now the pixmap for effect drawing is stored in each item. + There can be problems with coordinates, see above. + + * There is a lot of duplication in drawItems() for each effect. + + * Port to use the new layer feature in QGraphicsView. + This should solve the above pixmap problem. + + * Frame effect is likely useless. However it is very useful + to check than the effective bounding rect is handled properly. + + * Proper exposed region and rect for style option are missing. + + * Pixelize effect is using raster only, because there is no + pixmap filter for it. We need to implement the missing pixmap filter. + + * Blur effect is using raster only, with exponential blur algorithm. + Perhaps use stack blur (better approximate Gaussian blur) instead? + QPixmapConvolutionFilter is too slow for this simple blur effect. + + * Bloom and shadow effect are also raster only. Same reason as above. + + * Make it work with widgets (QGraphicsWidget). + +*/ + +QGraphicsEffect::QGraphicsEffect() +{ +} + +QGraphicsEffect::~QGraphicsEffect() +{ +} + +QRectF QGraphicsEffect::boundingRectFor(const QGraphicsItem *item) +{ + // default is to give the item's bounding rect + // do NOT call item->effectiveBoundRect() because + // that function will call this one (infinite loop) + return item->boundingRect(); +} + +// this helper function is only for subclasses of QGraphicsEffect +// the implementation is trivial, but this allows us to keep +// QGraphicsScene::drawItem() as a protected function +// (since QGraphicsEffect is a friend of QGraphicsScene) +QPixmap* QGraphicsEffect::drawItemOnPixmap(QPainter *painter, QGraphicsItem *item, + const QStyleOptionGraphicsItem *option, QWidget *widget, int flags) +{ + if (!item->scene()) + return 0; + return item->scene()->drawItemOnPixmap(painter, item, option, widget, flags); +} + +QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect(): QGraphicsEffect() +{ + filter = new QPixmapColorizeFilter; + filter->setColor(Qt::black); +} + +QGraphicsGrayscaleEffect::~QGraphicsGrayscaleEffect() +{ + delete filter; +} + +void QGraphicsGrayscaleEffect::drawItem(QGraphicsItem *item, QPainter *painter, + const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + // Find the item's bounds in device coordinates. + QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect()); + QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); + if (deviceRect.isEmpty()) + return; + + QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0); + if (!pixmap) + return; + + // Draw the pixmap with the filter using an untransformed painter. + QTransform restoreTransform = painter->worldTransform(); + painter->setWorldTransform(QTransform()); + filter->draw(painter, deviceRect.topLeft(), *pixmap, pixmap->rect()); + painter->setWorldTransform(restoreTransform); +} + +QGraphicsColorizeEffect::QGraphicsColorizeEffect(): QGraphicsEffect() +{ + filter = new QPixmapColorizeFilter; +} + +QGraphicsColorizeEffect::~QGraphicsColorizeEffect() +{ + delete filter; +} + +QColor QGraphicsColorizeEffect::color() const +{ + return filter->color(); +} + +void QGraphicsColorizeEffect::setColor(const QColor &c) +{ + filter->setColor(c); +} + +void QGraphicsColorizeEffect::drawItem(QGraphicsItem *item, QPainter *painter, + const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + // Find the item's bounds in device coordinates. + QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect()); + QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); + if (deviceRect.isEmpty()) + return; + + QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0); + if (!pixmap) + return; + + // Draw the pixmap with the filter using an untransformed painter. + QTransform restoreTransform = painter->worldTransform(); + painter->setWorldTransform(QTransform()); + filter->draw(painter, deviceRect.topLeft(), *pixmap, pixmap->rect()); + painter->setWorldTransform(restoreTransform); +} + +QGraphicsPixelizeEffect::QGraphicsPixelizeEffect(): QGraphicsEffect(), size(2) +{ +} + +QGraphicsPixelizeEffect::~QGraphicsPixelizeEffect() +{ +} + +void QGraphicsPixelizeEffect::drawItem(QGraphicsItem *item, QPainter *painter, + const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + // Find the item's bounds in device coordinates. + QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect()); + QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); + if (deviceRect.isEmpty()) + return; + + QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0); + if (!pixmap) + return; + + // pixelize routine + QImage img = pixmap->toImage().convertToFormat(QImage::Format_ARGB32); + if (size > 0) { + int width = img.width(); + int height = img.height(); + for (int y = 0; y < height; y += size) { + int ys = qMin(height - 1, y + size / 2); + QRgb *sbuf = reinterpret_cast(img.scanLine(ys)); + for (int x = 0; x < width; x += size) { + int xs = qMin(width - 1, x + size / 2); + QRgb color = sbuf[xs]; + for (int yi = 0; yi < qMin(size, height - y); ++yi) { + QRgb *buf = reinterpret_cast(img.scanLine(y + yi)); + for (int xi = 0; xi < qMin(size, width - x); ++xi) + buf[x + xi] = color; + } + } + } + } + + // Draw using an untransformed painter. + QTransform restoreTransform = painter->worldTransform(); + painter->setWorldTransform(QTransform()); + painter->drawImage(deviceRect.topLeft(), img); + painter->setWorldTransform(restoreTransform); +} + + +QGraphicsBlurEffect::QGraphicsBlurEffect(): QGraphicsEffect(), radius(6) +{ +} + +QGraphicsBlurEffect::~QGraphicsBlurEffect() +{ +} + +// Blur the image according to the blur radius +// Based on exponential blur algorithm by Jani Huhtanen +// (maximum radius is set to 16) +static QImage blurred(const QImage& image, const QRect& rect, int radius) +{ + int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 }; + int alpha = (radius < 1) ? 16 : (radius > 17) ? 1 : tab[radius-1]; + + QImage result = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); + int r1 = rect.top(); + int r2 = rect.bottom(); + int c1 = rect.left(); + int c2 = rect.right(); + + int bpl = result.bytesPerLine(); + int rgba[4]; + unsigned char* p; + + for (int col = c1; col <= c2; col++) { + p = result.scanLine(r1) + col * 4; + for (int i = 0; i < 4; i++) + rgba[i] = p[i] << 4; + + p += bpl; + for (int j = r1; j < r2; j++, p += bpl) + for (int i = 0; i < 4; i++) + p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; + } + + for (int row = r1; row <= r2; row++) { + p = result.scanLine(row) + c1 * 4; + for (int i = 0; i < 4; i++) + rgba[i] = p[i] << 4; + + p += 4; + for (int j = c1; j < c2; j++, p += 4) + for (int i = 0; i < 4; i++) + p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; + } + + for (int col = c1; col <= c2; col++) { + p = result.scanLine(r2) + col * 4; + for (int i = 0; i < 4; i++) + rgba[i] = p[i] << 4; + + p -= bpl; + for (int j = r1; j < r2; j++, p -= bpl) + for (int i = 0; i < 4; i++) + p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; + } + + for (int row = r1; row <= r2; row++) { + p = result.scanLine(row) + c2 * 4; + for (int i = 0; i < 4; i++) + rgba[i] = p[i] << 4; + + p -= 4; + for (int j = c1; j < c2; j++, p -= 4) + for (int i = 0; i < 4; i++) + p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; + } + + return result; +} + +QRectF QGraphicsBlurEffect::boundingRectFor(const QGraphicsItem *item) +{ + qreal delta = radius * 3; + QRectF blurRect = item->boundingRect(); + blurRect.adjust(-delta, -delta, delta, delta); + return blurRect; +} + +void QGraphicsBlurEffect::drawItem(QGraphicsItem *item, QPainter *painter, + const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + // Find the item's bounds in device coordinates. + QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect()); + QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); + if (deviceRect.isEmpty()) + return; + + QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0); + if (!pixmap) + return; + + // blur routine + QImage img = pixmap->toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); + img = blurred(img, img.rect(), radius); + + // Draw using an untransformed painter. + QTransform restoreTransform = painter->worldTransform(); + painter->setWorldTransform(QTransform()); + painter->drawImage(deviceRect.topLeft() - QPointF(radius * 3, radius * 3), img); + painter->setWorldTransform(restoreTransform); +} + + +QGraphicsBloomEffect::QGraphicsBloomEffect(): QGraphicsEffect(), radius(6), alpha(0.7) +{ +} + +QGraphicsBloomEffect::~QGraphicsBloomEffect() +{ +} + +QRectF QGraphicsBloomEffect::boundingRectFor(const QGraphicsItem *item) +{ + qreal delta = radius * 3; + QRectF blurRect = item->boundingRect(); + blurRect.adjust(-delta, -delta, delta, delta); + return blurRect; +} + +// Change brightness (positive integer) of each pixel +static QImage brightened(const QImage& image, int brightness) +{ + int tab[ 256 ]; + for (int i = 0; i < 256; ++i) + tab[i] = qMin(i + brightness, 255); + + QImage img = image.convertToFormat(QImage::Format_ARGB32); + for (int y = 0; y < img.height(); y++) { + QRgb* line = (QRgb*)(img.scanLine(y)); + for (int x = 0; x < img.width(); x++) { + QRgb c = line[x]; + line[x] = qRgba(tab[qRed(c)], tab[qGreen(c)], tab[qBlue(c)], qAlpha(c)); + } + } + + return img; +} + +// Composite two QImages using given composition mode and opacity +static QImage composited(const QImage& img1, const QImage& img2, qreal opacity, QPainter::CompositionMode mode) +{ + QImage result = img1.convertToFormat(QImage::Format_ARGB32_Premultiplied); + QPainter painter(&result); + painter.setCompositionMode(mode); + painter.setOpacity(opacity); + painter.drawImage(0, 0, img2); + painter.end(); + return result; +} + +void QGraphicsBloomEffect::drawItem(QGraphicsItem *item, QPainter *painter, + const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + // Find the item's bounds in device coordinates. + QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect()); + QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); + if (deviceRect.isEmpty()) + return; + + QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0); + if (!pixmap) + return; + + // bloom routine + QImage img = pixmap->toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); + QImage overlay = blurred(img, img.rect(), radius); + overlay = brightened(overlay, 70); + img = composited(img, overlay, alpha, QPainter::CompositionMode_Overlay); + + // Draw using an untransformed painter. + QTransform restoreTransform = painter->worldTransform(); + painter->setWorldTransform(QTransform()); + painter->drawImage(deviceRect.topLeft() - QPointF(radius * 3, radius * 3), img); + painter->setWorldTransform(restoreTransform); +} + +QGraphicsFrameEffect::QGraphicsFrameEffect() + : QGraphicsEffect() + , color(Qt::blue) + , width(5) + , alpha(0.6) +{ +} + +QGraphicsFrameEffect::~QGraphicsFrameEffect() +{ +} + +QRectF QGraphicsFrameEffect::boundingRectFor(const QGraphicsItem *item) +{ + QRectF frameRect = item->boundingRect(); + frameRect.adjust(-width, -width, width, width); + return frameRect; +} + +void QGraphicsFrameEffect::drawItem(QGraphicsItem *item, QPainter *painter, + const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + // Find the item's bounds in device coordinates. + QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect()); + QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); + if (deviceRect.isEmpty()) + return; + + QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0); + if (!pixmap) + return; + + QRectF frameRect = deviceBounds; + frameRect.adjust(-width, -width, width, width); + + painter->save(); + painter->setWorldTransform(QTransform()); + + painter->save(); + painter->setOpacity(painter->opacity() * alpha); + painter->setPen(Qt::NoPen); + painter->setBrush(color); + painter->drawRoundedRect(frameRect, 20, 20, Qt::RelativeSize); + painter->restore(); + + painter->drawPixmap(frameRect.topLeft(), *pixmap); + + painter->restore(); +} + + +QGraphicsShadowEffect::QGraphicsShadowEffect() + : QGraphicsEffect() + , offset(4,4) + , radius(8) + , alpha(0.7) +{ +} + +QGraphicsShadowEffect::~QGraphicsShadowEffect() +{ +} + +QRectF QGraphicsShadowEffect::boundingRectFor(const QGraphicsItem *item) +{ + QRectF shadowRect = item->boundingRect(); + shadowRect.adjust(offset.x(), offset.y(), offset.x(), offset.y()); + QRectF blurRect = shadowRect; + qreal delta = radius * 3; + blurRect.adjust(-delta, -delta, delta, delta); + QRectF totalRect = blurRect.united(item->boundingRect()); + return totalRect; +} + +void QGraphicsShadowEffect::drawItem(QGraphicsItem *item, QPainter *painter, + const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + // Find the item's bounds in device coordinates. + QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect()); + QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); + if (deviceRect.isEmpty()) + return; + + QRectF shadowRect = deviceBounds; + shadowRect.adjust(offset.x(), offset.y(), offset.x(), offset.y()); + QRectF blurRect = shadowRect; + qreal delta = radius * 3; + blurRect.adjust(-delta, -delta, delta, delta); + QRectF totalRect = blurRect.united(deviceRect); + + QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0); + if (!pixmap) + return; + + QImage img = pixmap->toImage(); + QImage shadowImage(img.size(), QImage::Format_ARGB32); + shadowImage.fill(qRgba(0, 0, 0, alpha * 255)); + shadowImage.setAlphaChannel(img.alphaChannel()); + shadowImage = blurred(shadowImage, shadowImage.rect(), radius); + + // Draw using an untransformed painter. + QTransform restoreTransform = painter->worldTransform(); + painter->setWorldTransform(QTransform()); + + QRect shadowAlignedRect = shadowRect.toAlignedRect(); + + qreal shadowx = blurRect.x() + delta; + qreal shadowy = blurRect.y() + delta; + if (blurRect.x() < deviceRect.x()) + shadowx = blurRect.x() + offset.x(); + if (blurRect.y() < deviceRect.y()) + shadowy = blurRect.y() + offset.y(); + painter->drawImage(shadowx, shadowy, shadowImage); + + qreal itemx = qMin(blurRect.x(), deviceBounds.x()); + qreal itemy = qMin(blurRect.y(), deviceBounds.y()); + painter->drawPixmap(itemx, itemy, *pixmap); + + painter->setWorldTransform(restoreTransform); +} + + +#endif diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h new file mode 100644 index 0000000..9f6fb07 --- /dev/null +++ b/src/gui/graphicsview/qgraphicseffect.h @@ -0,0 +1,258 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSEFFECT_H +#define QGRAPHICSEFFECT_H + +#include +#include +#include +#include + +QT_FORWARD_DECLARE_CLASS(QGraphicsItem); +QT_FORWARD_DECLARE_CLASS(QStyleOptionGraphicsItem); +QT_FORWARD_DECLARE_CLASS(QPainter); +QT_FORWARD_DECLARE_CLASS(QPixmap); +QT_FORWARD_DECLARE_CLASS(QWidget); +QT_FORWARD_DECLARE_CLASS(QPixmapColorizeFilter); + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + +class Q_GUI_EXPORT QGraphicsEffect { +public: + + QGraphicsEffect(); + virtual ~QGraphicsEffect(); + + virtual QRectF boundingRectFor(const QGraphicsItem *item); + + virtual void drawItem(QGraphicsItem *item, QPainter *painter, + const QStyleOptionGraphicsItem *option = 0, + QWidget *widget = 0) = 0; + +protected: + QPixmap* drawItemOnPixmap(QPainter *painter, QGraphicsItem *item, + const QStyleOptionGraphicsItem *option, QWidget *widget, int flags); + +private: + Q_DISABLE_COPY(QGraphicsEffect); +}; + +class Q_GUI_EXPORT QGraphicsGrayscaleEffect: public QGraphicsEffect { +public: + + QGraphicsGrayscaleEffect(); + ~QGraphicsGrayscaleEffect(); + + void drawItem(QGraphicsItem *item, QPainter *painter, + const QStyleOptionGraphicsItem *option = 0, + QWidget *widget = 0); + +private: + QPixmapColorizeFilter *filter; + Q_DISABLE_COPY(QGraphicsGrayscaleEffect); +}; + +class Q_GUI_EXPORT QGraphicsColorizeEffect: public QGraphicsEffect { +public: + + QGraphicsColorizeEffect(); + ~QGraphicsColorizeEffect(); + + QColor color() const; + void setColor(const QColor &c); + + void drawItem(QGraphicsItem *item, QPainter *painter, + const QStyleOptionGraphicsItem *option = 0, + QWidget *widget = 0); + +private: + QPixmapColorizeFilter *filter; + Q_DISABLE_COPY(QGraphicsColorizeEffect); +}; + +class Q_GUI_EXPORT QGraphicsPixelizeEffect: public QGraphicsEffect { +public: + + QGraphicsPixelizeEffect(); + ~QGraphicsPixelizeEffect(); + + int pixelSize() const { return size; } + void setPixelSize(int pixelSize) { size = pixelSize; } + + void drawItem(QGraphicsItem *item, QPainter *painter, + const QStyleOptionGraphicsItem *option = 0, + QWidget *widget = 0); + +private: + int size; + Q_DISABLE_COPY(QGraphicsPixelizeEffect); +}; + +class Q_GUI_EXPORT QGraphicsBlurEffect: public QGraphicsEffect { +public: + + QGraphicsBlurEffect(); + ~QGraphicsBlurEffect(); + + int blurRadius() const { return radius; } + void setBlurRadius(int blurRadius) { radius = blurRadius; } + + QRectF boundingRectFor(const QGraphicsItem *item); + + void drawItem(QGraphicsItem *item, QPainter *painter, + const QStyleOptionGraphicsItem *option = 0, + QWidget *widget = 0); + +private: + int radius; + Q_DISABLE_COPY(QGraphicsBlurEffect); +}; + +class Q_GUI_EXPORT QGraphicsBloomEffect: public QGraphicsEffect { +public: + + QGraphicsBloomEffect(); + ~QGraphicsBloomEffect(); + + int blurRadius() const { return radius; } + void setBlurRadius(int blurRadius) { radius = blurRadius; } + + QRectF boundingRectFor(const QGraphicsItem *item); + + qreal opacity() const { return alpha; } + void setOpacity(qreal opacity) { alpha = opacity; } + + void drawItem(QGraphicsItem *item, QPainter *painter, + const QStyleOptionGraphicsItem *option = 0, + QWidget *widget = 0); + +private: + int radius; + qreal alpha; + Q_DISABLE_COPY(QGraphicsBloomEffect); +}; + +class Q_GUI_EXPORT QGraphicsFrameEffect: public QGraphicsEffect { +public: + + QGraphicsFrameEffect(); + ~QGraphicsFrameEffect(); + + QColor frameColor() const { return color; } + void setFrameColor(const QColor &c) { color = c; } + + qreal frameWidth() const { return width; } + void setFrameWidth(qreal frameWidth) { width = frameWidth; } + + qreal frameOpacity() const { return alpha; } + void setFrameOpacity(qreal opacity) { alpha = opacity; } + + + QRectF boundingRectFor(const QGraphicsItem *item); + + void drawItem(QGraphicsItem *item, QPainter *painter, + const QStyleOptionGraphicsItem *option = 0, + QWidget *widget = 0); +private: + QColor color; + qreal width; + qreal alpha; + Q_DISABLE_COPY(QGraphicsFrameEffect); +}; + +class Q_GUI_EXPORT QGraphicsShadowEffect: public QGraphicsEffect { +public: + + QGraphicsShadowEffect(); + ~QGraphicsShadowEffect(); + + QPointF shadowOffset() const; + void setShadowOffset(const QPointF &ofs) { offset = ofs; } + inline void setShadowOffset(qreal dx, qreal dy) { setShadowOffset(QPointF(dx, dy)); } + inline void setShadowOffset(qreal d) { setShadowOffset(QPointF(d, d)); } + + int blurRadius() const { return radius; } + void setBlurRadius(int blurRadius) { radius = blurRadius; } + + qreal opacity() const { return alpha; } + void setOpacity(qreal opacity) { alpha = opacity; } + + QRectF boundingRectFor(const QGraphicsItem *item); + + void drawItem(QGraphicsItem *item, QPainter *painter, + const QStyleOptionGraphicsItem *option = 0, + QWidget *widget = 0); + +protected: + QPointF offset; + int radius; + qreal alpha; + +private: + Q_DISABLE_COPY(QGraphicsShadowEffect); +}; + + + +Q_DECLARE_METATYPE(QGraphicsEffect *) +Q_DECLARE_METATYPE(QGraphicsGrayscaleEffect *) +Q_DECLARE_METATYPE(QGraphicsColorizeEffect *) +Q_DECLARE_METATYPE(QGraphicsPixelizeEffect *) +Q_DECLARE_METATYPE(QGraphicsBlurEffect *) +Q_DECLARE_METATYPE(QGraphicsBloomEffect *) +Q_DECLARE_METATYPE(QGraphicsFrameEffect *) +Q_DECLARE_METATYPE(QGraphicsShadowEffect *) + +#endif // QT_NO_GRAPHICSVIEW + +QT_END_NAMESPACE + +QT_END_HEADER + + +#endif // QGRAPHICSEFFECT_H diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index b9e462b..f0a256a 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -531,6 +531,7 @@ #ifndef QT_NO_GRAPHICSVIEW +#include "qgraphicseffect.h" #include "qgraphicsscene.h" #include "qgraphicsscene_p.h" #include "qgraphicssceneevent.h" @@ -2047,6 +2048,124 @@ void QGraphicsItem::setOpacity(qreal opacity) } /*! + \since 4.6 + Returns this item's \e effect if it has one; otherwise, + returns 0. +*/ +QGraphicsEffect *QGraphicsItem::effect() const +{ + QGraphicsEffect *fx = 0; + if (d_ptr->hasEffect) + fx = d_ptr->extra(QGraphicsItemPrivate::ExtraEffect).value(); + + return fx; +} + +/*! + \since 4.6 + Sets \e effect as the item's effect. It will replace the previous effect + the item might have. +*/ +void QGraphicsItem::setEffect(QGraphicsEffect *effect) +{ + if (effect) { + d_ptr->hasEffect = true; + d_ptr->setExtra(QGraphicsItemPrivate::ExtraEffect, QVariant::fromValue(effect)); + } else { + d_ptr->hasEffect = false; + d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraEffect); + void *ptr = d_ptr->extra(QGraphicsItemPrivate::ExtraEffectPixmap).value(); + QPixmap *pixmap = reinterpret_cast(ptr); + delete pixmap; + d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraEffectPixmap); + } + + update(); +} + +/*! + \since 4.6 + Returns the effective bounding rect of the item. + If the item has no effect, this is the same as the item's bounding rect. + If the item has an effect, the effective rect can be larger than the item's + bouding rect, depending on the effect. + + \sa boundingRect() +*/ +QRectF QGraphicsItem::effectiveBoundingRect() const +{ + QGraphicsEffect *fx = effect(); + if (fx) + return fx->boundingRectFor(this); + + return boundingRect(); +} + +/*! + \since 4.6 + Returns the effective bounding rect of this item in scene coordinates, + by combining sceneTransform() with boundingRect(), taking into account + the effect that the item might have. + + If the item has no effect, this is the same as sceneBoundingRect(). + + \sa effectiveBoundingRect(), sceneBoundingRect() +*/ +QRectF QGraphicsItem::sceneEffectiveBoundingRect() const +{ + // Find translate-only offset + QPointF offset; + const QGraphicsItem *parentItem = this; + const QGraphicsItemPrivate *itemd; + do { + itemd = parentItem->d_ptr; + if (itemd->hasTransform) + break; + offset += itemd->pos; + } while ((parentItem = itemd->parent)); + + QRectF br = effectiveBoundingRect(); + br.translate(offset); + return !parentItem ? br : parentItem->sceneTransform().mapRect(br); +} + +/*! + \internal + + Used by QGraphicsScene. +*/ +QPixmap *QGraphicsItem::effectPixmap() +{ + if (!d_ptr->hasEffect) + return 0; + + // the exact size of the pixmap is not a big deal + // as long as it contains the effective bounding rect + // TODO: use smart resizing etc + // TODO: store per device and do everything in device coordinate? + // TODO: use layer + QRect rect = effectiveBoundingRect().toAlignedRect(); + + void *ptr = d_ptr->extra(QGraphicsItemPrivate::ExtraEffectPixmap).value(); + QPixmap *pixmap = reinterpret_cast(ptr); + bool avail = true; + if (!pixmap) + avail = false; + if (avail && pixmap->size() != rect.size()) + avail = false; + + if (!avail) { + delete pixmap; + pixmap = new QPixmap(rect.size()); + pixmap->fill(Qt::transparent); + ptr = reinterpret_cast(pixmap); + d_ptr->setExtra(QGraphicsItemPrivate::ExtraEffectPixmap, QVariant::fromValue(ptr)); + } + + return pixmap; +} + +/*! Returns true if this item can accept drag and drop events; otherwise, returns false. By default, items do not accept drag and drop events; items are transparent to drag and drop. diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index f6ee197..0c85245 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -62,6 +62,7 @@ QT_MODULE(Gui) class QBrush; class QCursor; class QFocusEvent; +class QGraphicsEffect; class QGraphicsItemGroup; class QGraphicsSceneContextMenuEvent; class QGraphicsSceneDragDropEvent; @@ -198,6 +199,12 @@ public: qreal effectiveOpacity() const; void setOpacity(qreal opacity); + // Effect + QGraphicsEffect *effect() const; + void setEffect(QGraphicsEffect *effect); + QRectF effectiveBoundingRect() const; + QRectF sceneEffectiveBoundingRect() const; + Qt::MouseButtons acceptedMouseButtons() const; void setAcceptedMouseButtons(Qt::MouseButtons buttons); @@ -418,6 +425,8 @@ protected: void removeFromIndex(); void prepareGeometryChange(); + QPixmap *effectPixmap(); + private: Q_DISABLE_COPY(QGraphicsItem) Q_DECLARE_PRIVATE(QGraphicsItem) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index bd81fe5..a2cb4ab 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -113,7 +113,9 @@ public: ExtraBoundingRegionGranularity, ExtraOpacity, ExtraEffectiveOpacity, - ExtraDecomposedTransform + ExtraDecomposedTransform, + ExtraEffect, + ExtraEffectPixmap, }; enum AncestorFlag { @@ -155,6 +157,7 @@ public: dirtyClipPath(1), emptyClipPath(0), inSetPosHelper(0), + hasEffect(0), flags(0), allChildrenCombineOpacity(1), hasDecomposedTransform(0), @@ -345,12 +348,13 @@ public: quint32 inSetPosHelper : 1; // New 32 bits + quint32 hasEffect : 1; quint32 flags : 10; quint32 allChildrenCombineOpacity : 1; quint32 hasDecomposedTransform : 1; quint32 dirtyTransform : 1; quint32 dirtyTransformComponents : 1; - quint32 padding : 18; // feel free to use + quint32 padding : 17; // feel free to use // Optional stacking order int globalStackingOrder; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 1fc4567..bf8ca0a 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -210,6 +210,7 @@ static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; #ifndef QT_NO_GRAPHICSVIEW +#include "qgraphicseffect.h" #include "qgraphicsitem.h" #include "qgraphicsitem_p.h" #include "qgraphicslayout.h" @@ -309,6 +310,14 @@ static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item) return boundingRect; } +static inline QRectF adjustedItemEffectiveBoundingRect(const QGraphicsItem *item) +{ + Q_ASSERT(item); + QRectF boundingRect(item->effectiveBoundingRect()); + _q_adjustRect(&boundingRect); + return boundingRect; +} + static void _q_hoverFromMouseEvent(QGraphicsSceneHoverEvent *hover, const QGraphicsSceneMouseEvent *mouseEvent) { hover->setWidget(mouseEvent->widget()); @@ -392,7 +401,7 @@ QList QGraphicsScenePrivate::estimateItemsInRect(const QRectF & for (int i = 0; i < unindexedItems.size(); ++i) { if (QGraphicsItem *item = unindexedItems.at(i)) { if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { - QRectF boundingRect = item->sceneBoundingRect(); + QRectF boundingRect = item->sceneEffectiveBoundingRect(); if (QRectF_intersects(boundingRect, rect)) { item->d_ptr->itemDiscovered = 1; items << item; @@ -435,7 +444,7 @@ void QGraphicsScenePrivate::addToIndex(QGraphicsItem *item) { if (indexMethod == QGraphicsScene::BspTreeIndex) { if (item->d_func()->index != -1) { - bspTree.insertItem(item, item->sceneBoundingRect()); + bspTree.insertItem(item, item->sceneEffectiveBoundingRect()); foreach (QGraphicsItem *child, item->children()) child->addToIndex(); } else { @@ -455,7 +464,7 @@ void QGraphicsScenePrivate::removeFromIndex(QGraphicsItem *item) if (indexMethod == QGraphicsScene::BspTreeIndex) { int index = item->d_func()->index; if (index != -1) { - bspTree.removeItem(item, item->sceneBoundingRect()); + bspTree.removeItem(item, item->sceneEffectiveBoundingRect()); freeItemIndexes << index; indexedItems[index] = 0; item->d_func()->index = -1; @@ -512,7 +521,7 @@ void QGraphicsScenePrivate::_q_updateIndex() QRectF unindexedItemsBoundingRect; for (int i = 0; i < unindexedItems.size(); ++i) { if (QGraphicsItem *item = unindexedItems.at(i)) { - unindexedItemsBoundingRect |= item->sceneBoundingRect(); + unindexedItemsBoundingRect |= item->sceneEffectiveBoundingRect(); if (!freeItemIndexes.isEmpty()) { int freeIndex = freeItemIndexes.takeFirst(); item->d_func()->index = freeIndex; @@ -559,7 +568,7 @@ void QGraphicsScenePrivate::_q_updateIndex() // Insert all unindexed items into the tree. for (int i = 0; i < unindexedItems.size(); ++i) { if (QGraphicsItem *item = unindexedItems.at(i)) { - QRectF rect = item->sceneBoundingRect(); + QRectF rect = item->sceneEffectiveBoundingRect(); if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) continue; if (indexMethod == QGraphicsScene::BspTreeIndex) @@ -612,7 +621,7 @@ void QGraphicsScenePrivate::_q_emitUpdated() // Ensure all dirty items's current positions are recorded in the list of // updated rects. for (int i = 0; i < dirtyItems.size(); ++i) - updatedRects += dirtyItems.at(i)->sceneBoundingRect(); + updatedRects += dirtyItems.at(i)->sceneEffectiveBoundingRect(); // Notify the changes to anybody interested. QList oldUpdatedRects; @@ -1465,7 +1474,7 @@ QList QGraphicsScenePrivate::items_helper(const QRectF &rect, // ### _q_adjustedRect is only needed because QRectF::intersects, // QRectF::contains and QTransform::map() and friends don't work with // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); + const QRectF br(adjustedItemEffectiveBoundingRect(item)); if (mode >= Qt::ContainsItemBoundingRect) { // Rect intersects/contains item's bounding rect QRectF mbr = x.mapRect(br); @@ -4716,6 +4725,19 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte QGraphicsItemPrivate *itemd = item->d_ptr; QGraphicsItem::CacheMode cacheMode = QGraphicsItem::CacheMode(itemd->cacheMode); + bool noCache = cacheMode == QGraphicsItem::NoCache || +#ifdef Q_WS_X11 + !X11->use_xrender; +#else + false; +#endif + + // Render using effect, works now only for no cache mode + if (noCache && itemd->hasEffect && item->effect()) { + item->effect()->drawItem(item, painter, option, widget); + return; + } + // Render directly, using no cache. if (cacheMode == QGraphicsItem::NoCache #ifdef Q_WS_X11 @@ -5011,6 +5033,63 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte } } +// FIXME: merge this with drawItems (needs refactoring) +QPixmap* QGraphicsScene::drawItemOnPixmap(QPainter *painter, + QGraphicsItem *item, + const QStyleOptionGraphicsItem *option, + QWidget *widget, + int flags) +{ + // TODO: use for choosing item or device coordinate + // FIXME: how about source, dest, and exposed rects? + Q_UNUSED(flags); + + // Item's (local) bounding rect, including the effect + QRectF brect = item->effectiveBoundingRect(); + QRectF adjustedBrect(brect); + _q_adjustRect(&adjustedBrect); + if (adjustedBrect.isEmpty()) + return 0; + + // Find the item's bounds in device coordinates. + QRectF deviceBounds = painter->worldTransform().mapRect(brect); + QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); + if (deviceRect.isEmpty()) + return 0; + + // If widget, check if it intersects or not + QRect viewRect = widget ? widget->rect() : QRect(); + if (widget && !viewRect.intersects(deviceRect)) + return 0; + + // Create offscreen pixmap + // TODO: use the pixmap from the layer + QPixmap *targetPixmap = item->effectPixmap(); + if (!targetPixmap) + targetPixmap = new QPixmap(deviceRect.size()); + + // FIXME: this is brute force + QRegion pixmapExposed; + pixmapExposed += targetPixmap->rect(); + + // Construct an item-to-pixmap transform. + QPointF p = deviceRect.topLeft(); + QTransform itemToPixmap = painter->worldTransform(); + if (!p.isNull()) + itemToPixmap *= QTransform::fromTranslate(-p.x(), -p.y()); + + // Calculate the style option's exposedRect. + QStyleOptionGraphicsItem fxOption = *option; + fxOption.exposedRect = brect.adjusted(-1, -1, 1, 1); + + // Render + _q_paintIntoCache(targetPixmap, item, pixmapExposed, itemToPixmap, painter->renderHints(), + &fxOption, false); + + return targetPixmap; +} + + /*! Paints the given \a items using the provided \a painter, after the background has been drawn, and before the foreground has been @@ -5278,10 +5357,10 @@ void QGraphicsScene::itemUpdated(QGraphicsItem *item, const QRectF &rect) // This block of code is kept for compatibility. Since 4.5, by default // QGraphicsView does not connect the signal and we use the below // method of delivering updates. - update(item->sceneBoundingRect()); + update(item->sceneEffectiveBoundingRect()); } else { // ### Remove _q_adjustedRects(). - QRectF boundingRect(adjustedItemBoundingRect(item)); + QRectF boundingRect(adjustedItemEffectiveBoundingRect(item)); if (!rect.isNull()) { QRectF adjustedRect(rect); _q_adjustRect(&adjustedRect); diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index 9802f87..c463736 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -262,6 +262,11 @@ protected: const QStyleOptionGraphicsItem options[], QWidget *widget = 0); + QPixmap* drawItemOnPixmap(QPainter *painter, QGraphicsItem *item, + const QStyleOptionGraphicsItem *option, QWidget *widget, int flags); + + + protected Q_SLOTS: bool focusNextPrevChild(bool next); @@ -288,6 +293,7 @@ private: friend class QGraphicsViewPrivate; friend class QGraphicsWidget; friend class QGraphicsWidgetPrivate; + friend class QGraphicsEffect; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsScene::SceneLayers) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 10b837a..9ad7249 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -803,6 +803,16 @@ static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item) boundingRect.adjust(0, -0.00001, 0, 0.00001); return boundingRect; } +static inline QRectF adjustedItemEffectiveBoundingRect(const QGraphicsItem *item) +{ + Q_ASSERT(item); + QRectF boundingRect(item->effectiveBoundingRect()); + if (!boundingRect.width()) + boundingRect.adjust(-0.00001, 0, 0.00001, 0); + if (!boundingRect.height()) + boundingRect.adjust(0, -0.00001, 0, 0.00001); + return boundingRect; +} /*! \internal @@ -811,12 +821,19 @@ void QGraphicsViewPrivate::itemUpdated(QGraphicsItem *item, const QRectF &rect) { if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate) return; + + // Delayed update can work only if the item has no effect. + // Reason: imagine the effect extends the effective (painting) bounding + // rect outside the item's bounding rect. If the item is moved around, + // delayed update only take into account the effective bounding rect + // of the new position, not the old one, thereby leaving painting trails. + if (!item->d_ptr->hasEffect) if (item->d_ptr->dirty) updateLater(); QRectF updateRect = rect; if ((item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) || item->d_ptr->children.isEmpty()) { - updateRect &= adjustedItemBoundingRect(item); + updateRect &= adjustedItemEffectiveBoundingRect(item); if (updateRect.isEmpty()) return; } @@ -874,7 +891,7 @@ void QGraphicsViewPrivate::_q_updateLaterSlot() continue; } QTransform x = item->sceneTransform() * viewTransform; - updateRect(x.mapRect(item->boundingRect()).toAlignedRect() & vr); + updateRect(x.mapRect(item->effectiveBoundingRect()).toAlignedRect() & vr); } dirtyRectCount += dirtyRects.size(); -- cgit v0.12 From 8353f8b91246024563403d5cf416964fff414f46 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Tue, 2 Jun 2009 14:44:05 +0200 Subject: First example using QGraphicsEffect class: drop shadows on items. The shadow is casted from a moving light source. The shadow offset for each item is different, depending on the relative position of the item to the light source. The same goes for the shadow opacity. --- examples/graphicsview/graphicsview.pro | 1 + examples/graphicsview/lighting/lighting.cpp | 126 ++++++++++++++++++++++++ examples/graphicsview/lighting/lighting.h | 72 ++++++++++++++ examples/graphicsview/lighting/lighting.pro | 8 ++ examples/graphicsview/lighting/main.cpp | 55 +++++++++++ examples/graphicsview/lighting/shadoweffect.cpp | 75 ++++++++++++++ examples/graphicsview/lighting/shadoweffect.h | 66 +++++++++++++ 7 files changed, 403 insertions(+) create mode 100644 examples/graphicsview/lighting/lighting.cpp create mode 100644 examples/graphicsview/lighting/lighting.h create mode 100644 examples/graphicsview/lighting/lighting.pro create mode 100644 examples/graphicsview/lighting/main.cpp create mode 100644 examples/graphicsview/lighting/shadoweffect.cpp create mode 100644 examples/graphicsview/lighting/shadoweffect.h diff --git a/examples/graphicsview/graphicsview.pro b/examples/graphicsview/graphicsview.pro index 66eb0b4..7e372fa 100644 --- a/examples/graphicsview/graphicsview.pro +++ b/examples/graphicsview/graphicsview.pro @@ -6,6 +6,7 @@ SUBDIRS = \ diagramscene \ dragdroprobot \ padnavigator \ + lighting \ basicgraphicslayouts contains(QT_CONFIG, qt3support):SUBDIRS += portedcanvas portedasteroids diff --git a/examples/graphicsview/lighting/lighting.cpp b/examples/graphicsview/lighting/lighting.cpp new file mode 100644 index 0000000..f92e428 --- /dev/null +++ b/examples/graphicsview/lighting/lighting.cpp @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "lighting.h" + +#include + +#include "shadoweffect.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +Lighting::Lighting(QWidget *parent): QGraphicsView(parent), angle(0.0) +{ + setScene(&m_scene); + + setupScene(); + + QTimer *timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), SLOT(animate())); + timer->setInterval(30); + timer->start(); + + setRenderHint(QPainter::Antialiasing, true); + setFrameStyle(QFrame::NoFrame); +} + +Lighting::~Lighting() +{ + delete m_shadowEffect; +} + +void Lighting::setupScene() +{ + m_scene.setSceneRect(-300, -200, 600, 460); + + QLinearGradient linearGrad(QPointF(-100, -100), QPointF(100, 100)); + linearGrad.setColorAt(0, QColor(255, 255, 255)); + linearGrad.setColorAt(1, QColor(192, 192, 255)); + setBackgroundBrush(linearGrad); + + QRadialGradient radialGrad(30, 30, 30); + radialGrad.setColorAt(0, Qt::yellow); + radialGrad.setColorAt(0.2, Qt::yellow); + radialGrad.setColorAt(1, Qt::transparent); + QPixmap pixmap(60, 60); + pixmap.fill(Qt::transparent); + QPainter painter(&pixmap); + painter.setPen(Qt::NoPen); + painter.setBrush(radialGrad); + painter.drawEllipse(0, 0, 60, 60); + painter.end(); + + m_lightSource = m_scene.addPixmap(pixmap); + m_lightSource->setZValue(2); + + m_shadowEffect = new ShadowEffect(m_lightSource); + + for (int i = -2; i < 3; ++i) + for (int j = -2; j < 3; ++j) { + QAbstractGraphicsShapeItem *item; + if ((i + j) & 1) + item = new QGraphicsEllipseItem(0, 0, 50, 50); + else + item = new QGraphicsRectItem(0, 0, 50, 50); + + item->setPen(QPen(Qt::black)); + item->setBrush(QBrush(Qt::white)); + item->setEffect(m_shadowEffect); + item->setZValue(1); + item->setPos(i * 80, j * 80); + m_scene.addItem(item); + m_items << item; + } + + +} + +void Lighting::animate() +{ + angle += (M_PI / 30); + qreal xs = 200 * sin(angle) - 40 + 25; + qreal ys = 200 * cos(angle) - 40 + 25; + m_lightSource->setPos(xs, ys); + m_scene.update(); +} + diff --git a/examples/graphicsview/lighting/lighting.h b/examples/graphicsview/lighting/lighting.h new file mode 100644 index 0000000..0334d10 --- /dev/null +++ b/examples/graphicsview/lighting/lighting.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LIGHTING_H +#define LIGHTING_H + +#include +#include + +#include "shadoweffect.h" + +class Lighting: public QGraphicsView +{ + Q_OBJECT + +public: + Lighting(QWidget *parent = 0); + ~Lighting(); + +private slots: + void animate(); + +private: + void setupScene(); + +private: + qreal angle; + QGraphicsScene m_scene; + QGraphicsItem *m_lightSource; + ShadowEffect *m_shadowEffect; + QList m_items; +}; + +#endif // LIGHTING_H diff --git a/examples/graphicsview/lighting/lighting.pro b/examples/graphicsview/lighting/lighting.pro new file mode 100644 index 0000000..440bb53 --- /dev/null +++ b/examples/graphicsview/lighting/lighting.pro @@ -0,0 +1,8 @@ +SOURCES += main.cpp lighting.cpp shadoweffect.cpp +HEADERS += lighting.h shadoweffect.h + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/graphicsview/lighting +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS lighting.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/graphicsview/lighting +INSTALLS += target sources diff --git a/examples/graphicsview/lighting/main.cpp b/examples/graphicsview/lighting/main.cpp new file mode 100644 index 0000000..07415f6 --- /dev/null +++ b/examples/graphicsview/lighting/main.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "lighting.h" +#include + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + Lighting lighting; + lighting.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Lighting and Shadows")); + lighting.resize(640, 480); + lighting.show(); + + return app.exec(); +} diff --git a/examples/graphicsview/lighting/shadoweffect.cpp b/examples/graphicsview/lighting/shadoweffect.cpp new file mode 100644 index 0000000..c1d384a --- /dev/null +++ b/examples/graphicsview/lighting/shadoweffect.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "shadoweffect.h" + +#include + +ShadowEffect::ShadowEffect(QGraphicsItem *source) + : QGraphicsShadowEffect() + , m_lightSource(source) +{ + setBlurRadius(8); +} + +void ShadowEffect::adjustForItem(const QGraphicsItem *item) +{ + QPointF delta = item->pos() - m_lightSource->pos(); + setShadowOffset(delta.toPoint() / 30); + + qreal dx = delta.x(); + qreal dy = delta.y(); + qreal dd = sqrt(dx * dx + dy * dy); + setOpacity(qBound(0.4, 1 - dd / 200.0, 0.7)); +} + +QRectF ShadowEffect::boundingRectFor(const QGraphicsItem *item) +{ + adjustForItem(item); + return QGraphicsShadowEffect::boundingRectFor(item); +} + +void ShadowEffect::drawItem(QGraphicsItem *item, QPainter *painter, + const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + adjustForItem(item); + QGraphicsShadowEffect::drawItem(item, painter, option, widget); +} diff --git a/examples/graphicsview/lighting/shadoweffect.h b/examples/graphicsview/lighting/shadoweffect.h new file mode 100644 index 0000000..09b63e3 --- /dev/null +++ b/examples/graphicsview/lighting/shadoweffect.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SHADOWEFFECT_H +#define SHADOWEFFECT_H + +#include +#include + +class ShadowEffect: public QGraphicsShadowEffect +{ +public: + ShadowEffect(QGraphicsItem *source); + + QRectF boundingRectFor(const QGraphicsItem *item); + + void drawItem(QGraphicsItem *item, QPainter *painter, + const QStyleOptionGraphicsItem *option = 0, + QWidget *widget = 0); + +private: + void adjustForItem(const QGraphicsItem *item); + +private: + QGraphicsItem *m_lightSource; +}; + +#endif // SHADOWEFFECT_H -- cgit v0.12 From 295c3927eb236483e6fd2e59f7588f35baa75ea2 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Tue, 2 Jun 2009 14:53:22 +0200 Subject: Another QGraphicsEffect example: application chooser with blur effect. Use left and right arrow to rotate the icons wheel. The blur effect is applied to each icon, the farthest icon becomes the most blurry one. --- examples/graphicsview/blurpicker/images/README.txt | 5 +++++ .../blurpicker/images/accessories-calculator.png | Bin 0 -> 3760 bytes .../blurpicker/images/accessories-text-editor.png | Bin 0 -> 4746 bytes examples/graphicsview/blurpicker/images/background.jpg | Bin 0 -> 16259 bytes .../graphicsview/blurpicker/images/help-browser.png | Bin 0 -> 5392 bytes .../blurpicker/images/internet-group-chat.png | Bin 0 -> 2809 bytes .../graphicsview/blurpicker/images/internet-mail.png | Bin 0 -> 3899 bytes .../blurpicker/images/internet-web-browser.png | Bin 0 -> 6376 bytes .../graphicsview/blurpicker/images/office-calendar.png | Bin 0 -> 4010 bytes .../graphicsview/blurpicker/images/system-users.png | Bin 0 -> 5353 bytes examples/graphicsview/graphicsview.pro | 1 + 11 files changed, 6 insertions(+) create mode 100644 examples/graphicsview/blurpicker/images/README.txt create mode 100644 examples/graphicsview/blurpicker/images/accessories-calculator.png create mode 100644 examples/graphicsview/blurpicker/images/accessories-text-editor.png create mode 100644 examples/graphicsview/blurpicker/images/background.jpg create mode 100644 examples/graphicsview/blurpicker/images/help-browser.png create mode 100644 examples/graphicsview/blurpicker/images/internet-group-chat.png create mode 100644 examples/graphicsview/blurpicker/images/internet-mail.png create mode 100644 examples/graphicsview/blurpicker/images/internet-web-browser.png create mode 100644 examples/graphicsview/blurpicker/images/office-calendar.png create mode 100644 examples/graphicsview/blurpicker/images/system-users.png diff --git a/examples/graphicsview/blurpicker/images/README.txt b/examples/graphicsview/blurpicker/images/README.txt new file mode 100644 index 0000000..0927e17 --- /dev/null +++ b/examples/graphicsview/blurpicker/images/README.txt @@ -0,0 +1,5 @@ +The background is taken from a public domain photo at: +http://www.photos8.com/view/computer_board2-800x600.html + +All other icons are from the Tango Desktop project: +http://tango.freedesktop.org/Tango_Desktop_Project diff --git a/examples/graphicsview/blurpicker/images/accessories-calculator.png b/examples/graphicsview/blurpicker/images/accessories-calculator.png new file mode 100644 index 0000000..4e7661f Binary files /dev/null and b/examples/graphicsview/blurpicker/images/accessories-calculator.png differ diff --git a/examples/graphicsview/blurpicker/images/accessories-text-editor.png b/examples/graphicsview/blurpicker/images/accessories-text-editor.png new file mode 100644 index 0000000..33bef0b Binary files /dev/null and b/examples/graphicsview/blurpicker/images/accessories-text-editor.png differ diff --git a/examples/graphicsview/blurpicker/images/background.jpg b/examples/graphicsview/blurpicker/images/background.jpg new file mode 100644 index 0000000..e75b388 Binary files /dev/null and b/examples/graphicsview/blurpicker/images/background.jpg differ diff --git a/examples/graphicsview/blurpicker/images/help-browser.png b/examples/graphicsview/blurpicker/images/help-browser.png new file mode 100644 index 0000000..8ef4fae Binary files /dev/null and b/examples/graphicsview/blurpicker/images/help-browser.png differ diff --git a/examples/graphicsview/blurpicker/images/internet-group-chat.png b/examples/graphicsview/blurpicker/images/internet-group-chat.png new file mode 100644 index 0000000..dd92d93 Binary files /dev/null and b/examples/graphicsview/blurpicker/images/internet-group-chat.png differ diff --git a/examples/graphicsview/blurpicker/images/internet-mail.png b/examples/graphicsview/blurpicker/images/internet-mail.png new file mode 100644 index 0000000..7e6b93b Binary files /dev/null and b/examples/graphicsview/blurpicker/images/internet-mail.png differ diff --git a/examples/graphicsview/blurpicker/images/internet-web-browser.png b/examples/graphicsview/blurpicker/images/internet-web-browser.png new file mode 100644 index 0000000..a979a92 Binary files /dev/null and b/examples/graphicsview/blurpicker/images/internet-web-browser.png differ diff --git a/examples/graphicsview/blurpicker/images/office-calendar.png b/examples/graphicsview/blurpicker/images/office-calendar.png new file mode 100644 index 0000000..e095906 Binary files /dev/null and b/examples/graphicsview/blurpicker/images/office-calendar.png differ diff --git a/examples/graphicsview/blurpicker/images/system-users.png b/examples/graphicsview/blurpicker/images/system-users.png new file mode 100644 index 0000000..a7f630a Binary files /dev/null and b/examples/graphicsview/blurpicker/images/system-users.png differ diff --git a/examples/graphicsview/graphicsview.pro b/examples/graphicsview/graphicsview.pro index 7e372fa..185c856 100644 --- a/examples/graphicsview/graphicsview.pro +++ b/examples/graphicsview/graphicsview.pro @@ -7,6 +7,7 @@ SUBDIRS = \ dragdroprobot \ padnavigator \ lighting \ + blurpicker \ basicgraphicslayouts contains(QT_CONFIG, qt3support):SUBDIRS += portedcanvas portedasteroids -- cgit v0.12 From 9f35183f534f04144c5498ba73ef804e9ed3fb67 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Wed, 3 Jun 2009 15:48:41 +0200 Subject: Refactor: QGraphicsEffect is now a subclass of QObject. This effectively makes other effect classes as QObject, too. It will facilitate the use of signal-slot to handle e.g. the change in effect parameters and the property system for doing animated effect. --- src/gui/graphicsview/qgraphicseffect.cpp | 365 +++++++++++++++++++++++++++---- src/gui/graphicsview/qgraphicseffect.h | 111 +++++----- 2 files changed, 375 insertions(+), 101 deletions(-) diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index 1d0e485..a1519c4 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -48,7 +48,8 @@ #include #include -#include +#include +#include /* @@ -104,7 +105,18 @@ */ -QGraphicsEffect::QGraphicsEffect() +/*! + \internal +*/ +class QGraphicsEffectPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsEffect) +public: + QGraphicsEffectPrivate() {} +}; + +QGraphicsEffect::QGraphicsEffect(QObject *parent) + : QObject(*new QGraphicsEffectPrivate, parent) { } @@ -120,6 +132,13 @@ QRectF QGraphicsEffect::boundingRectFor(const QGraphicsItem *item) return item->boundingRect(); } +/*! \internal +*/ +QGraphicsEffect::QGraphicsEffect(QGraphicsEffectPrivate &dd, QObject *parent) + : QObject(dd, parent) +{ +} + // this helper function is only for subclasses of QGraphicsEffect // the implementation is trivial, but this allows us to keep // QGraphicsScene::drawItem() as a protected function @@ -132,20 +151,39 @@ QPixmap* QGraphicsEffect::drawItemOnPixmap(QPainter *painter, QGraphicsItem *ite return item->scene()->drawItemOnPixmap(painter, item, option, widget, flags); } -QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect(): QGraphicsEffect() +/*! + \internal +*/ +class QGraphicsGrayscaleEffectPrivate : public QGraphicsEffectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsGrayscaleEffect) +public: + QGraphicsGrayscaleEffectPrivate() { + filter = new QPixmapColorizeFilter; + filter->setColor(Qt::black); + } + + ~QGraphicsGrayscaleEffectPrivate() { + delete filter; + } + + QPixmapColorizeFilter *filter; +}; + +QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect(QObject *parent) + : QGraphicsEffect(*new QGraphicsGrayscaleEffectPrivate, parent) { - filter = new QPixmapColorizeFilter; - filter->setColor(Qt::black); } QGraphicsGrayscaleEffect::~QGraphicsGrayscaleEffect() { - delete filter; } void QGraphicsGrayscaleEffect::drawItem(QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { + Q_D(QGraphicsGrayscaleEffect); + // Find the item's bounds in device coordinates. QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect()); QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); @@ -159,33 +197,54 @@ void QGraphicsGrayscaleEffect::drawItem(QGraphicsItem *item, QPainter *painter, // Draw the pixmap with the filter using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - filter->draw(painter, deviceRect.topLeft(), *pixmap, pixmap->rect()); + d->filter->draw(painter, deviceRect.topLeft(), *pixmap, pixmap->rect()); painter->setWorldTransform(restoreTransform); } -QGraphicsColorizeEffect::QGraphicsColorizeEffect(): QGraphicsEffect() +/*! + \internal +*/ +class QGraphicsColorizeEffectPrivate : public QGraphicsEffectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsColorizeEffect) +public: + QGraphicsColorizeEffectPrivate() { + filter = new QPixmapColorizeFilter; + } + + ~QGraphicsColorizeEffectPrivate() { + delete filter; + } + + QPixmapColorizeFilter *filter; +}; + +QGraphicsColorizeEffect::QGraphicsColorizeEffect(QObject *parent) + : QGraphicsEffect(*new QGraphicsColorizeEffectPrivate, parent) { - filter = new QPixmapColorizeFilter; } QGraphicsColorizeEffect::~QGraphicsColorizeEffect() { - delete filter; } QColor QGraphicsColorizeEffect::color() const { - return filter->color(); + Q_D(const QGraphicsColorizeEffect); + return d->filter->color(); } void QGraphicsColorizeEffect::setColor(const QColor &c) { - filter->setColor(c); + Q_D(QGraphicsColorizeEffect); + d->filter->setColor(c); } void QGraphicsColorizeEffect::drawItem(QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { + Q_D(QGraphicsColorizeEffect); + // Find the item's bounds in device coordinates. QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect()); QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); @@ -199,11 +258,25 @@ void QGraphicsColorizeEffect::drawItem(QGraphicsItem *item, QPainter *painter, // Draw the pixmap with the filter using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - filter->draw(painter, deviceRect.topLeft(), *pixmap, pixmap->rect()); + d->filter->draw(painter, deviceRect.topLeft(), *pixmap, pixmap->rect()); painter->setWorldTransform(restoreTransform); } -QGraphicsPixelizeEffect::QGraphicsPixelizeEffect(): QGraphicsEffect(), size(2) +/*! + \internal +*/ +class QGraphicsPixelizeEffectPrivate : public QGraphicsEffectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsPixelizeEffect) +public: + QGraphicsPixelizeEffectPrivate() + : pixelSize(3) { } + + int pixelSize; +}; + +QGraphicsPixelizeEffect::QGraphicsPixelizeEffect(QObject *parent) + : QGraphicsEffect(*new QGraphicsPixelizeEffectPrivate, parent) { } @@ -211,9 +284,23 @@ QGraphicsPixelizeEffect::~QGraphicsPixelizeEffect() { } +int QGraphicsPixelizeEffect::pixelSize() const +{ + Q_D(const QGraphicsPixelizeEffect); + return d->pixelSize; +} + +void QGraphicsPixelizeEffect::setPixelSize(int size) +{ + Q_D(QGraphicsPixelizeEffect); + d->pixelSize = size; +} + void QGraphicsPixelizeEffect::drawItem(QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { + Q_D(QGraphicsPixelizeEffect); + // Find the item's bounds in device coordinates. QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect()); QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); @@ -226,18 +313,18 @@ void QGraphicsPixelizeEffect::drawItem(QGraphicsItem *item, QPainter *painter, // pixelize routine QImage img = pixmap->toImage().convertToFormat(QImage::Format_ARGB32); - if (size > 0) { + if (d->pixelSize > 0) { int width = img.width(); int height = img.height(); - for (int y = 0; y < height; y += size) { - int ys = qMin(height - 1, y + size / 2); + for (int y = 0; y < height; y += d->pixelSize) { + int ys = qMin(height - 1, y + d->pixelSize / 2); QRgb *sbuf = reinterpret_cast(img.scanLine(ys)); - for (int x = 0; x < width; x += size) { - int xs = qMin(width - 1, x + size / 2); + for (int x = 0; x < width; x += d->pixelSize) { + int xs = qMin(width - 1, x + d->pixelSize / 2); QRgb color = sbuf[xs]; - for (int yi = 0; yi < qMin(size, height - y); ++yi) { + for (int yi = 0; yi < qMin(d->pixelSize, height - y); ++yi) { QRgb *buf = reinterpret_cast(img.scanLine(y + yi)); - for (int xi = 0; xi < qMin(size, width - x); ++xi) + for (int xi = 0; xi < qMin(d->pixelSize, width - x); ++xi) buf[x + xi] = color; } } @@ -251,8 +338,21 @@ void QGraphicsPixelizeEffect::drawItem(QGraphicsItem *item, QPainter *painter, painter->setWorldTransform(restoreTransform); } +/*! + \internal +*/ +class QGraphicsBlurEffectPrivate : public QGraphicsEffectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsBlurEffect) +public: + QGraphicsBlurEffectPrivate() + : blurRadius(4) { } + + int blurRadius; +}; -QGraphicsBlurEffect::QGraphicsBlurEffect(): QGraphicsEffect(), radius(6) +QGraphicsBlurEffect::QGraphicsBlurEffect(QObject *parent) + : QGraphicsEffect(*new QGraphicsBlurEffectPrivate, parent) { } @@ -325,9 +425,22 @@ static QImage blurred(const QImage& image, const QRect& rect, int radius) return result; } +int QGraphicsBlurEffect::blurRadius() const +{ + Q_D(const QGraphicsBlurEffect); + return d->blurRadius; +} + +void QGraphicsBlurEffect::setBlurRadius(int radius) +{ + Q_D(QGraphicsBlurEffect); + d->blurRadius = radius; +} + QRectF QGraphicsBlurEffect::boundingRectFor(const QGraphicsItem *item) { - qreal delta = radius * 3; + Q_D(const QGraphicsBlurEffect); + qreal delta = d->blurRadius * 3; QRectF blurRect = item->boundingRect(); blurRect.adjust(-delta, -delta, delta, delta); return blurRect; @@ -336,6 +449,8 @@ QRectF QGraphicsBlurEffect::boundingRectFor(const QGraphicsItem *item) void QGraphicsBlurEffect::drawItem(QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { + Q_D(QGraphicsBlurEffect); + // Find the item's bounds in device coordinates. QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect()); QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); @@ -347,6 +462,7 @@ void QGraphicsBlurEffect::drawItem(QGraphicsItem *item, QPainter *painter, return; // blur routine + int radius = d->blurRadius; QImage img = pixmap->toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); img = blurred(img, img.rect(), radius); @@ -357,8 +473,23 @@ void QGraphicsBlurEffect::drawItem(QGraphicsItem *item, QPainter *painter, painter->setWorldTransform(restoreTransform); } +/*! + \internal +*/ +class QGraphicsBloomEffectPrivate : public QGraphicsEffectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsBlurEffect) +public: + QGraphicsBloomEffectPrivate() + : blurRadius(6) + , opacity(0.7) { } + + int blurRadius; + qreal opacity; +}; -QGraphicsBloomEffect::QGraphicsBloomEffect(): QGraphicsEffect(), radius(6), alpha(0.7) +QGraphicsBloomEffect::QGraphicsBloomEffect(QObject *parent) + : QGraphicsEffect(*new QGraphicsBloomEffectPrivate, parent) { } @@ -366,9 +497,34 @@ QGraphicsBloomEffect::~QGraphicsBloomEffect() { } +int QGraphicsBloomEffect::blurRadius() const +{ + Q_D(const QGraphicsBloomEffect); + return d->blurRadius; +} + +void QGraphicsBloomEffect::setBlurRadius(int radius) +{ + Q_D(QGraphicsBloomEffect); + d->blurRadius = radius; +} + +qreal QGraphicsBloomEffect::opacity() const +{ + Q_D(const QGraphicsBloomEffect); + return d->opacity; +} + +void QGraphicsBloomEffect::setOpacity(qreal alpha) +{ + Q_D(QGraphicsBloomEffect); + d->opacity = alpha; +} + QRectF QGraphicsBloomEffect::boundingRectFor(const QGraphicsItem *item) { - qreal delta = radius * 3; + Q_D(QGraphicsBloomEffect); + qreal delta = d->blurRadius * 3; QRectF blurRect = item->boundingRect(); blurRect.adjust(-delta, -delta, delta, delta); return blurRect; @@ -408,6 +564,8 @@ static QImage composited(const QImage& img1, const QImage& img2, qreal opacity, void QGraphicsBloomEffect::drawItem(QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { + Q_D(QGraphicsBloomEffect); + // Find the item's bounds in device coordinates. QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect()); QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); @@ -419,10 +577,11 @@ void QGraphicsBloomEffect::drawItem(QGraphicsItem *item, QPainter *painter, return; // bloom routine + int radius = d->blurRadius; QImage img = pixmap->toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); QImage overlay = blurred(img, img.rect(), radius); overlay = brightened(overlay, 70); - img = composited(img, overlay, alpha, QPainter::CompositionMode_Overlay); + img = composited(img, overlay, d->opacity, QPainter::CompositionMode_Overlay); // Draw using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); @@ -431,11 +590,27 @@ void QGraphicsBloomEffect::drawItem(QGraphicsItem *item, QPainter *painter, painter->setWorldTransform(restoreTransform); } -QGraphicsFrameEffect::QGraphicsFrameEffect() - : QGraphicsEffect() - , color(Qt::blue) - , width(5) - , alpha(0.6) +/*! + \internal +*/ +class QGraphicsFrameEffectPrivate : public QGraphicsEffectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsFrameEffect) +public: + QGraphicsFrameEffectPrivate() + : color(Qt::blue) + , width(5) + , alpha(0.6) + { + } + + QColor color; + qreal width; + qreal alpha; +}; + +QGraphicsFrameEffect::QGraphicsFrameEffect(QObject *parent) + : QGraphicsEffect(*new QGraphicsFrameEffectPrivate, parent) { } @@ -443,16 +618,55 @@ QGraphicsFrameEffect::~QGraphicsFrameEffect() { } +QColor QGraphicsFrameEffect::frameColor() const +{ + Q_D(const QGraphicsFrameEffect); + return d->color; +} + +void QGraphicsFrameEffect::setFrameColor(const QColor &c) +{ + Q_D(QGraphicsFrameEffect); + d->color = c; +} + +qreal QGraphicsFrameEffect::frameWidth() const +{ + Q_D(const QGraphicsFrameEffect); + return d->width; +} + +void QGraphicsFrameEffect::setFrameWidth(qreal frameWidth) +{ + Q_D(QGraphicsFrameEffect); + d->width = frameWidth; +} + +qreal QGraphicsFrameEffect::frameOpacity() const +{ + Q_D(const QGraphicsFrameEffect); + return d->alpha; +} + +void QGraphicsFrameEffect::setFrameOpacity(qreal opacity) +{ + Q_D(QGraphicsFrameEffect); + d->alpha = opacity; +} + QRectF QGraphicsFrameEffect::boundingRectFor(const QGraphicsItem *item) { + Q_D(QGraphicsFrameEffect); QRectF frameRect = item->boundingRect(); - frameRect.adjust(-width, -width, width, width); + frameRect.adjust(-d->width, -d->width, d->width, d->width); return frameRect; } void QGraphicsFrameEffect::drawItem(QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { + Q_D(QGraphicsFrameEffect); + // Find the item's bounds in device coordinates. QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect()); QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); @@ -464,15 +678,15 @@ void QGraphicsFrameEffect::drawItem(QGraphicsItem *item, QPainter *painter, return; QRectF frameRect = deviceBounds; - frameRect.adjust(-width, -width, width, width); + frameRect.adjust(-d->width, -d->width, d->width, d->width); painter->save(); painter->setWorldTransform(QTransform()); painter->save(); - painter->setOpacity(painter->opacity() * alpha); + painter->setOpacity(painter->opacity() * d->alpha); painter->setPen(Qt::NoPen); - painter->setBrush(color); + painter->setBrush(d->color); painter->drawRoundedRect(frameRect, 20, 20, Qt::RelativeSize); painter->restore(); @@ -482,11 +696,27 @@ void QGraphicsFrameEffect::drawItem(QGraphicsItem *item, QPainter *painter, } -QGraphicsShadowEffect::QGraphicsShadowEffect() - : QGraphicsEffect() - , offset(4,4) - , radius(8) - , alpha(0.7) +/*! + \internal +*/ +class QGraphicsShadowEffectPrivate : public QGraphicsEffectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsShadowEffect) +public: + QGraphicsShadowEffectPrivate() + : offset(4,4) + , radius(8) + , alpha(0.7) + { + } + + QPointF offset; + int radius; + qreal alpha; +}; + +QGraphicsShadowEffect::QGraphicsShadowEffect(QObject *parent) + : QGraphicsEffect(*new QGraphicsShadowEffectPrivate, parent) { } @@ -494,12 +724,49 @@ QGraphicsShadowEffect::~QGraphicsShadowEffect() { } +QPointF QGraphicsShadowEffect::shadowOffset() const +{ + Q_D(const QGraphicsShadowEffect); + return d->offset; +} + +void QGraphicsShadowEffect::setShadowOffset(const QPointF &ofs) +{ + Q_D(QGraphicsShadowEffect); + d->offset = ofs; +} + +int QGraphicsShadowEffect::blurRadius() const +{ + Q_D(const QGraphicsShadowEffect); + return d->radius; +} + +void QGraphicsShadowEffect::setBlurRadius(int blurRadius) +{ + Q_D(QGraphicsShadowEffect); + d->radius = blurRadius; +} + +qreal QGraphicsShadowEffect::opacity() const +{ + Q_D(const QGraphicsShadowEffect); + return d->alpha; +} + +void QGraphicsShadowEffect::setOpacity(qreal opacity) +{ + Q_D(QGraphicsShadowEffect); + d->alpha = opacity; +} + QRectF QGraphicsShadowEffect::boundingRectFor(const QGraphicsItem *item) { + Q_D(QGraphicsShadowEffect); QRectF shadowRect = item->boundingRect(); - shadowRect.adjust(offset.x(), offset.y(), offset.x(), offset.y()); + shadowRect.adjust(d->offset.x(), d->offset.y(), d->offset.x(), d->offset.y()); QRectF blurRect = shadowRect; - qreal delta = radius * 3; + qreal delta = d->radius * 3; blurRect.adjust(-delta, -delta, delta, delta); QRectF totalRect = blurRect.united(item->boundingRect()); return totalRect; @@ -508,6 +775,8 @@ QRectF QGraphicsShadowEffect::boundingRectFor(const QGraphicsItem *item) void QGraphicsShadowEffect::drawItem(QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { + Q_D(QGraphicsShadowEffect); + // Find the item's bounds in device coordinates. QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect()); QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); @@ -515,9 +784,9 @@ void QGraphicsShadowEffect::drawItem(QGraphicsItem *item, QPainter *painter, return; QRectF shadowRect = deviceBounds; - shadowRect.adjust(offset.x(), offset.y(), offset.x(), offset.y()); + shadowRect.adjust(d->offset.x(), d->offset.y(), d->offset.x(), d->offset.y()); QRectF blurRect = shadowRect; - qreal delta = radius * 3; + qreal delta = d->radius * 3; blurRect.adjust(-delta, -delta, delta, delta); QRectF totalRect = blurRect.united(deviceRect); @@ -527,9 +796,9 @@ void QGraphicsShadowEffect::drawItem(QGraphicsItem *item, QPainter *painter, QImage img = pixmap->toImage(); QImage shadowImage(img.size(), QImage::Format_ARGB32); - shadowImage.fill(qRgba(0, 0, 0, alpha * 255)); + shadowImage.fill(qRgba(0, 0, 0, d->alpha * 255)); shadowImage.setAlphaChannel(img.alphaChannel()); - shadowImage = blurred(shadowImage, shadowImage.rect(), radius); + shadowImage = blurred(shadowImage, shadowImage.rect(), d->radius); // Draw using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); @@ -540,9 +809,9 @@ void QGraphicsShadowEffect::drawItem(QGraphicsItem *item, QPainter *painter, qreal shadowx = blurRect.x() + delta; qreal shadowy = blurRect.y() + delta; if (blurRect.x() < deviceRect.x()) - shadowx = blurRect.x() + offset.x(); + shadowx = blurRect.x() + d->offset.x(); if (blurRect.y() < deviceRect.y()) - shadowy = blurRect.y() + offset.y(); + shadowy = blurRect.y() + d->offset.y(); painter->drawImage(shadowx, shadowy, shadowImage); qreal itemx = qMin(blurRect.x(), deviceBounds.x()); diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h index 9f6fb07..f15b172 100644 --- a/src/gui/graphicsview/qgraphicseffect.h +++ b/src/gui/graphicsview/qgraphicseffect.h @@ -42,6 +42,7 @@ #ifndef QGRAPHICSEFFECT_H #define QGRAPHICSEFFECT_H +#include #include #include #include @@ -62,10 +63,12 @@ QT_MODULE(Gui) #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW -class Q_GUI_EXPORT QGraphicsEffect { +class QGraphicsEffectPrivate; +class Q_GUI_EXPORT QGraphicsEffect : public QObject +{ public: - QGraphicsEffect(); + QGraphicsEffect(QObject *parent = 0); virtual ~QGraphicsEffect(); virtual QRectF boundingRectFor(const QGraphicsItem *item); @@ -75,17 +78,21 @@ public: QWidget *widget = 0) = 0; protected: + QGraphicsEffect(QGraphicsEffectPrivate &d, QObject* parent); QPixmap* drawItemOnPixmap(QPainter *painter, QGraphicsItem *item, const QStyleOptionGraphicsItem *option, QWidget *widget, int flags); private: - Q_DISABLE_COPY(QGraphicsEffect); + Q_DECLARE_PRIVATE(QGraphicsEffect) + Q_DISABLE_COPY(QGraphicsEffect) }; -class Q_GUI_EXPORT QGraphicsGrayscaleEffect: public QGraphicsEffect { +class QGraphicsGrayscaleEffectPrivate; +class Q_GUI_EXPORT QGraphicsGrayscaleEffect: public QGraphicsEffect +{ public: - QGraphicsGrayscaleEffect(); + QGraphicsGrayscaleEffect(QObject *parent = 0); ~QGraphicsGrayscaleEffect(); void drawItem(QGraphicsItem *item, QPainter *painter, @@ -93,14 +100,15 @@ public: QWidget *widget = 0); private: - QPixmapColorizeFilter *filter; - Q_DISABLE_COPY(QGraphicsGrayscaleEffect); + Q_DECLARE_PRIVATE(QGraphicsGrayscaleEffect) + Q_DISABLE_COPY(QGraphicsGrayscaleEffect) }; +class QGraphicsColorizeEffectPrivate; class Q_GUI_EXPORT QGraphicsColorizeEffect: public QGraphicsEffect { public: - QGraphicsColorizeEffect(); + QGraphicsColorizeEffect(QObject *parent = 0); ~QGraphicsColorizeEffect(); QColor color() const; @@ -111,36 +119,38 @@ public: QWidget *widget = 0); private: - QPixmapColorizeFilter *filter; - Q_DISABLE_COPY(QGraphicsColorizeEffect); + Q_DECLARE_PRIVATE(QGraphicsColorizeEffect) + Q_DISABLE_COPY(QGraphicsColorizeEffect) }; +class QGraphicsPixelizeEffectPrivate; class Q_GUI_EXPORT QGraphicsPixelizeEffect: public QGraphicsEffect { public: - QGraphicsPixelizeEffect(); + QGraphicsPixelizeEffect(QObject *parent = 0); ~QGraphicsPixelizeEffect(); - int pixelSize() const { return size; } - void setPixelSize(int pixelSize) { size = pixelSize; } + int pixelSize() const; + void setPixelSize(int pixelSize); void drawItem(QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option = 0, QWidget *widget = 0); private: - int size; - Q_DISABLE_COPY(QGraphicsPixelizeEffect); + Q_DECLARE_PRIVATE(QGraphicsPixelizeEffect) + Q_DISABLE_COPY(QGraphicsPixelizeEffect) }; +class QGraphicsBlurEffectPrivate; class Q_GUI_EXPORT QGraphicsBlurEffect: public QGraphicsEffect { public: - QGraphicsBlurEffect(); + QGraphicsBlurEffect(QObject *parent = 0); ~QGraphicsBlurEffect(); - int blurRadius() const { return radius; } - void setBlurRadius(int blurRadius) { radius = blurRadius; } + int blurRadius() const; + void setBlurRadius(int blurRadius); QRectF boundingRectFor(const QGraphicsItem *item); @@ -149,49 +159,49 @@ public: QWidget *widget = 0); private: - int radius; - Q_DISABLE_COPY(QGraphicsBlurEffect); + Q_DECLARE_PRIVATE(QGraphicsBlurEffect) + Q_DISABLE_COPY(QGraphicsBlurEffect) }; +class QGraphicsBloomEffectPrivate; class Q_GUI_EXPORT QGraphicsBloomEffect: public QGraphicsEffect { public: - QGraphicsBloomEffect(); + QGraphicsBloomEffect(QObject *parent = 0); ~QGraphicsBloomEffect(); - int blurRadius() const { return radius; } - void setBlurRadius(int blurRadius) { radius = blurRadius; } + int blurRadius() const; + void setBlurRadius(int blurRadius); - QRectF boundingRectFor(const QGraphicsItem *item); + qreal opacity() const; + void setOpacity(qreal opacity); - qreal opacity() const { return alpha; } - void setOpacity(qreal opacity) { alpha = opacity; } + QRectF boundingRectFor(const QGraphicsItem *item); void drawItem(QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option = 0, QWidget *widget = 0); private: - int radius; - qreal alpha; - Q_DISABLE_COPY(QGraphicsBloomEffect); + Q_DECLARE_PRIVATE(QGraphicsBloomEffect) + Q_DISABLE_COPY(QGraphicsBloomEffect) }; +class QGraphicsFrameEffectPrivate; class Q_GUI_EXPORT QGraphicsFrameEffect: public QGraphicsEffect { public: - QGraphicsFrameEffect(); + QGraphicsFrameEffect(QObject *parent = 0); ~QGraphicsFrameEffect(); - QColor frameColor() const { return color; } - void setFrameColor(const QColor &c) { color = c; } - - qreal frameWidth() const { return width; } - void setFrameWidth(qreal frameWidth) { width = frameWidth; } + QColor frameColor() const; + void setFrameColor(const QColor &c); - qreal frameOpacity() const { return alpha; } - void setFrameOpacity(qreal opacity) { alpha = opacity; } + qreal frameWidth() const; + void setFrameWidth(qreal frameWidth); + qreal frameOpacity() const; + void setFrameOpacity(qreal opacity); QRectF boundingRectFor(const QGraphicsItem *item); @@ -199,28 +209,27 @@ public: const QStyleOptionGraphicsItem *option = 0, QWidget *widget = 0); private: - QColor color; - qreal width; - qreal alpha; - Q_DISABLE_COPY(QGraphicsFrameEffect); + Q_DECLARE_PRIVATE(QGraphicsFrameEffect) + Q_DISABLE_COPY(QGraphicsFrameEffect) }; +class QGraphicsShadowEffectPrivate; class Q_GUI_EXPORT QGraphicsShadowEffect: public QGraphicsEffect { public: - QGraphicsShadowEffect(); + QGraphicsShadowEffect(QObject *parent = 0); ~QGraphicsShadowEffect(); QPointF shadowOffset() const; - void setShadowOffset(const QPointF &ofs) { offset = ofs; } + void setShadowOffset(const QPointF &ofs); inline void setShadowOffset(qreal dx, qreal dy) { setShadowOffset(QPointF(dx, dy)); } inline void setShadowOffset(qreal d) { setShadowOffset(QPointF(d, d)); } - int blurRadius() const { return radius; } - void setBlurRadius(int blurRadius) { radius = blurRadius; } + int blurRadius() const; + void setBlurRadius(int blurRadius); - qreal opacity() const { return alpha; } - void setOpacity(qreal opacity) { alpha = opacity; } + qreal opacity() const; + void setOpacity(qreal opacity); QRectF boundingRectFor(const QGraphicsItem *item); @@ -229,16 +238,12 @@ public: QWidget *widget = 0); protected: - QPointF offset; - int radius; - qreal alpha; private: - Q_DISABLE_COPY(QGraphicsShadowEffect); + Q_DECLARE_PRIVATE(QGraphicsShadowEffect) + Q_DISABLE_COPY(QGraphicsShadowEffect) }; - - Q_DECLARE_METATYPE(QGraphicsEffect *) Q_DECLARE_METATYPE(QGraphicsGrayscaleEffect *) Q_DECLARE_METATYPE(QGraphicsColorizeEffect *) -- cgit v0.12 From 655f64cd697f3883889d1d77f2545bec0faee8d3 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Wed, 3 Jun 2009 16:05:54 +0200 Subject: Simplify the examples, since effect is a QObject now. --- examples/graphicsview/lighting/lighting.cpp | 7 +------ examples/graphicsview/lighting/lighting.h | 1 - examples/graphicsview/lighting/shadoweffect.cpp | 4 ++-- examples/graphicsview/lighting/shadoweffect.h | 2 +- 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/examples/graphicsview/lighting/lighting.cpp b/examples/graphicsview/lighting/lighting.cpp index f92e428..445d7f9 100644 --- a/examples/graphicsview/lighting/lighting.cpp +++ b/examples/graphicsview/lighting/lighting.cpp @@ -64,11 +64,6 @@ Lighting::Lighting(QWidget *parent): QGraphicsView(parent), angle(0.0) setFrameStyle(QFrame::NoFrame); } -Lighting::~Lighting() -{ - delete m_shadowEffect; -} - void Lighting::setupScene() { m_scene.setSceneRect(-300, -200, 600, 460); @@ -93,7 +88,7 @@ void Lighting::setupScene() m_lightSource = m_scene.addPixmap(pixmap); m_lightSource->setZValue(2); - m_shadowEffect = new ShadowEffect(m_lightSource); + m_shadowEffect = new ShadowEffect(m_lightSource, this); for (int i = -2; i < 3; ++i) for (int j = -2; j < 3; ++j) { diff --git a/examples/graphicsview/lighting/lighting.h b/examples/graphicsview/lighting/lighting.h index 0334d10..66237f6 100644 --- a/examples/graphicsview/lighting/lighting.h +++ b/examples/graphicsview/lighting/lighting.h @@ -53,7 +53,6 @@ class Lighting: public QGraphicsView public: Lighting(QWidget *parent = 0); - ~Lighting(); private slots: void animate(); diff --git a/examples/graphicsview/lighting/shadoweffect.cpp b/examples/graphicsview/lighting/shadoweffect.cpp index c1d384a..726cbd0 100644 --- a/examples/graphicsview/lighting/shadoweffect.cpp +++ b/examples/graphicsview/lighting/shadoweffect.cpp @@ -43,8 +43,8 @@ #include -ShadowEffect::ShadowEffect(QGraphicsItem *source) - : QGraphicsShadowEffect() +ShadowEffect::ShadowEffect(QGraphicsItem *source, QObject *parent) + : QGraphicsShadowEffect(parent) , m_lightSource(source) { setBlurRadius(8); diff --git a/examples/graphicsview/lighting/shadoweffect.h b/examples/graphicsview/lighting/shadoweffect.h index 09b63e3..02d0bf1 100644 --- a/examples/graphicsview/lighting/shadoweffect.h +++ b/examples/graphicsview/lighting/shadoweffect.h @@ -48,7 +48,7 @@ class ShadowEffect: public QGraphicsShadowEffect { public: - ShadowEffect(QGraphicsItem *source); + ShadowEffect(QGraphicsItem *source, QObject *parent = 0); QRectF boundingRectFor(const QGraphicsItem *item); -- cgit v0.12 From 29fc0074cf30a466be732246500d5312d2920784 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Wed, 3 Jun 2009 19:14:58 +0200 Subject: Source files for the blur picker example. This should be in 295c3927eb236483e6fd2e59f7588f35baa75ea2, but I forgot them. --- examples/graphicsview/blurpicker/blureffect.cpp | 70 +++++++++++ examples/graphicsview/blurpicker/blureffect.h | 68 +++++++++++ examples/graphicsview/blurpicker/blurpicker.cpp | 148 ++++++++++++++++++++++++ examples/graphicsview/blurpicker/blurpicker.h | 76 ++++++++++++ examples/graphicsview/blurpicker/blurpicker.pro | 9 ++ examples/graphicsview/blurpicker/blurpicker.qrc | 14 +++ examples/graphicsview/blurpicker/main.cpp | 55 +++++++++ 7 files changed, 440 insertions(+) create mode 100644 examples/graphicsview/blurpicker/blureffect.cpp create mode 100644 examples/graphicsview/blurpicker/blureffect.h create mode 100644 examples/graphicsview/blurpicker/blurpicker.cpp create mode 100644 examples/graphicsview/blurpicker/blurpicker.h create mode 100644 examples/graphicsview/blurpicker/blurpicker.pro create mode 100644 examples/graphicsview/blurpicker/blurpicker.qrc create mode 100644 examples/graphicsview/blurpicker/main.cpp diff --git a/examples/graphicsview/blurpicker/blureffect.cpp b/examples/graphicsview/blurpicker/blureffect.cpp new file mode 100644 index 0000000..8345d0b --- /dev/null +++ b/examples/graphicsview/blurpicker/blureffect.cpp @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "blureffect.h" + +#include + +BlurEffect::BlurEffect(QObject *parent) + : QGraphicsBlurEffect() + , m_baseLine(200) +{ +} + +void BlurEffect::adjustForItem(const QGraphicsItem *item) +{ + qreal y = m_baseLine - item->pos().y(); + qreal radius = qBound(0.0, y / 32, 16.0); + setBlurRadius(radius); +} + +QRectF BlurEffect::boundingRectFor(const QGraphicsItem *item) +{ + adjustForItem(item); + return QGraphicsBlurEffect::boundingRectFor(item); +} + +void BlurEffect::drawItem(QGraphicsItem *item, QPainter *painter, + const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + adjustForItem(item); + QGraphicsBlurEffect::drawItem(item, painter, option, widget); +} diff --git a/examples/graphicsview/blurpicker/blureffect.h b/examples/graphicsview/blurpicker/blureffect.h new file mode 100644 index 0000000..24a6867 --- /dev/null +++ b/examples/graphicsview/blurpicker/blureffect.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BLUREFFECT_H +#define BLUREFFECT_H + +#include +#include + +class BlurEffect: public QGraphicsBlurEffect +{ +public: + BlurEffect(QObject *parent = 0); + + void setBaseLine(qreal y) { m_baseLine = y; } + + QRectF boundingRectFor(const QGraphicsItem *item); + + void drawItem(QGraphicsItem *item, QPainter *painter, + const QStyleOptionGraphicsItem *option = 0, + QWidget *widget = 0); + +private: + void adjustForItem(const QGraphicsItem *item); + +private: + qreal m_baseLine; +}; + +#endif // BLUREFFECT_H diff --git a/examples/graphicsview/blurpicker/blurpicker.cpp b/examples/graphicsview/blurpicker/blurpicker.cpp new file mode 100644 index 0000000..cfc2d67 --- /dev/null +++ b/examples/graphicsview/blurpicker/blurpicker.cpp @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "blurpicker.h" + +#include + +#include "blureffect.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +BlurPicker::BlurPicker(QWidget *parent): QGraphicsView(parent), m_index(0.0) +{ + setBackgroundBrush(QPixmap(":/images/background.jpg")); + setScene(&m_scene); + + setupScene(); + updateIconPositions(); + + connect(&m_timeLine, SIGNAL(valueChanged(qreal)), SLOT(updateIconPositions())); + m_timeLine.setDuration(400); + + setRenderHint(QPainter::Antialiasing, true); + setFrameStyle(QFrame::NoFrame); +} + +BlurPicker::~BlurPicker() +{ +} + +void BlurPicker::updateIconPositions() +{ + m_index = m_timeLine.currentFrame() / 1000.0; + + qreal baseline = 0; + for (int i = 0; i < m_icons.count(); ++i) { + QGraphicsItem *icon = m_icons[i]; + qreal a = ((i + m_index) * 2 * M_PI) / m_icons.count(); + qreal xs = 170 * sin(a); + qreal ys = 100 * cos(a); + QPointF pos(xs, ys); + pos = QTransform().rotate(-20).map(pos); + pos -= QPointF(40, 40); + icon->setPos(pos); + baseline = qMax(baseline, ys); + } + +#if 0 + // seems broken + for (int i = 0; i < m_icons.count(); ++i) { + QGraphicsItem *icon = m_icons[i]; + qreal y = baseline - icon->pos().y(); + qreal factor = qBound(0.0, 1 - y / 600, 1.0); + icon->setTransform(QTransform().scale(factor, factor), false); + } +#endif + + m_blurEffect->setBaseLine(baseline); + m_scene.update(); +} + +void BlurPicker::setupScene() +{ + m_scene.setSceneRect(-200, -120, 400, 240); + + m_blurEffect = new BlurEffect(this); + + QStringList names; + names << ":/images/accessories-calculator.png"; + names << ":/images/accessories-text-editor.png"; + names << ":/images/help-browser.png"; + names << ":/images/internet-group-chat.png"; + names << ":/images/internet-mail.png"; + names << ":/images/internet-web-browser.png"; + names << ":/images/office-calendar.png"; + names << ":/images/system-users.png"; + + for (int i = 0; i < names.count(); i++) { + QPixmap pixmap(names[i]); + QGraphicsPixmapItem *icon = m_scene.addPixmap(pixmap); + icon->setZValue(1); + icon->setEffect(m_blurEffect); + m_icons << icon; + } + + QGraphicsPixmapItem *bg = m_scene.addPixmap(QPixmap(":/images/background.jpg")); + bg->setZValue(0); + bg->setPos(-200, -150); +} + +void BlurPicker::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_Left) { + if (m_timeLine.state() == QTimeLine::NotRunning) { + m_timeLine.setFrameRange(m_index * 1000, m_index * 1000 - 1000); + m_timeLine.start(); + event->accept(); + } + } + + if (event->key() == Qt::Key_Right) { + if (m_timeLine.state() == QTimeLine::NotRunning) { + m_timeLine.setFrameRange(m_index * 1000, m_index * 1000 + 1000); + m_timeLine.start(); + event->accept(); + } + } +} diff --git a/examples/graphicsview/blurpicker/blurpicker.h b/examples/graphicsview/blurpicker/blurpicker.h new file mode 100644 index 0000000..f97f220 --- /dev/null +++ b/examples/graphicsview/blurpicker/blurpicker.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BLURPICKER_H +#define BLURPICKER_H + +#include +#include +#include + +#include "blureffect.h" + +class BlurPicker: public QGraphicsView +{ + Q_OBJECT + +public: + BlurPicker(QWidget *parent = 0); + ~BlurPicker(); + +protected: + void keyPressEvent(QKeyEvent *event); + +private slots: + void updateIconPositions(); + +private: + void setupScene(); + +private: + qreal m_index; + QGraphicsScene m_scene; + BlurEffect *m_blurEffect; + QList m_icons; + QTimeLine m_timeLine; +}; + +#endif // BLURPICKER_H diff --git a/examples/graphicsview/blurpicker/blurpicker.pro b/examples/graphicsview/blurpicker/blurpicker.pro new file mode 100644 index 0000000..e42cc0f --- /dev/null +++ b/examples/graphicsview/blurpicker/blurpicker.pro @@ -0,0 +1,9 @@ +SOURCES += main.cpp blurpicker.cpp blureffect.cpp +HEADERS += blurpicker.h blureffect.h +RESOURCES += blurpicker.qrc + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/graphicsview/blurpicker +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS blurpicker.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/graphicsview/blurpicker +INSTALLS += target sources diff --git a/examples/graphicsview/blurpicker/blurpicker.qrc b/examples/graphicsview/blurpicker/blurpicker.qrc new file mode 100644 index 0000000..e88eaca --- /dev/null +++ b/examples/graphicsview/blurpicker/blurpicker.qrc @@ -0,0 +1,14 @@ + + + images/background.jpg + images/accessories-calculator.png + images/accessories-text-editor.png + images/help-browser.png + images/internet-group-chat.png + images/internet-mail.png + images/internet-web-browser.png + images/office-calendar.png + images/system-users.png + + + diff --git a/examples/graphicsview/blurpicker/main.cpp b/examples/graphicsview/blurpicker/main.cpp new file mode 100644 index 0000000..b88a51d --- /dev/null +++ b/examples/graphicsview/blurpicker/main.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "blurpicker.h" +#include + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + BlurPicker blurPicker; + blurPicker.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Application Picker")); + blurPicker.setFixedSize(400, 300); + blurPicker.show(); + + return app.exec(); +} -- cgit v0.12 From 4865dd2a0818d56adb108edb15944592c353c061 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Thu, 4 Jun 2009 20:01:17 +0200 Subject: Remove unused code in the blurpicker example. --- examples/graphicsview/blurpicker/blurpicker.cpp | 14 -------------- examples/graphicsview/blurpicker/blurpicker.h | 1 - 2 files changed, 15 deletions(-) diff --git a/examples/graphicsview/blurpicker/blurpicker.cpp b/examples/graphicsview/blurpicker/blurpicker.cpp index cfc2d67..887d7ef 100644 --- a/examples/graphicsview/blurpicker/blurpicker.cpp +++ b/examples/graphicsview/blurpicker/blurpicker.cpp @@ -64,10 +64,6 @@ BlurPicker::BlurPicker(QWidget *parent): QGraphicsView(parent), m_index(0.0) setFrameStyle(QFrame::NoFrame); } -BlurPicker::~BlurPicker() -{ -} - void BlurPicker::updateIconPositions() { m_index = m_timeLine.currentFrame() / 1000.0; @@ -85,16 +81,6 @@ void BlurPicker::updateIconPositions() baseline = qMax(baseline, ys); } -#if 0 - // seems broken - for (int i = 0; i < m_icons.count(); ++i) { - QGraphicsItem *icon = m_icons[i]; - qreal y = baseline - icon->pos().y(); - qreal factor = qBound(0.0, 1 - y / 600, 1.0); - icon->setTransform(QTransform().scale(factor, factor), false); - } -#endif - m_blurEffect->setBaseLine(baseline); m_scene.update(); } diff --git a/examples/graphicsview/blurpicker/blurpicker.h b/examples/graphicsview/blurpicker/blurpicker.h index f97f220..e41c608 100644 --- a/examples/graphicsview/blurpicker/blurpicker.h +++ b/examples/graphicsview/blurpicker/blurpicker.h @@ -54,7 +54,6 @@ class BlurPicker: public QGraphicsView public: BlurPicker(QWidget *parent = 0); - ~BlurPicker(); protected: void keyPressEvent(QKeyEvent *event); -- cgit v0.12 From 7e53a66171ee3358abe4b022ce0fa721259fa604 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Fri, 5 Jun 2009 17:41:26 +0200 Subject: Sprinkle Q_OBJECT in all graphics classes. --- src/gui/graphicsview/qgraphicseffect.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h index f15b172..29d97a6 100644 --- a/src/gui/graphicsview/qgraphicseffect.h +++ b/src/gui/graphicsview/qgraphicseffect.h @@ -66,6 +66,8 @@ QT_MODULE(Gui) class QGraphicsEffectPrivate; class Q_GUI_EXPORT QGraphicsEffect : public QObject { + Q_OBJECT + public: QGraphicsEffect(QObject *parent = 0); @@ -90,6 +92,8 @@ private: class QGraphicsGrayscaleEffectPrivate; class Q_GUI_EXPORT QGraphicsGrayscaleEffect: public QGraphicsEffect { + Q_OBJECT + public: QGraphicsGrayscaleEffect(QObject *parent = 0); @@ -106,6 +110,8 @@ private: class QGraphicsColorizeEffectPrivate; class Q_GUI_EXPORT QGraphicsColorizeEffect: public QGraphicsEffect { + Q_OBJECT + public: QGraphicsColorizeEffect(QObject *parent = 0); @@ -125,6 +131,8 @@ private: class QGraphicsPixelizeEffectPrivate; class Q_GUI_EXPORT QGraphicsPixelizeEffect: public QGraphicsEffect { + Q_OBJECT + public: QGraphicsPixelizeEffect(QObject *parent = 0); @@ -144,6 +152,8 @@ private: class QGraphicsBlurEffectPrivate; class Q_GUI_EXPORT QGraphicsBlurEffect: public QGraphicsEffect { + Q_OBJECT + public: QGraphicsBlurEffect(QObject *parent = 0); @@ -165,6 +175,8 @@ private: class QGraphicsBloomEffectPrivate; class Q_GUI_EXPORT QGraphicsBloomEffect: public QGraphicsEffect { + Q_OBJECT + public: QGraphicsBloomEffect(QObject *parent = 0); @@ -189,6 +201,8 @@ private: class QGraphicsFrameEffectPrivate; class Q_GUI_EXPORT QGraphicsFrameEffect: public QGraphicsEffect { + Q_OBJECT + public: QGraphicsFrameEffect(QObject *parent = 0); @@ -215,6 +229,8 @@ private: class QGraphicsShadowEffectPrivate; class Q_GUI_EXPORT QGraphicsShadowEffect: public QGraphicsEffect { + Q_OBJECT + public: QGraphicsShadowEffect(QObject *parent = 0); -- cgit v0.12 From 5b52ab8161d7731c7728d176b13a4a28480bc1db Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Mon, 29 Jun 2009 16:37:57 +0200 Subject: Fix drawing with effect after the recursive-drawing refactoring. --- src/gui/graphicsview/qgraphicsscene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 3f6404b..1557c2c 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5420,7 +5420,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * painter->setClipPath(item->shape(), Qt::IntersectClip); painter->setOpacity(opacity); - if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget) + if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget && !item->d_ptr->hasEffect) item->paint(painter, &styleOptionTmp, widget); else drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection); -- cgit v0.12 From 351e890aa13faac69a0ceaa8cb02660b2275cf82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 30 Jun 2009 09:45:14 +0200 Subject: Added custom shader hook to the GL 2 paint engine. This will make it easier to implement pixmap filters, YUV->RGB conversions, etc in other parts of Qt. --- .../gl2paintengineex/qglengineshadermanager.cpp | 65 +++++++++++++++++++--- .../gl2paintengineex/qglengineshadermanager_p.h | 41 +++++++++++--- .../gl2paintengineex/qglengineshadersource_p.h | 8 +++ .../gl2paintengineex/qpaintengineex_opengl2.cpp | 12 ++-- .../gl2paintengineex/qpaintengineex_opengl2_p.h | 5 +- 5 files changed, 107 insertions(+), 24 deletions(-) diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index 4b73ca9..068f804 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -49,6 +49,30 @@ QT_BEGIN_NAMESPACE +QGLCustomShader::QGLCustomShader(QGLShader *shader) + : m_shader(shader) +{ +} + +QGLCustomShader::~QGLCustomShader() +{ + delete m_shader; +} + +void QGLCustomShader::updateUniforms(QGLShaderProgram *) +{ +} + +void QGLCustomShader::setShader(QGLShader *shader) +{ + m_shader = shader; +} + +QGLShader *QGLCustomShader::shader() const +{ + return m_shader; +} + const char* QGLEngineShaderManager::qglEngineShaderSourceCode[] = { 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, @@ -66,7 +90,8 @@ QGLEngineShaderManager::QGLEngineShaderManager(QGLContext* context) compositionMode(QPainter::CompositionMode_SourceOver), blitShaderProg(0), simpleShaderProg(0), - currentShaderProg(0) + currentShaderProg(0), + customShader(0) { memset(compiledShaders, 0, sizeof(compiledShaders)); @@ -107,6 +132,7 @@ QGLEngineShaderManager::QGLEngineShaderManager(QGLContext* context) code[MainFragmentShader] = qglslMainFragmentShader; code[ImageSrcFragmentShader] = qglslImageSrcFragmentShader; + code[CustomSrcFragmentShader] = qglslCustomSrcFragmentShader; code[ImageSrcWithPatternFragmentShader] = qglslImageSrcWithPatternFragmentShader; code[NonPremultipliedImageSrcFragmentShader] = qglslNonPremultipliedImageSrcFragmentShader; code[SolidBrushSrcFragmentShader] = qglslSolidBrushSrcFragmentShader; @@ -228,7 +254,7 @@ void QGLEngineShaderManager::setDirty() void QGLEngineShaderManager::setSrcPixelType(Qt::BrushStyle style) { - if (srcPixelType == PixelSrcType(style)) + if (customShader || srcPixelType == PixelSrcType(style)) return; srcPixelType = style; @@ -237,13 +263,20 @@ void QGLEngineShaderManager::setSrcPixelType(Qt::BrushStyle style) void QGLEngineShaderManager::setSrcPixelType(PixelSrcType type) { - if (srcPixelType == type) + if (customShader || srcPixelType == type) return; srcPixelType = type; shaderProgNeedsChanging = true; //### } +void QGLEngineShaderManager::setCustomShader(QGLCustomShader *shader) +{ + srcPixelType = CustomSrc; + shaderProgNeedsChanging = true; + customShader = shader; +} + void QGLEngineShaderManager::setTextureCoordsEnabled(bool enabled) { if (useTextureCoords == enabled) @@ -338,6 +371,10 @@ bool QGLEngineShaderManager::useCorrectShaderProg() srcPixelFragShaderName = ImageSrcFragmentShader; positionVertexShaderName = PositionOnlyVertexShader; break; + case QGLEngineShaderManager::CustomSrc: + srcPixelFragShaderName = CustomSrcFragmentShader; + positionVertexShaderName = PositionOnlyVertexShader; + break; case QGLEngineShaderManager::PatternSrc: srcPixelFragShaderName = ImageSrcWithPatternFragmentShader; positionVertexShaderName = PositionOnlyVertexShader; @@ -381,7 +418,6 @@ bool QGLEngineShaderManager::useCorrectShaderProg() requiredProgram.positionVertexShader = compiledShaders[positionVertexShaderName]; requiredProgram.srcPixelFragShader = compiledShaders[srcPixelFragShaderName]; - const bool hasCompose = compositionMode > QPainter::CompositionMode_Plus; const bool hasMask = maskType != QGLEngineShaderManager::NoMask; @@ -483,6 +519,7 @@ bool QGLEngineShaderManager::useCorrectShaderProg() currentShaderProg = &prog; currentShaderProg->program->enable(); shaderProgNeedsChanging = false; + return true; } } @@ -496,6 +533,9 @@ bool QGLEngineShaderManager::useCorrectShaderProg() requiredProgram.program->addShader(requiredProgram.maskFragShader); requiredProgram.program->addShader(requiredProgram.compositionFragShader); + if (customShader) + requiredProgram.program->addShader(customShader->shader()); + // We have to bind the vertex attribute names before the program is linked: requiredProgram.program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); if (useTextureCoords) @@ -520,11 +560,20 @@ bool QGLEngineShaderManager::useCorrectShaderProg() qWarning() << error; } else { - cachedPrograms.append(requiredProgram); - // taking the address here is safe since - // cachePrograms isn't resized anywhere else - currentShaderProg = &cachedPrograms.last(); + if (customShader) { + // don't cache custom shaders + customShaderProg = requiredProgram; + currentShaderProg = &customShaderProg; + } else { + cachedPrograms.append(requiredProgram); + // taking the address here is safe since + // cachePrograms isn't resized anywhere else + currentShaderProg = &cachedPrograms.last(); + } currentShaderProg->program->enable(); + + if (customShader) + customShader->updateUniforms(currentShaderProg->program); } shaderProgNeedsChanging = false; return true; diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h index 34f0768..891776f 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h @@ -199,18 +199,19 @@ O = Global Opacity - CUSTOM SHADER CODE (idea, depricated) + CUSTOM SHADER CODE ================== The use of custom shader code is supported by the engine for drawImage and drawPixmap calls. This is implemented via hooks in the fragment pipeline. - The custom shader is passed to the engine as a partial fragment shader - (QGLCustomizedShader). The shader will implement a pre-defined method name - which Qt's fragment pipeline will call. There are two different hooks which - can be implemented as custom shader code: + The custom shader is passed to the shader manager as a partial fragment shader + by calling setCustomShader(). Qt's fragment pipeline will call the following + method name in the custom shader: mediump vec4 customShader(sampler2d src, vec2 srcCoords) - mediump vec4 customShaderWithDest(sampler2d dest, sampler2d src, vec2 srcCoords) + + Transformations, clipping, opacity, and composition modes set using QPainter + will be respected when using the custom shader hook. */ @@ -227,6 +228,22 @@ QT_BEGIN_NAMESPACE QT_MODULE(OpenGL) +class Q_OPENGL_EXPORT QGLCustomShader +{ +public: + QGLCustomShader(QGLShader *shader = 0); + virtual ~QGLCustomShader(); + + virtual void updateUniforms(QGLShaderProgram *program); + + void setShader(QGLShader *shader); + QGLShader *shader() const; + +private: + Q_DISABLE_COPY(QGLCustomShader) + + QGLShader *m_shader; +}; struct QGLEngineShaderProg { @@ -259,7 +276,7 @@ struct QGLEngineCachedShaderProg static const GLuint QT_VERTEX_COORDS_ATTR = 0; static const GLuint QT_TEXTURE_COORDS_ATTR = 1; -class QGLEngineShaderManager : public QObject +class Q_OPENGL_EXPORT QGLEngineShaderManager : public QObject { Q_OBJECT public: @@ -271,7 +288,8 @@ public: ImageSrc = Qt::TexturePattern+1, NonPremultipliedImageSrc = Qt::TexturePattern+2, PatternSrc = Qt::TexturePattern+3, - TextureSrcWithPattern = Qt::TexturePattern+4 + TextureSrcWithPattern = Qt::TexturePattern+4, + CustomSrc = Qt::TexturePattern + 5 }; // There are optimisations we can do, depending on the brush transform: @@ -285,6 +303,8 @@ public: void setMaskType(MaskType); void setCompositionMode(QPainter::CompositionMode); + void setCustomShader(QGLCustomShader *shader); + uint getUniformIdentifier(const char *uniformName); uint getUniformLocation(uint id); @@ -322,6 +342,7 @@ public: MainFragmentShader, ImageSrcFragmentShader, + CustomSrcFragmentShader, ImageSrcWithPatternFragmentShader, NonPremultipliedImageSrcFragmentShader, SolidBrushSrcFragmentShader, @@ -366,7 +387,6 @@ public: Q_ENUMS(ShaderName) #endif - private: QGLContext* ctx; bool shaderProgNeedsChanging; @@ -383,6 +403,9 @@ private: QGLShaderProgram* simpleShaderProg; QGLEngineShaderProg* currentShaderProg; + QGLEngineShaderProg customShaderProg; + QGLCustomShader* customShader; + // TODO: Possibly convert to a LUT QList cachedPrograms; diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h index 4e32f91..e379aa3 100644 --- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h @@ -290,6 +290,14 @@ static const char* const qglslImageSrcFragmentShader = "\ return texture2D(imageTexture, textureCoords); \ }"; +static const char* const qglslCustomSrcFragmentShader = "\ + varying highp vec2 textureCoords; \ + uniform sampler2D imageTexture; \ + lowp vec4 customShader(sampler2D texture, vec2 coords); \ + lowp vec4 srcPixel() { \ + return customShader(imageTexture, textureCoords); \ + }"; + static const char* const qglslImageSrcWithPatternFragmentShader = "\ varying highp vec2 textureCoords; \ uniform lowp vec4 patternColor; \ diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 4bf5d4c..a679a62 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -130,10 +130,6 @@ QGLTextureGlyphCache::QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyph QGLTextureGlyphCache::~QGLTextureGlyphCache() { - glDeleteFramebuffers(1, &m_fbo); - - if (m_width || m_height) - glDeleteTextures(1, &m_texture); } void QGLTextureGlyphCache::createTextureData(int width, int height) @@ -251,7 +247,7 @@ QGL2PaintEngineExPrivate::~QGL2PaintEngineExPrivate() void QGL2PaintEngineExPrivate::updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id) { // glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); //### Is it always this texture unit? - if (id != -1 && id == lastTexture) + if (id != GLuint(-1) && id == lastTexture) return; lastTexture = id; @@ -1605,4 +1601,10 @@ QOpenGL2PaintEngineState::~QOpenGL2PaintEngineState() { } +QGLEngineShaderManager *QGL2PaintEngineEx::shaderManager() const +{ + Q_D(const QGL2PaintEngineEx); + return d->shaderManager; +} + QT_END_NAMESPACE diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 0d28a49..f8d3b53 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -88,8 +88,7 @@ public: bool canRestoreClip; }; - -class QGL2PaintEngineEx : public QPaintEngineEx +class Q_OPENGL_EXPORT QGL2PaintEngineEx : public QPaintEngineEx { Q_DECLARE_PRIVATE(QGL2PaintEngineEx) public: @@ -133,6 +132,8 @@ public: } virtual void sync(); + QGLEngineShaderManager *shaderManager() const; + private: Q_DISABLE_COPY(QGL2PaintEngineEx) }; -- cgit v0.12 From 23f589030f41166ccb0b650cba83c5569787b9c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 30 Jun 2009 14:21:03 +0200 Subject: Added drawTexture function to GL 2 paint engine. Works just like drawImage / drawPixmap but uses the given texture id. --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 15 +++++++++++++++ src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h | 3 ++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index a679a62..03ef8c8 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1045,6 +1045,21 @@ void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const d->drawTexture(dest, src, image.size(), !image.hasAlphaChannel()); } +void QGL2PaintEngineEx::drawTexture(const QRectF &dest, GLuint textureId, const QSize &size, const QRectF &src) +{ + Q_D(QGL2PaintEngineEx); + ensureActive(); + d->transferMode(ImageDrawingMode); + + QGLContext *ctx = d->ctx; + glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); + glBindTexture(GL_TEXTURE_2D, textureId); + + d->updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, + state()->renderHints & QPainter::SmoothPixmapTransform, textureId); + d->drawTexture(dest, src, size, false); +} + void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem) { Q_D(QGL2PaintEngineEx); diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index f8d3b53..5e15f40 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -115,9 +115,10 @@ public: virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); - virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags = Qt::AutoColor); + virtual void drawTexture(const QRectF &r, GLuint textureId, const QSize &size, const QRectF &sr); + virtual void drawTextItem(const QPointF &p, const QTextItem &textItem); Type type() const { return OpenGL; } -- cgit v0.12 From a50aa375477c88e688bb919cd1776be9afe4f6c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 30 Jun 2009 14:22:42 +0200 Subject: Added missing createPixmapFilter() implementation in GL 2 engine. --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 8 ++++++++ src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 03ef8c8..6b0dc04 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1622,4 +1622,12 @@ QGLEngineShaderManager *QGL2PaintEngineEx::shaderManager() const return d->shaderManager; } +QPixmapFilter *QGL2PaintEngineEx::createPixmapFilter(int type) const +{ + const QGLContext *ctx = QGLContext::currentContext(); + if (ctx) + return ctx->d_func()->createPixmapFilter(type); + return 0; +} + QT_END_NAMESPACE diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 5e15f40..6b34418 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -135,6 +135,8 @@ public: QGLEngineShaderManager *shaderManager() const; + QPixmapFilter *createPixmapFilter(int type) const; + private: Q_DISABLE_COPY(QGL2PaintEngineEx) }; -- cgit v0.12 From c92b73a19b34ec97262c0959653ac1faf6621de6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 30 Jun 2009 14:23:20 +0200 Subject: Added QPixmapBlurFilter with GL implementation. No raster engine based fallback so far... Also, performance is lacking since the QGLShaderProgram isn't cached. --- src/gui/image/qpixmapfilter.cpp | 183 ++++++++++++++++++++++++++++ src/gui/image/qpixmapfilter_p.h | 25 ++++ src/opengl/qglpixmapfilter.cpp | 256 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 463 insertions(+), 1 deletion(-) diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp index c5f3663..ee4f7cf 100644 --- a/src/gui/image/qpixmapfilter.cpp +++ b/src/gui/image/qpixmapfilter.cpp @@ -87,6 +87,8 @@ public: \value ConvolutionFilter A filter that is used to calculate the convolution of the image with a kernel. See QPixmapConvolutionFilter for more information. + \value BlurFilter A filter that is used to blur an image. See + QPixmapConvolutionFilter for more information. \value ColorizeFilter A filter that is used to change the overall color of an image. See QPixmapColorizeFilter for more information. @@ -479,6 +481,187 @@ void QPixmapConvolutionFilter::draw(QPainter *painter, const QPointF &p, const Q } } +/*! + \class QPixmapBlurFilter + \since 4.6 + \ingroup multimedia + + \brief The QPixmapBlurFilter class provides blur filtering + for pixmaps. + + QPixmapBlurFilter implements a blur pixmap filter, + which is applied when \l{QPixmapFilter::}{draw()} is called. + + The filter lets you specialize the radius of the blur as well + as the quality. + + \sa {Pixmap Filters Example}, QPixmapConvolutionFilter, QPixmapDropShadowFilter + + \internal +*/ + +class QPixmapBlurFilterPrivate : public QPixmapFilterPrivate +{ +public: + QPixmapBlurFilterPrivate() : radius(5), quality(Qt::FastTransformation) {} + + int radius; + Qt::TransformationMode quality; +}; + + +/*! + Constructs a pixmap blur filter. + + \internal +*/ +QPixmapBlurFilter::QPixmapBlurFilter(QObject *parent) + : QPixmapFilter(*new QPixmapBlurFilterPrivate, BlurFilter, parent) +{ +} + +/*! + Destructor of pixmap blur filter. + + \internal +*/ +QPixmapBlurFilter::~QPixmapBlurFilter() +{ +} + +/*! + Sets the radius of the blur filter. Higher radius produces increased blurriness. + + \internal +*/ +void QPixmapBlurFilter::setRadius(int radius) +{ + Q_D(QPixmapBlurFilter); + d->radius = radius; +} + +/*! + Gets the radius of the blur filter. + + \internal +*/ +int QPixmapBlurFilter::radius() const +{ + Q_D(const QPixmapBlurFilter); + return d->radius; +} + +/*! + Sets the quality of the blur filter. Lower quality yields better performance. + + \internal +*/ +void QPixmapBlurFilter::setQuality(Qt::TransformationMode quality) +{ + Q_D(QPixmapBlurFilter); + d->quality = quality; +} + +/*! + Gets the quality of the blur filter. + + \internal +*/ +Qt::TransformationMode QPixmapBlurFilter::quality() const +{ + Q_D(const QPixmapBlurFilter); + return d->quality; +} + +/*! + \reimp + + \internal +*/ +QRectF QPixmapBlurFilter::boundingRectFor(const QRectF &rect) const +{ + return rect; +} + +/*! + \reimp + + \internal +*/ +void QPixmapBlurFilter::draw(QPainter *painter, const QPointF &p, const QPixmap &src, const QRectF &srcRect) const +{ + Q_D(const QPixmapBlurFilter); + if (!painter->isActive()) + return; + + if (d->radius == 0) { + painter->drawPixmap(srcRect.translated(p), src, srcRect); + return; + } + + QPixmapFilter *filter = painter->paintEngine() && painter->paintEngine()->isExtended() ? + static_cast(painter->paintEngine())->createPixmapFilter(type()) : 0; + QPixmapBlurFilter *blurFilter = static_cast(filter); + if (blurFilter) { + blurFilter->setRadius(d->radius); + blurFilter->setQuality(d->quality); + blurFilter->draw(painter, p, src, srcRect); + delete blurFilter; + return; + } + +#if 0 + // falling back to raster implementation + + QImage *target = 0; + if (painter->paintEngine()->paintDevice()->devType() == QInternal::Image) { + target = static_cast(painter->paintEngine()->paintDevice()); + + QTransform mat = painter->combinedTransform(); + + if (mat.type() > QTransform::TxTranslate) { + // Disabled because of transformation... + target = 0; + } else { + QRasterPaintEngine *pe = static_cast(painter->paintEngine()); + if (pe->clipType() == QRasterPaintEngine::ComplexClip) + // disabled because of complex clipping... + target = 0; + else { + QRectF clip = pe->clipBoundingRect(); + QRectF rect = boundingRectFor(srcRect.isEmpty() ? src.rect() : srcRect); + QTransform x = painter->deviceTransform(); + if (!clip.contains(rect.translated(x.dx() + p.x(), x.dy() + p.y()))) { + target = 0; + } + + } + } + } + + if (target) { + QTransform x = painter->deviceTransform(); + QPointF offset(x.dx(), x.dy()); + + convolute(target, p+offset, src.toImage(), srcRect, QPainter::CompositionMode_SourceOver, d->convolutionKernel, d->kernelWidth, d->kernelHeight); + } else { + QRect srect = srcRect.isNull() ? src.rect() : srcRect.toRect(); + QRect rect = boundingRectFor(srect).toRect(); + QImage result = QImage(rect.size(), QImage::Format_ARGB32_Premultiplied); + QPoint offset = srect.topLeft() - rect.topLeft(); + convolute(&result, + offset, + src.toImage(), + srect, + QPainter::CompositionMode_Source, + d->convolutionKernel, + d->kernelWidth, + d->kernelHeight); + painter->drawImage(p - offset, result); + } +#endif +} + // grayscales the image to dest (could be same). If rect isn't defined // destination image size is used to determine the dimension of grayscaling // process. diff --git a/src/gui/image/qpixmapfilter_p.h b/src/gui/image/qpixmapfilter_p.h index 51292b3..6978f03 100644 --- a/src/gui/image/qpixmapfilter_p.h +++ b/src/gui/image/qpixmapfilter_p.h @@ -78,6 +78,7 @@ public: ConvolutionFilter, ColorizeFilter, DropShadowFilter, + BlurFilter, UserFilter = 1024 }; @@ -117,6 +118,30 @@ private: int columns() const; }; +class QPixmapBlurFilterPrivate; + +class Q_GUI_EXPORT QPixmapBlurFilter : public QPixmapFilter +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QPixmapBlurFilter) + +public: + QPixmapBlurFilter(QObject *parent = 0); + ~QPixmapBlurFilter(); + + void setRadius(int radius); + void setQuality(Qt::TransformationMode mode); + + QRectF boundingRectFor(const QRectF &rect) const; + void draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect = QRectF()) const; + +private: + friend class QGLPixmapBlurFilter; + + int radius() const; + Qt::TransformationMode quality() const; +}; + class QPixmapColorizeFilterPrivate; class Q_GUI_EXPORT QPixmapColorizeFilter : public QPixmapFilter diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp index 7514743..6812c43 100644 --- a/src/opengl/qglpixmapfilter.cpp +++ b/src/opengl/qglpixmapfilter.cpp @@ -40,15 +40,19 @@ ****************************************************************************/ #include "private/qpixmapfilter_p.h" +#include "private/qpaintengineex_opengl2_p.h" +#include "private/qglengineshadermanager_p.h" #include "qglpixmapfilter_p.h" #include "qgraphicssystem_gl_p.h" #include "qpaintengine_opengl_p.h" +#include "qcache.h" -#include "qglpixelbuffer.h" +#include "qglframebufferobject.h" #include "qglshaderprogram.h" #include "qgl_p.h" #include "private/qapplication_p.h" +#include "private/qmath_p.h" QT_BEGIN_NAMESPACE @@ -97,6 +101,28 @@ private: mutable int m_kernelHeight; }; +class QGLPixmapBlurFilter : public QGLCustomShader, public QGLPixmapFilter +{ +public: + QGLPixmapBlurFilter(); + ~QGLPixmapBlurFilter(); + + void updateUniforms(QGLShaderProgram *program); + +protected: + bool processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const; + +private: + static QByteArray generateBlurShader(int radius, bool gaussianBlur); + + mutable QGLShader *m_shader; + mutable QGLFramebufferObject *m_fbo; + + mutable QSize m_textureSize; + + QGLShaderProgram *m_program; +}; + extern QGLWidget *qt_gl_share_widget(); QPixmapFilter *QGLContextPrivate::createPixmapFilter(int type) const @@ -105,6 +131,8 @@ QPixmapFilter *QGLContextPrivate::createPixmapFilter(int type) const case QPixmapFilter::ColorizeFilter: return new QGLPixmapColorizeFilter; + case QPixmapFilter::BlurFilter: + return new QGLPixmapBlurFilter; case QPixmapFilter::ConvolutionFilter: return new QGLPixmapConvolutionFilter; @@ -281,4 +309,230 @@ bool QGLPixmapConvolutionFilter::processGL(QPainter *, const QPointF &pos, const return true; } +QGLPixmapBlurFilter::QGLPixmapBlurFilter() + : m_fbo(0) +{ +} + +QGLPixmapBlurFilter::~QGLPixmapBlurFilter() +{ + delete m_fbo; +} + +bool QGLPixmapBlurFilter::processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &) const +{ + QGLCustomShader *customShader = const_cast(this); + + if (!shader()) { + QGLShader *blurShader = new QGLShader(QGLShader::FragmentShader); + blurShader->compile(generateBlurShader(radius(), quality() == Qt::SmoothTransformation)); + + customShader->setShader(blurShader); + + m_fbo = new QGLFramebufferObject(src.size()); + + glBindTexture(GL_TEXTURE_2D, m_fbo->texture()); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glBindTexture(GL_TEXTURE_2D, 0); + } + + QGL2PaintEngineEx *engine = static_cast(painter->paintEngine()); + QGLEngineShaderManager *manager = engine->shaderManager(); + + engine->syncState(); + painter->save(); + + // ensure GL_LINEAR filtering is used + painter->setRenderHint(QPainter::SmoothPixmapTransform); + + // prepare for updateUniforms + m_textureSize = src.size(); + + // first pass, to fbo + m_fbo->bind(); + manager->setCustomShader(customShader); + engine->drawPixmap(src.rect(), src, src.rect()); + m_fbo->release(); + + // second pass, to widget + m_program->setUniformValue("delta", 0.0, 1.0); + engine->drawTexture(src.rect().translated(pos.x(), pos.y()), m_fbo->texture(), src.size(), src.rect()); + manager->setCustomShader(0); + + painter->restore(); + + return true; +} + +void QGLPixmapBlurFilter::updateUniforms(QGLShaderProgram *program) +{ + program->setUniformValue("invTextureSize", 1.0 / m_textureSize.width(), 1.0 / m_textureSize.height()); + program->setUniformValue("delta", 1.0, 0.0); + + m_program = program; +} + +static inline qreal gaussian(qreal dx, qreal sigma) +{ + return exp(-dx * dx / (2 * sigma * sigma)) / (Q_2PI * sigma * sigma); +} + +QByteArray QGLPixmapBlurFilter::generateBlurShader(int radius, bool gaussianBlur) +{ + Q_ASSERT(radius >= 1); + + QByteArray source; + + source.append("uniform highp vec2 invTextureSize;\n"); + + bool separateXY = true; + bool clip = false; + + if (separateXY) { + source.append("uniform highp vec2 delta;\n"); + + if (clip) + source.append("uniform highp vec2 clip;\n"); + } else if (clip) { + source.append("uniform highp vec4 clip;\n"); + } + + source.append("mediump vec4 customShader(sampler2D src, vec2 srcCoords) {\n"); + + QVector sampleOffsets; + QVector weights; + + if (gaussianBlur) { + QVector gaussianComponents; + + qreal sigma = radius / 1.65; + + qreal sum = 0; + for (int i = -radius; i <= radius; ++i) { + float value = gaussian(i, sigma); + gaussianComponents << value; + sum += value; + } + + // normalize + for (int i = 0; i < gaussianComponents.size(); ++i) + gaussianComponents[i] /= sum; + + for (int i = 0; i < gaussianComponents.size() - 1; i += 2) { + qreal weight = gaussianComponents.at(i) + gaussianComponents.at(i + 1); + qreal offset = i - radius + gaussianComponents.at(i + 1) / weight; + + sampleOffsets << offset; + weights << weight; + } + + // odd size ? + if (gaussianComponents.size() & 1) { + sampleOffsets << radius; + weights << gaussianComponents.last(); + } + } else { + for (int i = 0; i < radius; ++i) { + sampleOffsets << 2 * i - radius + 0.5; + weights << qreal(1); + } + sampleOffsets << radius; + weights << qreal(0.5); + } + + int currentVariable = 1; + source.append(" mediump vec4 sample = vec4(0.0);\n"); + source.append(" mediump vec2 coord;\n"); + + qreal weightSum = 0; + if (separateXY) { + source.append(" mediump float c;\n"); + for (int i = 0; i < sampleOffsets.size(); ++i) { + qreal delta = sampleOffsets.at(i); + + ++currentVariable; + + QByteArray coordinate = "srcCoords"; + if (delta != qreal(0)) { + coordinate.append(" + invTextureSize * delta * float("); + coordinate.append(QByteArray::number(delta)); + coordinate.append(")"); + } + + source.append(" coord = "); + source.append(coordinate); + source.append(";\n"); + + if (clip) { + source.append(" c = dot(coord, delta);\n"); + source.append(" if (c > clip.x && c < clip.y)\n "); + } + + source.append(" sample += texture2D(src, coord)"); + + weightSum += weights.at(i); + if (weights.at(i) != qreal(1)) { + source.append(" * float("); + source.append(QByteArray::number(weights.at(i))); + source.append(");\n"); + } else { + source.append(";\n"); + } + } + } else { + for (int y = 0; y < sampleOffsets.size(); ++y) { + for (int x = 0; x < sampleOffsets.size(); ++x) { + QByteArray coordinate = "srcCoords"; + + qreal dx = sampleOffsets.at(x); + qreal dy = sampleOffsets.at(y); + + if (dx != qreal(0) || dy != qreal(0)) { + coordinate.append(" + invTextureSize * vec2(float("); + coordinate.append(QByteArray::number(dx)); + coordinate.append("), float("); + coordinate.append(QByteArray::number(dy)); + coordinate.append("))"); + } + + source.append(" coord = "); + source.append(coordinate); + source.append(";\n"); + + if (clip) + source.append(" if (coord.x > clip.x && coord.x < clip.y && coord.y > clip.z && coord.y < clip.w)\n "); + + source.append(" sample += texture2D(src, coord)"); + + ++currentVariable; + + weightSum += weights.at(x) * weights.at(y); + if ((weights.at(x) != qreal(1) || weights.at(y) != qreal(1))) { + source.append(" * float("); + source.append(QByteArray::number(weights.at(x) * weights.at(y))); + source.append(");\n"); + } else { + source.append(";\n"); + } + } + } + } + + source.append(" return "); + if (!gaussianBlur) { + source.append("float("); + if (separateXY) + source.append(QByteArray::number(1 / weightSum)); + else + source.append(QByteArray::number(1 / weightSum)); + source.append(") * "); + } + source.append("sample;\n"); + source.append("}\n"); + + return source; +} + QT_END_NAMESPACE -- cgit v0.12 From f86a6467c0dbfd54603b588e6c001265b0d527e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Wed, 1 Jul 2009 15:17:15 +0200 Subject: Added caching of custom shader programs as well in GL 2 shader manager. Ensures that the programs are evicted from the cache when the shaders are destroyed. --- .../gl2paintengineex/qglengineshadermanager.cpp | 42 ++++++++++++++-------- .../gl2paintengineex/qglengineshadermanager_p.h | 5 ++- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index 068f804..10654ae 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -506,6 +506,7 @@ bool QGLEngineShaderManager::useCorrectShaderProg() else requiredProgram.compositionFragShader = 0; + requiredProgram.customShader = customShader ? customShader->shader() : 0; // At this point, requiredProgram is fully populated so try to find the program in the cache for (int i = 0; i < cachedPrograms.size(); ++i) { @@ -514,12 +515,16 @@ bool QGLEngineShaderManager::useCorrectShaderProg() && (prog.positionVertexShader == requiredProgram.positionVertexShader) && (prog.mainFragShader == requiredProgram.mainFragShader) && (prog.srcPixelFragShader == requiredProgram.srcPixelFragShader) - && (prog.compositionFragShader == requiredProgram.compositionFragShader) ) + && (prog.compositionFragShader == requiredProgram.compositionFragShader) + && (prog.customShader == requiredProgram.customShader) ) { currentShaderProg = &prog; currentShaderProg->program->enable(); shaderProgNeedsChanging = false; + if (customShader) + customShader->updateUniforms(currentShaderProg->program); + return true; } } @@ -533,8 +538,8 @@ bool QGLEngineShaderManager::useCorrectShaderProg() requiredProgram.program->addShader(requiredProgram.maskFragShader); requiredProgram.program->addShader(requiredProgram.compositionFragShader); - if (customShader) - requiredProgram.program->addShader(customShader->shader()); + if (requiredProgram.customShader) + requiredProgram.program->addShader(requiredProgram.customShader); // We have to bind the vertex attribute names before the program is linked: requiredProgram.program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); @@ -560,25 +565,34 @@ bool QGLEngineShaderManager::useCorrectShaderProg() qWarning() << error; } else { - if (customShader) { - // don't cache custom shaders - customShaderProg = requiredProgram; - currentShaderProg = &customShaderProg; - } else { - cachedPrograms.append(requiredProgram); - // taking the address here is safe since - // cachePrograms isn't resized anywhere else - currentShaderProg = &cachedPrograms.last(); - } + cachedPrograms.append(requiredProgram); + // taking the address here is safe since + // cachePrograms isn't resized anywhere else + currentShaderProg = &cachedPrograms.last(); currentShaderProg->program->enable(); - if (customShader) + if (customShader) { customShader->updateUniforms(currentShaderProg->program); + connect(customShader->shader(), SIGNAL(destroyed(QObject *)), + this, SLOT(shaderDestroyed(QObject *))); + } } shaderProgNeedsChanging = false; return true; } +void QGLEngineShaderManager::shaderDestroyed(QObject *shader) +{ + for (int i = 0; i < cachedPrograms.size(); ++i) { + if (cachedPrograms.at(i).customShader == shader) { + delete cachedPrograms.at(i).program; + cachedPrograms.removeAt(i--); + } + } + + shaderProgNeedsChanging = true; +} + void QGLEngineShaderManager::compileNamedShader(QGLEngineShaderManager::ShaderName name, QGLShader::ShaderType type) { if (compiledShaders[name]) diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h index 891776f..c749f52 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h @@ -253,6 +253,7 @@ struct QGLEngineShaderProg QGLShader* srcPixelFragShader; QGLShader* maskFragShader; // Can be null for no mask QGLShader* compositionFragShader; // Can be null for GL-handled mode + QGLShader* customShader; QGLShaderProgram* program; QVector uniformLocations; @@ -387,6 +388,9 @@ public: Q_ENUMS(ShaderName) #endif +private slots: + void shaderDestroyed(QObject *shader); + private: QGLContext* ctx; bool shaderProgNeedsChanging; @@ -403,7 +407,6 @@ private: QGLShaderProgram* simpleShaderProg; QGLEngineShaderProg* currentShaderProg; - QGLEngineShaderProg customShaderProg; QGLCustomShader* customShader; // TODO: Possibly convert to a LUT -- cgit v0.12 From ef9fad3391f7b5c59d3fe62b491a4760c2917810 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Thu, 2 Jul 2009 09:41:40 +0200 Subject: Refactored the GL QPixmap backend to use an FBO pool class. The FBO pool will be useful in other places as well, plus it makes it easier to deal with graphics memory management issues. --- src/opengl/qpixmapdata_gl.cpp | 134 +++++++++++++++++++++++++++++------------- src/opengl/qpixmapdata_gl_p.h | 13 ++++ 2 files changed, 106 insertions(+), 41 deletions(-) diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp index f0c7e20..f6a9bf4 100644 --- a/src/opengl/qpixmapdata_gl.cpp +++ b/src/opengl/qpixmapdata_gl.cpp @@ -55,6 +55,85 @@ QT_BEGIN_NAMESPACE extern QGLWidget* qt_gl_share_widget(); +/*! + \class QGLFramebufferObjectPool + \since 4.6 + + \brief The QGLFramebufferObject class provides a pool of framebuffer + objects for offscreen rendering purposes. + + When requesting an FBO of a given size and format, an FBO of the same + format and a size at least as big as the requested size will be returned. + + \internal +*/ + +static inline int areaDiff(const QSize &size, const QGLFramebufferObject *fbo) +{ + return qAbs(size.width() * size.height() - fbo->width() * fbo->height()); +} + +QGLFramebufferObject *QGLFramebufferObjectPool::acquire(const QSize &requestSize, const QGLFramebufferObjectFormat &requestFormat) +{ + QGLFramebufferObject *chosen = 0; + QGLFramebufferObject *candidate = 0; + for (int i = 0; !chosen && i < m_fbos.size(); ++i) { + QGLFramebufferObject *fbo = m_fbos.at(i); + + QGLFramebufferObjectFormat format = fbo->format(); + if (format.samples() == requestFormat.samples() + && format.attachment() == requestFormat.attachment() + && format.textureTarget() == requestFormat.textureTarget() + && format.internalFormat() == requestFormat.internalFormat()) + { + // choose the fbo with a matching format and the closest size + if (!candidate || areaDiff(requestSize, candidate) > areaDiff(requestSize, fbo)) + candidate = fbo; + } + + if (candidate) { + m_fbos.removeOne(candidate); + + const QSize fboSize = candidate->size(); + QSize sz = fboSize; + + if (sz.width() < requestSize.width()) + sz.setWidth(qMax(requestSize.width(), qRound(sz.width() * 1.5))); + if (sz.height() < requestSize.height()) + sz.setHeight(qMax(requestSize.height(), qRound(sz.height() * 1.5))); + + // wasting too much space? + if (sz.width() * sz.height() > requestSize.width() * requestSize.height() * 2.5) + sz = requestSize; + + if (sz != fboSize) { + delete candidate; + qDebug() << "Resizing fbo in pool:" << sz; + candidate = new QGLFramebufferObject(sz, requestFormat); + } + + chosen = candidate; + } + } + + if (!chosen) { + qDebug() << "Creating new fbo in pool:" << requestSize; + chosen = new QGLFramebufferObject(requestSize, requestFormat); + } + + if (!chosen->isValid()) { + delete chosen; + chosen = 0; + } + + return chosen; +} + +void QGLFramebufferObjectPool::release(QGLFramebufferObject *fbo) +{ + m_fbos << fbo; +} + class QGLShareContextScope { public: @@ -330,8 +409,11 @@ struct TextureBuffer QGL2PaintEngineEx *engine; }; -static QVector textureBufferStack; -static int currentTextureBuffer = 0; +Q_GLOBAL_STATIC(QGLFramebufferObjectPool, _qgl_fbo_pool) +QGLFramebufferObjectPool* qgl_fbo_pool() +{ + return _qgl_fbo_pool(); +} void QGLPixmapData::copyBackFromRenderFbo(bool keepCurrentFboBound) const { @@ -378,7 +460,8 @@ void QGLPixmapData::swapBuffers() copyBackFromRenderFbo(false); m_renderFbo->release(); - --currentTextureBuffer; + qgl_fbo_pool()->release(m_renderFbo); + delete m_engine; m_renderFbo = 0; m_engine = 0; @@ -396,19 +479,6 @@ void QGLPixmapData::doneCurrent() m_renderFbo->release(); } -static TextureBuffer createTextureBuffer(const QSize &size, QGL2PaintEngineEx *engine = 0) -{ - TextureBuffer buffer; - QGLFramebufferObjectFormat fmt; - fmt.setAttachment(QGLFramebufferObject::CombinedDepthStencil); - fmt.setSamples(4); - - buffer.fbo = new QGLFramebufferObject(size, fmt); - buffer.engine = engine ? engine : new QGL2PaintEngineEx; - - return buffer; -} - bool QGLPixmapData::useFramebufferObjects() { return QGLFramebufferObject::hasOpenGLFramebufferObjects() @@ -431,33 +501,15 @@ QPaintEngine* QGLPixmapData::paintEngine() const qt_gl_share_widget()->makeCurrent(); QGLShareContextScope ctx(qt_gl_share_widget()->context()); - if (textureBufferStack.size() <= currentTextureBuffer) { - textureBufferStack << createTextureBuffer(size()); - } else { - QSize sz = textureBufferStack.at(currentTextureBuffer).fbo->size(); - if (sz.width() < w || sz.height() < h) { - if (sz.width() < w) - sz.setWidth(qMax(w, qRound(sz.width() * 1.5))); - if (sz.height() < h) - sz.setHeight(qMax(h, qRound(sz.height() * 1.5))); - - // wasting too much space? - if (sz.width() * sz.height() > w * h * 2.5) - sz = QSize(w, h); - - delete textureBufferStack.at(currentTextureBuffer).fbo; - textureBufferStack[currentTextureBuffer] = - createTextureBuffer(sz, textureBufferStack.at(currentTextureBuffer).engine); - qDebug() << "Creating new pixmap texture buffer:" << sz; - } - } - - if (textureBufferStack.at(currentTextureBuffer).fbo->isValid()) { - m_renderFbo = textureBufferStack.at(currentTextureBuffer).fbo; - m_engine = textureBufferStack.at(currentTextureBuffer).engine; + QGLFramebufferObjectFormat format; + format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); + format.setSamples(4); + format.setInternalFormat(m_hasAlpha ? GL_RGBA : GL_RGB); - ++currentTextureBuffer; + m_renderFbo = qgl_fbo_pool()->acquire(size(), format); + if (m_renderFbo) { + m_engine = new QGL2PaintEngineEx; return m_engine; } diff --git a/src/opengl/qpixmapdata_gl_p.h b/src/opengl/qpixmapdata_gl_p.h index a6aa22d..aaeb8ac 100644 --- a/src/opengl/qpixmapdata_gl_p.h +++ b/src/opengl/qpixmapdata_gl_p.h @@ -61,6 +61,19 @@ QT_BEGIN_NAMESPACE class QPaintEngine; class QGLFramebufferObject; +class QGLFramebufferObjectFormat; + +class QGLFramebufferObjectPool +{ +public: + QGLFramebufferObject *acquire(const QSize &size, const QGLFramebufferObjectFormat &format); + void release(QGLFramebufferObject *fbo); + +private: + QList m_fbos; +}; + +QGLFramebufferObjectPool* qgl_fbo_pool(); class QGLPixmapData : public QPixmapData { -- cgit v0.12 From b1832b5a32e1ff5536e5fe9efeca3013ba947eec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Thu, 2 Jul 2009 10:01:56 +0200 Subject: Made GL blur filter use the new FBO pool for improved performance. --- src/opengl/qglpixmapfilter.cpp | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp index 6812c43..4e859d4 100644 --- a/src/opengl/qglpixmapfilter.cpp +++ b/src/opengl/qglpixmapfilter.cpp @@ -116,7 +116,6 @@ private: static QByteArray generateBlurShader(int radius, bool gaussianBlur); mutable QGLShader *m_shader; - mutable QGLFramebufferObject *m_fbo; mutable QSize m_textureSize; @@ -310,13 +309,11 @@ bool QGLPixmapConvolutionFilter::processGL(QPainter *, const QPointF &pos, const } QGLPixmapBlurFilter::QGLPixmapBlurFilter() - : m_fbo(0) { } QGLPixmapBlurFilter::~QGLPixmapBlurFilter() { - delete m_fbo; } bool QGLPixmapBlurFilter::processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &) const @@ -328,15 +325,20 @@ bool QGLPixmapBlurFilter::processGL(QPainter *painter, const QPointF &pos, const blurShader->compile(generateBlurShader(radius(), quality() == Qt::SmoothTransformation)); customShader->setShader(blurShader); + } - m_fbo = new QGLFramebufferObject(src.size()); + QGLFramebufferObjectFormat format; + format.setInternalFormat(src.hasAlphaChannel() ? GL_RGBA : GL_RGB); + QGLFramebufferObject *fbo = qgl_fbo_pool()->acquire(src.size(), format); - glBindTexture(GL_TEXTURE_2D, m_fbo->texture()); + if (!fbo) + return false; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glBindTexture(GL_TEXTURE_2D, 0); - } + glBindTexture(GL_TEXTURE_2D, fbo->texture()); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glBindTexture(GL_TEXTURE_2D, 0); QGL2PaintEngineEx *engine = static_cast(painter->paintEngine()); QGLEngineShaderManager *manager = engine->shaderManager(); @@ -351,18 +353,20 @@ bool QGLPixmapBlurFilter::processGL(QPainter *painter, const QPointF &pos, const m_textureSize = src.size(); // first pass, to fbo - m_fbo->bind(); + fbo->bind(); manager->setCustomShader(customShader); engine->drawPixmap(src.rect(), src, src.rect()); - m_fbo->release(); + fbo->release(); // second pass, to widget m_program->setUniformValue("delta", 0.0, 1.0); - engine->drawTexture(src.rect().translated(pos.x(), pos.y()), m_fbo->texture(), src.size(), src.rect()); + engine->drawTexture(src.rect().translated(pos.x(), pos.y()), fbo->texture(), src.size(), src.rect()); manager->setCustomShader(0); painter->restore(); + qgl_fbo_pool()->release(fbo); + return true; } -- cgit v0.12 From 6dc1536c1d3964a16484b2a55aa161b49e639901 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Thu, 2 Jul 2009 12:28:53 +0200 Subject: Fixed GL blur filter to handle painter translates and larger FBO sizes. --- src/opengl/qglpixmapfilter.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp index 4e859d4..662e818 100644 --- a/src/opengl/qglpixmapfilter.cpp +++ b/src/opengl/qglpixmapfilter.cpp @@ -338,6 +338,8 @@ bool QGLPixmapBlurFilter::processGL(QPainter *painter, const QPointF &pos, const glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(GL_TEXTURE_2D, 0); QGL2PaintEngineEx *engine = static_cast(painter->paintEngine()); @@ -355,12 +357,26 @@ bool QGLPixmapBlurFilter::processGL(QPainter *painter, const QPointF &pos, const // first pass, to fbo fbo->bind(); manager->setCustomShader(customShader); + + QTransform transform = engine->state()->matrix; + + if (!transform.isIdentity()) { + engine->state()->matrix = QTransform(); + engine->transformChanged(); + } + engine->drawPixmap(src.rect(), src, src.rect()); + + if (!transform.isIdentity()) { + engine->state()->matrix = transform; + engine->transformChanged(); + } + fbo->release(); // second pass, to widget m_program->setUniformValue("delta", 0.0, 1.0); - engine->drawTexture(src.rect().translated(pos.x(), pos.y()), fbo->texture(), src.size(), src.rect()); + engine->drawTexture(src.rect().translated(pos.x(), pos.y()), fbo->texture(), fbo->size(), src.rect().translated(0, fbo->height() - src.height())); manager->setCustomShader(0); painter->restore(); -- cgit v0.12 From 0431548ddffc56f74cc60e7d341ade3920adefb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Thu, 2 Jul 2009 13:16:25 +0200 Subject: Further optimized the GL blur filter by caching the QGLShader. --- src/opengl/gl2paintengineex/qglengineshadermanager.cpp | 1 - src/opengl/qglpixmapfilter.cpp | 12 +++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index 10654ae..9f62b59 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -56,7 +56,6 @@ QGLCustomShader::QGLCustomShader(QGLShader *shader) QGLCustomShader::~QGLCustomShader() { - delete m_shader; } void QGLCustomShader::updateUniforms(QGLShaderProgram *) diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp index 662e818..06542a1 100644 --- a/src/opengl/qglpixmapfilter.cpp +++ b/src/opengl/qglpixmapfilter.cpp @@ -57,6 +57,7 @@ QT_BEGIN_NAMESPACE +static QCache shaderCache; void QGLPixmapFilterBase::bindTexture(const QPixmap &src) const { @@ -321,9 +322,13 @@ bool QGLPixmapBlurFilter::processGL(QPainter *painter, const QPointF &pos, const QGLCustomShader *customShader = const_cast(this); if (!shader()) { - QGLShader *blurShader = new QGLShader(QGLShader::FragmentShader); - blurShader->compile(generateBlurShader(radius(), quality() == Qt::SmoothTransformation)); - + const QByteArray blurSource = generateBlurShader(radius(), quality() == Qt::SmoothTransformation); + QGLShader *blurShader = shaderCache.object(blurSource); + if (!blurShader) { + blurShader = new QGLShader(QGLShader::FragmentShader); + blurShader->compile(blurSource); + shaderCache.insert(blurSource, blurShader); + } customShader->setShader(blurShader); } @@ -404,6 +409,7 @@ QByteArray QGLPixmapBlurFilter::generateBlurShader(int radius, bool gaussianBlur Q_ASSERT(radius >= 1); QByteArray source; + source.reserve(1000); source.append("uniform highp vec2 invTextureSize;\n"); -- cgit v0.12 From e0c84298b2d4ed0b8b564dd491e5687296b75ebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 21 Jul 2009 07:30:58 +0200 Subject: Compile after merge commit 8079a0c5b4ee6550501476410fab457d63c705b6 --- src/gui/graphicsview/graphicsview.pri | 1 + src/gui/graphicsview/qgraphicsitem_p.h | 2 +- src/gui/graphicsview/qgraphicsscene.cpp | 41 +++++++++++---------------------- src/gui/graphicsview/qgraphicsscene_p.h | 8 +++++++ 4 files changed, 24 insertions(+), 28 deletions(-) diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri index 4c3ac42..c3cb574 100644 --- a/src/gui/graphicsview/graphicsview.pri +++ b/src/gui/graphicsview/graphicsview.pri @@ -3,6 +3,7 @@ HEADERS += graphicsview/qgraphicsgridlayout.h \ graphicsview/qgraphicsitem.h \ graphicsview/qgraphicsitem_p.h \ graphicsview/qgraphicsitemanimation.h \ + graphicsview/qgraphicslayout.h \ graphicsview/qgraphicslayout_p.h \ graphicsview/qgraphicslayoutitem.h \ graphicsview/qgraphicslayoutitem_p.h \ diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 279a4e6..09f296a 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -147,11 +147,11 @@ public: dirtyClipPath(1), emptyClipPath(0), inSetPosHelper(0), - hasEffect(0), needSortChildren(1), allChildrenDirty(0), fullUpdatePending(0), flags(0), + hasEffect(0), dirtyChildrenBoundingRect(1), paintedViewBoundingRectsNeedRepaint(0), dirtySceneTransform(1), diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index bc42752..2807673 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -254,33 +254,6 @@ QT_BEGIN_NAMESPACE -// QRectF::intersects() returns false always if either the source or target -// rectangle's width or height are 0. This works around that problem. -static inline void _q_adjustRect(QRectF *rect) -{ - Q_ASSERT(rect); - if (!rect->width()) - rect->adjust(-0.00001, 0, 0.00001, 0); - if (!rect->height()) - rect->adjust(0, -0.00001, 0, 0.00001); -} - -static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item) -{ - Q_ASSERT(item); - QRectF boundingRect(item->boundingRect()); - _q_adjustRect(&boundingRect); - return boundingRect; -} - -static inline QRectF adjustedItemEffectiveBoundingRect(const QGraphicsItem *item) -{ - Q_ASSERT(item); - QRectF boundingRect(item->effectiveBoundingRect()); - _q_adjustRect(&boundingRect); - return boundingRect; -} - static void _q_hoverFromMouseEvent(QGraphicsSceneHoverEvent *hover, const QGraphicsSceneMouseEvent *mouseEvent) { hover->setWidget(mouseEvent->widget()); @@ -4311,6 +4284,20 @@ QPixmap* QGraphicsScene::drawItemOnPixmap(QPainter *painter, return targetPixmap; } +void QGraphicsScenePrivate::drawItems(QPainter *painter, const QTransform *const viewTransform, + QRegion *exposedRegion, QWidget *widget) +{ + QRectF exposedSceneRect; + if (exposedRegion && indexMethod != QGraphicsScene::NoIndex) { + exposedSceneRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1); + if (viewTransform) + exposedSceneRect = viewTransform->inverted().mapRect(exposedSceneRect); + } + const QList tli = index->estimateTopLevelItems(exposedSceneRect, Qt::DescendingOrder); + for (int i = 0; i < tli.size(); ++i) + drawSubtreeRecursive(tli.at(i), painter, viewTransform, exposedRegion, widget); +} + void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform *const viewTransform, QRegion *exposedRegion, QWidget *widget, diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 9a91acc..38f5682 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -278,6 +278,14 @@ static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item) return boundingRect; } +static inline QRectF adjustedItemEffectiveBoundingRect(const QGraphicsItem *item) +{ + Q_ASSERT(item); + QRectF boundingRect(item->effectiveBoundingRect()); + _q_adjustRect(&boundingRect); + return boundingRect; +} + QT_END_NAMESPACE #endif // QT_NO_GRAPHICSVIEW -- cgit v0.12 From 787f2252077434581101df64d0f0d576c26b7ce8 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Thu, 23 Jul 2009 13:53:06 +1000 Subject: Add QPixmapBlurFilter for non-convolution blur effects. Reviewed-by: trustme --- src/gui/graphicsview/qgraphicseffect.cpp | 28 ++-- src/gui/image/qpixmapfilter.cpp | 235 +++++++++++++++++++++++++++++++ src/gui/image/qpixmapfilter_p.h | 28 ++++ 3 files changed, 276 insertions(+), 15 deletions(-) diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index a1519c4..6b1f12a 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -346,9 +346,15 @@ class QGraphicsBlurEffectPrivate : public QGraphicsEffectPrivate Q_DECLARE_PUBLIC(QGraphicsBlurEffect) public: QGraphicsBlurEffectPrivate() - : blurRadius(4) { } + { + filter = new QPixmapBlurFilter; + } + ~QGraphicsBlurEffectPrivate() + { + delete filter; + } - int blurRadius; + QPixmapBlurFilter *filter; }; QGraphicsBlurEffect::QGraphicsBlurEffect(QObject *parent) @@ -428,22 +434,19 @@ static QImage blurred(const QImage& image, const QRect& rect, int radius) int QGraphicsBlurEffect::blurRadius() const { Q_D(const QGraphicsBlurEffect); - return d->blurRadius; + return int(d->filter->blurRadius()); } void QGraphicsBlurEffect::setBlurRadius(int radius) { Q_D(QGraphicsBlurEffect); - d->blurRadius = radius; + d->filter->setBlurRadius(radius); } QRectF QGraphicsBlurEffect::boundingRectFor(const QGraphicsItem *item) { Q_D(const QGraphicsBlurEffect); - qreal delta = d->blurRadius * 3; - QRectF blurRect = item->boundingRect(); - blurRect.adjust(-delta, -delta, delta, delta); - return blurRect; + return d->filter->boundingRectFor(item->boundingRect()); } void QGraphicsBlurEffect::drawItem(QGraphicsItem *item, QPainter *painter, @@ -461,15 +464,10 @@ void QGraphicsBlurEffect::drawItem(QGraphicsItem *item, QPainter *painter, if (!pixmap) return; - // blur routine - int radius = d->blurRadius; - QImage img = pixmap->toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); - img = blurred(img, img.rect(), radius); - - // Draw using an untransformed painter. + // Draw the pixmap with the filter using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - painter->drawImage(deviceRect.topLeft() - QPointF(radius * 3, radius * 3), img); + d->filter->draw(painter, deviceRect.topLeft(), *pixmap, pixmap->rect()); painter->setWorldTransform(restoreTransform); } diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp index 184bd65..2b275a3 100644 --- a/src/gui/image/qpixmapfilter.cpp +++ b/src/gui/image/qpixmapfilter.cpp @@ -93,6 +93,9 @@ public: \value DropShadowFilter A filter that is used to add a drop shadow to an image. See QPixmapDropShadowFilter for more information. + \value BlurFilter A filter that is used to blur an image using + a simple blur radius. See QPixmapBlurFilter + for more information. \value UserFilter The first filter type that can be used for application-specific purposes. @@ -837,4 +840,236 @@ void QPixmapDropShadowFilter::draw(QPainter *p, // Draw the actual pixmap... p->drawPixmap(pos, px, src); } + +/*! + \class QPixmapBlurFilter + \since 4.6 + \ingroup multimedia + + \brief The QPixmapBlurFilter class is a convenience class + for drawing pixmaps with blur effects. + + By default, the blur effect is produced by applying an exponential + filter generated from the specified blurRadius(). Paint engines + may override this with a custom blur that is faster on the + underlying hardware. + + \sa QPixmapConvolutionFilter + + \internal + */ + +class QPixmapBlurFilterPrivate : public QPixmapFilterPrivate +{ +public: + QPixmapBlurFilterPrivate() + : quality(QPixmapBlurFilter::High), radius(1) {} + + QPixmapBlurFilter::BlurQuality quality; + qreal radius; +}; + +/*! + Constructs blur filter and attaches it to \a parent. + + \internal +*/ +QPixmapBlurFilter::QPixmapBlurFilter(QObject *parent) + : QPixmapFilter(*new QPixmapBlurFilterPrivate, BlurFilter, parent) +{ + Q_D(QPixmapBlurFilter); + setBlurRadius(4); +} + +/*! + Destroys blur filter. + + \internal +*/ +QPixmapBlurFilter::~QPixmapBlurFilter() +{ +} + +/*! + \enum QPixmapFilter::BlurQuality + \since 4.6 + \ingroup multimedia + This enum describes the quality of blur to apply to pixmaps. + + \value Fast Blur faster, potentially losing some quality. + \value High Produce the best high-quality blur possible, even if slower. + + \internal +*/ + +/*! + Returns the quality of the blur. The default value is High. + + \sa blurRadius() + \internal +*/ +QPixmapBlurFilter::BlurQuality QPixmapBlurFilter::blurQuality() const +{ + Q_D(const QPixmapBlurFilter); + return d->quality; +} + +/*! + Sets the quality of the blur to the \a blurQuality specified. + + Setting the quality to Faster causes the implementation to trade + off visual quality to blur the image faster. Setting the quality + to High causes the implementation to improve visual quality + at the expense of speed. The implementation is free to ignore + this value if it only has a single blur algorithm. + + \sa setBlurRadius() + \internal +*/ +void QPixmapBlurFilter::setBlurQuality(BlurQuality blurQuality) +{ + Q_D(QPixmapBlurFilter); + d->quality = blurQuality; +} + +/*! + Returns the radius in pixels of the blur. The default value is 4. + + A smaller radius results in a sharper image. + + \sa blurQuality() + \internal +*/ +qreal QPixmapBlurFilter::blurRadius() const +{ + Q_D(const QPixmapBlurFilter); + return d->radius; +} + +/*! + Sets the radius in pixels of the blur to the \a radius specified. + + Using a smaller radius results in a sharper image. + + \sa setBlurQuality() + \internal +*/ +void QPixmapBlurFilter::setBlurRadius(qreal blurRadius) +{ + Q_D(QPixmapBlurFilter); + d->radius = blurRadius; +} + +/*! + \internal + */ +QRectF QPixmapBlurFilter::boundingRectFor(const QRectF &rect) const +{ + Q_D(const QPixmapBlurFilter); + qreal delta = d->radius * 3; + QRectF blurRect(rect); + blurRect.adjust(-delta, -delta, delta, delta); + return blurRect; +} + +// Blur the image according to the blur radius +// Based on exponential blur algorithm by Jani Huhtanen +// (maximum radius is set to 16) +static QImage blurred(const QImage& image, const QRect& rect, int radius) +{ + int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 }; + int alpha = (radius < 1) ? 16 : (radius > 17) ? 1 : tab[radius-1]; + + QImage result = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); + int r1 = rect.top(); + int r2 = rect.bottom(); + int c1 = rect.left(); + int c2 = rect.right(); + + int bpl = result.bytesPerLine(); + int rgba[4]; + unsigned char* p; + + for (int col = c1; col <= c2; col++) { + p = result.scanLine(r1) + col * 4; + for (int i = 0; i < 4; i++) + rgba[i] = p[i] << 4; + + p += bpl; + for (int j = r1; j < r2; j++, p += bpl) + for (int i = 0; i < 4; i++) + p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; + } + + for (int row = r1; row <= r2; row++) { + p = result.scanLine(row) + c1 * 4; + for (int i = 0; i < 4; i++) + rgba[i] = p[i] << 4; + + p += 4; + for (int j = c1; j < c2; j++, p += 4) + for (int i = 0; i < 4; i++) + p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; + } + + for (int col = c1; col <= c2; col++) { + p = result.scanLine(r2) + col * 4; + for (int i = 0; i < 4; i++) + rgba[i] = p[i] << 4; + + p -= bpl; + for (int j = r1; j < r2; j++, p -= bpl) + for (int i = 0; i < 4; i++) + p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; + } + + for (int row = r1; row <= r2; row++) { + p = result.scanLine(row) + c2 * 4; + for (int i = 0; i < 4; i++) + rgba[i] = p[i] << 4; + + p -= 4; + for (int j = c1; j < c2; j++, p -= 4) + for (int i = 0; i < 4; i++) + p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; + } + + return result; +} + +/*! + \internal + */ +void QPixmapBlurFilter::draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const +{ + Q_D(const QPixmapBlurFilter); + + QPixmapFilter *filter = painter->paintEngine() && painter->paintEngine()->isExtended() ? + static_cast(painter->paintEngine())->createPixmapFilter(type()) : 0; + QPixmapBlurFilter *blurFilter = static_cast(filter); + if (blurFilter) { + blurFilter->setBlurQuality(d->quality); + blurFilter->setBlurRadius(d->radius); + blurFilter->draw(painter, dest, src, srcRect); + delete blurFilter; + return; + } + + QImage srcImage; + QImage destImage; + + if (srcRect.isNull()) { + srcImage = src.toImage(); + destImage = blurred(srcImage, srcImage.rect(), int(d->radius + 0.5)); + } else { + QRect rect = srcRect.toAlignedRect().intersected(src.rect()); + + srcImage = src.copy(rect).toImage(); + destImage = blurred(srcImage, srcImage.rect(), int(d->radius + 0.5)); + } + + qreal delta = d->radius * 3; + painter->drawImage(dest - QPointF(delta, delta), destImage); +} + QT_END_NAMESPACE diff --git a/src/gui/image/qpixmapfilter_p.h b/src/gui/image/qpixmapfilter_p.h index 51292b3..ca27cbf 100644 --- a/src/gui/image/qpixmapfilter_p.h +++ b/src/gui/image/qpixmapfilter_p.h @@ -78,6 +78,7 @@ public: ConvolutionFilter, ColorizeFilter, DropShadowFilter, + BlurFilter, UserFilter = 1024 }; @@ -158,6 +159,33 @@ public: inline void setOffset(qreal dx, qreal dy) { setOffset(QPointF(dx, dy)); } }; +class QPixmapBlurFilterPrivate; + +class Q_GUI_EXPORT QPixmapBlurFilter : public QPixmapFilter +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QPixmapBlurFilter) + +public: + QPixmapBlurFilter(QObject *parent = 0); + ~QPixmapBlurFilter(); + + enum BlurQuality + { + Fast, + High + }; + + BlurQuality blurQuality() const; + void setBlurQuality(BlurQuality blurQuality); + + qreal blurRadius() const; + void setBlurRadius(qreal blurRadius); + + QRectF boundingRectFor(const QRectF &rect) const; + void draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect = QRectF()) const; +}; + QT_END_NAMESPACE QT_END_HEADER -- cgit v0.12 From 140ce8705f47a65bac32e804421b63d0c7b97d7d Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Thu, 23 Jul 2009 17:03:24 +0200 Subject: Initial stab at a custom shader stage API --- src/gui/painting/qpaintengine.h | 1 + .../gl2paintengineex/qglengineshadermanager.cpp | 143 ++++++++++++++------- .../gl2paintengineex/qglengineshadermanager_p.h | 30 ++++- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 6 + .../gl2paintengineex/qpaintengineex_opengl2_p.h | 4 +- src/opengl/opengl.pro | 6 +- 6 files changed, 134 insertions(+), 56 deletions(-) diff --git a/src/gui/painting/qpaintengine.h b/src/gui/painting/qpaintengine.h index 57c9e2d..5298b6a 100644 --- a/src/gui/painting/qpaintengine.h +++ b/src/gui/painting/qpaintengine.h @@ -210,6 +210,7 @@ public: Direct3D, Pdf, OpenVG, + OpenGL2, User = 50, // first user type id MaxUser = 100 // last user type id diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index d7c91b8..327a699 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -308,6 +308,37 @@ void QGLEngineShaderManager::setCompositionMode(QPainter::CompositionMode mode) shaderProgNeedsChanging = true; //### } +void QGLEngineShaderManager::setCustomStage(QGLCustomShaderStage* stage) +{ + customSrcStage = stage; + shaderProgNeedsChanging = true; +} + +void QGLEngineShaderManager::removeCustomStage(QGLCustomShaderStage* stage) +{ + Q_UNUSED(stage); // Currently we only support one at a time... + + QGLShader* compiledShader = compiledShaders[CustomImageSrcFragmentShader]; + + if (!compiledShader) + return; + + // Remove any shader programs which has this as the srcPixel shader: + for (int i = 0; i < cachedPrograms.size(); ++i) { + QGLEngineShaderProg &prog = cachedPrograms[i]; + if (prog.srcPixelFragShader == compiledShader) { + delete prog.program; + cachedPrograms.removeOne(prog); + break; + } + } + + delete compiledShader; + compiledShaders[CustomImageSrcFragmentShader] = 0; + shaderProgNeedsChanging = true; +} + + QGLShaderProgram* QGLEngineShaderManager::currentProgram() { return currentShaderProg->program; @@ -332,6 +363,12 @@ bool QGLEngineShaderManager::useCorrectShaderProg() if (!shaderProgNeedsChanging) return false; + bool useCustomSrc = customSrcStage != 0; + if (useCustomSrc && srcPixelType != QGLEngineShaderManager::ImageSrc) { + useCustomSrc = false; + qWarning("QGLEngineShaderManager - Ignoring custom shader stage for non image src"); + } + QGLEngineShaderProg requiredProgram; requiredProgram.program = 0; @@ -363,7 +400,11 @@ bool QGLEngineShaderManager::useCorrectShaderProg() qCritical("QGLEngineShaderManager::useCorrectShaderProg() - I'm scared, Qt::NoBrush style is set"); break; case QGLEngineShaderManager::ImageSrc: - srcPixelFragShaderName = ImageSrcFragmentShader; + srcPixelFragShaderName = useCustomSrc ? CustomImageSrcFragmentShader : ImageSrcFragmentShader; + positionVertexShaderName = PositionOnlyVertexShader; + break; + case QGLEngineShaderManager::NonPremultipliedImageSrc: + srcPixelFragShaderName = NonPremultipliedImageSrcFragmentShader; positionVertexShaderName = PositionOnlyVertexShader; break; case QGLEngineShaderManager::PatternSrc: @@ -375,10 +416,6 @@ bool QGLEngineShaderManager::useCorrectShaderProg() positionVertexShaderName = isAffine ? AffinePositionWithTextureBrushVertexShader : PositionWithTextureBrushVertexShader; break; - case QGLEngineShaderManager::NonPremultipliedImageSrc: - srcPixelFragShaderName = NonPremultipliedImageSrcFragmentShader; - positionVertexShaderName = PositionOnlyVertexShader; - break; case Qt::SolidPattern: srcPixelFragShaderName = SolidBrushSrcFragmentShader; positionVertexShaderName = PositionOnlyVertexShader; @@ -500,60 +537,63 @@ bool QGLEngineShaderManager::useCorrectShaderProg() // At this point, requiredProgram is fully populated so try to find the program in the cache + bool foundProgramInCache = false; for (int i = 0; i < cachedPrograms.size(); ++i) { - QGLEngineShaderProg &prog = cachedPrograms[i]; - if ( (prog.mainVertexShader == requiredProgram.mainVertexShader) - && (prog.positionVertexShader == requiredProgram.positionVertexShader) - && (prog.mainFragShader == requiredProgram.mainFragShader) - && (prog.srcPixelFragShader == requiredProgram.srcPixelFragShader) - && (prog.compositionFragShader == requiredProgram.compositionFragShader) ) - { - currentShaderProg = &prog; - currentShaderProg->program->enable(); - shaderProgNeedsChanging = false; - return true; + if (cachedPrograms[i] == requiredProgram) { + currentShaderProg = &cachedPrograms[i]; + foundProgramInCache = true; + break; } } - // Shader program not found in cache, create it now. - requiredProgram.program = new QGLShaderProgram(ctx, this); - requiredProgram.program->addShader(requiredProgram.mainVertexShader); - requiredProgram.program->addShader(requiredProgram.positionVertexShader); - requiredProgram.program->addShader(requiredProgram.mainFragShader); - requiredProgram.program->addShader(requiredProgram.srcPixelFragShader); - requiredProgram.program->addShader(requiredProgram.maskFragShader); - requiredProgram.program->addShader(requiredProgram.compositionFragShader); - - // We have to bind the vertex attribute names before the program is linked: - requiredProgram.program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); - if (useTextureCoords) - requiredProgram.program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); - - requiredProgram.program->link(); - if (!requiredProgram.program->isLinked()) { - QString error; - qWarning() << "Shader program failed to link," + // If the shader program's not found in the cache, create it now. + while (!foundProgramInCache) { + requiredProgram.program = new QGLShaderProgram(ctx, this); + requiredProgram.program->addShader(requiredProgram.mainVertexShader); + requiredProgram.program->addShader(requiredProgram.positionVertexShader); + requiredProgram.program->addShader(requiredProgram.mainFragShader); + requiredProgram.program->addShader(requiredProgram.srcPixelFragShader); + requiredProgram.program->addShader(requiredProgram.maskFragShader); + requiredProgram.program->addShader(requiredProgram.compositionFragShader); + + // We have to bind the vertex attribute names before the program is linked: + requiredProgram.program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); + if (useTextureCoords) + requiredProgram.program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); + + requiredProgram.program->link(); + if (!requiredProgram.program->isLinked()) { + QString error; + qWarning() << "Shader program failed to link," #if defined(QT_DEBUG) - << '\n' - << " Shaders Used:" << '\n' - << " mainVertexShader = " << requiredProgram.mainVertexShader->objectName() << '\n' - << " positionVertexShader = " << requiredProgram.positionVertexShader->objectName() << '\n' - << " mainFragShader = " << requiredProgram.mainFragShader->objectName() << '\n' - << " srcPixelFragShader = " << requiredProgram.srcPixelFragShader->objectName() << '\n' - << " maskFragShader = " << requiredProgram.maskFragShader->objectName() << '\n' - << " compositionFragShader = "<< requiredProgram.compositionFragShader->objectName() << '\n' + << '\n' + << " Shaders Used:" << '\n' + << " mainVertexShader = " << requiredProgram.mainVertexShader->objectName() << '\n' + << " positionVertexShader = " << requiredProgram.positionVertexShader->objectName() << '\n' + << " mainFragShader = " << requiredProgram.mainFragShader->objectName() << '\n' + << " srcPixelFragShader = " << requiredProgram.srcPixelFragShader->objectName() << '\n' + << " maskFragShader = " << requiredProgram.maskFragShader->objectName() << '\n' + << " compositionFragShader = "<< requiredProgram.compositionFragShader->objectName() << '\n' #endif - << " Error Log:" << '\n' - << " " << requiredProgram.program->log(); - qWarning() << error; - } - else { + << " Error Log:" << '\n' + << " " << requiredProgram.program->log(); + qWarning() << error; + delete requiredProgram.program; + break; + } + cachedPrograms.append(requiredProgram); // taking the address here is safe since // cachePrograms isn't resized anywhere else currentShaderProg = &cachedPrograms.last(); + } + + if (currentShaderProg) { currentShaderProg->program->enable(); + if (useCustomSrc) + customSrcStage->setUniforms(currentShaderProg->program); } + shaderProgNeedsChanging = false; return true; } @@ -564,7 +604,14 @@ void QGLEngineShaderManager::compileNamedShader(QGLEngineShaderManager::ShaderNa return; QGLShader *newShader = new QGLShader(type, ctx, this); - newShader->compile(qglEngineShaderSourceCode[name]); + + const char* sourceCode; + if (name == CustomImageSrcFragmentShader) + sourceCode = customSrcStage->source(); + else + sourceCode = qglEngineShaderSourceCode[name]; + + newShader->compile(sourceCode); #if defined(QT_DEBUG) // Name the shader for easier debugging diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h index 99711bd40..15082c3 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h @@ -205,12 +205,16 @@ The use of custom shader code is supported by the engine for drawImage and drawPixmap calls. This is implemented via hooks in the fragment pipeline. The custom shader is passed to the engine as a partial fragment shader - (QGLCustomizedShader). The shader will implement a pre-defined method name - which Qt's fragment pipeline will call. There are two different hooks which - can be implemented as custom shader code: + (QGLCustomShaderStage). The shader will implement a pre-defined method name + which Qt's fragment pipeline will call: - mediump vec4 customShader(sampler2d src, vec2 srcCoords) - mediump vec4 customShaderWithDest(sampler2d dest, sampler2d src, vec2 srcCoords) + lowp vec4 customShader() + + Depending on the custom type, the custom shader has a small API it can use + to read pixels. The basic custom type is for image/pixmap drawing and thus + can use the following to sample the src texture (non-premultiplied) + + lowp vec4 QSampleSrcPixel(mediump vec2 coords) */ @@ -221,6 +225,7 @@ #include #include #include +#include QT_BEGIN_HEADER @@ -240,6 +245,17 @@ struct QGLEngineShaderProg QGLShaderProgram* program; QVector uniformLocations; + + bool operator==(const QGLEngineShaderProg& other) { + // We don't care about the program + return ( mainVertexShader == other.mainVertexShader && + positionVertexShader == other.positionVertexShader && + mainFragShader == other.mainFragShader && + srcPixelFragShader == other.srcPixelFragShader && + maskFragShader == other.maskFragShader && + compositionFragShader == other.compositionFragShader + ); + } }; /* @@ -305,6 +321,8 @@ public: void setUseGlobalOpacity(bool); void setMaskType(MaskType); void setCompositionMode(QPainter::CompositionMode); + void setCustomStage(QGLCustomShaderStage* stage); + void removeCustomStage(QGLCustomShaderStage* stage); uint getUniformLocation(Uniform id); @@ -346,6 +364,7 @@ public: ImageSrcFragmentShader, ImageSrcWithPatternFragmentShader, NonPremultipliedImageSrcFragmentShader, + CustomImageSrcFragmentShader, SolidBrushSrcFragmentShader, TextureBrushSrcFragmentShader, TextureBrushSrcWithPatternFragmentShader, @@ -401,6 +420,7 @@ private: MaskType maskType; bool useTextureCoords; QPainter::CompositionMode compositionMode; + QGLCustomShaderStage* customSrcStage; QGLShaderProgram* blitShaderProg; QGLShaderProgram* simpleShaderProg; diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 167eb64..b04c7e6 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -690,6 +690,12 @@ void QGL2PaintEngineEx::sync() d->needsSync = true; } +const QGLContext *QGL2PaintEngineEx::context() +{ + Q_D(QGL2PaintEngineEx); + return d->ctx; +} + void QGL2PaintEngineExPrivate::transferMode(EngineMode newMode) { if (newMode == mode) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index ec447a3..21c296d 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -121,7 +121,7 @@ public: Qt::ImageConversionFlags flags = Qt::AutoColor); virtual void drawTextItem(const QPointF &p, const QTextItem &textItem); - Type type() const { return OpenGL; } + Type type() const { return OpenGL2; } void setState(QPainterState *s); QPainterState *createState(QPainterState *orig) const; @@ -133,10 +133,12 @@ public: } virtual void sync(); + const QGLContext* context(); private: Q_DISABLE_COPY(QGL2PaintEngineEx) }; + class QGL2PaintEngineExPrivate : public QPaintEngineExPrivate { Q_DECLARE_PUBLIC(QGL2PaintEngineEx) diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro index c92b8cf..5a76cb1 100644 --- a/src/opengl/opengl.pro +++ b/src/opengl/opengl.pro @@ -44,7 +44,8 @@ SOURCES += qgl.cpp \ gl2paintengineex/qglengineshadermanager_p.h \ gl2paintengineex/qgl2pexvertexarray_p.h \ gl2paintengineex/qpaintengineex_opengl2_p.h \ - gl2paintengineex/qglengineshadersource_p.h + gl2paintengineex/qglengineshadersource_p.h \ + gl2paintengineex/qglcustomshaderstage_p.h SOURCES += qglshaderprogram.cpp \ qglpixmapfilter.cpp \ @@ -54,7 +55,8 @@ SOURCES += qgl.cpp \ gl2paintengineex/qglgradientcache.cpp \ gl2paintengineex/qglengineshadermanager.cpp \ gl2paintengineex/qgl2pexvertexarray.cpp \ - gl2paintengineex/qpaintengineex_opengl2.cpp + gl2paintengineex/qpaintengineex_opengl2.cpp \ + gl2paintengineex/qglcustomshaderstage.cpp } -- cgit v0.12 From b31186b720d239daad69c49d8a862dce4e301d5d Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Thu, 23 Jul 2009 17:36:42 +0200 Subject: Actually add the files... :-) --- .../gl2paintengineex/qglcustomshaderstage.cpp | 106 +++++++++++++++++++++ .../gl2paintengineex/qglcustomshaderstage_p.h | 90 +++++++++++++++++ 2 files changed, 196 insertions(+) create mode 100644 src/opengl/gl2paintengineex/qglcustomshaderstage.cpp create mode 100644 src/opengl/gl2paintengineex/qglcustomshaderstage_p.h diff --git a/src/opengl/gl2paintengineex/qglcustomshaderstage.cpp b/src/opengl/gl2paintengineex/qglcustomshaderstage.cpp new file mode 100644 index 0000000..efc3b93 --- /dev/null +++ b/src/opengl/gl2paintengineex/qglcustomshaderstage.cpp @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenGL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qglcustomshaderstage_p.h" +#include "qglengineshadermanager_p.h" +#include "qpaintengineex_opengl2_p.h" +#include + +class QGLCustomShaderStagePrivate +{ +public: + QGLCustomShaderStagePrivate() : + m_manager(0) {} + + QGLEngineShaderManager* m_manager; + QByteArray m_source; +}; + + + + +QGLCustomShaderStage::QGLCustomShaderStage() + : d_ptr(new QGLCustomShaderStagePrivate) +{ +} + +QGLCustomShaderStage::~QGLCustomShaderStage() +{ + Q_D(QGLCustomShaderStage); + if (d->m_manager) + d->m_manager->removeCustomStage(this); +} + +void QGLCustomShaderStage::setUniformsDirty() +{ + Q_D(QGLCustomShaderStage); + if (d->m_manager) + d->m_manager->setDirty(); // ### Probably a bit overkill! +} + +bool QGLCustomShaderStage::setOnPainter(QPainter* p) +{ + Q_D(QGLCustomShaderStage); + if (p->paintEngine()->type() != QPaintEngine::OpenGL2) { + qWarning("QGLCustomShaderStage::setOnPainter() - paint engine not OpenGL2"); + return false; + } + + // Might as well go through the paint engine to get to the context + const QGLContext* ctx = static_cast(p->paintEngine())->context(); + d->m_manager = QGLEngineShaderManager::managerForContext(ctx); + Q_ASSERT(d->m_manager); + + d->m_manager->setCustomStage(this); + return true; +} + +const char* QGLCustomShaderStage::source() +{ + Q_D(QGLCustomShaderStage); + return d->m_source.constData(); +} + +void QGLCustomShaderStage::setSource(const QByteArray& s) +{ + Q_D(QGLCustomShaderStage); + d->m_source = s; +} diff --git a/src/opengl/gl2paintengineex/qglcustomshaderstage_p.h b/src/opengl/gl2paintengineex/qglcustomshaderstage_p.h new file mode 100644 index 0000000..6e4ca1c --- /dev/null +++ b/src/opengl/gl2paintengineex/qglcustomshaderstage_p.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenGL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#ifndef QGL_CUSTOM_SHADER_STAGE_H +#define QGL_CUSTOM_SHADER_STAGE_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(OpenGL) + +class QGLCustomShaderStagePrivate; +class Q_OPENGL_EXPORT QGLCustomShaderStage +{ + Q_DECLARE_PRIVATE(QGLCustomShaderStage); +public: + QGLCustomShaderStage(); + virtual ~QGLCustomShaderStage(); + virtual void setUniforms(QGLShaderProgram*) = 0; + + void setUniformsDirty(); + bool setOnPainter(QPainter*); + const char* source(); + +protected: + void setSource(const QByteArray&); + +private: + QGLCustomShaderStagePrivate* d_ptr; +}; + + +QT_END_NAMESPACE + +QT_END_HEADER + + +#endif -- cgit v0.12 From 8e18256d023e6e78081a34b573d548d52137575d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 22 Jul 2009 09:15:55 +0200 Subject: QGraphicsEffect API cleanup. --- examples/graphicsview/blurpicker/blureffect.cpp | 2 +- examples/graphicsview/blurpicker/blureffect.h | 2 +- examples/graphicsview/blurpicker/blurpicker.cpp | 6 +- examples/graphicsview/blurpicker/blurpicker.h | 1 - examples/graphicsview/lighting/lighting.cpp | 4 +- examples/graphicsview/lighting/lighting.h | 1 - examples/graphicsview/lighting/shadoweffect.cpp | 4 +- examples/graphicsview/lighting/shadoweffect.h | 2 +- src/gui/graphicsview/graphicsview.pri | 3 +- src/gui/graphicsview/qgraphicseffect.cpp | 178 +++--------------------- src/gui/graphicsview/qgraphicseffect.h | 37 ++--- src/gui/graphicsview/qgraphicseffect_p.h | 150 ++++++++++++++++++++ src/gui/graphicsview/qgraphicsitem.cpp | 53 ++++--- src/gui/graphicsview/qgraphicsitem.h | 4 +- src/gui/graphicsview/qgraphicsscene.cpp | 4 +- 15 files changed, 234 insertions(+), 217 deletions(-) create mode 100644 src/gui/graphicsview/qgraphicseffect_p.h diff --git a/examples/graphicsview/blurpicker/blureffect.cpp b/examples/graphicsview/blurpicker/blureffect.cpp index 8345d0b..6c2095d 100644 --- a/examples/graphicsview/blurpicker/blureffect.cpp +++ b/examples/graphicsview/blurpicker/blureffect.cpp @@ -43,7 +43,7 @@ #include -BlurEffect::BlurEffect(QObject *parent) +BlurEffect::BlurEffect() : QGraphicsBlurEffect() , m_baseLine(200) { diff --git a/examples/graphicsview/blurpicker/blureffect.h b/examples/graphicsview/blurpicker/blureffect.h index 24a6867..cafd910 100644 --- a/examples/graphicsview/blurpicker/blureffect.h +++ b/examples/graphicsview/blurpicker/blureffect.h @@ -48,7 +48,7 @@ class BlurEffect: public QGraphicsBlurEffect { public: - BlurEffect(QObject *parent = 0); + BlurEffect(); void setBaseLine(qreal y) { m_baseLine = y; } diff --git a/examples/graphicsview/blurpicker/blurpicker.cpp b/examples/graphicsview/blurpicker/blurpicker.cpp index 887d7ef..10ce44f 100644 --- a/examples/graphicsview/blurpicker/blurpicker.cpp +++ b/examples/graphicsview/blurpicker/blurpicker.cpp @@ -79,9 +79,9 @@ void BlurPicker::updateIconPositions() pos -= QPointF(40, 40); icon->setPos(pos); baseline = qMax(baseline, ys); + static_cast(icon->effect())->setBaseLine(baseline); } - m_blurEffect->setBaseLine(baseline); m_scene.update(); } @@ -89,8 +89,6 @@ void BlurPicker::setupScene() { m_scene.setSceneRect(-200, -120, 400, 240); - m_blurEffect = new BlurEffect(this); - QStringList names; names << ":/images/accessories-calculator.png"; names << ":/images/accessories-text-editor.png"; @@ -105,7 +103,7 @@ void BlurPicker::setupScene() QPixmap pixmap(names[i]); QGraphicsPixmapItem *icon = m_scene.addPixmap(pixmap); icon->setZValue(1); - icon->setEffect(m_blurEffect); + icon->setGraphicsEffect(new BlurEffect); m_icons << icon; } diff --git a/examples/graphicsview/blurpicker/blurpicker.h b/examples/graphicsview/blurpicker/blurpicker.h index e41c608..b7ea3b4 100644 --- a/examples/graphicsview/blurpicker/blurpicker.h +++ b/examples/graphicsview/blurpicker/blurpicker.h @@ -67,7 +67,6 @@ private: private: qreal m_index; QGraphicsScene m_scene; - BlurEffect *m_blurEffect; QList m_icons; QTimeLine m_timeLine; }; diff --git a/examples/graphicsview/lighting/lighting.cpp b/examples/graphicsview/lighting/lighting.cpp index 445d7f9..fff2204 100644 --- a/examples/graphicsview/lighting/lighting.cpp +++ b/examples/graphicsview/lighting/lighting.cpp @@ -88,8 +88,6 @@ void Lighting::setupScene() m_lightSource = m_scene.addPixmap(pixmap); m_lightSource->setZValue(2); - m_shadowEffect = new ShadowEffect(m_lightSource, this); - for (int i = -2; i < 3; ++i) for (int j = -2; j < 3; ++j) { QAbstractGraphicsShapeItem *item; @@ -100,7 +98,7 @@ void Lighting::setupScene() item->setPen(QPen(Qt::black)); item->setBrush(QBrush(Qt::white)); - item->setEffect(m_shadowEffect); + item->setGraphicsEffect(new ShadowEffect(m_lightSource)); item->setZValue(1); item->setPos(i * 80, j * 80); m_scene.addItem(item); diff --git a/examples/graphicsview/lighting/lighting.h b/examples/graphicsview/lighting/lighting.h index 66237f6..70a4d48 100644 --- a/examples/graphicsview/lighting/lighting.h +++ b/examples/graphicsview/lighting/lighting.h @@ -64,7 +64,6 @@ private: qreal angle; QGraphicsScene m_scene; QGraphicsItem *m_lightSource; - ShadowEffect *m_shadowEffect; QList m_items; }; diff --git a/examples/graphicsview/lighting/shadoweffect.cpp b/examples/graphicsview/lighting/shadoweffect.cpp index 726cbd0..c1d384a 100644 --- a/examples/graphicsview/lighting/shadoweffect.cpp +++ b/examples/graphicsview/lighting/shadoweffect.cpp @@ -43,8 +43,8 @@ #include -ShadowEffect::ShadowEffect(QGraphicsItem *source, QObject *parent) - : QGraphicsShadowEffect(parent) +ShadowEffect::ShadowEffect(QGraphicsItem *source) + : QGraphicsShadowEffect() , m_lightSource(source) { setBlurRadius(8); diff --git a/examples/graphicsview/lighting/shadoweffect.h b/examples/graphicsview/lighting/shadoweffect.h index 02d0bf1..09b63e3 100644 --- a/examples/graphicsview/lighting/shadoweffect.h +++ b/examples/graphicsview/lighting/shadoweffect.h @@ -48,7 +48,7 @@ class ShadowEffect: public QGraphicsShadowEffect { public: - ShadowEffect(QGraphicsItem *source, QObject *parent = 0); + ShadowEffect(QGraphicsItem *source); QRectF boundingRectFor(const QGraphicsItem *item); diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri index c3cb574..55bb9e0 100644 --- a/src/gui/graphicsview/graphicsview.pri +++ b/src/gui/graphicsview/graphicsview.pri @@ -21,7 +21,8 @@ HEADERS += graphicsview/qgraphicsgridlayout.h \ graphicsview/qgraphicswidget.h \ graphicsview/qgraphicswidget_p.h \ graphicsview/qgridlayoutengine_p.h \ - graphicsview/qgraphicseffect.h + graphicsview/qgraphicseffect.h \ + graphicsview/qgraphicseffect_p.h \ SOURCES += graphicsview/qgraphicsgridlayout.cpp \ graphicsview/qgraphicsitem.cpp \ diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index 6b1f12a..c173d1b 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include "qgraphicseffect.h" +#include "qgraphicseffect_p.h" #ifndef QT_NO_GRAPHICSVIEW @@ -48,9 +48,6 @@ #include #include -#include -#include - /* List of known drawbacks which are being discussed: @@ -105,19 +102,11 @@ */ -/*! - \internal -*/ -class QGraphicsEffectPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsEffect) -public: - QGraphicsEffectPrivate() {} -}; - -QGraphicsEffect::QGraphicsEffect(QObject *parent) - : QObject(*new QGraphicsEffectPrivate, parent) +QGraphicsEffect::QGraphicsEffect() + : QObject(*new QGraphicsEffectPrivate, 0) { + Q_D(QGraphicsEffect); + d->parentItem = 0; } QGraphicsEffect::~QGraphicsEffect() @@ -134,9 +123,11 @@ QRectF QGraphicsEffect::boundingRectFor(const QGraphicsItem *item) /*! \internal */ -QGraphicsEffect::QGraphicsEffect(QGraphicsEffectPrivate &dd, QObject *parent) - : QObject(dd, parent) +QGraphicsEffect::QGraphicsEffect(QGraphicsEffectPrivate &dd) + : QObject(dd, 0) { + Q_D(QGraphicsEffect); + d->parentItem = 0; } // this helper function is only for subclasses of QGraphicsEffect @@ -151,27 +142,8 @@ QPixmap* QGraphicsEffect::drawItemOnPixmap(QPainter *painter, QGraphicsItem *ite return item->scene()->drawItemOnPixmap(painter, item, option, widget, flags); } -/*! - \internal -*/ -class QGraphicsGrayscaleEffectPrivate : public QGraphicsEffectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsGrayscaleEffect) -public: - QGraphicsGrayscaleEffectPrivate() { - filter = new QPixmapColorizeFilter; - filter->setColor(Qt::black); - } - - ~QGraphicsGrayscaleEffectPrivate() { - delete filter; - } - - QPixmapColorizeFilter *filter; -}; - -QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect(QObject *parent) - : QGraphicsEffect(*new QGraphicsGrayscaleEffectPrivate, parent) +QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect() + : QGraphicsEffect(*new QGraphicsGrayscaleEffectPrivate) { } @@ -201,26 +173,8 @@ void QGraphicsGrayscaleEffect::drawItem(QGraphicsItem *item, QPainter *painter, painter->setWorldTransform(restoreTransform); } -/*! - \internal -*/ -class QGraphicsColorizeEffectPrivate : public QGraphicsEffectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsColorizeEffect) -public: - QGraphicsColorizeEffectPrivate() { - filter = new QPixmapColorizeFilter; - } - - ~QGraphicsColorizeEffectPrivate() { - delete filter; - } - - QPixmapColorizeFilter *filter; -}; - -QGraphicsColorizeEffect::QGraphicsColorizeEffect(QObject *parent) - : QGraphicsEffect(*new QGraphicsColorizeEffectPrivate, parent) +QGraphicsColorizeEffect::QGraphicsColorizeEffect() + : QGraphicsEffect(*new QGraphicsColorizeEffectPrivate) { } @@ -262,21 +216,8 @@ void QGraphicsColorizeEffect::drawItem(QGraphicsItem *item, QPainter *painter, painter->setWorldTransform(restoreTransform); } -/*! - \internal -*/ -class QGraphicsPixelizeEffectPrivate : public QGraphicsEffectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsPixelizeEffect) -public: - QGraphicsPixelizeEffectPrivate() - : pixelSize(3) { } - - int pixelSize; -}; - -QGraphicsPixelizeEffect::QGraphicsPixelizeEffect(QObject *parent) - : QGraphicsEffect(*new QGraphicsPixelizeEffectPrivate, parent) +QGraphicsPixelizeEffect::QGraphicsPixelizeEffect() + : QGraphicsEffect(*new QGraphicsPixelizeEffectPrivate) { } @@ -338,27 +279,8 @@ void QGraphicsPixelizeEffect::drawItem(QGraphicsItem *item, QPainter *painter, painter->setWorldTransform(restoreTransform); } -/*! - \internal -*/ -class QGraphicsBlurEffectPrivate : public QGraphicsEffectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsBlurEffect) -public: - QGraphicsBlurEffectPrivate() - { - filter = new QPixmapBlurFilter; - } - ~QGraphicsBlurEffectPrivate() - { - delete filter; - } - - QPixmapBlurFilter *filter; -}; - -QGraphicsBlurEffect::QGraphicsBlurEffect(QObject *parent) - : QGraphicsEffect(*new QGraphicsBlurEffectPrivate, parent) +QGraphicsBlurEffect::QGraphicsBlurEffect() + : QGraphicsEffect(*new QGraphicsBlurEffectPrivate) { } @@ -471,23 +393,8 @@ void QGraphicsBlurEffect::drawItem(QGraphicsItem *item, QPainter *painter, painter->setWorldTransform(restoreTransform); } -/*! - \internal -*/ -class QGraphicsBloomEffectPrivate : public QGraphicsEffectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsBlurEffect) -public: - QGraphicsBloomEffectPrivate() - : blurRadius(6) - , opacity(0.7) { } - - int blurRadius; - qreal opacity; -}; - -QGraphicsBloomEffect::QGraphicsBloomEffect(QObject *parent) - : QGraphicsEffect(*new QGraphicsBloomEffectPrivate, parent) +QGraphicsBloomEffect::QGraphicsBloomEffect() + : QGraphicsEffect(*new QGraphicsBloomEffectPrivate) { } @@ -588,27 +495,8 @@ void QGraphicsBloomEffect::drawItem(QGraphicsItem *item, QPainter *painter, painter->setWorldTransform(restoreTransform); } -/*! - \internal -*/ -class QGraphicsFrameEffectPrivate : public QGraphicsEffectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsFrameEffect) -public: - QGraphicsFrameEffectPrivate() - : color(Qt::blue) - , width(5) - , alpha(0.6) - { - } - - QColor color; - qreal width; - qreal alpha; -}; - -QGraphicsFrameEffect::QGraphicsFrameEffect(QObject *parent) - : QGraphicsEffect(*new QGraphicsFrameEffectPrivate, parent) +QGraphicsFrameEffect::QGraphicsFrameEffect() + : QGraphicsEffect(*new QGraphicsFrameEffectPrivate) { } @@ -693,28 +581,8 @@ void QGraphicsFrameEffect::drawItem(QGraphicsItem *item, QPainter *painter, painter->restore(); } - -/*! - \internal -*/ -class QGraphicsShadowEffectPrivate : public QGraphicsEffectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsShadowEffect) -public: - QGraphicsShadowEffectPrivate() - : offset(4,4) - , radius(8) - , alpha(0.7) - { - } - - QPointF offset; - int radius; - qreal alpha; -}; - -QGraphicsShadowEffect::QGraphicsShadowEffect(QObject *parent) - : QGraphicsEffect(*new QGraphicsShadowEffectPrivate, parent) +QGraphicsShadowEffect::QGraphicsShadowEffect() + : QGraphicsEffect(*new QGraphicsShadowEffectPrivate) { } diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h index 29d97a6..9f6e342 100644 --- a/src/gui/graphicsview/qgraphicseffect.h +++ b/src/gui/graphicsview/qgraphicseffect.h @@ -67,10 +67,8 @@ class QGraphicsEffectPrivate; class Q_GUI_EXPORT QGraphicsEffect : public QObject { Q_OBJECT - public: - - QGraphicsEffect(QObject *parent = 0); + QGraphicsEffect(); virtual ~QGraphicsEffect(); virtual QRectF boundingRectFor(const QGraphicsItem *item); @@ -80,11 +78,12 @@ public: QWidget *widget = 0) = 0; protected: - QGraphicsEffect(QGraphicsEffectPrivate &d, QObject* parent); + QGraphicsEffect(QGraphicsEffectPrivate &d); QPixmap* drawItemOnPixmap(QPainter *painter, QGraphicsItem *item, const QStyleOptionGraphicsItem *option, QWidget *widget, int flags); private: + friend class QGraphicsItem; Q_DECLARE_PRIVATE(QGraphicsEffect) Q_DISABLE_COPY(QGraphicsEffect) }; @@ -93,10 +92,8 @@ class QGraphicsGrayscaleEffectPrivate; class Q_GUI_EXPORT QGraphicsGrayscaleEffect: public QGraphicsEffect { Q_OBJECT - public: - - QGraphicsGrayscaleEffect(QObject *parent = 0); + QGraphicsGrayscaleEffect(); ~QGraphicsGrayscaleEffect(); void drawItem(QGraphicsItem *item, QPainter *painter, @@ -111,10 +108,8 @@ private: class QGraphicsColorizeEffectPrivate; class Q_GUI_EXPORT QGraphicsColorizeEffect: public QGraphicsEffect { Q_OBJECT - public: - - QGraphicsColorizeEffect(QObject *parent = 0); + QGraphicsColorizeEffect(); ~QGraphicsColorizeEffect(); QColor color() const; @@ -132,10 +127,8 @@ private: class QGraphicsPixelizeEffectPrivate; class Q_GUI_EXPORT QGraphicsPixelizeEffect: public QGraphicsEffect { Q_OBJECT - public: - - QGraphicsPixelizeEffect(QObject *parent = 0); + QGraphicsPixelizeEffect(); ~QGraphicsPixelizeEffect(); int pixelSize() const; @@ -153,10 +146,8 @@ private: class QGraphicsBlurEffectPrivate; class Q_GUI_EXPORT QGraphicsBlurEffect: public QGraphicsEffect { Q_OBJECT - public: - - QGraphicsBlurEffect(QObject *parent = 0); + QGraphicsBlurEffect(); ~QGraphicsBlurEffect(); int blurRadius() const; @@ -176,10 +167,8 @@ private: class QGraphicsBloomEffectPrivate; class Q_GUI_EXPORT QGraphicsBloomEffect: public QGraphicsEffect { Q_OBJECT - public: - - QGraphicsBloomEffect(QObject *parent = 0); + QGraphicsBloomEffect(); ~QGraphicsBloomEffect(); int blurRadius() const; @@ -202,10 +191,8 @@ private: class QGraphicsFrameEffectPrivate; class Q_GUI_EXPORT QGraphicsFrameEffect: public QGraphicsEffect { Q_OBJECT - public: - - QGraphicsFrameEffect(QObject *parent = 0); + QGraphicsFrameEffect(); ~QGraphicsFrameEffect(); QColor frameColor() const; @@ -230,10 +217,8 @@ private: class QGraphicsShadowEffectPrivate; class Q_GUI_EXPORT QGraphicsShadowEffect: public QGraphicsEffect { Q_OBJECT - public: - - QGraphicsShadowEffect(QObject *parent = 0); + QGraphicsShadowEffect(); ~QGraphicsShadowEffect(); QPointF shadowOffset() const; @@ -253,8 +238,6 @@ public: const QStyleOptionGraphicsItem *option = 0, QWidget *widget = 0); -protected: - private: Q_DECLARE_PRIVATE(QGraphicsShadowEffect) Q_DISABLE_COPY(QGraphicsShadowEffect) diff --git a/src/gui/graphicsview/qgraphicseffect_p.h b/src/gui/graphicsview/qgraphicseffect_p.h new file mode 100644 index 0000000..999e013 --- /dev/null +++ b/src/gui/graphicsview/qgraphicseffect_p.h @@ -0,0 +1,150 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSEFFECT_P_H +#define QGRAPHICSEFFECT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +#include "qgraphicseffect.h" +#include +#include + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + +QT_BEGIN_NAMESPACE + +class QGraphicsEffectPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsEffect) +public: + QGraphicsEffectPrivate(): parentItem(0) {} + QGraphicsItem *parentItem; +}; + +class QGraphicsGrayscaleEffectPrivate : public QGraphicsEffectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsGrayscaleEffect) +public: + QGraphicsGrayscaleEffectPrivate() + { + filter = new QPixmapColorizeFilter; + filter->setColor(Qt::black); + } + ~QGraphicsGrayscaleEffectPrivate() { delete filter; } + + QPixmapColorizeFilter *filter; +}; + +class QGraphicsColorizeEffectPrivate : public QGraphicsEffectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsColorizeEffect) +public: + QGraphicsColorizeEffectPrivate() { filter = new QPixmapColorizeFilter; } + ~QGraphicsColorizeEffectPrivate() { delete filter; } + + QPixmapColorizeFilter *filter; +}; + +class QGraphicsPixelizeEffectPrivate : public QGraphicsEffectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsPixelizeEffect) +public: + QGraphicsPixelizeEffectPrivate() : pixelSize(3) {} + + int pixelSize; +}; + +class QGraphicsBlurEffectPrivate : public QGraphicsEffectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsBlurEffect) +public: + QGraphicsBlurEffectPrivate() : blurRadius(4) {} + + int blurRadius; +}; + +class QGraphicsBloomEffectPrivate : public QGraphicsEffectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsBlurEffect) +public: + QGraphicsBloomEffectPrivate() : blurRadius(6), opacity(0.7) {} + + int blurRadius; + qreal opacity; +}; + +class QGraphicsFrameEffectPrivate : public QGraphicsEffectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsFrameEffect) +public: + QGraphicsFrameEffectPrivate() : color(Qt::blue), width(5), alpha(0.6) {} + + QColor color; + qreal width; + qreal alpha; +}; + +class QGraphicsShadowEffectPrivate : public QGraphicsEffectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsShadowEffect) +public: + QGraphicsShadowEffectPrivate() : offset(4,4), radius(8), alpha(0.7) {} + + QPointF offset; + int radius; + qreal alpha; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_GRAPHICSVIEW + +#endif // QGRAPHICSEFFECT_P_H diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index a044fbd..3a350e0 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -552,7 +552,7 @@ #ifndef QT_NO_GRAPHICSVIEW -#include "qgraphicseffect.h" +#include "qgraphicseffect_p.h" #include "qgraphicsscene.h" #include "qgraphicsscene_p.h" #include "qgraphicssceneevent.h" @@ -1180,6 +1180,8 @@ QGraphicsItem::~QGraphicsItem() else d_ptr->setParentItemHelper(0); + QGraphicsEffect *e = graphicsEffect(); + delete e; delete d_ptr->transformData; delete d_ptr; @@ -2190,11 +2192,11 @@ void QGraphicsItem::setOpacity(qreal opacity) } /*! + Returns a pointer to this item's effect if it has one; otherwise 0. + \since 4.6 - Returns this item's \e effect if it has one; otherwise, - returns 0. */ -QGraphicsEffect *QGraphicsItem::effect() const +QGraphicsEffect *QGraphicsItem::graphicsEffect() const { QGraphicsEffect *fx = 0; if (d_ptr->hasEffect) @@ -2204,22 +2206,41 @@ QGraphicsEffect *QGraphicsItem::effect() const } /*! + Sets \a effect as the item's effect. If there already is an effect installed + on this item, QGraphicsItem won't let you install another. You must first + delete the existing effect (returned by graphicsEffect()) before you can call + setGraphicsEffect() with the new effect. + + If \a effect is the installed on a different item, setGraphicsEffect() will remove + the effect from the item and install it on this item. + + \note This function will apply the effect on itself and all its children. + \since 4.6 - Sets \e effect as the item's effect. It will replace the previous effect - the item might have. */ -void QGraphicsItem::setEffect(QGraphicsEffect *effect) +void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect) { if (effect) { - d_ptr->hasEffect = true; - d_ptr->setExtra(QGraphicsItemPrivate::ExtraEffect, QVariant::fromValue(effect)); + if (QGraphicsEffect *currentEffect = this->graphicsEffect()) { + if (currentEffect != effect) { + qWarning("QGraphicsItem::setEffect: Attempting to set QGraphicsEffect " + "%p on %p, which already has an effect", effect, this); + } + return; + } + + if (effect->d_func()->parentItem) + effect->d_func()->parentItem->setGraphicsEffect(0); + effect->d_func()->parentItem = this; + d_ptr->hasEffect = true; + d_ptr->setExtra(QGraphicsItemPrivate::ExtraEffect, QVariant::fromValue(effect)); } else { - d_ptr->hasEffect = false; - d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraEffect); - void *ptr = d_ptr->extra(QGraphicsItemPrivate::ExtraEffectPixmap).value(); - QPixmap *pixmap = reinterpret_cast(ptr); - delete pixmap; - d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraEffectPixmap); + d_ptr->hasEffect = false; + d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraEffect); + void *ptr = d_ptr->extra(QGraphicsItemPrivate::ExtraEffectPixmap).value(); + QPixmap *pixmap = reinterpret_cast(ptr); + delete pixmap; + d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraEffectPixmap); } update(); @@ -2236,7 +2257,7 @@ void QGraphicsItem::setEffect(QGraphicsEffect *effect) */ QRectF QGraphicsItem::effectiveBoundingRect() const { - QGraphicsEffect *fx = effect(); + QGraphicsEffect *fx = graphicsEffect(); if (fx) return fx->boundingRectFor(this); diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index c230928..0beb07c 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -208,8 +208,8 @@ public: void setOpacity(qreal opacity); // Effect - QGraphicsEffect *effect() const; - void setEffect(QGraphicsEffect *effect); + QGraphicsEffect *graphicsEffect() const; + void setGraphicsEffect(QGraphicsEffect *effect); QRectF effectiveBoundingRect() const; QRectF sceneEffectiveBoundingRect() const; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 2807673..c56f34c 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -3928,8 +3928,8 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte #endif // Render using effect, works now only for no cache mode - if (noCache && itemd->hasEffect && item->effect()) { - item->effect()->drawItem(item, painter, option, widget); + if (noCache && itemd->hasEffect && item->graphicsEffect()) { + item->graphicsEffect()->drawItem(item, painter, option, widget); return; } -- cgit v0.12 From 92c19412b5a4178436defee2900119cc05fed191 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Fri, 24 Jul 2009 10:27:00 +1000 Subject: Make ordinary shaders work again after custom shader changes. --- src/opengl/gl2paintengineex/qglengineshadermanager.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index 327a699..c110c50 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -131,6 +131,7 @@ QGLEngineShaderManager::QGLEngineShaderManager(QGLContext* context) code[ImageSrcFragmentShader] = qglslImageSrcFragmentShader; code[ImageSrcWithPatternFragmentShader] = qglslImageSrcWithPatternFragmentShader; code[NonPremultipliedImageSrcFragmentShader] = qglslNonPremultipliedImageSrcFragmentShader; + code[CustomImageSrcFragmentShader] = ""; // Supplied by app. code[SolidBrushSrcFragmentShader] = qglslSolidBrushSrcFragmentShader; code[TextureBrushSrcFragmentShader] = qglslTextureBrushSrcFragmentShader; code[TextureBrushSrcWithPatternFragmentShader] = qglslTextureBrushSrcWithPatternFragmentShader; @@ -547,7 +548,7 @@ bool QGLEngineShaderManager::useCorrectShaderProg() } // If the shader program's not found in the cache, create it now. - while (!foundProgramInCache) { + if (!foundProgramInCache) { requiredProgram.program = new QGLShaderProgram(ctx, this); requiredProgram.program->addShader(requiredProgram.mainVertexShader); requiredProgram.program->addShader(requiredProgram.positionVertexShader); @@ -579,13 +580,12 @@ bool QGLEngineShaderManager::useCorrectShaderProg() << " " << requiredProgram.program->log(); qWarning() << error; delete requiredProgram.program; - break; + } else { + cachedPrograms.append(requiredProgram); + // taking the address here is safe since + // cachePrograms isn't resized anywhere else + currentShaderProg = &cachedPrograms.last(); } - - cachedPrograms.append(requiredProgram); - // taking the address here is safe since - // cachePrograms isn't resized anywhere else - currentShaderProg = &cachedPrograms.last(); } if (currentShaderProg) { -- cgit v0.12 From e646d08593dc18cad4e59176c2fe8c10fa5b9497 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 23 Jul 2009 17:11:54 +0200 Subject: Make QGraphicsEffect independent of QGraphicsItem. This makes it possible to basically implement support for graphics effects on pretty much everything, e.g. QWidget. We currently only support effects on QGraphicsItem, but there's more to come :-) --- examples/graphicsview/blurpicker/blureffect.cpp | 19 +- examples/graphicsview/blurpicker/blureffect.h | 11 +- examples/graphicsview/blurpicker/blurpicker.cpp | 4 +- examples/graphicsview/lighting/lighting.cpp | 2 +- examples/graphicsview/lighting/shadoweffect.cpp | 19 +- examples/graphicsview/lighting/shadoweffect.h | 11 +- src/gui/graphicsview/qgraphicseffect.cpp | 234 ++++++++++++++---------- src/gui/graphicsview/qgraphicseffect.h | 58 +++--- src/gui/graphicsview/qgraphicseffect_p.h | 27 ++- src/gui/graphicsview/qgraphicsitem.cpp | 91 +++------ src/gui/graphicsview/qgraphicsitem.h | 2 - src/gui/graphicsview/qgraphicsitem_p.h | 45 ++++- src/gui/graphicsview/qgraphicsscene.cpp | 72 ++------ src/gui/graphicsview/qgraphicsscene.h | 5 - 14 files changed, 297 insertions(+), 303 deletions(-) diff --git a/examples/graphicsview/blurpicker/blureffect.cpp b/examples/graphicsview/blurpicker/blureffect.cpp index 6c2095d..43791c6 100644 --- a/examples/graphicsview/blurpicker/blureffect.cpp +++ b/examples/graphicsview/blurpicker/blureffect.cpp @@ -43,28 +43,27 @@ #include -BlurEffect::BlurEffect() +BlurEffect::BlurEffect(QGraphicsItem *item) : QGraphicsBlurEffect() - , m_baseLine(200) + , m_baseLine(200), item(item) { } -void BlurEffect::adjustForItem(const QGraphicsItem *item) +void BlurEffect::adjustForItem() { qreal y = m_baseLine - item->pos().y(); qreal radius = qBound(0.0, y / 32, 16.0); setBlurRadius(radius); } -QRectF BlurEffect::boundingRectFor(const QGraphicsItem *item) +QRectF BlurEffect::boundingRect() const { - adjustForItem(item); - return QGraphicsBlurEffect::boundingRectFor(item); + const_cast(this)->adjustForItem(); + return QGraphicsBlurEffect::boundingRect(); } -void BlurEffect::drawItem(QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option, QWidget *widget) +void BlurEffect::draw(QPainter *painter) { - adjustForItem(item); - QGraphicsBlurEffect::drawItem(item, painter, option, widget); + adjustForItem(); + QGraphicsBlurEffect::draw(painter); } diff --git a/examples/graphicsview/blurpicker/blureffect.h b/examples/graphicsview/blurpicker/blureffect.h index cafd910..2aea8bf 100644 --- a/examples/graphicsview/blurpicker/blureffect.h +++ b/examples/graphicsview/blurpicker/blureffect.h @@ -48,21 +48,20 @@ class BlurEffect: public QGraphicsBlurEffect { public: - BlurEffect(); + BlurEffect(QGraphicsItem *item); void setBaseLine(qreal y) { m_baseLine = y; } - QRectF boundingRectFor(const QGraphicsItem *item); + QRectF boundingRect() const; - void drawItem(QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option = 0, - QWidget *widget = 0); + void draw(QPainter *painter); private: - void adjustForItem(const QGraphicsItem *item); + void adjustForItem(); private: qreal m_baseLine; + QGraphicsItem *item; }; #endif // BLUREFFECT_H diff --git a/examples/graphicsview/blurpicker/blurpicker.cpp b/examples/graphicsview/blurpicker/blurpicker.cpp index 10ce44f..9904dfa 100644 --- a/examples/graphicsview/blurpicker/blurpicker.cpp +++ b/examples/graphicsview/blurpicker/blurpicker.cpp @@ -79,7 +79,7 @@ void BlurPicker::updateIconPositions() pos -= QPointF(40, 40); icon->setPos(pos); baseline = qMax(baseline, ys); - static_cast(icon->effect())->setBaseLine(baseline); + static_cast(icon->graphicsEffect())->setBaseLine(baseline); } m_scene.update(); @@ -103,7 +103,7 @@ void BlurPicker::setupScene() QPixmap pixmap(names[i]); QGraphicsPixmapItem *icon = m_scene.addPixmap(pixmap); icon->setZValue(1); - icon->setGraphicsEffect(new BlurEffect); + icon->setGraphicsEffect(new BlurEffect(icon)); m_icons << icon; } diff --git a/examples/graphicsview/lighting/lighting.cpp b/examples/graphicsview/lighting/lighting.cpp index fff2204..63f0a6c 100644 --- a/examples/graphicsview/lighting/lighting.cpp +++ b/examples/graphicsview/lighting/lighting.cpp @@ -98,7 +98,7 @@ void Lighting::setupScene() item->setPen(QPen(Qt::black)); item->setBrush(QBrush(Qt::white)); - item->setGraphicsEffect(new ShadowEffect(m_lightSource)); + item->setGraphicsEffect(new ShadowEffect(item, m_lightSource)); item->setZValue(1); item->setPos(i * 80, j * 80); m_scene.addItem(item); diff --git a/examples/graphicsview/lighting/shadoweffect.cpp b/examples/graphicsview/lighting/shadoweffect.cpp index c1d384a..e2dd864 100644 --- a/examples/graphicsview/lighting/shadoweffect.cpp +++ b/examples/graphicsview/lighting/shadoweffect.cpp @@ -43,14 +43,14 @@ #include -ShadowEffect::ShadowEffect(QGraphicsItem *source) +ShadowEffect::ShadowEffect(QGraphicsItem *item, QGraphicsItem *source) : QGraphicsShadowEffect() - , m_lightSource(source) + , item(item), m_lightSource(source) { setBlurRadius(8); } -void ShadowEffect::adjustForItem(const QGraphicsItem *item) +void ShadowEffect::adjustForItem() { QPointF delta = item->pos() - m_lightSource->pos(); setShadowOffset(delta.toPoint() / 30); @@ -61,15 +61,14 @@ void ShadowEffect::adjustForItem(const QGraphicsItem *item) setOpacity(qBound(0.4, 1 - dd / 200.0, 0.7)); } -QRectF ShadowEffect::boundingRectFor(const QGraphicsItem *item) +QRectF ShadowEffect::boundingRect() const { - adjustForItem(item); - return QGraphicsShadowEffect::boundingRectFor(item); + const_cast(this)->adjustForItem(); + return QGraphicsShadowEffect::boundingRect(); } -void ShadowEffect::drawItem(QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option, QWidget *widget) +void ShadowEffect::draw(QPainter *painter) { - adjustForItem(item); - QGraphicsShadowEffect::drawItem(item, painter, option, widget); + adjustForItem(); + QGraphicsShadowEffect::draw(painter); } diff --git a/examples/graphicsview/lighting/shadoweffect.h b/examples/graphicsview/lighting/shadoweffect.h index 09b63e3..d4aa440 100644 --- a/examples/graphicsview/lighting/shadoweffect.h +++ b/examples/graphicsview/lighting/shadoweffect.h @@ -48,18 +48,17 @@ class ShadowEffect: public QGraphicsShadowEffect { public: - ShadowEffect(QGraphicsItem *source); + ShadowEffect(QGraphicsItem *item, QGraphicsItem *source); - QRectF boundingRectFor(const QGraphicsItem *item); + QRectF boundingRect() const; - void drawItem(QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option = 0, - QWidget *widget = 0); + void draw(QPainter *painter); private: - void adjustForItem(const QGraphicsItem *item); + void adjustForItem(); private: + QGraphicsItem *item; QGraphicsItem *m_lightSource; }; diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index c173d1b..8d2c416 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -104,83 +104,90 @@ QGraphicsEffect::QGraphicsEffect() : QObject(*new QGraphicsEffectPrivate, 0) +{} + +/*! + \internal +*/ +QGraphicsEffect::QGraphicsEffect(QGraphicsEffectPrivate &dd) + : QObject(dd, 0) +{} + +QGraphicsEffect::~QGraphicsEffect() { Q_D(QGraphicsEffect); - d->parentItem = 0; + d->setGraphicsEffectSource(0); } -QGraphicsEffect::~QGraphicsEffect() +QRectF QGraphicsEffect::boundingRect() const { + return sourceBoundingRect(); } -QRectF QGraphicsEffect::boundingRectFor(const QGraphicsItem *item) +QRectF QGraphicsEffect::sourceBoundingRect() const { - // default is to give the item's bounding rect - // do NOT call item->effectiveBoundRect() because - // that function will call this one (infinite loop) - return item->boundingRect(); + Q_D(const QGraphicsEffect); + if (d->source) + return d->source->boundingRect(); + return QRectF(); } -/*! \internal -*/ -QGraphicsEffect::QGraphicsEffect(QGraphicsEffectPrivate &dd) - : QObject(dd, 0) +void QGraphicsEffect::drawSource(QPainter *painter) { Q_D(QGraphicsEffect); - d->parentItem = 0; + if (d->source) + d->source->draw(painter); } -// this helper function is only for subclasses of QGraphicsEffect -// the implementation is trivial, but this allows us to keep -// QGraphicsScene::drawItem() as a protected function -// (since QGraphicsEffect is a friend of QGraphicsScene) -QPixmap* QGraphicsEffect::drawItemOnPixmap(QPainter *painter, QGraphicsItem *item, - const QStyleOptionGraphicsItem *option, QWidget *widget, int flags) +bool QGraphicsEffect::drawSourceIntoPixmap(QPixmap *pixmap, const QTransform &itemToPixmapTransform) { - if (!item->scene()) - return 0; - return item->scene()->drawItemOnPixmap(painter, item, option, widget, flags); + Q_D(QGraphicsEffect); + if (d->source) + return d->source->drawIntoPixmap(pixmap, itemToPixmapTransform); + return false; } QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect() : QGraphicsEffect(*new QGraphicsGrayscaleEffectPrivate) -{ -} +{} QGraphicsGrayscaleEffect::~QGraphicsGrayscaleEffect() -{ -} +{} -void QGraphicsGrayscaleEffect::drawItem(QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option, QWidget *widget) +void QGraphicsGrayscaleEffect::draw(QPainter *painter) { Q_D(QGraphicsGrayscaleEffect); + if (!d->source) + return; // Find the item's bounds in device coordinates. - QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect()); + QTransform itemToPixmapTransform(painter->worldTransform()); + QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect()); QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); if (deviceRect.isEmpty()) return; - QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0); - if (!pixmap) + if (deviceRect.x() != 0 || deviceRect.y() != 0) + itemToPixmapTransform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y()); + + QPixmap pixmap(deviceRect.size()); + if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform)) return; // Draw the pixmap with the filter using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - d->filter->draw(painter, deviceRect.topLeft(), *pixmap, pixmap->rect()); + d->filter->draw(painter, deviceRect.topLeft(), pixmap, pixmap.rect()); painter->setWorldTransform(restoreTransform); + } QGraphicsColorizeEffect::QGraphicsColorizeEffect() : QGraphicsEffect(*new QGraphicsColorizeEffectPrivate) -{ -} +{} QGraphicsColorizeEffect::~QGraphicsColorizeEffect() -{ -} +{} QColor QGraphicsColorizeEffect::color() const { @@ -194,25 +201,30 @@ void QGraphicsColorizeEffect::setColor(const QColor &c) d->filter->setColor(c); } -void QGraphicsColorizeEffect::drawItem(QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option, QWidget *widget) +void QGraphicsColorizeEffect::draw(QPainter *painter) { Q_D(QGraphicsColorizeEffect); + if (!d->source) + return; // Find the item's bounds in device coordinates. - QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect()); + QTransform itemToPixmapTransform(painter->worldTransform()); + QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect()); QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); if (deviceRect.isEmpty()) return; - QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0); - if (!pixmap) + if (deviceRect.x() != 0 || deviceRect.y() != 0) + itemToPixmapTransform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y()); + + QPixmap pixmap(deviceRect.size()); + if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform)) return; // Draw the pixmap with the filter using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - d->filter->draw(painter, deviceRect.topLeft(), *pixmap, pixmap->rect()); + d->filter->draw(painter, deviceRect.topLeft(), pixmap, pixmap.rect()); painter->setWorldTransform(restoreTransform); } @@ -237,23 +249,28 @@ void QGraphicsPixelizeEffect::setPixelSize(int size) d->pixelSize = size; } -void QGraphicsPixelizeEffect::drawItem(QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option, QWidget *widget) +void QGraphicsPixelizeEffect::draw(QPainter *painter) { Q_D(QGraphicsPixelizeEffect); + if (!d->source) + return; // Find the item's bounds in device coordinates. - QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect()); + QTransform itemToPixmapTransform(painter->worldTransform()); + QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect()); QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); if (deviceRect.isEmpty()) return; - QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0); - if (!pixmap) + if (deviceRect.x() != 0 || deviceRect.y() != 0) + itemToPixmapTransform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y()); + + QPixmap pixmap(deviceRect.size()); + if (!d->source->drawIntoPixmap(&pixmap)) return; // pixelize routine - QImage img = pixmap->toImage().convertToFormat(QImage::Format_ARGB32); + QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); if (d->pixelSize > 0) { int width = img.width(); int height = img.height(); @@ -365,31 +382,42 @@ void QGraphicsBlurEffect::setBlurRadius(int radius) d->filter->setBlurRadius(radius); } -QRectF QGraphicsBlurEffect::boundingRectFor(const QGraphicsItem *item) +QRectF QGraphicsBlurEffect::boundingRect() const { Q_D(const QGraphicsBlurEffect); - return d->filter->boundingRectFor(item->boundingRect()); + if (d->source) + return d->filter->boundingRectFor(d->source->boundingRect()); + return QRectF(); } -void QGraphicsBlurEffect::drawItem(QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option, QWidget *widget) +void QGraphicsBlurEffect::draw(QPainter *painter) { Q_D(QGraphicsBlurEffect); + if (!d->source) + return; // Find the item's bounds in device coordinates. - QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect()); + QTransform itemToPixmapTransform(painter->worldTransform()); + QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect()); QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); if (deviceRect.isEmpty()) return; - QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0); - if (!pixmap) + // ### Potentially big rect; must be clipped to the viewport rect. + const qreal delta = d->blurRadius * 3; + const QRect effectRect = deviceBounds.adjusted(-delta, -delta, delta, delta) + .toRect().adjusted(-1, -1, 1, 1); + if (effectRect.x() != 0 || effectRect.y() != 0) + itemToPixmapTransform *= QTransform::fromTranslate(-effectRect.x(), -effectRect.y()); + + QPixmap pixmap(effectRect.size()); + if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform)) return; // Draw the pixmap with the filter using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - d->filter->draw(painter, deviceRect.topLeft(), *pixmap, pixmap->rect()); + d->filter->draw(painter, deviceRect.topLeft(), pixmap, pixmap.rect()); painter->setWorldTransform(restoreTransform); } @@ -426,13 +454,13 @@ void QGraphicsBloomEffect::setOpacity(qreal alpha) d->opacity = alpha; } -QRectF QGraphicsBloomEffect::boundingRectFor(const QGraphicsItem *item) +QRectF QGraphicsBloomEffect::boundingRect() const { - Q_D(QGraphicsBloomEffect); + Q_D(const QGraphicsBloomEffect); + if (!d->source) + return QRectF(); qreal delta = d->blurRadius * 3; - QRectF blurRect = item->boundingRect(); - blurRect.adjust(-delta, -delta, delta, delta); - return blurRect; + return d->source->boundingRect().adjusted(-delta, -delta, delta, delta); } // Change brightness (positive integer) of each pixel @@ -466,24 +494,29 @@ static QImage composited(const QImage& img1, const QImage& img2, qreal opacity, return result; } -void QGraphicsBloomEffect::drawItem(QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option, QWidget *widget) +void QGraphicsBloomEffect::draw(QPainter *painter) { Q_D(QGraphicsBloomEffect); + if (!d->source) + return; // Find the item's bounds in device coordinates. - QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect()); + QTransform itemToPixmapTransform(painter->worldTransform()); + QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect()); QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); if (deviceRect.isEmpty()) return; - QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0); - if (!pixmap) + if (deviceRect.x() != 0 || deviceRect.y() != 0) + itemToPixmapTransform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y()); + + QPixmap pixmap(deviceRect.size()); + if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform)) return; // bloom routine int radius = d->blurRadius; - QImage img = pixmap->toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); + QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); QImage overlay = blurred(img, img.rect(), radius); overlay = brightened(overlay, 70); img = composited(img, overlay, d->opacity, QPainter::CompositionMode_Overlay); @@ -540,31 +573,35 @@ void QGraphicsFrameEffect::setFrameOpacity(qreal opacity) d->alpha = opacity; } -QRectF QGraphicsFrameEffect::boundingRectFor(const QGraphicsItem *item) +QRectF QGraphicsFrameEffect::boundingRect() const { - Q_D(QGraphicsFrameEffect); - QRectF frameRect = item->boundingRect(); - frameRect.adjust(-d->width, -d->width, d->width, d->width); - return frameRect; + Q_D(const QGraphicsFrameEffect); + if (!d->source) + return QRectF(); + return d->source->boundingRect().adjusted(-d->width, -d->width, d->width, d->width); } -void QGraphicsFrameEffect::drawItem(QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option, QWidget *widget) +void QGraphicsFrameEffect::draw(QPainter *painter) { Q_D(QGraphicsFrameEffect); + if (!d->source) + return; // Find the item's bounds in device coordinates. - QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect()); - QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); - if (deviceRect.isEmpty()) + QTransform itemToPixmapTransform(painter->worldTransform()); + QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect()); + if (deviceBounds.isEmpty()) return; - QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0); - if (!pixmap) - return; + QRect frameRect = deviceBounds.adjusted(-d->width, -d->width, d->width, d->width) + .toRect().adjusted(-1, -1, 1, 1); + + if (frameRect.x() != 0 || frameRect.y() != 0) + itemToPixmapTransform *= QTransform::fromTranslate(-frameRect.x(), -frameRect.y()); - QRectF frameRect = deviceBounds; - frameRect.adjust(-d->width, -d->width, d->width, d->width); + QPixmap pixmap(frameRect.size()); + if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform)) + return; painter->save(); painter->setWorldTransform(QTransform()); @@ -576,7 +613,7 @@ void QGraphicsFrameEffect::drawItem(QGraphicsItem *item, QPainter *painter, painter->drawRoundedRect(frameRect, 20, 20, Qt::RelativeSize); painter->restore(); - painter->drawPixmap(frameRect.topLeft(), *pixmap); + painter->drawPixmap(frameRect.topLeft(), pixmap); painter->restore(); } @@ -626,25 +663,30 @@ void QGraphicsShadowEffect::setOpacity(qreal opacity) d->alpha = opacity; } -QRectF QGraphicsShadowEffect::boundingRectFor(const QGraphicsItem *item) +QRectF QGraphicsShadowEffect::boundingRect() const { - Q_D(QGraphicsShadowEffect); - QRectF shadowRect = item->boundingRect(); + Q_D(const QGraphicsShadowEffect); + if (!d->source) + return QRectF(); + const QRectF srcBrect = d->source->boundingRect(); + QRectF shadowRect = srcBrect; shadowRect.adjust(d->offset.x(), d->offset.y(), d->offset.x(), d->offset.y()); QRectF blurRect = shadowRect; qreal delta = d->radius * 3; blurRect.adjust(-delta, -delta, delta, delta); - QRectF totalRect = blurRect.united(item->boundingRect()); + QRectF totalRect = blurRect.united(srcBrect); return totalRect; } -void QGraphicsShadowEffect::drawItem(QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option, QWidget *widget) +void QGraphicsShadowEffect::draw(QPainter *painter) { Q_D(QGraphicsShadowEffect); + if (!d->source) + return; // Find the item's bounds in device coordinates. - QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect()); + QTransform itemToPixmapTransform(painter->worldTransform()); + QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect()); QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); if (deviceRect.isEmpty()) return; @@ -654,13 +696,16 @@ void QGraphicsShadowEffect::drawItem(QGraphicsItem *item, QPainter *painter, QRectF blurRect = shadowRect; qreal delta = d->radius * 3; blurRect.adjust(-delta, -delta, delta, delta); - QRectF totalRect = blurRect.united(deviceRect); + QRect totalRect = blurRect.united(deviceRect).toRect().adjusted(-1, -1, 1, 1); - QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0); - if (!pixmap) + if (totalRect.x() != 0 || totalRect.y() != 0) + itemToPixmapTransform *= QTransform::fromTranslate(-totalRect.x(), -totalRect.y()); + + QPixmap pixmap(totalRect.size()); + if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform)) return; - QImage img = pixmap->toImage(); + QImage img = pixmap.toImage(); QImage shadowImage(img.size(), QImage::Format_ARGB32); shadowImage.fill(qRgba(0, 0, 0, d->alpha * 255)); shadowImage.setAlphaChannel(img.alphaChannel()); @@ -682,10 +727,9 @@ void QGraphicsShadowEffect::drawItem(QGraphicsItem *item, QPainter *painter, qreal itemx = qMin(blurRect.x(), deviceBounds.x()); qreal itemy = qMin(blurRect.y(), deviceBounds.y()); - painter->drawPixmap(itemx, itemy, *pixmap); + painter->drawPixmap(itemx, itemy, pixmap); painter->setWorldTransform(restoreTransform); } - #endif diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h index 9f6e342..74a8430 100644 --- a/src/gui/graphicsview/qgraphicseffect.h +++ b/src/gui/graphicsview/qgraphicseffect.h @@ -46,6 +46,7 @@ #include #include #include +#include #include QT_FORWARD_DECLARE_CLASS(QGraphicsItem); @@ -71,18 +72,17 @@ public: QGraphicsEffect(); virtual ~QGraphicsEffect(); - virtual QRectF boundingRectFor(const QGraphicsItem *item); - - virtual void drawItem(QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option = 0, - QWidget *widget = 0) = 0; + virtual QRectF boundingRect() const; protected: QGraphicsEffect(QGraphicsEffectPrivate &d); - QPixmap* drawItemOnPixmap(QPainter *painter, QGraphicsItem *item, - const QStyleOptionGraphicsItem *option, QWidget *widget, int flags); + virtual void draw(QPainter *painter) = 0; + void drawSource(QPainter *painter); + bool drawSourceIntoPixmap(QPixmap *pixmap, const QTransform &xform = QTransform()); + QRectF sourceBoundingRect() const; private: + friend class QGraphicsScenePrivate; friend class QGraphicsItem; Q_DECLARE_PRIVATE(QGraphicsEffect) Q_DISABLE_COPY(QGraphicsEffect) @@ -96,9 +96,8 @@ public: QGraphicsGrayscaleEffect(); ~QGraphicsGrayscaleEffect(); - void drawItem(QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option = 0, - QWidget *widget = 0); +protected: + void draw(QPainter *painter); private: Q_DECLARE_PRIVATE(QGraphicsGrayscaleEffect) @@ -115,9 +114,8 @@ public: QColor color() const; void setColor(const QColor &c); - void drawItem(QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option = 0, - QWidget *widget = 0); +protected: + void draw(QPainter *painter); private: Q_DECLARE_PRIVATE(QGraphicsColorizeEffect) @@ -134,9 +132,8 @@ public: int pixelSize() const; void setPixelSize(int pixelSize); - void drawItem(QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option = 0, - QWidget *widget = 0); +protected: + void draw(QPainter *painter); private: Q_DECLARE_PRIVATE(QGraphicsPixelizeEffect) @@ -153,11 +150,10 @@ public: int blurRadius() const; void setBlurRadius(int blurRadius); - QRectF boundingRectFor(const QGraphicsItem *item); + QRectF boundingRect() const; - void drawItem(QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option = 0, - QWidget *widget = 0); +protected: + void draw(QPainter *painter); private: Q_DECLARE_PRIVATE(QGraphicsBlurEffect) @@ -177,11 +173,10 @@ public: qreal opacity() const; void setOpacity(qreal opacity); - QRectF boundingRectFor(const QGraphicsItem *item); + QRectF boundingRect() const; - void drawItem(QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option = 0, - QWidget *widget = 0); +protected: + void draw(QPainter *painter); private: Q_DECLARE_PRIVATE(QGraphicsBloomEffect) @@ -204,11 +199,11 @@ public: qreal frameOpacity() const; void setFrameOpacity(qreal opacity); - QRectF boundingRectFor(const QGraphicsItem *item); + QRectF boundingRect() const; + +protected: + void draw(QPainter *painter); - void drawItem(QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option = 0, - QWidget *widget = 0); private: Q_DECLARE_PRIVATE(QGraphicsFrameEffect) Q_DISABLE_COPY(QGraphicsFrameEffect) @@ -232,11 +227,10 @@ public: qreal opacity() const; void setOpacity(qreal opacity); - QRectF boundingRectFor(const QGraphicsItem *item); + QRectF boundingRect() const; - void drawItem(QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option = 0, - QWidget *widget = 0); +protected: + void draw(QPainter *painter); private: Q_DECLARE_PRIVATE(QGraphicsShadowEffect) diff --git a/src/gui/graphicsview/qgraphicseffect_p.h b/src/gui/graphicsview/qgraphicseffect_p.h index 999e013..9204789 100644 --- a/src/gui/graphicsview/qgraphicseffect_p.h +++ b/src/gui/graphicsview/qgraphicseffect_p.h @@ -61,12 +61,31 @@ QT_BEGIN_NAMESPACE +class QGraphicsEffectSource +{ +public: + QGraphicsEffectSource() {} + virtual ~QGraphicsEffectSource() {} + virtual void detach() = 0; + virtual QRectF boundingRect() = 0; + virtual void draw(QPainter *p) = 0; + virtual bool drawIntoPixmap(QPixmap *, const QTransform & = QTransform()) = 0; +}; + class QGraphicsEffectPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QGraphicsEffect) public: - QGraphicsEffectPrivate(): parentItem(0) {} - QGraphicsItem *parentItem; + QGraphicsEffectPrivate() : source(0) {} + QGraphicsEffectSource *source; + inline void setGraphicsEffectSource(QGraphicsEffectSource *newSource) + { + if (source) { + source->detach(); + delete source; + } + source = newSource; + } }; class QGraphicsGrayscaleEffectPrivate : public QGraphicsEffectPrivate @@ -106,8 +125,10 @@ class QGraphicsBlurEffectPrivate : public QGraphicsEffectPrivate { Q_DECLARE_PUBLIC(QGraphicsBlurEffect) public: - QGraphicsBlurEffectPrivate() : blurRadius(4) {} + QGraphicsBlurEffectPrivate() : filter(new QPixmapBlurFilter), blurRadius(4) {} + ~QGraphicsBlurEffectPrivate() { delete filter; } + QPixmapBlurFilter *filter; int blurRadius; }; diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 3a350e0..1d271c9 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -552,7 +552,6 @@ #ifndef QT_NO_GRAPHICSVIEW -#include "qgraphicseffect_p.h" #include "qgraphicsscene.h" #include "qgraphicsscene_p.h" #include "qgraphicssceneevent.h" @@ -1180,8 +1179,7 @@ QGraphicsItem::~QGraphicsItem() else d_ptr->setParentItemHelper(0); - QGraphicsEffect *e = graphicsEffect(); - delete e; + delete d_ptr->graphicsEffect; delete d_ptr->transformData; delete d_ptr; @@ -2198,11 +2196,7 @@ void QGraphicsItem::setOpacity(qreal opacity) */ QGraphicsEffect *QGraphicsItem::graphicsEffect() const { - QGraphicsEffect *fx = 0; - if (d_ptr->hasEffect) - fx = d_ptr->extra(QGraphicsItemPrivate::ExtraEffect).value(); - - return fx; + return d_ptr->graphicsEffect; } /*! @@ -2220,30 +2214,29 @@ QGraphicsEffect *QGraphicsItem::graphicsEffect() const */ void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect) { - if (effect) { - if (QGraphicsEffect *currentEffect = this->graphicsEffect()) { - if (currentEffect != effect) { - qWarning("QGraphicsItem::setEffect: Attempting to set QGraphicsEffect " - "%p on %p, which already has an effect", effect, this); - } - return; - } + if (d_ptr->graphicsEffect == effect) + return; - if (effect->d_func()->parentItem) - effect->d_func()->parentItem->setGraphicsEffect(0); - effect->d_func()->parentItem = this; - d_ptr->hasEffect = true; - d_ptr->setExtra(QGraphicsItemPrivate::ExtraEffect, QVariant::fromValue(effect)); + if (d_ptr->graphicsEffect && effect) { + qWarning("QGraphicsItem::setGraphicsEffect: Attempting to set QGraphicsEffect " + "%p on %p, which already has an effect installed", effect, this); + return; + } + + if (!effect) { + // Unset current effect. + QGraphicsEffectPrivate *oldEffectPrivate = d_ptr->graphicsEffect->d_func(); + d_ptr->graphicsEffect = 0; + if (oldEffectPrivate) + oldEffectPrivate->setGraphicsEffectSource(0); // deletes the current source. } else { - d_ptr->hasEffect = false; - d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraEffect); - void *ptr = d_ptr->extra(QGraphicsItemPrivate::ExtraEffectPixmap).value(); - QPixmap *pixmap = reinterpret_cast(ptr); - delete pixmap; - d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraEffectPixmap); + // Set new effect. + effect->d_func()->setGraphicsEffectSource(new QGraphicsItemEffectSource(this)); + d_ptr->graphicsEffect = effect; } - update(); + if (d_ptr->scene) + d_ptr->scene->d_func()->markDirty(this); } /*! @@ -2257,10 +2250,8 @@ void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect) */ QRectF QGraphicsItem::effectiveBoundingRect() const { - QGraphicsEffect *fx = graphicsEffect(); - if (fx) - return fx->boundingRectFor(this); - + if (d_ptr->graphicsEffect) + return d_ptr->graphicsEffect->boundingRect(); return boundingRect(); } @@ -2294,42 +2285,6 @@ QRectF QGraphicsItem::sceneEffectiveBoundingRect() const } /*! - \internal - - Used by QGraphicsScene. -*/ -QPixmap *QGraphicsItem::effectPixmap() -{ - if (!d_ptr->hasEffect) - return 0; - - // the exact size of the pixmap is not a big deal - // as long as it contains the effective bounding rect - // TODO: use smart resizing etc - // TODO: store per device and do everything in device coordinate? - // TODO: use layer - QRect rect = effectiveBoundingRect().toAlignedRect(); - - void *ptr = d_ptr->extra(QGraphicsItemPrivate::ExtraEffectPixmap).value(); - QPixmap *pixmap = reinterpret_cast(ptr); - bool avail = true; - if (!pixmap) - avail = false; - if (avail && pixmap->size() != rect.size()) - avail = false; - - if (!avail) { - delete pixmap; - pixmap = new QPixmap(rect.size()); - pixmap->fill(Qt::transparent); - ptr = reinterpret_cast(pixmap); - d_ptr->setExtra(QGraphicsItemPrivate::ExtraEffectPixmap, QVariant::fromValue(ptr)); - } - - return pixmap; -} - -/*! Returns true if this item can accept drag and drop events; otherwise, returns false. By default, items do not accept drag and drop events; items are transparent to drag and drop. diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index 0beb07c..0c0b341 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -440,8 +440,6 @@ protected: void removeFromIndex(); void prepareGeometryChange(); - QPixmap *effectPixmap(); - private: Q_DISABLE_COPY(QGraphicsItem) Q_DECLARE_PRIVATE(QGraphicsItem) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 09f296a..dc875f7 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -57,6 +57,7 @@ #include "qset.h" #include "qpixmapcache.h" #include "qgraphicsview_p.h" +#include "qgraphicseffect_p.h" #include @@ -103,8 +104,6 @@ public: ExtraCacheData, ExtraMaxDeviceCoordCacheSize, ExtraBoundingRegionGranularity, - ExtraEffect, - ExtraEffectPixmap, ExtraGestures }; @@ -122,6 +121,7 @@ public: scene(0), parent(0), transformData(0), + graphicsEffect(0), index(-1), siblingIndex(-1), depth(0), @@ -151,7 +151,6 @@ public: allChildrenDirty(0), fullUpdatePending(0), flags(0), - hasEffect(0), dirtyChildrenBoundingRect(1), paintedViewBoundingRectsNeedRepaint(0), dirtySceneTransform(1), @@ -409,6 +408,7 @@ public: QList children; struct TransformData; TransformData *transformData; + QGraphicsEffect *graphicsEffect; QTransform sceneTransform; int index; int siblingIndex; @@ -443,7 +443,6 @@ public: // New 32 bits quint32 fullUpdatePending : 1; quint32 flags : 12; - quint32 hasEffect : 1; quint32 dirtyChildrenBoundingRect : 1; quint32 paintedViewBoundingRectsNeedRepaint : 1; quint32 dirtySceneTransform : 1; @@ -511,6 +510,44 @@ struct QGraphicsItemPrivate::TransformData { } }; +class QGraphicsItemEffectSource : public QGraphicsEffectSource +{ +public: + QGraphicsItemEffectSource(QGraphicsItem *i) + : QGraphicsEffectSource(), item(i), option(0), widget(0) + {} + + inline void detach() + { item->setGraphicsEffect(0); } + + inline QRectF boundingRect() + { return item->boundingRect(); } + + inline void draw(QPainter *painter) + { item->paint(painter, option, widget); } + + inline bool drawIntoPixmap(QPixmap *pixmap, const QTransform &itemToPixmapTransform) + { + pixmap->fill(Qt::transparent); + QPainter pixmapPainter(pixmap); + if (!itemToPixmapTransform.isIdentity()) + pixmapPainter.setWorldTransform(itemToPixmapTransform); + item->paint(&pixmapPainter, option, widget); + return true; + } + + inline void setPaintInfo(const QStyleOptionGraphicsItem *o, QWidget *w) + { option = o; widget = w; } + + void resetPaintInfo() + { option = 0; widget = 0; } + +private: + QGraphicsItem *item; + const QStyleOptionGraphicsItem *option; + QWidget *widget; +}; + /*! \internal */ diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index c56f34c..f4fd4ce 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -3928,8 +3928,8 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte #endif // Render using effect, works now only for no cache mode - if (noCache && itemd->hasEffect && item->graphicsEffect()) { - item->graphicsEffect()->drawItem(item, painter, option, widget); + if (noCache && itemd->graphicsEffect) { + itemd->graphicsEffect->draw(painter); return; } @@ -4228,62 +4228,6 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte } } -// FIXME: merge this with drawItems (needs refactoring) -QPixmap* QGraphicsScene::drawItemOnPixmap(QPainter *painter, - QGraphicsItem *item, - const QStyleOptionGraphicsItem *option, - QWidget *widget, - int flags) -{ - // TODO: use for choosing item or device coordinate - // FIXME: how about source, dest, and exposed rects? - Q_UNUSED(flags); - - // Item's (local) bounding rect, including the effect - QRectF brect = item->effectiveBoundingRect(); - QRectF adjustedBrect(brect); - _q_adjustRect(&adjustedBrect); - if (adjustedBrect.isEmpty()) - return 0; - - // Find the item's bounds in device coordinates. - QRectF deviceBounds = painter->worldTransform().mapRect(brect); - QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); - if (deviceRect.isEmpty()) - return 0; - - // If widget, check if it intersects or not - QRect viewRect = widget ? widget->rect() : QRect(); - if (widget && !viewRect.intersects(deviceRect)) - return 0; - - // Create offscreen pixmap - // TODO: use the pixmap from the layer - QPixmap *targetPixmap = item->effectPixmap(); - if (!targetPixmap) - targetPixmap = new QPixmap(deviceRect.size()); - - // FIXME: this is brute force - QRegion pixmapExposed; - pixmapExposed += targetPixmap->rect(); - - // Construct an item-to-pixmap transform. - QPointF p = deviceRect.topLeft(); - QTransform itemToPixmap = painter->worldTransform(); - if (!p.isNull()) - itemToPixmap *= QTransform::fromTranslate(-p.x(), -p.y()); - - // Calculate the style option's exposedRect. - QStyleOptionGraphicsItem fxOption = *option; - fxOption.exposedRect = brect.adjusted(-1, -1, 1, 1); - - // Render - _q_paintIntoCache(targetPixmap, item, pixmapExposed, itemToPixmap, painter->renderHints(), - &fxOption, false); - - return targetPixmap; -} - void QGraphicsScenePrivate::drawItems(QPainter *painter, const QTransform *const viewTransform, QRegion *exposedRegion, QWidget *widget) { @@ -4412,11 +4356,21 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * painter->setClipPath(item->shape(), Qt::IntersectClip); painter->setOpacity(opacity); - if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget && !item->d_ptr->hasEffect) + QGraphicsItemEffectSource *source = item->d_ptr->graphicsEffect + ? static_cast + (item->d_ptr->graphicsEffect->d_func()->source) + : 0; + if (source) + source->setPaintInfo(&styleOptionTmp, widget); + + if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget && !source) item->paint(painter, &styleOptionTmp, widget); else drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection); + if (source) + source->resetPaintInfo(); + if (savePainter) painter->restore(); } diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index 68bd3e1..1606053 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -281,11 +281,6 @@ protected: const QStyleOptionGraphicsItem options[], QWidget *widget = 0); - QPixmap* drawItemOnPixmap(QPainter *painter, QGraphicsItem *item, - const QStyleOptionGraphicsItem *option, QWidget *widget, int flags); - - - protected Q_SLOTS: bool focusNextPrevChild(bool next); -- cgit v0.12 From 64bbd69d75c7b90500c3fe57e66221684d5a8d92 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Fri, 24 Jul 2009 11:08:23 +1000 Subject: Make it easier to change custom shaders. --- src/opengl/gl2paintengineex/qglcustomshaderstage.cpp | 17 +++++++++++++++++ src/opengl/gl2paintengineex/qglcustomshaderstage_p.h | 1 + src/opengl/gl2paintengineex/qglengineshadermanager.cpp | 7 +++++++ src/opengl/gl2paintengineex/qglengineshadermanager_p.h | 1 + 4 files changed, 26 insertions(+) diff --git a/src/opengl/gl2paintengineex/qglcustomshaderstage.cpp b/src/opengl/gl2paintengineex/qglcustomshaderstage.cpp index efc3b93..bcd9f27 100644 --- a/src/opengl/gl2paintengineex/qglcustomshaderstage.cpp +++ b/src/opengl/gl2paintengineex/qglcustomshaderstage.cpp @@ -93,6 +93,23 @@ bool QGLCustomShaderStage::setOnPainter(QPainter* p) return true; } +void QGLCustomShaderStage::removeFromPainter(QPainter* p) +{ + Q_D(QGLCustomShaderStage); + if (p->paintEngine()->type() != QPaintEngine::OpenGL2) + return; + + // Might as well go through the paint engine to get to the context + const QGLContext* ctx = static_cast(p->paintEngine())->context(); + d->m_manager = QGLEngineShaderManager::managerForContext(ctx); + Q_ASSERT(d->m_manager); + + // Just set the stage to null, don't call removeCustomStage(). + // This should leave the program in a compiled/linked state + // if the next custom shader stage is this one again. + d->m_manager->setCustomStage(0); +} + const char* QGLCustomShaderStage::source() { Q_D(QGLCustomShaderStage); diff --git a/src/opengl/gl2paintengineex/qglcustomshaderstage_p.h b/src/opengl/gl2paintengineex/qglcustomshaderstage_p.h index 6e4ca1c..659f7ba 100644 --- a/src/opengl/gl2paintengineex/qglcustomshaderstage_p.h +++ b/src/opengl/gl2paintengineex/qglcustomshaderstage_p.h @@ -72,6 +72,7 @@ public: void setUniformsDirty(); bool setOnPainter(QPainter*); + void removeFromPainter(QPainter*); const char* source(); protected: diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index c110c50..6363212 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -86,6 +86,8 @@ QGLEngineShaderManager::QGLEngineShaderManager(QGLContext* context) maskType(NoMask), useTextureCoords(false), compositionMode(QPainter::CompositionMode_SourceOver), + customSrcStage(0), + customSrcStagePrev(0), blitShaderProg(0), simpleShaderProg(0), currentShaderProg(0) @@ -311,6 +313,11 @@ void QGLEngineShaderManager::setCompositionMode(QPainter::CompositionMode mode) void QGLEngineShaderManager::setCustomStage(QGLCustomShaderStage* stage) { + // If the custom shader has changed, then destroy the previous compilation. + if (customSrcStagePrev && stage && customSrcStagePrev != stage) + removeCustomStage(customSrcStagePrev); + + customSrcStagePrev = customSrcStage; customSrcStage = stage; shaderProgNeedsChanging = true; } diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h index 15082c3..9d881cc 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h @@ -421,6 +421,7 @@ private: bool useTextureCoords; QPainter::CompositionMode compositionMode; QGLCustomShaderStage* customSrcStage; + QGLCustomShaderStage* customSrcStagePrev; QGLShaderProgram* blitShaderProg; QGLShaderProgram* simpleShaderProg; -- cgit v0.12 From 80fcfd401ff436c10458ccddd1ae4a37401e74fc Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Fri, 24 Jul 2009 11:14:03 +1000 Subject: Implement QGraphicsShaderEffect for custom shader-based effects --- src/opengl/opengl.pro | 2 + src/opengl/qgraphicsshadereffect.cpp | 319 +++++++++++++++++++++++++++++++++++ src/opengl/qgraphicsshadereffect.h | 92 ++++++++++ 3 files changed, 413 insertions(+) create mode 100644 src/opengl/qgraphicsshadereffect.cpp create mode 100644 src/opengl/qgraphicsshadereffect.h diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro index 5a76cb1..b217949 100644 --- a/src/opengl/opengl.pro +++ b/src/opengl/opengl.pro @@ -37,6 +37,7 @@ SOURCES += qgl.cpp \ !contains(QT_CONFIG, opengles1):!contains(QT_CONFIG, opengles1cl) { HEADERS += qglshaderprogram.h \ qglpixmapfilter_p.h \ + qgraphicsshadereffect.h \ qgraphicssystem_gl_p.h \ qwindowsurface_gl_p.h \ qpixmapdata_gl_p.h \ @@ -49,6 +50,7 @@ SOURCES += qgl.cpp \ SOURCES += qglshaderprogram.cpp \ qglpixmapfilter.cpp \ + qgraphicsshadereffect.cpp \ qgraphicssystem_gl.cpp \ qwindowsurface_gl.cpp \ qpixmapdata_gl.cpp \ diff --git a/src/opengl/qgraphicsshadereffect.cpp b/src/opengl/qgraphicsshadereffect.cpp new file mode 100644 index 0000000..121dd90 --- /dev/null +++ b/src/opengl/qgraphicsshadereffect.cpp @@ -0,0 +1,319 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgraphicsshadereffect.h" +#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL) +#include "qglshaderprogram.h" +#include "gl2paintengineex/qglcustomshaderstage_p.h" +#define QGL_HAVE_CUSTOM_SHADERS 1 +#endif +#include +#include + +QT_BEGIN_NAMESPACE + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + +/*! + \class QGraphicsShaderEffect + \brief The QGraphicsShaderEffect class is the base class for creating + custom GLSL shader effects in a QGraphicsScene. + \since 4.6 + \ingroup multimedia + \ingroup graphicsview-api + + The specific effect is defined by a fragment of GLSL source code + supplied to setPixelShaderFragment(). This source code must define a + function called \c{srcPixel()} that returns the source pixel value + to use in the paint engine's shader program. The shader fragment + is linked with the regular shader code used by the GL2 paint engine + to construct a complete QGLShaderProgram. + + The following example shader converts the incoming pixmap to + grayscale and then applies a colorize operation using the + \c effectColor value: + + \code + static char const colorizeShaderCode[] = + "varying highp vec2 textureCoords;\n" + "uniform sampler2D imageTexture;\n" + "uniform lowp vec4 effectColor;\n" + "lowp vec4 srcPixel() {\n" + " vec4 src = texture2D(imageTexture, textureCoords);\n" + " float gray = dot(src.rgb, vec3(0.212671, 0.715160, 0.072169));\n" + " vec4 colorize = 1.0-((1.0-gray)*(1.0-effectColor));\n" + " return vec4(colorize.rgb, src.a);\n" + "}"; + \endcode + + To use this shader code, it is necessary to define a subclass + of QGraphicsShaderEffect as follows: + + \code + class ColorizeEffect : public QGraphicsShaderEffect + { + Q_OBJECT + public: + ColorizeEffect(QObject *parent = 0) + : QGraphicsShaderEffect(parent), color(Qt::black) + { + setPixelShaderFragment(colorizeShaderCode); + } + + QColor effectColor() const { return color; } + void setEffectColor(const QColor& c) + { + color = c; + setUniformsDirty(); + } + + protected: + void setUniforms(QGLShaderProgram *program) + { + program->setUniformValue("effectColor", color); + } + + private: + QColor color; + }; + \endcode + + The setUniforms() function is called when the effect is about + to be used for drawing to give the subclass the opportunity to + set effect-specific uniform variables. + + QGraphicsShaderEffect is only supported when the GL2 paint engine + is in use. When any other paint engine is in use (GL1, raster, etc), + the drawItem() method will draw its item argument directly with + no effect applied. + + \sa QGrapicsEffect +*/ + +static const char qglslDefaultImageFragmentShader[] = "\ + varying highp vec2 textureCoords; \ + uniform sampler2D imageTexture; \ + lowp vec4 srcPixel() { \ + return texture2D(imageTexture, textureCoords); \ + }\n"; + +#ifdef QGL_HAVE_CUSTOM_SHADERS + +class QGLCustomShaderEffectStage : public QGLCustomShaderStage +{ +public: + QGLCustomShaderEffectStage + (QGraphicsShaderEffect *e, const QByteArray& source) + : QGLCustomShaderStage(), + effect(e) + { + setSource(source); + } + + void setUniforms(QGLShaderProgram *program); + + QGraphicsShaderEffect *effect; +}; + +void QGLCustomShaderEffectStage::setUniforms(QGLShaderProgram *program) +{ + effect->setUniforms(program); +} + +#endif + +class QGraphicsShaderEffectPrivate +{ +public: + QGraphicsShaderEffectPrivate() + : pixelShaderFragment(qglslDefaultImageFragmentShader) +#ifdef QGL_HAVE_CUSTOM_SHADERS + , customShaderStage(0) +#endif + { + } + + QByteArray pixelShaderFragment; +#ifdef QGL_HAVE_CUSTOM_SHADERS + QGLCustomShaderEffectStage *customShaderStage; +#endif +}; + +/*! + Constructs a shader effect and attaches it to \a parent. +*/ +QGraphicsShaderEffect::QGraphicsShaderEffect(QObject *parent) + : QGraphicsEffect(parent) +{ + d_ptr = new QGraphicsShaderEffectPrivate(); +} + +/*! + Destroys this shader effect. +*/ +QGraphicsShaderEffect::~QGraphicsShaderEffect() +{ +#ifdef QGL_HAVE_CUSTOM_SHADERS + delete d_ptr->customShaderStage; +#endif + delete d_ptr; +} + +/*! + Returns the source code for the pixel shader fragment for + this shader effect. The default is a shader that copies + its incoming pixmap directly to the output with no effect + applied. + + \sa setPixelShaderFragment() +*/ +QByteArray QGraphicsShaderEffect::pixelShaderFragment() const +{ + return d_ptr->pixelShaderFragment; +} + +/*! + Sets the source code for the pixel shader fragment for + this shader effect to \a code. + + The \a code must define a GLSL function called \c{srcPixel()} + that returns the source pixel value to use in the paint engine's + shader program. The following is the default pixel shader fragment, + which draws a pixmap with no effect applied: + + \code + varying highp vec2 textureCoords; + uniform sampler2D imageTexture; + lowp vec4 srcPixel() { + return texture2D(imageTexture, textureCoords); + } + \endcode + + \sa pixelShaderFragment(), setUniforms() +*/ +void QGraphicsShaderEffect::setPixelShaderFragment(const QByteArray& code) +{ + if (d_ptr->pixelShaderFragment != code) { + d_ptr->pixelShaderFragment = code; +#ifdef QGL_HAVE_CUSTOM_SHADERS + delete d_ptr->customShaderStage; + d_ptr->customShaderStage = 0; +#endif + } +} + +/*! + \reimp +*/ +void QGraphicsShaderEffect::drawItem + (QGraphicsItem *item, QPainter *painter, + const QStyleOptionGraphicsItem *option, QWidget *widget) +{ +#ifdef QGL_HAVE_CUSTOM_SHADERS + // Find the item's bounds in device coordinates. + QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect()); + QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); + if (deviceRect.isEmpty()) + return; + + QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0); + if (!pixmap) + return; + + // Set the custom shader on the paint engine. The setOnPainter() + // call may fail if the paint engine is not GL2. In that case, + // we fall through to drawing the pixmap normally. + if (!d_ptr->customShaderStage) { + d_ptr->customShaderStage = new QGLCustomShaderEffectStage + (this, d_ptr->pixelShaderFragment); + } + bool usingShader = d_ptr->customShaderStage->setOnPainter(painter); + + // Draw using an untransformed painter. + QTransform restoreTransform = painter->worldTransform(); + painter->setWorldTransform(QTransform()); + painter->drawPixmap(deviceRect.topLeft(), *pixmap); + painter->setWorldTransform(restoreTransform); + + // Remove the custom shader to return to normal painting operations. + if (usingShader) + d_ptr->customShaderStage->removeFromPainter(painter); +#else + item->paint(painter, option, widget); +#endif +} + +/*! + Sets the custom uniform variables on this shader effect to + be dirty. The setUniforms() function will be called the next + time the shader program corresponding to this effect is used. + + This function is typically called by subclasses when an + effect-specific parameter is changed by the application. + + \sa setUniforms() +*/ +void QGraphicsShaderEffect::setUniformsDirty() +{ +#ifdef QGL_HAVE_CUSTOM_SHADERS + if (d_ptr->customShaderStage) + d_ptr->customShaderStage->setUniformsDirty(); +#endif +} + +/*! + Sets custom uniform variables on the current GL context when + \a program is about to be used by the paint engine. + + This function should be overridden if the shader set with + setPixelShaderFragment() has additional parameters beyond + those that the paint engine normally sets itself. + + \sa setUniformsDirty() +*/ +void QGraphicsShaderEffect::setUniforms(QGLShaderProgram *program) +{ + Q_UNUSED(program); +} + +#endif // QT_NO_GRAPHICSVIEW + +QT_END_NAMESPACE diff --git a/src/opengl/qgraphicsshadereffect.h b/src/opengl/qgraphicsshadereffect.h new file mode 100644 index 0000000..124f30c --- /dev/null +++ b/src/opengl/qgraphicsshadereffect.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSHADEREFFECT_H +#define QGRAPHICSSHADEREFFECT_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(OpenGL) + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + +class QGLShaderProgram; +class QGLCustomShaderEffectStage; +class QGraphicsShaderEffectPrivate; + +class Q_OPENGL_EXPORT QGraphicsShaderEffect : public QGraphicsEffect +{ + Q_OBJECT +public: + QGraphicsShaderEffect(QObject *parent = 0); + virtual ~QGraphicsShaderEffect(); + + QByteArray pixelShaderFragment() const; + void setPixelShaderFragment(const QByteArray& code); + + void drawItem(QGraphicsItem *item, QPainter *painter, + const QStyleOptionGraphicsItem *option, + QWidget *widget); + +protected: + void setUniformsDirty(); + virtual void setUniforms(QGLShaderProgram *program); + +private: + QGraphicsShaderEffectPrivate *d_ptr; + Q_DISABLE_COPY(QGraphicsShaderEffect) + + friend class QGLCustomShaderEffectStage; +}; + +Q_DECLARE_METATYPE(QGraphicsShaderEffect *) + +#endif // QT_NO_GRAPHICSVIEW + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGRAPHICSSHADEREFFECT_H -- cgit v0.12 From c5c716a12c6b8a7aa5cb5c30873cfe134b4c334c Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Fri, 24 Jul 2009 11:16:02 +1000 Subject: Reset shader stage variables when the custom shader is explicitly removed. --- src/opengl/gl2paintengineex/qglengineshadermanager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index 6363212..848a7f1 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -343,6 +343,8 @@ void QGLEngineShaderManager::removeCustomStage(QGLCustomShaderStage* stage) delete compiledShader; compiledShaders[CustomImageSrcFragmentShader] = 0; + customSrcStage = 0; + customSrcStagePrev = 0; shaderProgNeedsChanging = true; } -- cgit v0.12 From 3b974f5b45429675630040224a3ce34b762cc360 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Fri, 24 Jul 2009 11:17:18 +1000 Subject: Implement a variant on blurpicker that shows a custom shader. --- examples/graphicsview/customshader/blureffect.cpp | 70 +++++++++++ examples/graphicsview/customshader/blureffect.h | 68 ++++++++++ examples/graphicsview/customshader/blurpicker.cpp | 138 +++++++++++++++++++++ examples/graphicsview/customshader/blurpicker.h | 77 ++++++++++++ examples/graphicsview/customshader/blurpicker.qrc | 14 +++ .../graphicsview/customshader/customshader.pro | 10 ++ .../customshader/customshadereffect.cpp | 72 +++++++++++ .../graphicsview/customshader/customshadereffect.h | 64 ++++++++++ examples/graphicsview/customshader/main.cpp | 55 ++++++++ examples/graphicsview/graphicsview.pro | 1 + 10 files changed, 569 insertions(+) create mode 100644 examples/graphicsview/customshader/blureffect.cpp create mode 100644 examples/graphicsview/customshader/blureffect.h create mode 100644 examples/graphicsview/customshader/blurpicker.cpp create mode 100644 examples/graphicsview/customshader/blurpicker.h create mode 100644 examples/graphicsview/customshader/blurpicker.qrc create mode 100644 examples/graphicsview/customshader/customshader.pro create mode 100644 examples/graphicsview/customshader/customshadereffect.cpp create mode 100644 examples/graphicsview/customshader/customshadereffect.h create mode 100644 examples/graphicsview/customshader/main.cpp diff --git a/examples/graphicsview/customshader/blureffect.cpp b/examples/graphicsview/customshader/blureffect.cpp new file mode 100644 index 0000000..8345d0b --- /dev/null +++ b/examples/graphicsview/customshader/blureffect.cpp @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "blureffect.h" + +#include + +BlurEffect::BlurEffect(QObject *parent) + : QGraphicsBlurEffect() + , m_baseLine(200) +{ +} + +void BlurEffect::adjustForItem(const QGraphicsItem *item) +{ + qreal y = m_baseLine - item->pos().y(); + qreal radius = qBound(0.0, y / 32, 16.0); + setBlurRadius(radius); +} + +QRectF BlurEffect::boundingRectFor(const QGraphicsItem *item) +{ + adjustForItem(item); + return QGraphicsBlurEffect::boundingRectFor(item); +} + +void BlurEffect::drawItem(QGraphicsItem *item, QPainter *painter, + const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + adjustForItem(item); + QGraphicsBlurEffect::drawItem(item, painter, option, widget); +} diff --git a/examples/graphicsview/customshader/blureffect.h b/examples/graphicsview/customshader/blureffect.h new file mode 100644 index 0000000..24a6867 --- /dev/null +++ b/examples/graphicsview/customshader/blureffect.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BLUREFFECT_H +#define BLUREFFECT_H + +#include +#include + +class BlurEffect: public QGraphicsBlurEffect +{ +public: + BlurEffect(QObject *parent = 0); + + void setBaseLine(qreal y) { m_baseLine = y; } + + QRectF boundingRectFor(const QGraphicsItem *item); + + void drawItem(QGraphicsItem *item, QPainter *painter, + const QStyleOptionGraphicsItem *option = 0, + QWidget *widget = 0); + +private: + void adjustForItem(const QGraphicsItem *item); + +private: + qreal m_baseLine; +}; + +#endif // BLUREFFECT_H diff --git a/examples/graphicsview/customshader/blurpicker.cpp b/examples/graphicsview/customshader/blurpicker.cpp new file mode 100644 index 0000000..32bfc89 --- /dev/null +++ b/examples/graphicsview/customshader/blurpicker.cpp @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "blurpicker.h" + +#include + +#include "blureffect.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +BlurPicker::BlurPicker(QWidget *parent): QGraphicsView(parent), m_index(0.0) +{ + setBackgroundBrush(QPixmap(":/images/background.jpg")); + setScene(&m_scene); + + setupScene(); + updateIconPositions(); + + connect(&m_timeLine, SIGNAL(valueChanged(qreal)), SLOT(updateIconPositions())); + m_timeLine.setDuration(400); + + setRenderHint(QPainter::Antialiasing, true); + setFrameStyle(QFrame::NoFrame); +} + +void BlurPicker::updateIconPositions() +{ + m_index = m_timeLine.currentFrame() / 1000.0; + + qreal baseline = 0; + for (int i = 0; i < m_icons.count(); ++i) { + QGraphicsItem *icon = m_icons[i]; + qreal a = ((i + m_index) * 2 * M_PI) / m_icons.count(); + qreal xs = 170 * sin(a); + qreal ys = 100 * cos(a); + QPointF pos(xs, ys); + pos = QTransform().rotate(-20).map(pos); + pos -= QPointF(40, 40); + icon->setPos(pos); + baseline = qMax(baseline, ys); + } + + m_blurEffect->setBaseLine(baseline); + m_scene.update(); +} + +void BlurPicker::setupScene() +{ + m_scene.setSceneRect(-200, -120, 400, 240); + + m_blurEffect = new BlurEffect(this); + m_customEffect = new CustomShaderEffect(this); + + QStringList names; + names << ":/images/accessories-calculator.png"; + names << ":/images/accessories-text-editor.png"; + names << ":/images/help-browser.png"; + names << ":/images/internet-group-chat.png"; + names << ":/images/internet-mail.png"; + names << ":/images/internet-web-browser.png"; + names << ":/images/office-calendar.png"; + names << ":/images/system-users.png"; + + for (int i = 0; i < names.count(); i++) { + QPixmap pixmap(names[i]); + QGraphicsPixmapItem *icon = m_scene.addPixmap(pixmap); + icon->setZValue(1); + if (i == 3) + icon->setEffect(m_customEffect); + else + icon->setEffect(m_blurEffect); + m_icons << icon; + } + + QGraphicsPixmapItem *bg = m_scene.addPixmap(QPixmap(":/images/background.jpg")); + bg->setZValue(0); + bg->setPos(-200, -150); +} + +void BlurPicker::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_Left) { + if (m_timeLine.state() == QTimeLine::NotRunning) { + m_timeLine.setFrameRange(m_index * 1000, m_index * 1000 - 1000); + m_timeLine.start(); + event->accept(); + } + } + + if (event->key() == Qt::Key_Right) { + if (m_timeLine.state() == QTimeLine::NotRunning) { + m_timeLine.setFrameRange(m_index * 1000, m_index * 1000 + 1000); + m_timeLine.start(); + event->accept(); + } + } +} diff --git a/examples/graphicsview/customshader/blurpicker.h b/examples/graphicsview/customshader/blurpicker.h new file mode 100644 index 0000000..b4ac97b --- /dev/null +++ b/examples/graphicsview/customshader/blurpicker.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BLURPICKER_H +#define BLURPICKER_H + +#include +#include +#include + +#include "blureffect.h" +#include "customshadereffect.h" + +class BlurPicker: public QGraphicsView +{ + Q_OBJECT + +public: + BlurPicker(QWidget *parent = 0); + +protected: + void keyPressEvent(QKeyEvent *event); + +private slots: + void updateIconPositions(); + +private: + void setupScene(); + +private: + qreal m_index; + QGraphicsScene m_scene; + BlurEffect *m_blurEffect; + CustomShaderEffect *m_customEffect; + QList m_icons; + QTimeLine m_timeLine; +}; + +#endif // BLURPICKER_H diff --git a/examples/graphicsview/customshader/blurpicker.qrc b/examples/graphicsview/customshader/blurpicker.qrc new file mode 100644 index 0000000..e88eaca --- /dev/null +++ b/examples/graphicsview/customshader/blurpicker.qrc @@ -0,0 +1,14 @@ + + + images/background.jpg + images/accessories-calculator.png + images/accessories-text-editor.png + images/help-browser.png + images/internet-group-chat.png + images/internet-mail.png + images/internet-web-browser.png + images/office-calendar.png + images/system-users.png + + + diff --git a/examples/graphicsview/customshader/customshader.pro b/examples/graphicsview/customshader/customshader.pro new file mode 100644 index 0000000..bc07d7a --- /dev/null +++ b/examples/graphicsview/customshader/customshader.pro @@ -0,0 +1,10 @@ +SOURCES += main.cpp blurpicker.cpp blureffect.cpp customshadereffect.cpp +HEADERS += blurpicker.h blureffect.h customshadereffect.h +RESOURCES += blurpicker.qrc +QT += opengl + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/graphicsview/blurpicker +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS blurpicker.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/graphicsview/blurpicker +INSTALLS += target sources diff --git a/examples/graphicsview/customshader/customshadereffect.cpp b/examples/graphicsview/customshader/customshadereffect.cpp new file mode 100644 index 0000000..9f1945d --- /dev/null +++ b/examples/graphicsview/customshader/customshadereffect.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "customshadereffect.h" +#include + +static char const colorizeShaderCode[] = + "varying highp vec2 textureCoords;\n" + "uniform sampler2D imageTexture;\n" + "uniform lowp vec4 effectColor;\n" + "lowp vec4 srcPixel() {\n" + " vec4 src = texture2D(imageTexture, textureCoords);\n" + " float gray = dot(src.rgb, vec3(0.212671, 0.715160, 0.072169));\n" + " vec4 colorize = 1.0-((1.0-gray)*(1.0-effectColor));\n" + " return vec4(colorize.rgb, src.a);\n" + "}"; + +CustomShaderEffect::CustomShaderEffect(QObject *parent) + : QGraphicsShaderEffect(parent), + color(Qt::red) +{ + setPixelShaderFragment(colorizeShaderCode); +} + +void CustomShaderEffect::setEffectColor(const QColor& c) +{ + color = c; + setUniformsDirty(); +} + +void CustomShaderEffect::setUniforms(QGLShaderProgram *program) +{ + program->setUniformValue("effectColor", color); +} diff --git a/examples/graphicsview/customshader/customshadereffect.h b/examples/graphicsview/customshader/customshadereffect.h new file mode 100644 index 0000000..b4e0fb9 --- /dev/null +++ b/examples/graphicsview/customshader/customshadereffect.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CUSTOMSHADEREFFECT_H +#define CUSTOMSHADEREFFECT_H + +#include +#include +#include + +class CustomShaderEffect: public QGraphicsShaderEffect +{ +public: + CustomShaderEffect(QObject *parent = 0); + + QColor effectColor() const { return color; } + void setEffectColor(const QColor& c); + +protected: + void setUniforms(QGLShaderProgram *program); + +private: + QColor color; +}; + +#endif // CUSTOMSHADEREFFECT_H diff --git a/examples/graphicsview/customshader/main.cpp b/examples/graphicsview/customshader/main.cpp new file mode 100644 index 0000000..b88a51d --- /dev/null +++ b/examples/graphicsview/customshader/main.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "blurpicker.h" +#include + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + BlurPicker blurPicker; + blurPicker.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Application Picker")); + blurPicker.setFixedSize(400, 300); + blurPicker.show(); + + return app.exec(); +} diff --git a/examples/graphicsview/graphicsview.pro b/examples/graphicsview/graphicsview.pro index 185c856..4dd0b13 100644 --- a/examples/graphicsview/graphicsview.pro +++ b/examples/graphicsview/graphicsview.pro @@ -12,6 +12,7 @@ SUBDIRS = \ contains(QT_CONFIG, qt3support):SUBDIRS += portedcanvas portedasteroids contains(DEFINES, QT_NO_CURSOR): SUBDIRS -= dragdroprobot +contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles2):SUBDIRS += customshader # install target.path = $$[QT_INSTALL_EXAMPLES]/graphicsview -- cgit v0.12 From 610aa1737a206fe97628a3375a543400ea0761fa Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Fri, 24 Jul 2009 12:51:31 +1000 Subject: Update QGraphicsShaderEffect to match new API --- examples/graphicsview/customshader/blureffect.cpp | 19 ++++--- examples/graphicsview/customshader/blureffect.h | 11 ++-- examples/graphicsview/customshader/blurpicker.cpp | 11 ++-- examples/graphicsview/customshader/blurpicker.h | 3 -- .../customshader/customshadereffect.cpp | 4 +- .../graphicsview/customshader/customshadereffect.h | 2 +- src/gui/graphicsview/qgraphicseffect_p.h | 4 +- src/opengl/qgraphicsshadereffect.cpp | 60 ++++++++++++---------- src/opengl/qgraphicsshadereffect.h | 9 ++-- 9 files changed, 61 insertions(+), 62 deletions(-) diff --git a/examples/graphicsview/customshader/blureffect.cpp b/examples/graphicsview/customshader/blureffect.cpp index 8345d0b..43791c6 100644 --- a/examples/graphicsview/customshader/blureffect.cpp +++ b/examples/graphicsview/customshader/blureffect.cpp @@ -43,28 +43,27 @@ #include -BlurEffect::BlurEffect(QObject *parent) +BlurEffect::BlurEffect(QGraphicsItem *item) : QGraphicsBlurEffect() - , m_baseLine(200) + , m_baseLine(200), item(item) { } -void BlurEffect::adjustForItem(const QGraphicsItem *item) +void BlurEffect::adjustForItem() { qreal y = m_baseLine - item->pos().y(); qreal radius = qBound(0.0, y / 32, 16.0); setBlurRadius(radius); } -QRectF BlurEffect::boundingRectFor(const QGraphicsItem *item) +QRectF BlurEffect::boundingRect() const { - adjustForItem(item); - return QGraphicsBlurEffect::boundingRectFor(item); + const_cast(this)->adjustForItem(); + return QGraphicsBlurEffect::boundingRect(); } -void BlurEffect::drawItem(QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option, QWidget *widget) +void BlurEffect::draw(QPainter *painter) { - adjustForItem(item); - QGraphicsBlurEffect::drawItem(item, painter, option, widget); + adjustForItem(); + QGraphicsBlurEffect::draw(painter); } diff --git a/examples/graphicsview/customshader/blureffect.h b/examples/graphicsview/customshader/blureffect.h index 24a6867..2aea8bf 100644 --- a/examples/graphicsview/customshader/blureffect.h +++ b/examples/graphicsview/customshader/blureffect.h @@ -48,21 +48,20 @@ class BlurEffect: public QGraphicsBlurEffect { public: - BlurEffect(QObject *parent = 0); + BlurEffect(QGraphicsItem *item); void setBaseLine(qreal y) { m_baseLine = y; } - QRectF boundingRectFor(const QGraphicsItem *item); + QRectF boundingRect() const; - void drawItem(QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option = 0, - QWidget *widget = 0); + void draw(QPainter *painter); private: - void adjustForItem(const QGraphicsItem *item); + void adjustForItem(); private: qreal m_baseLine; + QGraphicsItem *item; }; #endif // BLUREFFECT_H diff --git a/examples/graphicsview/customshader/blurpicker.cpp b/examples/graphicsview/customshader/blurpicker.cpp index 32bfc89..de80312 100644 --- a/examples/graphicsview/customshader/blurpicker.cpp +++ b/examples/graphicsview/customshader/blurpicker.cpp @@ -44,6 +44,7 @@ #include #include "blureffect.h" +#include "customshadereffect.h" #ifndef M_PI #define M_PI 3.14159265358979323846 @@ -79,9 +80,10 @@ void BlurPicker::updateIconPositions() pos -= QPointF(40, 40); icon->setPos(pos); baseline = qMax(baseline, ys); + if (i != 3) + static_cast(icon->graphicsEffect())->setBaseLine(baseline); } - m_blurEffect->setBaseLine(baseline); m_scene.update(); } @@ -89,9 +91,6 @@ void BlurPicker::setupScene() { m_scene.setSceneRect(-200, -120, 400, 240); - m_blurEffect = new BlurEffect(this); - m_customEffect = new CustomShaderEffect(this); - QStringList names; names << ":/images/accessories-calculator.png"; names << ":/images/accessories-text-editor.png"; @@ -107,9 +106,9 @@ void BlurPicker::setupScene() QGraphicsPixmapItem *icon = m_scene.addPixmap(pixmap); icon->setZValue(1); if (i == 3) - icon->setEffect(m_customEffect); + icon->setGraphicsEffect(new CustomShaderEffect()); else - icon->setEffect(m_blurEffect); + icon->setGraphicsEffect(new BlurEffect(icon)); m_icons << icon; } diff --git a/examples/graphicsview/customshader/blurpicker.h b/examples/graphicsview/customshader/blurpicker.h index b4ac97b..b7ea3b4 100644 --- a/examples/graphicsview/customshader/blurpicker.h +++ b/examples/graphicsview/customshader/blurpicker.h @@ -47,7 +47,6 @@ #include #include "blureffect.h" -#include "customshadereffect.h" class BlurPicker: public QGraphicsView { @@ -68,8 +67,6 @@ private: private: qreal m_index; QGraphicsScene m_scene; - BlurEffect *m_blurEffect; - CustomShaderEffect *m_customEffect; QList m_icons; QTimeLine m_timeLine; }; diff --git a/examples/graphicsview/customshader/customshadereffect.cpp b/examples/graphicsview/customshader/customshadereffect.cpp index 9f1945d..293123c 100644 --- a/examples/graphicsview/customshader/customshadereffect.cpp +++ b/examples/graphicsview/customshader/customshadereffect.cpp @@ -53,8 +53,8 @@ static char const colorizeShaderCode[] = " return vec4(colorize.rgb, src.a);\n" "}"; -CustomShaderEffect::CustomShaderEffect(QObject *parent) - : QGraphicsShaderEffect(parent), +CustomShaderEffect::CustomShaderEffect() + : QGraphicsShaderEffect(), color(Qt::red) { setPixelShaderFragment(colorizeShaderCode); diff --git a/examples/graphicsview/customshader/customshadereffect.h b/examples/graphicsview/customshader/customshadereffect.h index b4e0fb9..6482bd5 100644 --- a/examples/graphicsview/customshader/customshadereffect.h +++ b/examples/graphicsview/customshader/customshadereffect.h @@ -49,7 +49,7 @@ class CustomShaderEffect: public QGraphicsShaderEffect { public: - CustomShaderEffect(QObject *parent = 0); + CustomShaderEffect(); QColor effectColor() const { return color; } void setEffectColor(const QColor& c); diff --git a/src/gui/graphicsview/qgraphicseffect_p.h b/src/gui/graphicsview/qgraphicseffect_p.h index 9204789..37bcfdf 100644 --- a/src/gui/graphicsview/qgraphicseffect_p.h +++ b/src/gui/graphicsview/qgraphicseffect_p.h @@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE -class QGraphicsEffectSource +class Q_GUI_EXPORT QGraphicsEffectSource { public: QGraphicsEffectSource() {} @@ -72,7 +72,7 @@ public: virtual bool drawIntoPixmap(QPixmap *, const QTransform & = QTransform()) = 0; }; -class QGraphicsEffectPrivate : public QObjectPrivate +class Q_GUI_EXPORT QGraphicsEffectPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QGraphicsEffect) public: diff --git a/src/opengl/qgraphicsshadereffect.cpp b/src/opengl/qgraphicsshadereffect.cpp index 121dd90..d4f5fa0 100644 --- a/src/opengl/qgraphicsshadereffect.cpp +++ b/src/opengl/qgraphicsshadereffect.cpp @@ -47,6 +47,7 @@ #endif #include #include +#include QT_BEGIN_NAMESPACE @@ -160,8 +161,9 @@ void QGLCustomShaderEffectStage::setUniforms(QGLShaderProgram *program) #endif -class QGraphicsShaderEffectPrivate +class QGraphicsShaderEffectPrivate : public QGraphicsEffectPrivate { + Q_DECLARE_PUBLIC(QGraphicsShaderEffect) public: QGraphicsShaderEffectPrivate() : pixelShaderFragment(qglslDefaultImageFragmentShader) @@ -180,10 +182,9 @@ public: /*! Constructs a shader effect and attaches it to \a parent. */ -QGraphicsShaderEffect::QGraphicsShaderEffect(QObject *parent) - : QGraphicsEffect(parent) +QGraphicsShaderEffect::QGraphicsShaderEffect() + : QGraphicsEffect(*new QGraphicsShaderEffectPrivate()) { - d_ptr = new QGraphicsShaderEffectPrivate(); } /*! @@ -192,9 +193,9 @@ QGraphicsShaderEffect::QGraphicsShaderEffect(QObject *parent) QGraphicsShaderEffect::~QGraphicsShaderEffect() { #ifdef QGL_HAVE_CUSTOM_SHADERS - delete d_ptr->customShaderStage; + Q_D(QGraphicsShaderEffect); + delete d->customShaderStage; #endif - delete d_ptr; } /*! @@ -207,7 +208,8 @@ QGraphicsShaderEffect::~QGraphicsShaderEffect() */ QByteArray QGraphicsShaderEffect::pixelShaderFragment() const { - return d_ptr->pixelShaderFragment; + Q_D(const QGraphicsShaderEffect); + return d->pixelShaderFragment; } /*! @@ -231,11 +233,12 @@ QByteArray QGraphicsShaderEffect::pixelShaderFragment() const */ void QGraphicsShaderEffect::setPixelShaderFragment(const QByteArray& code) { - if (d_ptr->pixelShaderFragment != code) { - d_ptr->pixelShaderFragment = code; + Q_D(QGraphicsShaderEffect); + if (d->pixelShaderFragment != code) { + d->pixelShaderFragment = code; #ifdef QGL_HAVE_CUSTOM_SHADERS - delete d_ptr->customShaderStage; - d_ptr->customShaderStage = 0; + delete d->customShaderStage; + d->customShaderStage = 0; #endif } } @@ -243,41 +246,45 @@ void QGraphicsShaderEffect::setPixelShaderFragment(const QByteArray& code) /*! \reimp */ -void QGraphicsShaderEffect::drawItem - (QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option, QWidget *widget) +void QGraphicsShaderEffect::draw(QPainter *painter) { + Q_D(QGraphicsShaderEffect); + #ifdef QGL_HAVE_CUSTOM_SHADERS // Find the item's bounds in device coordinates. - QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect()); + QTransform itemToPixmapTransform(painter->worldTransform()); + QRectF deviceBounds = itemToPixmapTransform.mapRect(sourceBoundingRect()); QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); if (deviceRect.isEmpty()) return; - QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0); - if (!pixmap) + if (deviceRect.x() != 0 || deviceRect.y() != 0) + itemToPixmapTransform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y()); + + QPixmap pixmap(deviceRect.size()); + if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform)) return; // Set the custom shader on the paint engine. The setOnPainter() // call may fail if the paint engine is not GL2. In that case, // we fall through to drawing the pixmap normally. - if (!d_ptr->customShaderStage) { - d_ptr->customShaderStage = new QGLCustomShaderEffectStage - (this, d_ptr->pixelShaderFragment); + if (!d->customShaderStage) { + d->customShaderStage = new QGLCustomShaderEffectStage + (this, d->pixelShaderFragment); } - bool usingShader = d_ptr->customShaderStage->setOnPainter(painter); + bool usingShader = d->customShaderStage->setOnPainter(painter); // Draw using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - painter->drawPixmap(deviceRect.topLeft(), *pixmap); + painter->drawPixmap(deviceRect.topLeft(), pixmap); painter->setWorldTransform(restoreTransform); // Remove the custom shader to return to normal painting operations. if (usingShader) - d_ptr->customShaderStage->removeFromPainter(painter); + d->customShaderStage->removeFromPainter(painter); #else - item->paint(painter, option, widget); + drawSource(painter); #endif } @@ -294,8 +301,9 @@ void QGraphicsShaderEffect::drawItem void QGraphicsShaderEffect::setUniformsDirty() { #ifdef QGL_HAVE_CUSTOM_SHADERS - if (d_ptr->customShaderStage) - d_ptr->customShaderStage->setUniformsDirty(); + Q_D(QGraphicsShaderEffect); + if (d->customShaderStage) + d->customShaderStage->setUniformsDirty(); #endif } diff --git a/src/opengl/qgraphicsshadereffect.h b/src/opengl/qgraphicsshadereffect.h index 124f30c..032a233 100644 --- a/src/opengl/qgraphicsshadereffect.h +++ b/src/opengl/qgraphicsshadereffect.h @@ -60,22 +60,19 @@ class Q_OPENGL_EXPORT QGraphicsShaderEffect : public QGraphicsEffect { Q_OBJECT public: - QGraphicsShaderEffect(QObject *parent = 0); + QGraphicsShaderEffect(); virtual ~QGraphicsShaderEffect(); QByteArray pixelShaderFragment() const; void setPixelShaderFragment(const QByteArray& code); - void drawItem(QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option, - QWidget *widget); - protected: + void draw(QPainter *painter); void setUniformsDirty(); virtual void setUniforms(QGLShaderProgram *program); private: - QGraphicsShaderEffectPrivate *d_ptr; + Q_DECLARE_PRIVATE(QGraphicsShaderEffect) Q_DISABLE_COPY(QGraphicsShaderEffect) friend class QGLCustomShaderEffectStage; -- cgit v0.12 From 928eb3dee17f43d54262d1f3dfc5212f183e6ce9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 28 Jul 2009 14:46:21 +0200 Subject: Improve GL filter performance by caching custom shader programs. This brings performance back up to where it was pre-merge. --- .../gl2paintengineex/qglengineshadermanager.cpp | 26 +++++++++++++--------- .../gl2paintengineex/qglengineshadermanager_p.h | 3 +++ 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index dab1257..0692277 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -320,6 +320,19 @@ void QGLEngineShaderManager::setCustomStage(QGLCustomShaderStage* stage) shaderProgNeedsChanging = true; } +void QGLEngineShaderManager::shaderDestroyed(QObject *shader) +{ + // Remove any shader programs which has this as the srcPixel shader: + for (int i = 0; i < cachedPrograms.size(); ++i) { + if (cachedPrograms.at(i).srcPixelFragShader == shader) { + delete cachedPrograms.at(i).program; + cachedPrograms.removeAt(i--); + } + } + + shaderProgNeedsChanging = true; +} + void QGLEngineShaderManager::removeCustomStage(QGLCustomShaderStage* stage) { Q_UNUSED(stage); // Currently we only support one at a time... @@ -329,16 +342,6 @@ void QGLEngineShaderManager::removeCustomStage(QGLCustomShaderStage* stage) if (!compiledShader) return; - // Remove any shader programs which has this as the srcPixel shader: - for (int i = 0; i < cachedPrograms.size(); ++i) { - QGLEngineShaderProg &prog = cachedPrograms[i]; - if (prog.srcPixelFragShader == compiledShader) { - delete prog.program; - cachedPrograms.removeOne(prog); - break; - } - } - compiledShaders[CustomImageSrcFragmentShader] = 0; customSrcStage = 0; shaderProgNeedsChanging = true; @@ -618,6 +621,9 @@ void QGLEngineShaderManager::compileNamedShader(QGLEngineShaderManager::ShaderNa newShader = new QGLShader(type, ctx, this); newShader->compile(source); customShaderCache.insert(source, newShader); + + connect(newShader, SIGNAL(destroyed(QObject *)), + this, SLOT(shaderDestroyed(QObject *))); } } else { source = qglEngineShaderSourceCode[name]; diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h index 69574ba..8122a08 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h @@ -408,6 +408,9 @@ public: Q_ENUMS(ShaderName) #endif +private slots: + void shaderDestroyed(QObject *shader); + private: QGLContext* ctx; bool shaderProgNeedsChanging; -- cgit v0.12 From 854acb3478651312dbe84d9b4ef971b46485fe1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 29 Jul 2009 08:41:15 +0200 Subject: Add QGraphicsSourceEffect. --- examples/graphicsview/dragdroprobot/main.cpp | 102 ++++++++- examples/graphicsview/dragdroprobot/robot.cpp | 7 + src/gui/graphicsview/qgraphicseffect.cpp | 304 ++++++++++++-------------- src/gui/graphicsview/qgraphicseffect.h | 64 ++++-- src/gui/graphicsview/qgraphicseffect_p.h | 19 +- src/gui/graphicsview/qgraphicsitem.cpp | 64 +++++- src/gui/graphicsview/qgraphicsitem.h | 1 + src/gui/graphicsview/qgraphicsitem_p.h | 56 ++--- src/gui/graphicsview/qgraphicsscene.cpp | 73 ++++--- src/gui/graphicsview/qgraphicsscene.h | 1 + src/gui/graphicsview/qgraphicsscene_p.h | 6 +- 11 files changed, 440 insertions(+), 257 deletions(-) diff --git a/examples/graphicsview/dragdroprobot/main.cpp b/examples/graphicsview/dragdroprobot/main.cpp index 30b8b70..b00bf72 100644 --- a/examples/graphicsview/dragdroprobot/main.cpp +++ b/examples/graphicsview/dragdroprobot/main.cpp @@ -46,6 +46,100 @@ #include +Robot *robot = 0; + +class MyGraphicsEffect : public QGraphicsEffect +{ +public: + void draw(QPainter *painter, QGraphicsEffectSource *source) + { + painter->save(); + + QPen pen; + static int color = Qt::black; + pen.setColor(Qt::GlobalColor(color)); + if (color++ >= Qt::darkYellow) + color = Qt::black; + pen.setWidth(3); + painter->setPen(pen); + + source->draw(painter); + + painter->restore(); + } +}; + +class MyWidget : public QWidget +{ + Q_OBJECT +public: + MyWidget(QWidget *parent = 0) : QWidget(parent) + { + setLayout(new QVBoxLayout); + QComboBox *box = new QComboBox; + box->addItem("None"); + box->addItem("Blur"); + box->addItem("Colorize"); + box->addItem("Pixelize"); + box->addItem("Grayscale"); + box->addItem("Bloom"); + box->addItem("Shadow"); + box->addItem("Custom"); + layout()->addWidget(box); + connect(box, SIGNAL(currentIndexChanged(int)), this, SLOT(changeEffect(int))); + } + +public slots: + void changeEffect(int index) + { + switch (index) { + case 0: + delete robot->graphicsEffect(); + robot->setGraphicsEffect(0); + break; + case 1: + delete robot->graphicsEffect(); + robot->setGraphicsEffect(new QGraphicsBlurEffect); + break; + case 2: + delete robot->graphicsEffect(); + robot->setGraphicsEffect(new QGraphicsColorizeEffect); + break; + case 3: + delete robot->graphicsEffect(); + robot->setGraphicsEffect(new QGraphicsPixelizeEffect); + break; + case 4: + delete robot->graphicsEffect(); + robot->setGraphicsEffect(new QGraphicsGrayscaleEffect); + break; + case 5: + delete robot->graphicsEffect(); + robot->setGraphicsEffect(new QGraphicsBloomEffect); + break; + case 6: + delete robot->graphicsEffect(); + robot->setGraphicsEffect(new QGraphicsShadowEffect); + break; + case 7: + delete robot->graphicsEffect(); + robot->setGraphicsEffect(new MyGraphicsEffect); + break; + default: + break; + } + } +protected: + void paintEvent(QPaintEvent *) {} + void mousePressEvent(QMouseEvent *) {} + void mouseReleaseEvent(QMouseEvent *) {} + +private: +}; + +#include "main.moc" + + int main(int argc, char **argv) { QApplication app(argc, argv); @@ -62,17 +156,21 @@ int main(int argc, char **argv) scene.addItem(item); } - Robot *robot = new Robot; + robot = new Robot; robot->scale(1.2, 1.2); robot->setPos(0, -20); scene.addItem(robot); QGraphicsView view(&scene); view.setRenderHint(QPainter::Antialiasing); - view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); + view.setViewportUpdateMode(QGraphicsView::FullViewportUpdate); view.setBackgroundBrush(QColor(230, 200, 167)); view.setWindowTitle("Drag and Drop Robot"); + // view.rotate(45); view.show(); + MyWidget widget; + widget.show(); + return app.exec(); } diff --git a/examples/graphicsview/dragdroprobot/robot.cpp b/examples/graphicsview/dragdroprobot/robot.cpp index 029a2ce..796336a 100644 --- a/examples/graphicsview/dragdroprobot/robot.cpp +++ b/examples/graphicsview/dragdroprobot/robot.cpp @@ -164,6 +164,13 @@ void RobotLimb::paint(QPainter *painter, Robot::Robot() { QGraphicsItem *torsoItem = new RobotTorso(this); + // torsoItem->setGraphicsEffect(new QGraphicsBloomEffect); + // torsoItem->setGraphicsEffect(new QGraphicsBlurEffect); + // torsoItem->setGraphicsEffect(new QGraphicsFrameEffect); + // torsoItem->setGraphicsEffect(new QGraphicsShadowEffect); + // torsoItem->setGraphicsEffect(new QGraphicsColorizeEffect); + // torsoItem->setGraphicsEffect(new QGraphicsPixelizeEffect); + // torsoItem->setGraphicsEffect(new QGraphicsGrayscaleEffect); QGraphicsItem *headItem = new RobotHead(torsoItem); QGraphicsItem *upperLeftArmItem = new RobotLimb(torsoItem); QGraphicsItem *lowerLeftArmItem = new RobotLimb(upperLeftArmItem); diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index 8d2c416..ed529db 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -102,6 +102,29 @@ */ +QGraphicsEffectSource::QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, QObject *parent) + : QObject(dd, parent) +{} + +QGraphicsEffectSource::~QGraphicsEffectSource() +{} + +QRectF QGraphicsEffectSource::boundingRect(bool deviceCoordinates) const +{ return d_func()->boundingRect(deviceCoordinates); } + +const QGraphicsItem *QGraphicsEffectSource::graphicsItem() const +{ return d_func()->graphicsItem(); } + +const QStyleOption *QGraphicsEffectSource::styleOption() const +{ return d_func()->styleOption(); } + +void QGraphicsEffectSource::draw(QPainter *painter) +{ d_func()->draw(painter); } + +bool QGraphicsEffectSource::drawIntoPixmap(QPixmap *pixmap, const QPoint &offset) +{ return d_func()->drawIntoPixmap(pixmap, offset); } + + QGraphicsEffect::QGraphicsEffect() : QObject(*new QGraphicsEffectPrivate, 0) {} @@ -121,31 +144,40 @@ QGraphicsEffect::~QGraphicsEffect() QRectF QGraphicsEffect::boundingRect() const { - return sourceBoundingRect(); -} - -QRectF QGraphicsEffect::sourceBoundingRect() const -{ Q_D(const QGraphicsEffect); + // return d->boundingRect; if (d->source) - return d->source->boundingRect(); + return boundingRectFor(d->source->boundingRect()); return QRectF(); } -void QGraphicsEffect::drawSource(QPainter *painter) +QRectF QGraphicsEffect::boundingRectFor(const QRectF &rect) const { - Q_D(QGraphicsEffect); - if (d->source) - d->source->draw(painter); + return rect; } -bool QGraphicsEffect::drawSourceIntoPixmap(QPixmap *pixmap, const QTransform &itemToPixmapTransform) -{ - Q_D(QGraphicsEffect); - if (d->source) - return d->source->drawIntoPixmap(pixmap, itemToPixmapTransform); - return false; -} +//QRectF QGraphicsEffect::sourceBoundingRect(bool deviceCoordinates) const +//{ +// Q_D(const QGraphicsEffect); +// if (d->source) +// return d->source->boundingRect(deviceCoordinates); +// return QRectF(); +//} + +//void QGraphicsEffect::drawSource(QPainter *painter) +//{ +// Q_D(QGraphicsEffect); +// if (d->source) +// d->source->d_func()->draw(painter); +//} + +//bool QGraphicsEffect::drawSourceIntoPixmap(QPixmap *pixmap, const QPoint &offset) +//{ +// Q_D(QGraphicsEffect); +// if (d->source) +// return d->source->d_func()->drawIntoPixmap(pixmap, offset); +// return false; +//} QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect() : QGraphicsEffect(*new QGraphicsGrayscaleEffectPrivate) @@ -154,30 +186,20 @@ QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect() QGraphicsGrayscaleEffect::~QGraphicsGrayscaleEffect() {} -void QGraphicsGrayscaleEffect::draw(QPainter *painter) +void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsGrayscaleEffect); - if (!d->source) - return; - // Find the item's bounds in device coordinates. - QTransform itemToPixmapTransform(painter->worldTransform()); - QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect()); - QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); - if (deviceRect.isEmpty()) - return; - - if (deviceRect.x() != 0 || deviceRect.y() != 0) - itemToPixmapTransform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y()); - - QPixmap pixmap(deviceRect.size()); - if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform)) + const QRect sourceRect = source->boundingRect(/*deviceCoordinates=*/true) + .toRect().adjusted(-1, -1, 1, 1); + QPixmap pixmap(sourceRect.size()); + if (!source->drawIntoPixmap(&pixmap, sourceRect.topLeft())) return; // Draw the pixmap with the filter using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - d->filter->draw(painter, deviceRect.topLeft(), pixmap, pixmap.rect()); + d->filter->draw(painter, sourceRect.topLeft(), pixmap, pixmap.rect()); painter->setWorldTransform(restoreTransform); } @@ -201,30 +223,19 @@ void QGraphicsColorizeEffect::setColor(const QColor &c) d->filter->setColor(c); } -void QGraphicsColorizeEffect::draw(QPainter *painter) +void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsColorizeEffect); - if (!d->source) - return; - - // Find the item's bounds in device coordinates. - QTransform itemToPixmapTransform(painter->worldTransform()); - QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect()); - QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); - if (deviceRect.isEmpty()) - return; - - if (deviceRect.x() != 0 || deviceRect.y() != 0) - itemToPixmapTransform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y()); - - QPixmap pixmap(deviceRect.size()); - if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform)) + const QRect sourceRect = source->boundingRect(/*deviceCoordinates=*/true) + .toRect().adjusted(-1, -1, 1, 1); + QPixmap pixmap(sourceRect.size()); + if (!source->drawIntoPixmap(&pixmap, sourceRect.topLeft())) return; // Draw the pixmap with the filter using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - d->filter->draw(painter, deviceRect.topLeft(), pixmap, pixmap.rect()); + d->filter->draw(painter, sourceRect.topLeft(), pixmap, pixmap.rect()); painter->setWorldTransform(restoreTransform); } @@ -249,24 +260,14 @@ void QGraphicsPixelizeEffect::setPixelSize(int size) d->pixelSize = size; } -void QGraphicsPixelizeEffect::draw(QPainter *painter) +void QGraphicsPixelizeEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsPixelizeEffect); - if (!d->source) - return; - // Find the item's bounds in device coordinates. - QTransform itemToPixmapTransform(painter->worldTransform()); - QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect()); - QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); - if (deviceRect.isEmpty()) - return; - - if (deviceRect.x() != 0 || deviceRect.y() != 0) - itemToPixmapTransform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y()); - - QPixmap pixmap(deviceRect.size()); - if (!d->source->drawIntoPixmap(&pixmap)) + const QRect sourceRect = source->boundingRect(/*deviceCoordinates=*/true) + .toRect().adjusted(-1, -1, 1, 1); + QPixmap pixmap(sourceRect.size()); + if (!source->drawIntoPixmap(&pixmap, sourceRect.topLeft())) return; // pixelize routine @@ -292,7 +293,7 @@ void QGraphicsPixelizeEffect::draw(QPainter *painter) // Draw using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - painter->drawImage(deviceRect.topLeft(), img); + painter->drawImage(sourceRect.topLeft(), img); painter->setWorldTransform(restoreTransform); } @@ -382,42 +383,32 @@ void QGraphicsBlurEffect::setBlurRadius(int radius) d->filter->setBlurRadius(radius); } -QRectF QGraphicsBlurEffect::boundingRect() const +QRectF QGraphicsBlurEffect::boundingRectFor(const QRectF &rect) const { Q_D(const QGraphicsBlurEffect); - if (d->source) - return d->filter->boundingRectFor(d->source->boundingRect()); - return QRectF(); + return d->filter->boundingRectFor(rect); } -void QGraphicsBlurEffect::draw(QPainter *painter) +//QRectF QGraphicsBlurEffect::boundingRectFor(const QRectF &rect) const +//{ +// Q_D(const QGraphicsBlurEffect); +// return d->filter->boundingRectFor(rect); +//} + +void QGraphicsBlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsBlurEffect); - if (!d->source) - return; - - // Find the item's bounds in device coordinates. - QTransform itemToPixmapTransform(painter->worldTransform()); - QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect()); - QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); - if (deviceRect.isEmpty()) - return; - - // ### Potentially big rect; must be clipped to the viewport rect. - const qreal delta = d->blurRadius * 3; - const QRect effectRect = deviceBounds.adjusted(-delta, -delta, delta, delta) - .toRect().adjusted(-1, -1, 1, 1); - if (effectRect.x() != 0 || effectRect.y() != 0) - itemToPixmapTransform *= QTransform::fromTranslate(-effectRect.x(), -effectRect.y()); + const QRectF sourceRect = source->boundingRect(/*deviceCoordinates=*/true); + const QRect effectRect = d->filter->boundingRectFor(sourceRect).toRect().adjusted(-1, -1, 1, 1); QPixmap pixmap(effectRect.size()); - if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform)) + if (!source->drawIntoPixmap(&pixmap, effectRect.topLeft())) return; // Draw the pixmap with the filter using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - d->filter->draw(painter, deviceRect.topLeft(), pixmap, pixmap.rect()); + d->filter->draw(painter, sourceRect.topLeft(), pixmap, pixmap.rect()); painter->setWorldTransform(restoreTransform); } @@ -454,13 +445,20 @@ void QGraphicsBloomEffect::setOpacity(qreal alpha) d->opacity = alpha; } -QRectF QGraphicsBloomEffect::boundingRect() const +//QRectF QGraphicsBloomEffect::boundingRectFor(nst QGraphicsEffectSource *source) const +//{ +// Q_D(const QGraphicsBloomEffect); +// if (!d->source) +// return QRectF(); +// const qreal delta = d->blurRadius * 3; +// return sourceBoundingRect().adjusted(-delta, -delta, delta, delta); +//} + +QRectF QGraphicsBloomEffect::boundingRectFor(const QRectF &rect) const { Q_D(const QGraphicsBloomEffect); - if (!d->source) - return QRectF(); - qreal delta = d->blurRadius * 3; - return d->source->boundingRect().adjusted(-delta, -delta, delta, delta); + const qreal delta = d->blurRadius * 3; + return rect.adjusted(-delta, -delta, delta, delta); } // Change brightness (positive integer) of each pixel @@ -494,24 +492,14 @@ static QImage composited(const QImage& img1, const QImage& img2, qreal opacity, return result; } -void QGraphicsBloomEffect::draw(QPainter *painter) +void QGraphicsBloomEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsBloomEffect); - if (!d->source) - return; - - // Find the item's bounds in device coordinates. - QTransform itemToPixmapTransform(painter->worldTransform()); - QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect()); - QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); - if (deviceRect.isEmpty()) - return; - - if (deviceRect.x() != 0 || deviceRect.y() != 0) - itemToPixmapTransform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y()); + const QRectF sourceRect = source->boundingRect(/*deviceCoordinates=*/true); + const QRect effectRect = boundingRectFor(sourceRect).toRect().adjusted(-1, -1, 1, 1); - QPixmap pixmap(deviceRect.size()); - if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform)) + QPixmap pixmap(effectRect.size()); + if (!source->drawIntoPixmap(&pixmap, effectRect.topLeft())) return; // bloom routine @@ -524,7 +512,7 @@ void QGraphicsBloomEffect::draw(QPainter *painter) // Draw using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - painter->drawImage(deviceRect.topLeft() - QPointF(radius * 3, radius * 3), img); + painter->drawImage(effectRect.topLeft(), img); painter->setWorldTransform(restoreTransform); } @@ -573,49 +561,31 @@ void QGraphicsFrameEffect::setFrameOpacity(qreal opacity) d->alpha = opacity; } -QRectF QGraphicsFrameEffect::boundingRect() const +//QRectF QGraphicsFrameEffect::boundingRect() const +//{ +// Q_D(const QGraphicsFrameEffect); +// if (!d->source) +// return QRectF(); +// return d->source->boundingRect().adjusted(-d->width, -d->width, d->width, d->width); +//} + +QRectF QGraphicsFrameEffect::boundingRectFor(const QRectF &rect) const { Q_D(const QGraphicsFrameEffect); - if (!d->source) - return QRectF(); - return d->source->boundingRect().adjusted(-d->width, -d->width, d->width, d->width); + return rect.adjusted(-d->width, -d->width, d->width, d->width); } -void QGraphicsFrameEffect::draw(QPainter *painter) +void QGraphicsFrameEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsFrameEffect); - if (!d->source) - return; - - // Find the item's bounds in device coordinates. - QTransform itemToPixmapTransform(painter->worldTransform()); - QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect()); - if (deviceBounds.isEmpty()) - return; - - QRect frameRect = deviceBounds.adjusted(-d->width, -d->width, d->width, d->width) - .toRect().adjusted(-1, -1, 1, 1); - - if (frameRect.x() != 0 || frameRect.y() != 0) - itemToPixmapTransform *= QTransform::fromTranslate(-frameRect.x(), -frameRect.y()); - - QPixmap pixmap(frameRect.size()); - if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform)) - return; - - painter->save(); - painter->setWorldTransform(QTransform()); - painter->save(); painter->setOpacity(painter->opacity() * d->alpha); painter->setPen(Qt::NoPen); painter->setBrush(d->color); - painter->drawRoundedRect(frameRect, 20, 20, Qt::RelativeSize); + painter->drawRoundedRect(boundingRect(), 20, 20, Qt::RelativeSize); painter->restore(); - painter->drawPixmap(frameRect.topLeft(), pixmap); - - painter->restore(); + source->draw(painter); } QGraphicsShadowEffect::QGraphicsShadowEffect() @@ -663,46 +633,50 @@ void QGraphicsShadowEffect::setOpacity(qreal opacity) d->alpha = opacity; } -QRectF QGraphicsShadowEffect::boundingRect() const +//QRectF QGraphicsShadowEffect::boundingRect() const +//{ +// Q_D(const QGraphicsShadowEffect); +// if (!d->source) +// return QRectF(); +// const QRectF srcBrect = d->source->boundingRect(); +// QRectF shadowRect = srcBrect; +// shadowRect.adjust(d->offset.x(), d->offset.y(), d->offset.x(), d->offset.y()); +// QRectF blurRect = shadowRect; +// qreal delta = d->radius * 3; +// blurRect.adjust(-delta, -delta, delta, delta); +// QRectF totalRect = blurRect.united(srcBrect); +// return totalRect; +//} + +QRectF QGraphicsShadowEffect::boundingRectFor(const QRectF &rect) const { Q_D(const QGraphicsShadowEffect); - if (!d->source) - return QRectF(); - const QRectF srcBrect = d->source->boundingRect(); - QRectF shadowRect = srcBrect; + QRectF shadowRect = rect; shadowRect.adjust(d->offset.x(), d->offset.y(), d->offset.x(), d->offset.y()); QRectF blurRect = shadowRect; qreal delta = d->radius * 3; blurRect.adjust(-delta, -delta, delta, delta); - QRectF totalRect = blurRect.united(srcBrect); + QRectF totalRect = blurRect.united(rect); return totalRect; } -void QGraphicsShadowEffect::draw(QPainter *painter) +void QGraphicsShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsShadowEffect); if (!d->source) return; - // Find the item's bounds in device coordinates. - QTransform itemToPixmapTransform(painter->worldTransform()); - QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect()); - QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); - if (deviceRect.isEmpty()) - return; + const QRectF sourceRect = source->boundingRect(/*deviceCoordinates=*/true); - QRectF shadowRect = deviceBounds; + QRectF shadowRect = sourceRect; shadowRect.adjust(d->offset.x(), d->offset.y(), d->offset.x(), d->offset.y()); QRectF blurRect = shadowRect; qreal delta = d->radius * 3; blurRect.adjust(-delta, -delta, delta, delta); - QRect totalRect = blurRect.united(deviceRect).toRect().adjusted(-1, -1, 1, 1); - - if (totalRect.x() != 0 || totalRect.y() != 0) - itemToPixmapTransform *= QTransform::fromTranslate(-totalRect.x(), -totalRect.y()); + QRect totalRect = blurRect.united(sourceRect).toRect().adjusted(-1, -1, 1, 1); QPixmap pixmap(totalRect.size()); - if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform)) + if (!source->drawIntoPixmap(&pixmap, totalRect.topLeft())) return; QImage img = pixmap.toImage(); @@ -719,14 +693,14 @@ void QGraphicsShadowEffect::draw(QPainter *painter) qreal shadowx = blurRect.x() + delta; qreal shadowy = blurRect.y() + delta; - if (blurRect.x() < deviceRect.x()) - shadowx = blurRect.x() + d->offset.x(); - if (blurRect.y() < deviceRect.y()) + if (blurRect.x() < sourceRect.x()) + shadowx = sourceRect.x() + d->offset.x(); + if (blurRect.y() < sourceRect.y()) shadowy = blurRect.y() + d->offset.y(); painter->drawImage(shadowx, shadowy, shadowImage); - qreal itemx = qMin(blurRect.x(), deviceBounds.x()); - qreal itemy = qMin(blurRect.y(), deviceBounds.y()); + qreal itemx = qMin(blurRect.x(), sourceRect.x()); + qreal itemy = qMin(blurRect.y(), sourceRect.y()); painter->drawPixmap(itemx, itemy, pixmap); painter->setWorldTransform(restoreTransform); diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h index 74a8430..c13461e 100644 --- a/src/gui/graphicsview/qgraphicseffect.h +++ b/src/gui/graphicsview/qgraphicseffect.h @@ -64,6 +64,30 @@ QT_MODULE(Gui) #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW +class QGraphicsEffectSourcePrivate; +class Q_GUI_EXPORT QGraphicsEffectSource : public QObject +{ + Q_OBJECT +public: + ~QGraphicsEffectSource(); + QRectF boundingRect(bool deviceCoordinates = false) const; + const QGraphicsItem *graphicsItem() const; + const QStyleOption *styleOption() const; + void draw(QPainter *painter); + bool drawIntoPixmap(QPixmap *pixmap, const QPoint &offset = QPoint()); + +protected: + QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, QObject *parent = 0); + +private: + Q_DECLARE_PRIVATE(QGraphicsEffectSource); + Q_DISABLE_COPY(QGraphicsEffectSource); + friend class QGraphicsEffect; + friend class QGraphicsEffectPrivate; + friend class QGraphicsScenePrivate; + friend class QGraphicsItem; +}; + class QGraphicsEffectPrivate; class Q_GUI_EXPORT QGraphicsEffect : public QObject { @@ -71,21 +95,19 @@ class Q_GUI_EXPORT QGraphicsEffect : public QObject public: QGraphicsEffect(); virtual ~QGraphicsEffect(); - - virtual QRectF boundingRect() const; + QRectF boundingRect() const; protected: QGraphicsEffect(QGraphicsEffectPrivate &d); - virtual void draw(QPainter *painter) = 0; - void drawSource(QPainter *painter); - bool drawSourceIntoPixmap(QPixmap *pixmap, const QTransform &xform = QTransform()); - QRectF sourceBoundingRect() const; + virtual QRectF boundingRectFor(const QRectF &rect) const; + virtual void draw(QPainter *painter, QGraphicsEffectSource *source) = 0; private: - friend class QGraphicsScenePrivate; - friend class QGraphicsItem; Q_DECLARE_PRIVATE(QGraphicsEffect) Q_DISABLE_COPY(QGraphicsEffect) + friend class QGraphicsItem; + friend class QGraphicsItemPrivate; + friend class QGraphicsScenePrivate; }; class QGraphicsGrayscaleEffectPrivate; @@ -97,7 +119,7 @@ public: ~QGraphicsGrayscaleEffect(); protected: - void draw(QPainter *painter); + void draw(QPainter *painter, QGraphicsEffectSource *source); private: Q_DECLARE_PRIVATE(QGraphicsGrayscaleEffect) @@ -115,7 +137,7 @@ public: void setColor(const QColor &c); protected: - void draw(QPainter *painter); + void draw(QPainter *painter, QGraphicsEffectSource *source); private: Q_DECLARE_PRIVATE(QGraphicsColorizeEffect) @@ -133,7 +155,7 @@ public: void setPixelSize(int pixelSize); protected: - void draw(QPainter *painter); + void draw(QPainter *painter, QGraphicsEffectSource *source); private: Q_DECLARE_PRIVATE(QGraphicsPixelizeEffect) @@ -150,10 +172,11 @@ public: int blurRadius() const; void setBlurRadius(int blurRadius); - QRectF boundingRect() const; + // QRectF boundingRect() const; protected: - void draw(QPainter *painter); + QRectF boundingRectFor(const QRectF &rect) const; + void draw(QPainter *painter, QGraphicsEffectSource *source); private: Q_DECLARE_PRIVATE(QGraphicsBlurEffect) @@ -173,10 +196,11 @@ public: qreal opacity() const; void setOpacity(qreal opacity); - QRectF boundingRect() const; + // QRectF boundingRect() const; protected: - void draw(QPainter *painter); + QRectF boundingRectFor(const QRectF &rect) const; + void draw(QPainter *painter, QGraphicsEffectSource *source); private: Q_DECLARE_PRIVATE(QGraphicsBloomEffect) @@ -199,10 +223,11 @@ public: qreal frameOpacity() const; void setFrameOpacity(qreal opacity); - QRectF boundingRect() const; + // QRectF boundingRect() const; protected: - void draw(QPainter *painter); + QRectF boundingRectFor(const QRectF &rect) const; + void draw(QPainter *painter, QGraphicsEffectSource *source); private: Q_DECLARE_PRIVATE(QGraphicsFrameEffect) @@ -227,10 +252,11 @@ public: qreal opacity() const; void setOpacity(qreal opacity); - QRectF boundingRect() const; + // QRectF boundingRect() const; protected: - void draw(QPainter *painter); + QRectF boundingRectFor(const QRectF &rect) const; + void draw(QPainter *painter, QGraphicsEffectSource *source); private: Q_DECLARE_PRIVATE(QGraphicsShadowEffect) diff --git a/src/gui/graphicsview/qgraphicseffect_p.h b/src/gui/graphicsview/qgraphicseffect_p.h index 9204789..ce90193 100644 --- a/src/gui/graphicsview/qgraphicseffect_p.h +++ b/src/gui/graphicsview/qgraphicseffect_p.h @@ -61,15 +61,21 @@ QT_BEGIN_NAMESPACE -class QGraphicsEffectSource +class QGraphicsEffectSourcePrivate : public QObjectPrivate { + Q_DECLARE_PUBLIC(QGraphicsEffectSource) public: - QGraphicsEffectSource() {} - virtual ~QGraphicsEffectSource() {} + QGraphicsEffectSourcePrivate() : QObjectPrivate() {} + virtual ~QGraphicsEffectSourcePrivate() {} virtual void detach() = 0; - virtual QRectF boundingRect() = 0; + virtual QRectF boundingRect(bool deviceCoordinates = false) const = 0; + virtual const QGraphicsItem *graphicsItem() const = 0; + virtual const QStyleOption *styleOption() const = 0; virtual void draw(QPainter *p) = 0; - virtual bool drawIntoPixmap(QPixmap *, const QTransform & = QTransform()) = 0; + virtual bool drawIntoPixmap(QPixmap *, const QPoint &offset = QPoint()) = 0; + friend class QGraphicsScenePrivate; + friend class QGraphicsItem; + friend class QGraphicsItemPrivate; }; class QGraphicsEffectPrivate : public QObjectPrivate @@ -81,11 +87,12 @@ public: inline void setGraphicsEffectSource(QGraphicsEffectSource *newSource) { if (source) { - source->detach(); + source->d_func()->detach(); delete source; } source = newSource; } + QRectF boundingRect; }; class QGraphicsGrayscaleEffectPrivate : public QGraphicsEffectPrivate diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 1d271c9..b46abd4 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1016,10 +1016,10 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) */ void QGraphicsItemPrivate::childrenBoundingRectHelper(QTransform *x, QRectF *rect) { - if (!dirtyChildrenBoundingRect) { - *rect |= x->mapRect(childrenBoundingRect); - return; - } + // if (!dirtyChildrenBoundingRect) { + // *rect |= x->mapRect(childrenBoundingRect); + // return; + // } for (int i = 0; i < children.size(); ++i) { QGraphicsItem *child = children.at(i); @@ -2231,7 +2231,9 @@ void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect) oldEffectPrivate->setGraphicsEffectSource(0); // deletes the current source. } else { // Set new effect. - effect->d_func()->setGraphicsEffectSource(new QGraphicsItemEffectSource(this)); + QGraphicsEffectSourcePrivate *sourced = new QGraphicsItemEffectSourcePrivate(this); + QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced); + effect->d_func()->setGraphicsEffectSource(source); d_ptr->graphicsEffect = effect; } @@ -3843,8 +3845,8 @@ void QGraphicsItem::setZValue(qreal z) */ QRectF QGraphicsItem::childrenBoundingRect() const { - if (!d_ptr->dirtyChildrenBoundingRect) - return d_ptr->childrenBoundingRect; + // if (!d_ptr->dirtyChildrenBoundingRect) + // return d_ptr->childrenBoundingRect; QRectF childRect; QTransform x; @@ -9924,6 +9926,54 @@ int QGraphicsItemGroup::type() const return Type; } +QRectF QGraphicsItemEffectSourcePrivate::boundingRect(bool deviceCoordinates) const +{ + QRectF rect = item->boundingRect(); + rect |= item->childrenBoundingRect(); + if (deviceCoordinates && info) { + Q_ASSERT(info->transformPtr); + return info->transformPtr->mapRect(rect); + } + return rect; +} + +void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter) +{ + QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); + scened->draw(item, painter, info->viewTransform, info->transformPtr, info->exposedRegion, + info->widget, info->opacity, 0, info->wasDirtySceneTransform, info->drawItem); +} + +bool QGraphicsItemEffectSourcePrivate::drawIntoPixmap(QPixmap *pixmap, const QPoint &offset) +{ + QPoint effectOffset(offset); + + QTransform viewTransform(Qt::Uninitialized); + if (info->viewTransform) { + viewTransform = *info->viewTransform; + viewTransform *= QTransform::fromTranslate(-effectOffset.x(), -effectOffset.y()); + } else { + viewTransform = QTransform::fromTranslate(-effectOffset.x(), -effectOffset.y()); + } + + *info->transformPtr *= QTransform::fromTranslate(-effectOffset.x(), -effectOffset.y()); + + QRegion exposedRegion; + if (info->exposedRegion) { + exposedRegion = *info->exposedRegion; + exposedRegion.translate(-effectOffset.x(), -effectOffset.y()); + } + + pixmap->fill(Qt::transparent); + QPainter pixmapPainter(pixmap); + pixmapPainter.setRenderHints(QPainter::SmoothPixmapTransform | QPainter::Antialiasing); + QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); + scened->draw(item, &pixmapPainter, &viewTransform, info->transformPtr, &exposedRegion, + info->widget, info->opacity, &effectOffset, info->wasDirtySceneTransform, + info->drawItem); + return true; +} + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug debug, QGraphicsItem *item) { diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index 0c0b341..0c20829 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -457,6 +457,7 @@ private: friend class QGraphicsSceneIndexPrivate; friend class QGraphicsSceneBspTreeIndex; friend class QGraphicsSceneBspTreeIndexPrivate; + friend class QGraphicsItemEffectSourcePrivate; friend class ::tst_QGraphicsItem; friend bool qt_closestLeaf(const QGraphicsItem *, const QGraphicsItem *); friend bool qt_closestItemFirst(const QGraphicsItem *, const QGraphicsItem *); diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index dc875f7..0823e51 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -510,44 +510,50 @@ struct QGraphicsItemPrivate::TransformData { } }; -class QGraphicsItemEffectSource : public QGraphicsEffectSource +struct QGraphicsItemPaintInfo +{ + inline QGraphicsItemPaintInfo(const QTransform *const xform1, QTransform *xform2, + QRegion *r, QWidget *w, QStyleOptionGraphicsItem *opt, + qreal o, bool b1, bool b2) + : viewTransform(xform1), transformPtr(xform2), exposedRegion(r), widget(w), + option(opt), opacity(o), wasDirtySceneTransform(b1), drawItem(b2) + {} + + const QTransform *viewTransform; + QTransform *transformPtr; + QRegion *exposedRegion; + QWidget *widget; + QStyleOptionGraphicsItem *option; + qreal opacity; + quint32 wasDirtySceneTransform : 1; + quint32 drawItem : 1; +}; + +class QGraphicsItemEffectSourcePrivate : public QGraphicsEffectSourcePrivate { public: - QGraphicsItemEffectSource(QGraphicsItem *i) - : QGraphicsEffectSource(), item(i), option(0), widget(0) + QGraphicsItemEffectSourcePrivate(QGraphicsItem *i) + : QGraphicsEffectSourcePrivate(), item(i), info(0) {} inline void detach() { item->setGraphicsEffect(0); } - inline QRectF boundingRect() - { return item->boundingRect(); } + inline const QGraphicsItem *graphicsItem() const + { return item; } - inline void draw(QPainter *painter) - { item->paint(painter, option, widget); } + inline const QStyleOption *styleOption() const + { return info ? info->option : 0; } - inline bool drawIntoPixmap(QPixmap *pixmap, const QTransform &itemToPixmapTransform) - { - pixmap->fill(Qt::transparent); - QPainter pixmapPainter(pixmap); - if (!itemToPixmapTransform.isIdentity()) - pixmapPainter.setWorldTransform(itemToPixmapTransform); - item->paint(&pixmapPainter, option, widget); - return true; - } - - inline void setPaintInfo(const QStyleOptionGraphicsItem *o, QWidget *w) - { option = o; widget = w; } + QRectF boundingRect(bool deviceCoordinates) const; + void draw(QPainter *); + bool drawIntoPixmap(QPixmap *pixmap, const QPoint &offset); - void resetPaintInfo() - { option = 0; widget = 0; } - -private: QGraphicsItem *item; - const QStyleOptionGraphicsItem *option; - QWidget *widget; + QGraphicsItemPaintInfo *info; }; + /*! \internal */ diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index f4fd4ce..31ec1ba 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -208,7 +208,7 @@ #ifndef QT_NO_GRAPHICSVIEW -#include "qgraphicseffect.h" +#include "qgraphicseffect_p.h" #include "qgraphicsitem.h" #include "qgraphicsitem_p.h" #include "qgraphicslayout.h" @@ -3920,19 +3920,6 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte QGraphicsItemPrivate *itemd = item->d_ptr; QGraphicsItem::CacheMode cacheMode = QGraphicsItem::CacheMode(itemd->cacheMode); - bool noCache = cacheMode == QGraphicsItem::NoCache || -#ifdef Q_WS_X11 - !X11->use_xrender; -#else - false; -#endif - - // Render using effect, works now only for no cache mode - if (noCache && itemd->graphicsEffect) { - itemd->graphicsEffect->draw(painter); - return; - } - // Render directly, using no cache. if (cacheMode == QGraphicsItem::NoCache #ifdef Q_WS_X11 @@ -4245,7 +4232,7 @@ void QGraphicsScenePrivate::drawItems(QPainter *painter, const QTransform *const void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform *const viewTransform, QRegion *exposedRegion, QWidget *widget, - qreal parentOpacity) + qreal parentOpacity, QPoint *effectOffset) { Q_ASSERT(item); @@ -4298,7 +4285,10 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * ENSURE_TRANSFORM_PTR QRect viewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy()).toRect() : transformPtr->mapRect(brect).toRect(); - item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect); + if (widget) { + item->d_ptr->paintedViewBoundingRects.insert(widget, effectOffset ? + viewBoundingRect.translated(*effectOffset) : viewBoundingRect); + } viewBoundingRect.adjust(-1, -1, 1, 1); drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect) : !viewBoundingRect.isEmpty(); if (!drawItem) { @@ -4312,13 +4302,42 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * } } // else we know for sure this item has children we must process. + if (itemHasChildren && itemClipsChildrenToShape) + ENSURE_TRANSFORM_PTR; + + if (item->d_ptr->graphicsEffect) { + ENSURE_TRANSFORM_PTR; + QGraphicsItemPaintInfo info(viewTransform, transformPtr, exposedRegion, widget, &styleOptionTmp, + opacity, wasDirtyParentSceneTransform, drawItem); + QGraphicsEffectSource *source = item->d_ptr->graphicsEffect->d_func()->source; + QGraphicsItemEffectSourcePrivate *sourced = static_cast + (source->d_func()); + sourced->info = &info; + const QTransform restoreTransform = painter->worldTransform(); + painter->setWorldTransform(*transformPtr); + item->d_ptr->graphicsEffect->draw(painter, source); + painter->setWorldTransform(restoreTransform); + } else { + draw(item, painter, viewTransform, transformPtr, exposedRegion, widget, opacity, + effectOffset, wasDirtyParentSceneTransform, drawItem); + } +} + +void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const QTransform *const viewTransform, + const QTransform *const transformPtr, QRegion *exposedRegion, QWidget *widget, qreal opacity, + QPoint *effectOffset, bool wasDirtyParentSceneTransform, bool drawItem) +{ + const bool itemIsFullyTransparent = (opacity < 0.0001); + const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape); + const bool itemHasChildren = !item->d_ptr->children.isEmpty(); + int i = 0; if (itemHasChildren) { item->d_ptr->ensureSortedChildren(); if (itemClipsChildrenToShape) { painter->save(); - ENSURE_TRANSFORM_PTR + Q_ASSERT(transformPtr); painter->setWorldTransform(*transformPtr); painter->setClipPath(item->shape(), Qt::IntersectClip); } @@ -4332,15 +4351,15 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * break; if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)) continue; - drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity); + drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectOffset); } } // Draw item if (drawItem) { Q_ASSERT(!itemIsFullyTransparent); - Q_ASSERT(itemHasContents); - ENSURE_TRANSFORM_PTR + Q_ASSERT(!(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents)); + Q_ASSERT(transformPtr); item->d_ptr->initStyleOption(&styleOptionTmp, *transformPtr, exposedRegion ? *exposedRegion : QRegion(), exposedRegion == 0); @@ -4356,21 +4375,11 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * painter->setClipPath(item->shape(), Qt::IntersectClip); painter->setOpacity(opacity); - QGraphicsItemEffectSource *source = item->d_ptr->graphicsEffect - ? static_cast - (item->d_ptr->graphicsEffect->d_func()->source) - : 0; - if (source) - source->setPaintInfo(&styleOptionTmp, widget); - - if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget && !source) + if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget) item->paint(painter, &styleOptionTmp, widget); else drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection); - if (source) - source->resetPaintInfo(); - if (savePainter) painter->restore(); } @@ -4383,7 +4392,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * child->d_ptr->dirtySceneTransform = 1; if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)) continue; - drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity); + drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectOffset); } } diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index 1606053..813e000 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -306,6 +306,7 @@ private: friend class QGraphicsSceneIndexPrivate; friend class QGraphicsSceneBspTreeIndex; friend class QGraphicsSceneBspTreeIndexPrivate; + friend class QGraphicsItemEffectSourcePrivate; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsScene::SceneLayers) diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 38f5682..b602758 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -200,7 +200,11 @@ public: QRegion *exposedRegion, QWidget *widget); void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform *const, - QRegion *exposedRegion, QWidget *widget, qreal parentOpacity = qreal(1.0)); + QRegion *exposedRegion, QWidget *widget, qreal parentOpacity = qreal(1.0), + QPoint *effectOffset = 0); + void draw(QGraphicsItem *, QPainter *, const QTransform *const, const QTransform *const, + QRegion *, QWidget *, qreal, QPoint *, bool, bool); + void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false, bool maybeDirtyClipPath = false, bool force = false, bool ignoreOpacity = false, bool removingItemFromScene = false); -- cgit v0.12 From 72debacc7f57b9ea9115e549170341a9ad11bf0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 28 Jul 2009 12:24:32 +0200 Subject: Add QGraphicsEffectSource::pixmap. We need a convenient way of getting the pixmap representation of the source. --- examples/graphicsview/blurpicker/blureffect.cpp | 4 +-- examples/graphicsview/blurpicker/blureffect.h | 2 +- src/gui/graphicsview/qgraphicseffect.cpp | 31 ++++++++++++++++----- src/gui/graphicsview/qgraphicseffect.h | 8 +++++- src/gui/graphicsview/qgraphicseffect_p.h | 6 +++- src/gui/graphicsview/qgraphicsitem.cpp | 29 ++++++++++++++++++- src/gui/graphicsview/qgraphicsitem_p.h | 1 + src/gui/graphicsview/qgraphicsscene.cpp | 37 ++++++++++++++++--------- src/gui/graphicsview/qgraphicsscene_p.h | 6 ++-- 9 files changed, 95 insertions(+), 29 deletions(-) diff --git a/examples/graphicsview/blurpicker/blureffect.cpp b/examples/graphicsview/blurpicker/blureffect.cpp index 43791c6..82be44f 100644 --- a/examples/graphicsview/blurpicker/blureffect.cpp +++ b/examples/graphicsview/blurpicker/blureffect.cpp @@ -62,8 +62,8 @@ QRectF BlurEffect::boundingRect() const return QGraphicsBlurEffect::boundingRect(); } -void BlurEffect::draw(QPainter *painter) +void BlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { adjustForItem(); - QGraphicsBlurEffect::draw(painter); + QGraphicsBlurEffect::draw(painter, source); } diff --git a/examples/graphicsview/blurpicker/blureffect.h b/examples/graphicsview/blurpicker/blureffect.h index 2aea8bf..89694b6 100644 --- a/examples/graphicsview/blurpicker/blureffect.h +++ b/examples/graphicsview/blurpicker/blureffect.h @@ -54,7 +54,7 @@ public: QRectF boundingRect() const; - void draw(QPainter *painter); + void draw(QPainter *painter, QGraphicsEffectSource *source); private: void adjustForItem(); diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index ed529db..1281847 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -124,6 +124,8 @@ void QGraphicsEffectSource::draw(QPainter *painter) bool QGraphicsEffectSource::drawIntoPixmap(QPixmap *pixmap, const QPoint &offset) { return d_func()->drawIntoPixmap(pixmap, offset); } +QPixmap QGraphicsEffectSource::pixmap(bool deviceCoordinates, QPoint *offset) const +{ return d_func()->pixmap(deviceCoordinates, offset); } QGraphicsEffect::QGraphicsEffect() : QObject(*new QGraphicsEffectPrivate, 0) @@ -151,6 +153,25 @@ QRectF QGraphicsEffect::boundingRect() const return QRectF(); } +void QGraphicsEffect::setSourcePixmap(const QPixmap &pixmap) +{ + Q_D(QGraphicsEffect); + d->sourcePixmap = pixmap; + d->hasSourcePixmap = !pixmap.isNull(); +} + +QPixmap QGraphicsEffect::sourcePixmap() const +{ + Q_D(const QGraphicsEffect); + return d->sourcePixmap; +} + +bool QGraphicsEffect::hasSourcePixmap() const +{ + Q_D(const QGraphicsEffect); + return d->hasSourcePixmap; +} + QRectF QGraphicsEffect::boundingRectFor(const QRectF &rect) const { return rect; @@ -398,17 +419,13 @@ QRectF QGraphicsBlurEffect::boundingRectFor(const QRectF &rect) const void QGraphicsBlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsBlurEffect); - const QRectF sourceRect = source->boundingRect(/*deviceCoordinates=*/true); - const QRect effectRect = d->filter->boundingRectFor(sourceRect).toRect().adjusted(-1, -1, 1, 1); - - QPixmap pixmap(effectRect.size()); - if (!source->drawIntoPixmap(&pixmap, effectRect.topLeft())) - return; + QPoint offset; + const QPixmap pixmap = source->pixmap(true, &offset); // Draw the pixmap with the filter using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - d->filter->draw(painter, sourceRect.topLeft(), pixmap, pixmap.rect()); + d->filter->draw(painter, offset, pixmap, pixmap.rect()); painter->setWorldTransform(restoreTransform); } diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h index c13461e..77eebd6 100644 --- a/src/gui/graphicsview/qgraphicseffect.h +++ b/src/gui/graphicsview/qgraphicseffect.h @@ -65,6 +65,7 @@ QT_MODULE(Gui) #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW class QGraphicsEffectSourcePrivate; +class QStyleOption; class Q_GUI_EXPORT QGraphicsEffectSource : public QObject { Q_OBJECT @@ -75,6 +76,7 @@ public: const QStyleOption *styleOption() const; void draw(QPainter *painter); bool drawIntoPixmap(QPixmap *pixmap, const QPoint &offset = QPoint()); + QPixmap pixmap(bool deviceCoordinates, QPoint *offset = 0) const; protected: QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, QObject *parent = 0); @@ -97,9 +99,13 @@ public: virtual ~QGraphicsEffect(); QRectF boundingRect() const; + void setSourcePixmap(const QPixmap &pixmap); + QPixmap sourcePixmap() const; + bool hasSourcePixmap() const; + virtual QRectF boundingRectFor(const QRectF &rect) const; + protected: QGraphicsEffect(QGraphicsEffectPrivate &d); - virtual QRectF boundingRectFor(const QRectF &rect) const; virtual void draw(QPainter *painter, QGraphicsEffectSource *source) = 0; private: diff --git a/src/gui/graphicsview/qgraphicseffect_p.h b/src/gui/graphicsview/qgraphicseffect_p.h index ce90193..a575d3b 100644 --- a/src/gui/graphicsview/qgraphicseffect_p.h +++ b/src/gui/graphicsview/qgraphicseffect_p.h @@ -73,6 +73,7 @@ public: virtual const QStyleOption *styleOption() const = 0; virtual void draw(QPainter *p) = 0; virtual bool drawIntoPixmap(QPixmap *, const QPoint &offset = QPoint()) = 0; + virtual QPixmap pixmap(bool deviceCoordinates, QPoint *offset = 0) const = 0; friend class QGraphicsScenePrivate; friend class QGraphicsItem; friend class QGraphicsItemPrivate; @@ -82,7 +83,7 @@ class QGraphicsEffectPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QGraphicsEffect) public: - QGraphicsEffectPrivate() : source(0) {} + QGraphicsEffectPrivate() : source(0), hasSourcePixmap(0) {} QGraphicsEffectSource *source; inline void setGraphicsEffectSource(QGraphicsEffectSource *newSource) { @@ -93,6 +94,9 @@ public: source = newSource; } QRectF boundingRect; + QPixmap sourcePixmap; + quint32 hasSourcePixmap : 1; + quint32 padding : 31; // feel free to use }; class QGraphicsGrayscaleEffectPrivate : public QGraphicsEffectPrivate diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index b46abd4..425031f 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -9944,6 +9944,33 @@ void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter) info->widget, info->opacity, 0, info->wasDirtySceneTransform, info->drawItem); } +QPixmap QGraphicsItemEffectSourcePrivate::pixmap(bool deviceCoordinates, QPoint *offset) const +{ + const QRectF sourceRect = boundingRect(deviceCoordinates); + const QRect effectRect = item->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect(); + if (offset) + *offset = sourceRect.toAlignedRect().topLeft(); + + const QTransform translateTransform = QTransform::fromTranslate(-effectRect.x(), + -effectRect.y()); + QTransform effectTransform = deviceCoordinates ? translateTransform + : info->transformPtr->inverted(); + if (!deviceCoordinates) + effectTransform *= translateTransform; + *info->transformPtr *= effectTransform; + + QPixmap pixmap(effectRect.size()); + pixmap.fill(Qt::transparent); + QPainter pixmapPainter(&pixmap); + pixmapPainter.setRenderHints(QPainter::SmoothPixmapTransform | QPainter::Antialiasing); + + QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); + scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, info->exposedRegion, + info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform, + info->drawItem); + return pixmap; +} + bool QGraphicsItemEffectSourcePrivate::drawIntoPixmap(QPixmap *pixmap, const QPoint &offset) { QPoint effectOffset(offset); @@ -9969,7 +9996,7 @@ bool QGraphicsItemEffectSourcePrivate::drawIntoPixmap(QPixmap *pixmap, const QPo pixmapPainter.setRenderHints(QPainter::SmoothPixmapTransform | QPainter::Antialiasing); QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); scened->draw(item, &pixmapPainter, &viewTransform, info->transformPtr, &exposedRegion, - info->widget, info->opacity, &effectOffset, info->wasDirtySceneTransform, + info->widget, info->opacity, 0, info->wasDirtySceneTransform, info->drawItem); return true; } diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 0823e51..db79e07 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -548,6 +548,7 @@ public: QRectF boundingRect(bool deviceCoordinates) const; void draw(QPainter *); bool drawIntoPixmap(QPixmap *pixmap, const QPoint &offset); + QPixmap pixmap(bool deviceCoordinates, QPoint *offset) const; QGraphicsItem *item; QGraphicsItemPaintInfo *info; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 31ec1ba..3a899ff 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4232,7 +4232,7 @@ void QGraphicsScenePrivate::drawItems(QPainter *painter, const QTransform *const void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform *const viewTransform, QRegion *exposedRegion, QWidget *widget, - qreal parentOpacity, QPoint *effectOffset) + qreal parentOpacity, const QTransform *const effectTransform) { Q_ASSERT(item); @@ -4285,10 +4285,8 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * ENSURE_TRANSFORM_PTR QRect viewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy()).toRect() : transformPtr->mapRect(brect).toRect(); - if (widget) { - item->d_ptr->paintedViewBoundingRects.insert(widget, effectOffset ? - viewBoundingRect.translated(*effectOffset) : viewBoundingRect); - } + if (widget) + item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect); viewBoundingRect.adjust(-1, -1, 1, 1); drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect) : !viewBoundingRect.isEmpty(); if (!drawItem) { @@ -4306,6 +4304,10 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * ENSURE_TRANSFORM_PTR; if (item->d_ptr->graphicsEffect) { + if (item->type() == 7) { + item->d_ptr->graphicsEffect->setSourcePixmap(static_cast(item) + ->pixmap()); + } ENSURE_TRANSFORM_PTR; QGraphicsItemPaintInfo info(viewTransform, transformPtr, exposedRegion, widget, &styleOptionTmp, opacity, wasDirtyParentSceneTransform, drawItem); @@ -4319,13 +4321,13 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * painter->setWorldTransform(restoreTransform); } else { draw(item, painter, viewTransform, transformPtr, exposedRegion, widget, opacity, - effectOffset, wasDirtyParentSceneTransform, drawItem); + effectTransform, wasDirtyParentSceneTransform, drawItem); } } void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const QTransform *const viewTransform, - const QTransform *const transformPtr, QRegion *exposedRegion, QWidget *widget, qreal opacity, - QPoint *effectOffset, bool wasDirtyParentSceneTransform, bool drawItem) + QTransform *transformPtr, QRegion *exposedRegion, QWidget *widget, qreal opacity, + const QTransform *effectTransform, bool wasDirtyParentSceneTransform, bool drawItem) { const bool itemIsFullyTransparent = (opacity < 0.0001); const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape); @@ -4338,6 +4340,8 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q if (itemClipsChildrenToShape) { painter->save(); Q_ASSERT(transformPtr); + if (effectTransform) + *transformPtr *= *effectTransform; painter->setWorldTransform(*transformPtr); painter->setClipPath(item->shape(), Qt::IntersectClip); } @@ -4351,7 +4355,7 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q break; if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)) continue; - drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectOffset); + drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform); } } @@ -4368,8 +4372,11 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q if (savePainter) painter->save(); - if (!itemHasChildren || !itemClipsChildrenToShape) + if (!itemHasChildren || !itemClipsChildrenToShape) { + if (effectTransform) + *transformPtr *= *effectTransform; painter->setWorldTransform(*transformPtr); + } if (itemClipsToShape) painter->setClipPath(item->shape(), Qt::IntersectClip); @@ -4392,7 +4399,7 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q child->d_ptr->dirtySceneTransform = 1; if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)) continue; - drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectOffset); + drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform); } } @@ -4475,8 +4482,12 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b item->d_ptr->ignoreOpacity = 1; QGraphicsItem *p = item->d_ptr->parent; - while (p && !p->d_ptr->dirtyChildren) { + while (p) { p->d_ptr->dirtyChildren = 1; + if (p->d_ptr->graphicsEffect) { + p->d_ptr->dirty = 1; + p->d_ptr->fullUpdatePending = 1; + } p = p->d_ptr->parent; } } @@ -4585,7 +4596,7 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool // Process item. if (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint) { const bool useCompatUpdate = views.isEmpty() || (connectedSignals & changedSignalMask); - const QRectF itemBoundingRect = adjustedItemBoundingRect(item); + const QRectF itemBoundingRect = adjustedItemEffectiveBoundingRect(item); if (useCompatUpdate && !itemIsUntransformable && qFuzzyIsNull(item->boundingRegionGranularity())) { // This block of code is kept for compatibility. Since 4.5, by default diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index b602758..f380ced 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -201,9 +201,9 @@ public: void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform *const, QRegion *exposedRegion, QWidget *widget, qreal parentOpacity = qreal(1.0), - QPoint *effectOffset = 0); - void draw(QGraphicsItem *, QPainter *, const QTransform *const, const QTransform *const, - QRegion *, QWidget *, qreal, QPoint *, bool, bool); + const QTransform *const effectTransform = 0); + void draw(QGraphicsItem *, QPainter *, const QTransform *const, QTransform *, + QRegion *, QWidget *, qreal, const QTransform *const, bool, bool); void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false, bool maybeDirtyClipPath = false, bool force = false, bool ignoreOpacity = false, -- cgit v0.12 From f55576b670c69b69c5f1140661cf20cbda96853a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 28 Jul 2009 16:57:35 +0200 Subject: add support for passing arbitrary painters into QGraphicsEffectSource::draw --- src/gui/graphicsview/qgraphicsitem.cpp | 16 +++++++++++++--- src/gui/graphicsview/qgraphicsitem_p.h | 5 +++-- src/gui/graphicsview/qgraphicsscene.cpp | 2 +- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 425031f..120ca05 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -9939,9 +9939,19 @@ QRectF QGraphicsItemEffectSourcePrivate::boundingRect(bool deviceCoordinates) co void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter) { - QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); - scened->draw(item, painter, info->viewTransform, info->transformPtr, info->exposedRegion, - info->widget, info->opacity, 0, info->wasDirtySceneTransform, info->drawItem); + if (painter == info->painter) { + QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); + scened->draw(item, painter, info->viewTransform, info->transformPtr, info->exposedRegion, + info->widget, info->opacity, 0, info->wasDirtySceneTransform, + info->drawItem); + } else { + QTransform effectTransform = painter->worldTransform(); + effectTransform *= info->transformPtr->inverted(); + QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); + scened->draw(item, painter, info->viewTransform, info->transformPtr, info->exposedRegion, + info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform, + info->drawItem); + } } QPixmap QGraphicsItemEffectSourcePrivate::pixmap(bool deviceCoordinates, QPoint *offset) const diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index db79e07..c6161bf 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -514,9 +514,9 @@ struct QGraphicsItemPaintInfo { inline QGraphicsItemPaintInfo(const QTransform *const xform1, QTransform *xform2, QRegion *r, QWidget *w, QStyleOptionGraphicsItem *opt, - qreal o, bool b1, bool b2) + QPainter *p, qreal o, bool b1, bool b2) : viewTransform(xform1), transformPtr(xform2), exposedRegion(r), widget(w), - option(opt), opacity(o), wasDirtySceneTransform(b1), drawItem(b2) + option(opt), painter(p), opacity(o), wasDirtySceneTransform(b1), drawItem(b2) {} const QTransform *viewTransform; @@ -524,6 +524,7 @@ struct QGraphicsItemPaintInfo QRegion *exposedRegion; QWidget *widget; QStyleOptionGraphicsItem *option; + QPainter *painter; qreal opacity; quint32 wasDirtySceneTransform : 1; quint32 drawItem : 1; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 3a899ff..99aa347 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4310,7 +4310,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * } ENSURE_TRANSFORM_PTR; QGraphicsItemPaintInfo info(viewTransform, transformPtr, exposedRegion, widget, &styleOptionTmp, - opacity, wasDirtyParentSceneTransform, drawItem); + painter, opacity, wasDirtyParentSceneTransform, drawItem); QGraphicsEffectSource *source = item->d_ptr->graphicsEffect->d_func()->source; QGraphicsItemEffectSourcePrivate *sourced = static_cast (source->d_func()); -- cgit v0.12 From f0ed432d55ef6da7223ee3d58e45391e3f88be86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 29 Jul 2009 02:26:35 +0200 Subject: Remove drawIntoPixmap and implement all the effects with the new API. --- src/gui/graphicsview/qgraphicseffect.cpp | 159 +++++++------------------------ src/gui/graphicsview/qgraphicseffect.h | 1 - src/gui/graphicsview/qgraphicseffect_p.h | 3 +- src/gui/graphicsview/qgraphicsitem.cpp | 32 +------ src/gui/graphicsview/qgraphicsitem_p.h | 1 - 5 files changed, 37 insertions(+), 159 deletions(-) diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index 1281847..26dc35c 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -121,9 +121,6 @@ const QStyleOption *QGraphicsEffectSource::styleOption() const void QGraphicsEffectSource::draw(QPainter *painter) { d_func()->draw(painter); } -bool QGraphicsEffectSource::drawIntoPixmap(QPixmap *pixmap, const QPoint &offset) -{ return d_func()->drawIntoPixmap(pixmap, offset); } - QPixmap QGraphicsEffectSource::pixmap(bool deviceCoordinates, QPoint *offset) const { return d_func()->pixmap(deviceCoordinates, offset); } @@ -177,29 +174,6 @@ QRectF QGraphicsEffect::boundingRectFor(const QRectF &rect) const return rect; } -//QRectF QGraphicsEffect::sourceBoundingRect(bool deviceCoordinates) const -//{ -// Q_D(const QGraphicsEffect); -// if (d->source) -// return d->source->boundingRect(deviceCoordinates); -// return QRectF(); -//} - -//void QGraphicsEffect::drawSource(QPainter *painter) -//{ -// Q_D(QGraphicsEffect); -// if (d->source) -// d->source->d_func()->draw(painter); -//} - -//bool QGraphicsEffect::drawSourceIntoPixmap(QPixmap *pixmap, const QPoint &offset) -//{ -// Q_D(QGraphicsEffect); -// if (d->source) -// return d->source->d_func()->drawIntoPixmap(pixmap, offset); -// return false; -//} - QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect() : QGraphicsEffect(*new QGraphicsGrayscaleEffectPrivate) {} @@ -210,17 +184,13 @@ QGraphicsGrayscaleEffect::~QGraphicsGrayscaleEffect() void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsGrayscaleEffect); - // Find the item's bounds in device coordinates. - const QRect sourceRect = source->boundingRect(/*deviceCoordinates=*/true) - .toRect().adjusted(-1, -1, 1, 1); - QPixmap pixmap(sourceRect.size()); - if (!source->drawIntoPixmap(&pixmap, sourceRect.topLeft())) - return; + QPoint offset; + const QPixmap pixmap = source->pixmap(true, &offset); // Draw the pixmap with the filter using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - d->filter->draw(painter, sourceRect.topLeft(), pixmap, pixmap.rect()); + d->filter->draw(painter, offset, pixmap, pixmap.rect()); painter->setWorldTransform(restoreTransform); } @@ -247,16 +217,13 @@ void QGraphicsColorizeEffect::setColor(const QColor &c) void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsColorizeEffect); - const QRect sourceRect = source->boundingRect(/*deviceCoordinates=*/true) - .toRect().adjusted(-1, -1, 1, 1); - QPixmap pixmap(sourceRect.size()); - if (!source->drawIntoPixmap(&pixmap, sourceRect.topLeft())) - return; + QPoint offset; + const QPixmap pixmap = source->pixmap(true, &offset); // Draw the pixmap with the filter using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - d->filter->draw(painter, sourceRect.topLeft(), pixmap, pixmap.rect()); + d->filter->draw(painter, offset, pixmap, pixmap.rect()); painter->setWorldTransform(restoreTransform); } @@ -284,12 +251,8 @@ void QGraphicsPixelizeEffect::setPixelSize(int size) void QGraphicsPixelizeEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsPixelizeEffect); - // Find the item's bounds in device coordinates. - const QRect sourceRect = source->boundingRect(/*deviceCoordinates=*/true) - .toRect().adjusted(-1, -1, 1, 1); - QPixmap pixmap(sourceRect.size()); - if (!source->drawIntoPixmap(&pixmap, sourceRect.topLeft())) - return; + QPoint offset; + const QPixmap pixmap = source->pixmap(true, &offset); // pixelize routine QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); @@ -314,7 +277,7 @@ void QGraphicsPixelizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou // Draw using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - painter->drawImage(sourceRect.topLeft(), img); + painter->drawImage(offset, img); painter->setWorldTransform(restoreTransform); } @@ -410,9 +373,6 @@ QRectF QGraphicsBlurEffect::boundingRectFor(const QRectF &rect) const return d->filter->boundingRectFor(rect); } -//QRectF QGraphicsBlurEffect::boundingRectFor(const QRectF &rect) const -//{ -// Q_D(const QGraphicsBlurEffect); // return d->filter->boundingRectFor(rect); //} @@ -462,15 +422,6 @@ void QGraphicsBloomEffect::setOpacity(qreal alpha) d->opacity = alpha; } -//QRectF QGraphicsBloomEffect::boundingRectFor(nst QGraphicsEffectSource *source) const -//{ -// Q_D(const QGraphicsBloomEffect); -// if (!d->source) -// return QRectF(); -// const qreal delta = d->blurRadius * 3; -// return sourceBoundingRect().adjusted(-delta, -delta, delta, delta); -//} - QRectF QGraphicsBloomEffect::boundingRectFor(const QRectF &rect) const { Q_D(const QGraphicsBloomEffect); @@ -512,15 +463,11 @@ static QImage composited(const QImage& img1, const QImage& img2, qreal opacity, void QGraphicsBloomEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsBloomEffect); - const QRectF sourceRect = source->boundingRect(/*deviceCoordinates=*/true); - const QRect effectRect = boundingRectFor(sourceRect).toRect().adjusted(-1, -1, 1, 1); - - QPixmap pixmap(effectRect.size()); - if (!source->drawIntoPixmap(&pixmap, effectRect.topLeft())) - return; + QPoint offset; + const QPixmap pixmap = source->pixmap(true, &offset); // bloom routine - int radius = d->blurRadius; + const int radius = d->blurRadius; QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); QImage overlay = blurred(img, img.rect(), radius); overlay = brightened(overlay, 70); @@ -529,7 +476,7 @@ void QGraphicsBloomEffect::draw(QPainter *painter, QGraphicsEffectSource *source // Draw using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - painter->drawImage(effectRect.topLeft(), img); + painter->drawImage(offset - QPoint(radius * 3, radius * 3), img); painter->setWorldTransform(restoreTransform); } @@ -578,14 +525,6 @@ void QGraphicsFrameEffect::setFrameOpacity(qreal opacity) d->alpha = opacity; } -//QRectF QGraphicsFrameEffect::boundingRect() const -//{ -// Q_D(const QGraphicsFrameEffect); -// if (!d->source) -// return QRectF(); -// return d->source->boundingRect().adjusted(-d->width, -d->width, d->width, d->width); -//} - QRectF QGraphicsFrameEffect::boundingRectFor(const QRectF &rect) const { Q_D(const QGraphicsFrameEffect); @@ -614,87 +553,72 @@ QGraphicsShadowEffect::~QGraphicsShadowEffect() { } -QPointF QGraphicsShadowEffect::shadowOffset() const +QPointF QGraphicsShadowEffect::shadowOffset() const { Q_D(const QGraphicsShadowEffect); return d->offset; } -void QGraphicsShadowEffect::setShadowOffset(const QPointF &ofs) +void QGraphicsShadowEffect::setShadowOffset(const QPointF &ofs) { Q_D(QGraphicsShadowEffect); d->offset = ofs; } -int QGraphicsShadowEffect::blurRadius() const +int QGraphicsShadowEffect::blurRadius() const { Q_D(const QGraphicsShadowEffect); return d->radius; } -void QGraphicsShadowEffect::setBlurRadius(int blurRadius) +void QGraphicsShadowEffect::setBlurRadius(int blurRadius) { Q_D(QGraphicsShadowEffect); d->radius = blurRadius; } -qreal QGraphicsShadowEffect::opacity() const +qreal QGraphicsShadowEffect::opacity() const { Q_D(const QGraphicsShadowEffect); return d->alpha; } -void QGraphicsShadowEffect::setOpacity(qreal opacity) +void QGraphicsShadowEffect::setOpacity(qreal opacity) { Q_D(QGraphicsShadowEffect); d->alpha = opacity; } -//QRectF QGraphicsShadowEffect::boundingRect() const -//{ -// Q_D(const QGraphicsShadowEffect); -// if (!d->source) -// return QRectF(); -// const QRectF srcBrect = d->source->boundingRect(); -// QRectF shadowRect = srcBrect; -// shadowRect.adjust(d->offset.x(), d->offset.y(), d->offset.x(), d->offset.y()); -// QRectF blurRect = shadowRect; -// qreal delta = d->radius * 3; -// blurRect.adjust(-delta, -delta, delta, delta); -// QRectF totalRect = blurRect.united(srcBrect); -// return totalRect; -//} - QRectF QGraphicsShadowEffect::boundingRectFor(const QRectF &rect) const { Q_D(const QGraphicsShadowEffect); - QRectF shadowRect = rect; - shadowRect.adjust(d->offset.x(), d->offset.y(), d->offset.x(), d->offset.y()); + QRectF shadowRect = rect.translated(d->offset); QRectF blurRect = shadowRect; qreal delta = d->radius * 3; blurRect.adjust(-delta, -delta, delta, delta); - QRectF totalRect = blurRect.united(rect); - return totalRect; + blurRect |= rect; + return blurRect; } void QGraphicsShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsShadowEffect); - if (!d->source) - return; - const QRectF sourceRect = source->boundingRect(/*deviceCoordinates=*/true); - - QRectF shadowRect = sourceRect; - shadowRect.adjust(d->offset.x(), d->offset.y(), d->offset.x(), d->offset.y()); + const QRectF shadowRect = sourceRect.translated(d->offset); QRectF blurRect = shadowRect; qreal delta = d->radius * 3; blurRect.adjust(-delta, -delta, delta, delta); - QRect totalRect = blurRect.united(sourceRect).toRect().adjusted(-1, -1, 1, 1); + blurRect |= sourceRect; + const QRect effectRect = blurRect.toAlignedRect(); - QPixmap pixmap(totalRect.size()); - if (!source->drawIntoPixmap(&pixmap, totalRect.topLeft())) - return; + QPixmap pixmap(effectRect.size()); + pixmap.fill(Qt::transparent); + QPainter pixmapPainter(&pixmap); + pixmapPainter.setRenderHints(painter->renderHints()); + pixmapPainter.setWorldTransform(painter->worldTransform()); + pixmapPainter.translate(-effectRect.topLeft()); + source->draw(&pixmapPainter); + pixmapPainter.end(); QImage img = pixmap.toImage(); QImage shadowImage(img.size(), QImage::Format_ARGB32); @@ -705,21 +629,8 @@ void QGraphicsShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *sourc // Draw using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - - QRect shadowAlignedRect = shadowRect.toAlignedRect(); - - qreal shadowx = blurRect.x() + delta; - qreal shadowy = blurRect.y() + delta; - if (blurRect.x() < sourceRect.x()) - shadowx = sourceRect.x() + d->offset.x(); - if (blurRect.y() < sourceRect.y()) - shadowy = blurRect.y() + d->offset.y(); - painter->drawImage(shadowx, shadowy, shadowImage); - - qreal itemx = qMin(blurRect.x(), sourceRect.x()); - qreal itemy = qMin(blurRect.y(), sourceRect.y()); - painter->drawPixmap(itemx, itemy, pixmap); - + painter->drawImage(effectRect.topLeft() + d->offset, shadowImage); + painter->drawPixmap(effectRect.topLeft(), pixmap); painter->setWorldTransform(restoreTransform); } diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h index 77eebd6..175541f 100644 --- a/src/gui/graphicsview/qgraphicseffect.h +++ b/src/gui/graphicsview/qgraphicseffect.h @@ -75,7 +75,6 @@ public: const QGraphicsItem *graphicsItem() const; const QStyleOption *styleOption() const; void draw(QPainter *painter); - bool drawIntoPixmap(QPixmap *pixmap, const QPoint &offset = QPoint()); QPixmap pixmap(bool deviceCoordinates, QPoint *offset = 0) const; protected: diff --git a/src/gui/graphicsview/qgraphicseffect_p.h b/src/gui/graphicsview/qgraphicseffect_p.h index a575d3b..ddf65e9 100644 --- a/src/gui/graphicsview/qgraphicseffect_p.h +++ b/src/gui/graphicsview/qgraphicseffect_p.h @@ -72,7 +72,6 @@ public: virtual const QGraphicsItem *graphicsItem() const = 0; virtual const QStyleOption *styleOption() const = 0; virtual void draw(QPainter *p) = 0; - virtual bool drawIntoPixmap(QPixmap *, const QPoint &offset = QPoint()) = 0; virtual QPixmap pixmap(bool deviceCoordinates, QPoint *offset = 0) const = 0; friend class QGraphicsScenePrivate; friend class QGraphicsItem; @@ -168,7 +167,7 @@ class QGraphicsShadowEffectPrivate : public QGraphicsEffectPrivate { Q_DECLARE_PUBLIC(QGraphicsShadowEffect) public: - QGraphicsShadowEffectPrivate() : offset(4,4), radius(8), alpha(0.7) {} + QGraphicsShadowEffectPrivate() : offset(4, 4), radius(8), alpha(0.7) {} QPointF offset; int radius; diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 120ca05..c0fa271 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -9972,7 +9972,7 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(bool deviceCoordinates, QPoint QPixmap pixmap(effectRect.size()); pixmap.fill(Qt::transparent); QPainter pixmapPainter(&pixmap); - pixmapPainter.setRenderHints(QPainter::SmoothPixmapTransform | QPainter::Antialiasing); + pixmapPainter.setRenderHints(info->painter->renderHints()); QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, info->exposedRegion, @@ -9981,36 +9981,6 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(bool deviceCoordinates, QPoint return pixmap; } -bool QGraphicsItemEffectSourcePrivate::drawIntoPixmap(QPixmap *pixmap, const QPoint &offset) -{ - QPoint effectOffset(offset); - - QTransform viewTransform(Qt::Uninitialized); - if (info->viewTransform) { - viewTransform = *info->viewTransform; - viewTransform *= QTransform::fromTranslate(-effectOffset.x(), -effectOffset.y()); - } else { - viewTransform = QTransform::fromTranslate(-effectOffset.x(), -effectOffset.y()); - } - - *info->transformPtr *= QTransform::fromTranslate(-effectOffset.x(), -effectOffset.y()); - - QRegion exposedRegion; - if (info->exposedRegion) { - exposedRegion = *info->exposedRegion; - exposedRegion.translate(-effectOffset.x(), -effectOffset.y()); - } - - pixmap->fill(Qt::transparent); - QPainter pixmapPainter(pixmap); - pixmapPainter.setRenderHints(QPainter::SmoothPixmapTransform | QPainter::Antialiasing); - QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); - scened->draw(item, &pixmapPainter, &viewTransform, info->transformPtr, &exposedRegion, - info->widget, info->opacity, 0, info->wasDirtySceneTransform, - info->drawItem); - return true; -} - #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug debug, QGraphicsItem *item) { diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index c6161bf..f8b2ebc 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -548,7 +548,6 @@ public: QRectF boundingRect(bool deviceCoordinates) const; void draw(QPainter *); - bool drawIntoPixmap(QPixmap *pixmap, const QPoint &offset); QPixmap pixmap(bool deviceCoordinates, QPoint *offset) const; QGraphicsItem *item; -- cgit v0.12 From 1cff081464744774d9d3e76704c03209fca280c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 29 Jul 2009 04:56:22 +0200 Subject: Add new enum to global namespace: Qt::CoordinateSystem --- src/corelib/global/qnamespace.h | 5 +++++ src/gui/graphicsview/qgraphicseffect.cpp | 20 ++++++++++---------- src/gui/graphicsview/qgraphicseffect.h | 4 ++-- src/gui/graphicsview/qgraphicseffect_p.h | 4 ++-- src/gui/graphicsview/qgraphicsitem.cpp | 9 +++++---- src/gui/graphicsview/qgraphicsitem_p.h | 4 ++-- 6 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 7770fd6..834ad1a 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -1552,6 +1552,11 @@ public: Uninitialized }; + enum CoordinateSystem { + DeviceCoordinates, + LogicalCoordinates + }; + enum TouchPointState { TouchPointPressed = 0x01, TouchPointMoved = 0x02, diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index 26dc35c..63cf975 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -109,8 +109,8 @@ QGraphicsEffectSource::QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, Q QGraphicsEffectSource::~QGraphicsEffectSource() {} -QRectF QGraphicsEffectSource::boundingRect(bool deviceCoordinates) const -{ return d_func()->boundingRect(deviceCoordinates); } +QRectF QGraphicsEffectSource::boundingRect(Qt::CoordinateSystem system) const +{ return d_func()->boundingRect(system); } const QGraphicsItem *QGraphicsEffectSource::graphicsItem() const { return d_func()->graphicsItem(); } @@ -121,8 +121,8 @@ const QStyleOption *QGraphicsEffectSource::styleOption() const void QGraphicsEffectSource::draw(QPainter *painter) { d_func()->draw(painter); } -QPixmap QGraphicsEffectSource::pixmap(bool deviceCoordinates, QPoint *offset) const -{ return d_func()->pixmap(deviceCoordinates, offset); } +QPixmap QGraphicsEffectSource::pixmap(Qt::CoordinateSystem system, QPoint *offset) const +{ return d_func()->pixmap(system, offset); } QGraphicsEffect::QGraphicsEffect() : QObject(*new QGraphicsEffectPrivate, 0) @@ -185,7 +185,7 @@ void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *so { Q_D(QGraphicsGrayscaleEffect); QPoint offset; - const QPixmap pixmap = source->pixmap(true, &offset); + const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); // Draw the pixmap with the filter using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); @@ -218,7 +218,7 @@ void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou { Q_D(QGraphicsColorizeEffect); QPoint offset; - const QPixmap pixmap = source->pixmap(true, &offset); + const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); // Draw the pixmap with the filter using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); @@ -252,7 +252,7 @@ void QGraphicsPixelizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou { Q_D(QGraphicsPixelizeEffect); QPoint offset; - const QPixmap pixmap = source->pixmap(true, &offset); + const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); // pixelize routine QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); @@ -380,7 +380,7 @@ void QGraphicsBlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsBlurEffect); QPoint offset; - const QPixmap pixmap = source->pixmap(true, &offset); + const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); // Draw the pixmap with the filter using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); @@ -464,7 +464,7 @@ void QGraphicsBloomEffect::draw(QPainter *painter, QGraphicsEffectSource *source { Q_D(QGraphicsBloomEffect); QPoint offset; - const QPixmap pixmap = source->pixmap(true, &offset); + const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); // bloom routine const int radius = d->blurRadius; @@ -603,7 +603,7 @@ QRectF QGraphicsShadowEffect::boundingRectFor(const QRectF &rect) const void QGraphicsShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsShadowEffect); - const QRectF sourceRect = source->boundingRect(/*deviceCoordinates=*/true); + const QRectF sourceRect = source->boundingRect(Qt::DeviceCoordinates); const QRectF shadowRect = sourceRect.translated(d->offset); QRectF blurRect = shadowRect; qreal delta = d->radius * 3; diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h index 175541f..397651f 100644 --- a/src/gui/graphicsview/qgraphicseffect.h +++ b/src/gui/graphicsview/qgraphicseffect.h @@ -71,11 +71,11 @@ class Q_GUI_EXPORT QGraphicsEffectSource : public QObject Q_OBJECT public: ~QGraphicsEffectSource(); - QRectF boundingRect(bool deviceCoordinates = false) const; + QRectF boundingRect(Qt::CoordinateSystem s = Qt::LogicalCoordinates) const; const QGraphicsItem *graphicsItem() const; const QStyleOption *styleOption() const; void draw(QPainter *painter); - QPixmap pixmap(bool deviceCoordinates, QPoint *offset = 0) const; + QPixmap pixmap(Qt::CoordinateSystem coordinateSystem, QPoint *offset = 0) const; protected: QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, QObject *parent = 0); diff --git a/src/gui/graphicsview/qgraphicseffect_p.h b/src/gui/graphicsview/qgraphicseffect_p.h index ddf65e9..b106e8e 100644 --- a/src/gui/graphicsview/qgraphicseffect_p.h +++ b/src/gui/graphicsview/qgraphicseffect_p.h @@ -68,11 +68,11 @@ public: QGraphicsEffectSourcePrivate() : QObjectPrivate() {} virtual ~QGraphicsEffectSourcePrivate() {} virtual void detach() = 0; - virtual QRectF boundingRect(bool deviceCoordinates = false) const = 0; + virtual QRectF boundingRect(Qt::CoordinateSystem system) const = 0; virtual const QGraphicsItem *graphicsItem() const = 0; virtual const QStyleOption *styleOption() const = 0; virtual void draw(QPainter *p) = 0; - virtual QPixmap pixmap(bool deviceCoordinates, QPoint *offset = 0) const = 0; + virtual QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset = 0) const = 0; friend class QGraphicsScenePrivate; friend class QGraphicsItem; friend class QGraphicsItemPrivate; diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index c0fa271..bb3258d 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -9926,11 +9926,11 @@ int QGraphicsItemGroup::type() const return Type; } -QRectF QGraphicsItemEffectSourcePrivate::boundingRect(bool deviceCoordinates) const +QRectF QGraphicsItemEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const { QRectF rect = item->boundingRect(); rect |= item->childrenBoundingRect(); - if (deviceCoordinates && info) { + if (info && system == Qt::DeviceCoordinates) { Q_ASSERT(info->transformPtr); return info->transformPtr->mapRect(rect); } @@ -9954,15 +9954,16 @@ void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter) } } -QPixmap QGraphicsItemEffectSourcePrivate::pixmap(bool deviceCoordinates, QPoint *offset) const +QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset) const { - const QRectF sourceRect = boundingRect(deviceCoordinates); + const QRectF sourceRect = boundingRect(system); const QRect effectRect = item->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect(); if (offset) *offset = sourceRect.toAlignedRect().topLeft(); const QTransform translateTransform = QTransform::fromTranslate(-effectRect.x(), -effectRect.y()); + const bool deviceCoordinates = (system == Qt::DeviceCoordinates); QTransform effectTransform = deviceCoordinates ? translateTransform : info->transformPtr->inverted(); if (!deviceCoordinates) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index f8b2ebc..de8b0a5 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -546,9 +546,9 @@ public: inline const QStyleOption *styleOption() const { return info ? info->option : 0; } - QRectF boundingRect(bool deviceCoordinates) const; + QRectF boundingRect(Qt::CoordinateSystem system) const; void draw(QPainter *); - QPixmap pixmap(bool deviceCoordinates, QPoint *offset) const; + QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset) const; QGraphicsItem *item; QGraphicsItemPaintInfo *info; -- cgit v0.12 From 0eccc0f9ee9579883a829c373cfc1c072704bca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 29 Jul 2009 05:15:02 +0200 Subject: Make it possible to disable graphics effects. Adds QGraphicsEffect::setEnabled/isEnabled --- src/gui/graphicsview/qgraphicseffect.cpp | 12 ++++++++++++ src/gui/graphicsview/qgraphicseffect.h | 9 +++++++-- src/gui/graphicsview/qgraphicseffect_p.h | 5 +++-- src/gui/graphicsview/qgraphicsitem.cpp | 2 +- src/gui/graphicsview/qgraphicsscene.cpp | 4 ++-- 5 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index 63cf975..358826b 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -174,6 +174,18 @@ QRectF QGraphicsEffect::boundingRectFor(const QRectF &rect) const return rect; } +void QGraphicsEffect::setEnabled(bool enable) +{ + Q_D(QGraphicsEffect); + d->isEnabled = enable; +} + +bool QGraphicsEffect::isEnabled() const +{ + Q_D(const QGraphicsEffect); + return d->isEnabled; +} + QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect() : QGraphicsEffect(*new QGraphicsGrayscaleEffectPrivate) {} diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h index 397651f..e484f1a 100644 --- a/src/gui/graphicsview/qgraphicseffect.h +++ b/src/gui/graphicsview/qgraphicseffect.h @@ -71,11 +71,11 @@ class Q_GUI_EXPORT QGraphicsEffectSource : public QObject Q_OBJECT public: ~QGraphicsEffectSource(); - QRectF boundingRect(Qt::CoordinateSystem s = Qt::LogicalCoordinates) const; const QGraphicsItem *graphicsItem() const; const QStyleOption *styleOption() const; void draw(QPainter *painter); - QPixmap pixmap(Qt::CoordinateSystem coordinateSystem, QPoint *offset = 0) const; + QRectF boundingRect(Qt::CoordinateSystem coordinateSystem = Qt::LogicalCoordinates) const; + QPixmap pixmap(Qt::CoordinateSystem system = Qt::LogicalCoordinates, QPoint *offset = 0) const; protected: QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, QObject *parent = 0); @@ -93,6 +93,7 @@ class QGraphicsEffectPrivate; class Q_GUI_EXPORT QGraphicsEffect : public QObject { Q_OBJECT + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) public: QGraphicsEffect(); virtual ~QGraphicsEffect(); @@ -102,6 +103,10 @@ public: QPixmap sourcePixmap() const; bool hasSourcePixmap() const; virtual QRectF boundingRectFor(const QRectF &rect) const; + bool isEnabled() const; + +public Q_SLOTS: + void setEnabled(bool enable); protected: QGraphicsEffect(QGraphicsEffectPrivate &d); diff --git a/src/gui/graphicsview/qgraphicseffect_p.h b/src/gui/graphicsview/qgraphicseffect_p.h index b106e8e..f084a84 100644 --- a/src/gui/graphicsview/qgraphicseffect_p.h +++ b/src/gui/graphicsview/qgraphicseffect_p.h @@ -82,7 +82,7 @@ class QGraphicsEffectPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QGraphicsEffect) public: - QGraphicsEffectPrivate() : source(0), hasSourcePixmap(0) {} + QGraphicsEffectPrivate() : source(0), hasSourcePixmap(0), isEnabled(1) {} QGraphicsEffectSource *source; inline void setGraphicsEffectSource(QGraphicsEffectSource *newSource) { @@ -95,7 +95,8 @@ public: QRectF boundingRect; QPixmap sourcePixmap; quint32 hasSourcePixmap : 1; - quint32 padding : 31; // feel free to use + quint32 isEnabled : 1; + quint32 padding : 30; // feel free to use }; class QGraphicsGrayscaleEffectPrivate : public QGraphicsEffectPrivate diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index bb3258d..8c604e1 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2252,7 +2252,7 @@ void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect) */ QRectF QGraphicsItem::effectiveBoundingRect() const { - if (d_ptr->graphicsEffect) + if (d_ptr->graphicsEffect && d_ptr->graphicsEffect->isEnabled()) return d_ptr->graphicsEffect->boundingRect(); return boundingRect(); } diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 99aa347..9ce02a2 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4303,7 +4303,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (itemHasChildren && itemClipsChildrenToShape) ENSURE_TRANSFORM_PTR; - if (item->d_ptr->graphicsEffect) { + if (item->d_ptr->graphicsEffect && item->d_ptr->graphicsEffect->isEnabled()) { if (item->type() == 7) { item->d_ptr->graphicsEffect->setSourcePixmap(static_cast(item) ->pixmap()); @@ -4484,7 +4484,7 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b QGraphicsItem *p = item->d_ptr->parent; while (p) { p->d_ptr->dirtyChildren = 1; - if (p->d_ptr->graphicsEffect) { + if (p->d_ptr->graphicsEffect && p->d_ptr->graphicsEffect->isEnabled()) { p->d_ptr->dirty = 1; p->d_ptr->fullUpdatePending = 1; } -- cgit v0.12 From 8334e6f6590d801971a3ec9fe64ff087c750c26a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 29 Jul 2009 05:45:15 +0200 Subject: Add support for updating the source when bounding rect changes. --- src/gui/graphicsview/qgraphicseffect.cpp | 19 ++++++++++++++++--- src/gui/graphicsview/qgraphicseffect.h | 2 ++ src/gui/graphicsview/qgraphicseffect_p.h | 1 + src/gui/graphicsview/qgraphicsitem_p.h | 3 +++ 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index 358826b..6bf28ac 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -121,16 +121,17 @@ const QStyleOption *QGraphicsEffectSource::styleOption() const void QGraphicsEffectSource::draw(QPainter *painter) { d_func()->draw(painter); } +void QGraphicsEffectSource::update() +{ d_func()->update(); } + QPixmap QGraphicsEffectSource::pixmap(Qt::CoordinateSystem system, QPoint *offset) const { return d_func()->pixmap(system, offset); } + QGraphicsEffect::QGraphicsEffect() : QObject(*new QGraphicsEffectPrivate, 0) {} -/*! - \internal -*/ QGraphicsEffect::QGraphicsEffect(QGraphicsEffectPrivate &dd) : QObject(dd, 0) {} @@ -186,6 +187,13 @@ bool QGraphicsEffect::isEnabled() const return d->isEnabled; } +void QGraphicsEffect::updateBoundingRect() +{ + Q_D(QGraphicsEffect); + if (d->source) + d->source->update(); +} + QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect() : QGraphicsEffect(*new QGraphicsGrayscaleEffectPrivate) {} @@ -377,6 +385,7 @@ void QGraphicsBlurEffect::setBlurRadius(int radius) { Q_D(QGraphicsBlurEffect); d->filter->setBlurRadius(radius); + updateBoundingRect(); } QRectF QGraphicsBlurEffect::boundingRectFor(const QRectF &rect) const @@ -420,6 +429,7 @@ void QGraphicsBloomEffect::setBlurRadius(int radius) { Q_D(QGraphicsBloomEffect); d->blurRadius = radius; + updateBoundingRect(); } qreal QGraphicsBloomEffect::opacity() const @@ -523,6 +533,7 @@ void QGraphicsFrameEffect::setFrameWidth(qreal frameWidth) { Q_D(QGraphicsFrameEffect); d->width = frameWidth; + updateBoundingRect(); } qreal QGraphicsFrameEffect::frameOpacity() const @@ -575,6 +586,7 @@ void QGraphicsShadowEffect::setShadowOffset(const QPointF &ofs) { Q_D(QGraphicsShadowEffect); d->offset = ofs; + updateBoundingRect(); } int QGraphicsShadowEffect::blurRadius() const @@ -587,6 +599,7 @@ void QGraphicsShadowEffect::setBlurRadius(int blurRadius) { Q_D(QGraphicsShadowEffect); d->radius = blurRadius; + updateBoundingRect(); } qreal QGraphicsShadowEffect::opacity() const diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h index e484f1a..9deada1 100644 --- a/src/gui/graphicsview/qgraphicseffect.h +++ b/src/gui/graphicsview/qgraphicseffect.h @@ -74,6 +74,7 @@ public: const QGraphicsItem *graphicsItem() const; const QStyleOption *styleOption() const; void draw(QPainter *painter); + void update(); QRectF boundingRect(Qt::CoordinateSystem coordinateSystem = Qt::LogicalCoordinates) const; QPixmap pixmap(Qt::CoordinateSystem system = Qt::LogicalCoordinates, QPoint *offset = 0) const; @@ -111,6 +112,7 @@ public Q_SLOTS: protected: QGraphicsEffect(QGraphicsEffectPrivate &d); virtual void draw(QPainter *painter, QGraphicsEffectSource *source) = 0; + void updateBoundingRect(); private: Q_DECLARE_PRIVATE(QGraphicsEffect) diff --git a/src/gui/graphicsview/qgraphicseffect_p.h b/src/gui/graphicsview/qgraphicseffect_p.h index f084a84..63da37b 100644 --- a/src/gui/graphicsview/qgraphicseffect_p.h +++ b/src/gui/graphicsview/qgraphicseffect_p.h @@ -72,6 +72,7 @@ public: virtual const QGraphicsItem *graphicsItem() const = 0; virtual const QStyleOption *styleOption() const = 0; virtual void draw(QPainter *p) = 0; + virtual void update() = 0; virtual QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset = 0) const = 0; friend class QGraphicsScenePrivate; friend class QGraphicsItem; diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index de8b0a5..8a2dae9 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -543,6 +543,9 @@ public: inline const QGraphicsItem *graphicsItem() const { return item; } + inline void update() + { item->update(); } + inline const QStyleOption *styleOption() const { return info ? info->option : 0; } -- cgit v0.12 From 8ec8c7f97efc1e5ae6fc5deae4b4d7aeb0a93f31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 29 Jul 2009 05:54:43 +0200 Subject: Notify sub-classes of QGraphicsEffect whenever the source changes. --- src/gui/graphicsview/qgraphicseffect.cpp | 9 +++++++++ src/gui/graphicsview/qgraphicseffect.h | 2 ++ src/gui/graphicsview/qgraphicseffect_p.h | 1 + 3 files changed, 12 insertions(+) diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index 6bf28ac..f3f7f22 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -187,6 +187,12 @@ bool QGraphicsEffect::isEnabled() const return d->isEnabled; } +QGraphicsEffectSource *QGraphicsEffect::source() const +{ + Q_D(const QGraphicsEffect); + return d->source; +} + void QGraphicsEffect::updateBoundingRect() { Q_D(QGraphicsEffect); @@ -194,6 +200,9 @@ void QGraphicsEffect::updateBoundingRect() d->source->update(); } +void QGraphicsEffect::sourceChanged(QGraphicsEffectSource *) +{} + QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect() : QGraphicsEffect(*new QGraphicsGrayscaleEffectPrivate) {} diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h index 9deada1..1db8b6e 100644 --- a/src/gui/graphicsview/qgraphicseffect.h +++ b/src/gui/graphicsview/qgraphicseffect.h @@ -105,6 +105,7 @@ public: bool hasSourcePixmap() const; virtual QRectF boundingRectFor(const QRectF &rect) const; bool isEnabled() const; + QGraphicsEffectSource *source() const; public Q_SLOTS: void setEnabled(bool enable); @@ -112,6 +113,7 @@ public Q_SLOTS: protected: QGraphicsEffect(QGraphicsEffectPrivate &d); virtual void draw(QPainter *painter, QGraphicsEffectSource *source) = 0; + virtual void sourceChanged(QGraphicsEffectSource *newSource); void updateBoundingRect(); private: diff --git a/src/gui/graphicsview/qgraphicseffect_p.h b/src/gui/graphicsview/qgraphicseffect_p.h index 63da37b..7ebfe07 100644 --- a/src/gui/graphicsview/qgraphicseffect_p.h +++ b/src/gui/graphicsview/qgraphicseffect_p.h @@ -92,6 +92,7 @@ public: delete source; } source = newSource; + q_func()->sourceChanged(newSource); } QRectF boundingRect; QPixmap sourcePixmap; -- cgit v0.12 From a79b31aba0405b0a24e210a2479d4b1df729c608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 29 Jul 2009 06:39:31 +0200 Subject: Generalize QGraphicsEffectSource::pixmap. Before QGraphicsEffectSource::pixmap could only return something useful when called from QGraphicsEffect::draw. This patch removes this limitation. However, we still cannot provide pixmaps in device coordinates when not called from QGraphicsEffect::draw, though. --- src/gui/graphicsview/qgraphicsitem.cpp | 52 +++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 8c604e1..392fdaa 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -9939,6 +9939,11 @@ QRectF QGraphicsItemEffectSourcePrivate::boundingRect(Qt::CoordinateSystem syste void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter) { + if (!info) { + qWarning("QGraphicsEffectSource::draw: Can only begin as a result of QGraphicsEffect::draw"); + return; + } + if (painter == info->painter) { QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); scened->draw(item, painter, info->viewTransform, info->transformPtr, info->exposedRegion, @@ -9956,29 +9961,50 @@ void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter) QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset) const { + const bool deviceCoordinates = (system == Qt::DeviceCoordinates); + if (!info && deviceCoordinates) { + // Device coordinates without info not yet supported. + qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context"); + return QPixmap(); + } + const QRectF sourceRect = boundingRect(system); const QRect effectRect = item->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect(); if (offset) *offset = sourceRect.toAlignedRect().topLeft(); + QPixmap pixmap(effectRect.size()); + pixmap.fill(Qt::transparent); + QPainter pixmapPainter(&pixmap); + pixmapPainter.setRenderHints(info ? info->painter->renderHints() : QPainter::TextAntialiasing); + const QTransform translateTransform = QTransform::fromTranslate(-effectRect.x(), -effectRect.y()); - const bool deviceCoordinates = (system == Qt::DeviceCoordinates); - QTransform effectTransform = deviceCoordinates ? translateTransform - : info->transformPtr->inverted(); - if (!deviceCoordinates) + if (!info) { + // Logical coordinates without info. + QTransform sceneTransform = item->sceneTransform(); + QTransform effectTransform = sceneTransform.inverted(); effectTransform *= translateTransform; - *info->transformPtr *= effectTransform; - QPixmap pixmap(effectRect.size()); - pixmap.fill(Qt::transparent); - QPainter pixmapPainter(&pixmap); - pixmapPainter.setRenderHints(info->painter->renderHints()); + QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); + scened->draw(item, &pixmapPainter, 0, &sceneTransform, 0, 0, qreal(1.0), + &effectTransform, false, true); + } else if (deviceCoordinates) { + // Device coordinates with info. + QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); + scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, info->exposedRegion, + info->widget, info->opacity, &translateTransform, info->wasDirtySceneTransform, + info->drawItem); + } else { + // Item coordinates with info. + QTransform effectTransform = info->transformPtr->inverted(); + effectTransform *= translateTransform; - QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); - scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, info->exposedRegion, - info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform, - info->drawItem); + QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); + scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, info->exposedRegion, + info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform, + info->drawItem); + } return pixmap; } -- cgit v0.12 From a23977d78827ecf464f8f0aef96f7a9cb2abacd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 29 Jul 2009 07:30:28 +0200 Subject: QGraphicsEffect optimizations for pixmap based items. --- src/gui/graphicsview/qgraphicseffect.cpp | 116 ++++++++++++++++++++++--------- src/gui/graphicsview/qgraphicseffect.h | 1 + src/gui/graphicsview/qgraphicseffect_p.h | 1 + src/gui/graphicsview/qgraphicsitem_p.h | 6 ++ 4 files changed, 93 insertions(+), 31 deletions(-) diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index f3f7f22..d98ea3c 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -124,6 +124,9 @@ void QGraphicsEffectSource::draw(QPainter *painter) void QGraphicsEffectSource::update() { d_func()->update(); } +bool QGraphicsEffectSource::isPixmap() const +{ return d_func()->isPixmap(); } + QPixmap QGraphicsEffectSource::pixmap(Qt::CoordinateSystem system, QPoint *offset) const { return d_func()->pixmap(system, offset); } @@ -145,7 +148,6 @@ QGraphicsEffect::~QGraphicsEffect() QRectF QGraphicsEffect::boundingRect() const { Q_D(const QGraphicsEffect); - // return d->boundingRect; if (d->source) return boundingRectFor(d->source->boundingRect()); return QRectF(); @@ -214,9 +216,15 @@ void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *so { Q_D(QGraphicsGrayscaleEffect); QPoint offset; - const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &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, pixmap.rect()); + return; + } - // Draw the pixmap with the filter using an untransformed painter. + // 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, pixmap.rect()); @@ -247,9 +255,15 @@ void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou { Q_D(QGraphicsColorizeEffect); QPoint offset; - const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &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, pixmap.rect()); + return; + } - // Draw the pixmap with the filter using an untransformed painter. + // Draw pixmap in deviceCoordinates 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, pixmap.rect()); @@ -277,36 +291,54 @@ void QGraphicsPixelizeEffect::setPixelSize(int size) d->pixelSize = 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(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(image->scanLine(y + yi)); + for (int xi = 0; xi < qMin(pixelSize, width - x); ++xi) + buf[x + xi] = color; + } + } + } +} + 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 img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); - if (d->pixelSize > 0) { - int width = img.width(); - int height = img.height(); - for (int y = 0; y < height; y += d->pixelSize) { - int ys = qMin(height - 1, y + d->pixelSize / 2); - QRgb *sbuf = reinterpret_cast(img.scanLine(ys)); - for (int x = 0; x < width; x += d->pixelSize) { - int xs = qMin(width - 1, x + d->pixelSize / 2); - QRgb color = sbuf[xs]; - for (int yi = 0; yi < qMin(d->pixelSize, height - y); ++yi) { - QRgb *buf = reinterpret_cast(img.scanLine(y + yi)); - for (int xi = 0; xi < qMin(d->pixelSize, width - x); ++xi) - buf[x + xi] = color; - } - } - } - } + QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); + pixelize(&image, d->pixelSize); - // Draw using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - painter->drawImage(offset, img); + painter->drawImage(offset, image); painter->setWorldTransform(restoreTransform); } @@ -403,16 +435,20 @@ QRectF QGraphicsBlurEffect::boundingRectFor(const QRectF &rect) const return d->filter->boundingRectFor(rect); } -// return d->filter->boundingRectFor(rect); -//} - void QGraphicsBlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsBlurEffect); + QPoint offset; - const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &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, pixmap.rect()); + return; + } - // Draw the pixmap with the filter using an untransformed painter. + // 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, pixmap.rect()); @@ -494,11 +530,29 @@ static QImage composited(const QImage& img1, const QImage& img2, qreal opacity, void QGraphicsBloomEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsBloomEffect); + QPoint offset; + const int radius = d->blurRadius; + const int delta = radius * 3; + + if (source->isPixmap()) { + // No point in drawing in device coordinates (pixmap will be scaled anyways). + const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset); + + // bloom routine + QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); + QImage overlay = blurred(img, img.rect(), radius); + overlay = brightened(overlay, 70); + img = composited(img, overlay, d->opacity, QPainter::CompositionMode_Overlay); + + painter->drawImage(offset - QPoint(delta, delta), img); + return; + } + + // Draw pixmap in device coordinates to avoid pixmap scaling. const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); // bloom routine - const int radius = d->blurRadius; QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); QImage overlay = blurred(img, img.rect(), radius); overlay = brightened(overlay, 70); diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h index 1db8b6e..9714d3e 100644 --- a/src/gui/graphicsview/qgraphicseffect.h +++ b/src/gui/graphicsview/qgraphicseffect.h @@ -75,6 +75,7 @@ public: const QStyleOption *styleOption() const; void draw(QPainter *painter); void update(); + bool isPixmap() const; QRectF boundingRect(Qt::CoordinateSystem coordinateSystem = Qt::LogicalCoordinates) const; QPixmap pixmap(Qt::CoordinateSystem system = Qt::LogicalCoordinates, QPoint *offset = 0) const; diff --git a/src/gui/graphicsview/qgraphicseffect_p.h b/src/gui/graphicsview/qgraphicseffect_p.h index 7ebfe07..6a0bb3f 100644 --- a/src/gui/graphicsview/qgraphicseffect_p.h +++ b/src/gui/graphicsview/qgraphicseffect_p.h @@ -73,6 +73,7 @@ public: virtual const QStyleOption *styleOption() const = 0; 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; friend class QGraphicsScenePrivate; friend class QGraphicsItem; diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 8a2dae9..ff1ca09 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -546,6 +546,12 @@ public: inline void update() { item->update(); } + inline bool isPixmap() const + { + return (item->type() == QGraphicsPixmapItem::Type); + //|| (item->d_ptr->isObject && qobject_cast(q_func())); + } + inline const QStyleOption *styleOption() const { return info ? info->option : 0; } -- cgit v0.12 From 3f71875547a0d0857d9d44cefe59f99c1d1984c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 29 Jul 2009 07:39:00 +0200 Subject: Make examples/graphicsview/lightning compatible the new effects API. --- examples/graphicsview/lighting/shadoweffect.cpp | 8 ++++---- examples/graphicsview/lighting/shadoweffect.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/graphicsview/lighting/shadoweffect.cpp b/examples/graphicsview/lighting/shadoweffect.cpp index e2dd864..f447531 100644 --- a/examples/graphicsview/lighting/shadoweffect.cpp +++ b/examples/graphicsview/lighting/shadoweffect.cpp @@ -61,14 +61,14 @@ void ShadowEffect::adjustForItem() setOpacity(qBound(0.4, 1 - dd / 200.0, 0.7)); } -QRectF ShadowEffect::boundingRect() const +QRectF ShadowEffect::boundingRectFor(const QRectF &rect) const { const_cast(this)->adjustForItem(); - return QGraphicsShadowEffect::boundingRect(); + return QGraphicsShadowEffect::boundingRectFor(rect); } -void ShadowEffect::draw(QPainter *painter) +void ShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { adjustForItem(); - QGraphicsShadowEffect::draw(painter); + QGraphicsShadowEffect::draw(painter, source); } diff --git a/examples/graphicsview/lighting/shadoweffect.h b/examples/graphicsview/lighting/shadoweffect.h index d4aa440..68318b0 100644 --- a/examples/graphicsview/lighting/shadoweffect.h +++ b/examples/graphicsview/lighting/shadoweffect.h @@ -50,9 +50,9 @@ class ShadowEffect: public QGraphicsShadowEffect public: ShadowEffect(QGraphicsItem *item, QGraphicsItem *source); - QRectF boundingRect() const; + QRectF boundingRectFor(const QRectF &rect) const; - void draw(QPainter *painter); + void draw(QPainter *painter, QGraphicsEffectSource *source); private: void adjustForItem(); -- cgit v0.12 From 80bd3a13ee6f42a39d3d3c2985a648e2229778f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 29 Jul 2009 08:08:16 +0200 Subject: QGraphicsEffect cleanup. --- examples/graphicsview/dragdroprobot/main.cpp | 102 +------------------------- examples/graphicsview/dragdroprobot/robot.cpp | 7 -- src/gui/graphicsview/qgraphicseffect.cpp | 3 +- src/gui/graphicsview/qgraphicseffect.h | 53 +++++-------- src/gui/graphicsview/qgraphicseffect_p.h | 13 +++- src/gui/graphicsview/qgraphicsitem.cpp | 12 +-- src/gui/graphicsview/qgraphicsscene.cpp | 4 - 7 files changed, 39 insertions(+), 155 deletions(-) diff --git a/examples/graphicsview/dragdroprobot/main.cpp b/examples/graphicsview/dragdroprobot/main.cpp index b00bf72..30b8b70 100644 --- a/examples/graphicsview/dragdroprobot/main.cpp +++ b/examples/graphicsview/dragdroprobot/main.cpp @@ -46,100 +46,6 @@ #include -Robot *robot = 0; - -class MyGraphicsEffect : public QGraphicsEffect -{ -public: - void draw(QPainter *painter, QGraphicsEffectSource *source) - { - painter->save(); - - QPen pen; - static int color = Qt::black; - pen.setColor(Qt::GlobalColor(color)); - if (color++ >= Qt::darkYellow) - color = Qt::black; - pen.setWidth(3); - painter->setPen(pen); - - source->draw(painter); - - painter->restore(); - } -}; - -class MyWidget : public QWidget -{ - Q_OBJECT -public: - MyWidget(QWidget *parent = 0) : QWidget(parent) - { - setLayout(new QVBoxLayout); - QComboBox *box = new QComboBox; - box->addItem("None"); - box->addItem("Blur"); - box->addItem("Colorize"); - box->addItem("Pixelize"); - box->addItem("Grayscale"); - box->addItem("Bloom"); - box->addItem("Shadow"); - box->addItem("Custom"); - layout()->addWidget(box); - connect(box, SIGNAL(currentIndexChanged(int)), this, SLOT(changeEffect(int))); - } - -public slots: - void changeEffect(int index) - { - switch (index) { - case 0: - delete robot->graphicsEffect(); - robot->setGraphicsEffect(0); - break; - case 1: - delete robot->graphicsEffect(); - robot->setGraphicsEffect(new QGraphicsBlurEffect); - break; - case 2: - delete robot->graphicsEffect(); - robot->setGraphicsEffect(new QGraphicsColorizeEffect); - break; - case 3: - delete robot->graphicsEffect(); - robot->setGraphicsEffect(new QGraphicsPixelizeEffect); - break; - case 4: - delete robot->graphicsEffect(); - robot->setGraphicsEffect(new QGraphicsGrayscaleEffect); - break; - case 5: - delete robot->graphicsEffect(); - robot->setGraphicsEffect(new QGraphicsBloomEffect); - break; - case 6: - delete robot->graphicsEffect(); - robot->setGraphicsEffect(new QGraphicsShadowEffect); - break; - case 7: - delete robot->graphicsEffect(); - robot->setGraphicsEffect(new MyGraphicsEffect); - break; - default: - break; - } - } -protected: - void paintEvent(QPaintEvent *) {} - void mousePressEvent(QMouseEvent *) {} - void mouseReleaseEvent(QMouseEvent *) {} - -private: -}; - -#include "main.moc" - - int main(int argc, char **argv) { QApplication app(argc, argv); @@ -156,21 +62,17 @@ int main(int argc, char **argv) scene.addItem(item); } - robot = new Robot; + Robot *robot = new Robot; robot->scale(1.2, 1.2); robot->setPos(0, -20); scene.addItem(robot); QGraphicsView view(&scene); view.setRenderHint(QPainter::Antialiasing); - view.setViewportUpdateMode(QGraphicsView::FullViewportUpdate); + view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); view.setBackgroundBrush(QColor(230, 200, 167)); view.setWindowTitle("Drag and Drop Robot"); - // view.rotate(45); view.show(); - MyWidget widget; - widget.show(); - return app.exec(); } diff --git a/examples/graphicsview/dragdroprobot/robot.cpp b/examples/graphicsview/dragdroprobot/robot.cpp index 796336a..029a2ce 100644 --- a/examples/graphicsview/dragdroprobot/robot.cpp +++ b/examples/graphicsview/dragdroprobot/robot.cpp @@ -164,13 +164,6 @@ void RobotLimb::paint(QPainter *painter, Robot::Robot() { QGraphicsItem *torsoItem = new RobotTorso(this); - // torsoItem->setGraphicsEffect(new QGraphicsBloomEffect); - // torsoItem->setGraphicsEffect(new QGraphicsBlurEffect); - // torsoItem->setGraphicsEffect(new QGraphicsFrameEffect); - // torsoItem->setGraphicsEffect(new QGraphicsShadowEffect); - // torsoItem->setGraphicsEffect(new QGraphicsColorizeEffect); - // torsoItem->setGraphicsEffect(new QGraphicsPixelizeEffect); - // torsoItem->setGraphicsEffect(new QGraphicsGrayscaleEffect); QGraphicsItem *headItem = new RobotHead(torsoItem); QGraphicsItem *upperLeftArmItem = new RobotLimb(torsoItem); QGraphicsItem *lowerLeftArmItem = new RobotLimb(upperLeftArmItem); diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index d98ea3c..ef7341a 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -44,9 +44,8 @@ #ifndef QT_NO_GRAPHICSVIEW #include -#include -#include #include +#include /* diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h index 9714d3e..8cf80b9 100644 --- a/src/gui/graphicsview/qgraphicseffect.h +++ b/src/gui/graphicsview/qgraphicseffect.h @@ -43,18 +43,7 @@ #define QGRAPHICSEFFECT_H #include -#include #include -#include -#include -#include - -QT_FORWARD_DECLARE_CLASS(QGraphicsItem); -QT_FORWARD_DECLARE_CLASS(QStyleOptionGraphicsItem); -QT_FORWARD_DECLARE_CLASS(QPainter); -QT_FORWARD_DECLARE_CLASS(QPixmap); -QT_FORWARD_DECLARE_CLASS(QWidget); -QT_FORWARD_DECLARE_CLASS(QPixmapColorizeFilter); QT_BEGIN_HEADER @@ -64,8 +53,14 @@ QT_MODULE(Gui) #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW -class QGraphicsEffectSourcePrivate; +class QGraphicsItem; class QStyleOption; +class QColor; +class QPainter; +class QRectF; +class QPixmap; + +class QGraphicsEffectSourcePrivate; class Q_GUI_EXPORT QGraphicsEffectSource : public QObject { Q_OBJECT @@ -73,9 +68,11 @@ public: ~QGraphicsEffectSource(); const QGraphicsItem *graphicsItem() const; const QStyleOption *styleOption() const; + + bool isPixmap() const; void draw(QPainter *painter); void update(); - bool isPixmap() const; + QRectF boundingRect(Qt::CoordinateSystem coordinateSystem = Qt::LogicalCoordinates) const; QPixmap pixmap(Qt::CoordinateSystem system = Qt::LogicalCoordinates, QPoint *offset = 0) const; @@ -99,15 +96,18 @@ class Q_GUI_EXPORT QGraphicsEffect : public QObject public: QGraphicsEffect(); virtual ~QGraphicsEffect(); + + virtual QRectF boundingRectFor(const QRectF &rect) const; QRectF boundingRect() const; void setSourcePixmap(const QPixmap &pixmap); QPixmap sourcePixmap() const; bool hasSourcePixmap() const; - virtual QRectF boundingRectFor(const QRectF &rect) const; - bool isEnabled() const; + QGraphicsEffectSource *source() const; + bool isEnabled() const; + public Q_SLOTS: void setEnabled(bool enable); @@ -187,8 +187,6 @@ public: int blurRadius() const; void setBlurRadius(int blurRadius); - // QRectF boundingRect() const; - protected: QRectF boundingRectFor(const QRectF &rect) const; void draw(QPainter *painter, QGraphicsEffectSource *source); @@ -211,8 +209,6 @@ public: qreal opacity() const; void setOpacity(qreal opacity); - // QRectF boundingRect() const; - protected: QRectF boundingRectFor(const QRectF &rect) const; void draw(QPainter *painter, QGraphicsEffectSource *source); @@ -238,8 +234,6 @@ public: qreal frameOpacity() const; void setFrameOpacity(qreal opacity); - // QRectF boundingRect() const; - protected: QRectF boundingRectFor(const QRectF &rect) const; void draw(QPainter *painter, QGraphicsEffectSource *source); @@ -258,8 +252,10 @@ public: QPointF shadowOffset() const; void setShadowOffset(const QPointF &ofs); - inline void setShadowOffset(qreal dx, qreal dy) { setShadowOffset(QPointF(dx, dy)); } - inline void setShadowOffset(qreal d) { setShadowOffset(QPointF(d, d)); } + inline void setShadowOffset(qreal dx, qreal dy) + { setShadowOffset(QPointF(dx, dy)); } + inline void setShadowOffset(qreal d) + { setShadowOffset(QPointF(d, d)); } int blurRadius() const; void setBlurRadius(int blurRadius); @@ -267,8 +263,6 @@ public: qreal opacity() const; void setOpacity(qreal opacity); - // QRectF boundingRect() const; - protected: QRectF boundingRectFor(const QRectF &rect) const; void draw(QPainter *painter, QGraphicsEffectSource *source); @@ -278,15 +272,6 @@ private: Q_DISABLE_COPY(QGraphicsShadowEffect) }; -Q_DECLARE_METATYPE(QGraphicsEffect *) -Q_DECLARE_METATYPE(QGraphicsGrayscaleEffect *) -Q_DECLARE_METATYPE(QGraphicsColorizeEffect *) -Q_DECLARE_METATYPE(QGraphicsPixelizeEffect *) -Q_DECLARE_METATYPE(QGraphicsBlurEffect *) -Q_DECLARE_METATYPE(QGraphicsBloomEffect *) -Q_DECLARE_METATYPE(QGraphicsFrameEffect *) -Q_DECLARE_METATYPE(QGraphicsShadowEffect *) - #endif // QT_NO_GRAPHICSVIEW QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicseffect_p.h b/src/gui/graphicsview/qgraphicseffect_p.h index 6a0bb3f..2d4a5ee 100644 --- a/src/gui/graphicsview/qgraphicseffect_p.h +++ b/src/gui/graphicsview/qgraphicseffect_p.h @@ -54,13 +54,20 @@ // #include "qgraphicseffect.h" + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + #include #include -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW +#include +#include +#include QT_BEGIN_NAMESPACE +class QPainter; + class QGraphicsEffectSourcePrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QGraphicsEffectSource) @@ -85,7 +92,7 @@ class QGraphicsEffectPrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QGraphicsEffect) public: QGraphicsEffectPrivate() : source(0), hasSourcePixmap(0), isEnabled(1) {} - QGraphicsEffectSource *source; + inline void setGraphicsEffectSource(QGraphicsEffectSource *newSource) { if (source) { @@ -95,6 +102,8 @@ public: source = newSource; q_func()->sourceChanged(newSource); } + + QGraphicsEffectSource *source; QRectF boundingRect; QPixmap sourcePixmap; quint32 hasSourcePixmap : 1; diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 392fdaa..223c747 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1016,10 +1016,10 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) */ void QGraphicsItemPrivate::childrenBoundingRectHelper(QTransform *x, QRectF *rect) { - // if (!dirtyChildrenBoundingRect) { - // *rect |= x->mapRect(childrenBoundingRect); - // return; - // } + if (!dirtyChildrenBoundingRect) { + *rect |= x->mapRect(childrenBoundingRect); + return; + } for (int i = 0; i < children.size(); ++i) { QGraphicsItem *child = children.at(i); @@ -3845,8 +3845,8 @@ void QGraphicsItem::setZValue(qreal z) */ QRectF QGraphicsItem::childrenBoundingRect() const { - // if (!d_ptr->dirtyChildrenBoundingRect) - // return d_ptr->childrenBoundingRect; + if (!d_ptr->dirtyChildrenBoundingRect) + return d_ptr->childrenBoundingRect; QRectF childRect; QTransform x; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 9ce02a2..7b02883 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4304,10 +4304,6 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * ENSURE_TRANSFORM_PTR; if (item->d_ptr->graphicsEffect && item->d_ptr->graphicsEffect->isEnabled()) { - if (item->type() == 7) { - item->d_ptr->graphicsEffect->setSourcePixmap(static_cast(item) - ->pixmap()); - } ENSURE_TRANSFORM_PTR; QGraphicsItemPaintInfo info(viewTransform, transformPtr, exposedRegion, widget, &styleOptionTmp, painter, opacity, wasDirtyParentSceneTransform, drawItem); -- cgit v0.12 From d279a24b93b749ca27db39239f1eb03b4992eebb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Wed, 29 Jul 2009 15:32:02 +0200 Subject: Fixed various valgrind-reported issues in GL 2 engine. --- src/opengl/gl2paintengineex/qglengineshadermanager_p.h | 3 +-- src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h | 2 +- src/opengl/qpixmapdata_gl.cpp | 9 +++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h index 8122a08..884e687 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h @@ -428,10 +428,9 @@ private: QGLShaderProgram* simpleShaderProg; QGLEngineShaderProg* currentShaderProg; - QCache customShaderCache; - // TODO: Possibly convert to a LUT QList cachedPrograms; + QCache customShaderCache; QGLShader* compiledShaders[TotalShaderCount]; diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 3ff2dca..6a96877 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -150,7 +150,7 @@ public: q(q_ptr), width(0), height(0), ctx(0), - currentBrush( &(q->state()->brush) ), + currentBrush(0), inverseScale(1), shaderManager(0) { } diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp index c0eed4d..f9d09b7 100644 --- a/src/opengl/qpixmapdata_gl.cpp +++ b/src/opengl/qpixmapdata_gl.cpp @@ -191,6 +191,8 @@ QGLPixmapData::~QGLPixmapData() if (!shareWidget) return; + delete m_engine; + if (m_texture.id) { QGLShareContextScope ctx(shareWidget->context()); glDeleteTextures(1, &m_texture.id); @@ -463,10 +465,8 @@ void QGLPixmapData::swapBuffers() m_renderFbo->release(); qgl_fbo_pool()->release(m_renderFbo); - delete m_engine; m_renderFbo = 0; - m_engine = 0; } void QGLPixmapData::makeCurrent() @@ -493,7 +493,7 @@ QPaintEngine* QGLPixmapData::paintEngine() const if (!isValid()) return 0; - if (m_engine) + if (m_renderFbo) return m_engine; if (useFramebufferObjects()) { @@ -511,7 +511,8 @@ QPaintEngine* QGLPixmapData::paintEngine() const m_renderFbo = qgl_fbo_pool()->acquire(size(), format); if (m_renderFbo) { - m_engine = new QGL2PaintEngineEx; + if (!m_engine) + m_engine = new QGL2PaintEngineEx; return m_engine; } -- cgit v0.12 From 24f041b30f576a2f6ca1cd9e07cba91fc32fac59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 29 Jul 2009 15:46:13 +0200 Subject: Conflicts after merge commit 07c2b17276057a8b47c3be57ab7c2cf66dac0edd Makes QGraphicsShaderEffect compatible with the new QGraphicsEffect API. --- src/gui/graphicsview/qgraphicseffect.cpp | 2 +- src/opengl/qgraphicsshadereffect.cpp | 36 +++++++++++++------------------- src/opengl/qgraphicsshadereffect.h | 2 +- 3 files changed, 17 insertions(+), 23 deletions(-) diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index 1f9f944..45955f2 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -424,7 +424,7 @@ int QGraphicsBlurEffect::blurRadius() const void QGraphicsBlurEffect::setBlurRadius(int radius) { Q_D(QGraphicsBlurEffect); - d->filter->setBlurRadius(radius); + d->filter->setRadius(radius); updateBoundingRect(); } diff --git a/src/opengl/qgraphicsshadereffect.cpp b/src/opengl/qgraphicsshadereffect.cpp index d4f5fa0..e8d9ae3 100644 --- a/src/opengl/qgraphicsshadereffect.cpp +++ b/src/opengl/qgraphicsshadereffect.cpp @@ -246,25 +246,11 @@ void QGraphicsShaderEffect::setPixelShaderFragment(const QByteArray& code) /*! \reimp */ -void QGraphicsShaderEffect::draw(QPainter *painter) +void QGraphicsShaderEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsShaderEffect); #ifdef QGL_HAVE_CUSTOM_SHADERS - // Find the item's bounds in device coordinates. - QTransform itemToPixmapTransform(painter->worldTransform()); - QRectF deviceBounds = itemToPixmapTransform.mapRect(sourceBoundingRect()); - QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); - if (deviceRect.isEmpty()) - return; - - if (deviceRect.x() != 0 || deviceRect.y() != 0) - itemToPixmapTransform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y()); - - QPixmap pixmap(deviceRect.size()); - if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform)) - return; - // Set the custom shader on the paint engine. The setOnPainter() // call may fail if the paint engine is not GL2. In that case, // we fall through to drawing the pixmap normally. @@ -274,17 +260,25 @@ void QGraphicsShaderEffect::draw(QPainter *painter) } bool usingShader = d->customShaderStage->setOnPainter(painter); - // Draw using an untransformed painter. - QTransform restoreTransform = painter->worldTransform(); - painter->setWorldTransform(QTransform()); - painter->drawPixmap(deviceRect.topLeft(), pixmap); - painter->setWorldTransform(restoreTransform); + QPoint offset; + if (source->isPixmap()) { + // No point in drawing in device coordinates (pixmap will be scaled anyways). + const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset); + painter->drawPixmap(offset, pixmap); + } else { + // Draw pixmap in device coordinates to avoid pixmap scaling. + const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); + QTransform restoreTransform = painter->worldTransform(); + painter->setWorldTransform(QTransform()); + painter->drawPixmap(offset, pixmap); + painter->setWorldTransform(restoreTransform); + } // Remove the custom shader to return to normal painting operations. if (usingShader) d->customShaderStage->removeFromPainter(painter); #else - drawSource(painter); + source->draw(painter); #endif } diff --git a/src/opengl/qgraphicsshadereffect.h b/src/opengl/qgraphicsshadereffect.h index 032a233..d9f2d4f 100644 --- a/src/opengl/qgraphicsshadereffect.h +++ b/src/opengl/qgraphicsshadereffect.h @@ -67,7 +67,7 @@ public: void setPixelShaderFragment(const QByteArray& code); protected: - void draw(QPainter *painter); + void draw(QPainter *painter, QGraphicsEffectSource *source); void setUniformsDirty(); virtual void setUniforms(QGLShaderProgram *program); -- cgit v0.12 From f8a0a013243011b8ff107d1967d9befcc3689f15 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Thu, 30 Jul 2009 09:30:14 +1000 Subject: QGraphicsShaderEffect doesn't need to be a metatype any more Reviewed-by: trustme --- src/opengl/qgraphicsshadereffect.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/opengl/qgraphicsshadereffect.h b/src/opengl/qgraphicsshadereffect.h index d9f2d4f..29b7c9f 100644 --- a/src/opengl/qgraphicsshadereffect.h +++ b/src/opengl/qgraphicsshadereffect.h @@ -78,8 +78,6 @@ private: friend class QGLCustomShaderEffectStage; }; -Q_DECLARE_METATYPE(QGraphicsShaderEffect *) - #endif // QT_NO_GRAPHICSVIEW QT_END_NAMESPACE -- cgit v0.12 From 420356570670dfccd3c03a778e8490717f4675ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 30 Jul 2009 01:34:46 +0200 Subject: A few QGraphicsEffect optimizations. First of all we shouldn't pass pixmap.rect() into the filter, we always want to draw the entire pixmap (without making a copy). We can also skip the filter entirely if the filter is effectively not doing anything. --- src/gui/graphicsview/qgraphicseffect.cpp | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index 45955f2..f9a99fc 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -218,7 +218,7 @@ void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *so 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, pixmap.rect()); + d->filter->draw(painter, offset, pixmap); return; } @@ -226,7 +226,7 @@ void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *so const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - d->filter->draw(painter, offset, pixmap, pixmap.rect()); + d->filter->draw(painter, offset, pixmap); painter->setWorldTransform(restoreTransform); } @@ -257,7 +257,7 @@ void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou 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, pixmap.rect()); + d->filter->draw(painter, offset, pixmap); return; } @@ -265,7 +265,7 @@ void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - d->filter->draw(painter, offset, pixmap, pixmap.rect()); + d->filter->draw(painter, offset, pixmap); painter->setWorldTransform(restoreTransform); } @@ -418,7 +418,7 @@ static QImage blurred(const QImage& image, const QRect& rect, int radius) int QGraphicsBlurEffect::blurRadius() const { Q_D(const QGraphicsBlurEffect); - return int(d->filter->radius()); + return d->filter->radius(); } void QGraphicsBlurEffect::setBlurRadius(int radius) @@ -437,12 +437,16 @@ QRectF QGraphicsBlurEffect::boundingRectFor(const QRectF &rect) const void QGraphicsBlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsBlurEffect); + if (d->filter->radius() <= 0) { + 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, pixmap.rect()); + d->filter->draw(painter, offset, pixmap); return; } @@ -450,7 +454,7 @@ void QGraphicsBlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - d->filter->draw(painter, offset, pixmap, pixmap.rect()); + d->filter->draw(painter, offset, pixmap); painter->setWorldTransform(restoreTransform); } @@ -529,6 +533,10 @@ static QImage composited(const QImage& img1, const QImage& img2, qreal opacity, void QGraphicsBloomEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsBloomEffect); + if (d->blurRadius <= 0) { + source->draw(painter); + return; + } QPoint offset; const int radius = d->blurRadius; @@ -690,6 +698,11 @@ QRectF QGraphicsShadowEffect::boundingRectFor(const QRectF &rect) const void QGraphicsShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsShadowEffect); + if (d->radius <= 0 && d->offset.isNull()) { + source->draw(painter); + return; + } + const QRectF sourceRect = source->boundingRect(Qt::DeviceCoordinates); const QRectF shadowRect = sourceRect.translated(d->offset); QRectF blurRect = shadowRect; -- cgit v0.12 From 4b7ba7d5209a041b85abf1e335ad7aceb2158454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 30 Jul 2009 01:51:29 +0200 Subject: Small optimization to QGraphicsEffectSource::boundingRect. Don't bother asking for the childrenBoundingRect if the item has no children. --- src/gui/graphicsview/qgraphicsitem.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 5178d80..b26e038 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -9995,7 +9995,8 @@ int QGraphicsItemGroup::type() const QRectF QGraphicsItemEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const { QRectF rect = item->boundingRect(); - rect |= item->childrenBoundingRect(); + if (!item->d_ptr->children.isEmpty()) + rect |= item->childrenBoundingRect(); if (info && system == Qt::DeviceCoordinates) { Q_ASSERT(info->transformPtr); return info->transformPtr->mapRect(rect); -- cgit v0.12 From 2444a2e92ae959d350ce5e4c2c984c1e5b714421 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 30 Jul 2009 07:08:30 +0200 Subject: Prevent potential QGraphicsEffect crashes. --- src/gui/graphicsview/qgraphicsitem.cpp | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index b26e038..9d9c3af 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2233,8 +2233,8 @@ void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect) // Set new effect. QGraphicsEffectSourcePrivate *sourced = new QGraphicsItemEffectSourcePrivate(this); QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced); - effect->d_func()->setGraphicsEffectSource(source); d_ptr->graphicsEffect = effect; + effect->d_func()->setGraphicsEffectSource(source); } if (d_ptr->scene) @@ -9994,12 +9994,20 @@ int QGraphicsItemGroup::type() const QRectF QGraphicsItemEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const { + const bool deviceCoordinates = (system == Qt::DeviceCoordinates); + if (!info && deviceCoordinates) { + // Device coordinates without info not yet supported. + qWarning("QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context"); + return QRectF(); + } + QRectF rect = item->boundingRect(); if (!item->d_ptr->children.isEmpty()) rect |= item->childrenBoundingRect(); - if (info && system == Qt::DeviceCoordinates) { + + if (info && deviceCoordinates) { Q_ASSERT(info->transformPtr); - return info->transformPtr->mapRect(rect); + rect = info->transformPtr->mapRect(rect); } return rect; } @@ -10011,15 +10019,15 @@ void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter) return; } + Q_ASSERT(item->d_ptr->scene); + QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); if (painter == info->painter) { - QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); scened->draw(item, painter, info->viewTransform, info->transformPtr, info->exposedRegion, info->widget, info->opacity, 0, info->wasDirtySceneTransform, info->drawItem); } else { QTransform effectTransform = painter->worldTransform(); effectTransform *= info->transformPtr->inverted(); - QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); scened->draw(item, painter, info->viewTransform, info->transformPtr, info->exposedRegion, info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform, info->drawItem); @@ -10035,6 +10043,10 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP return QPixmap(); } + if (!item->d_ptr->scene) + return QPixmap(); + QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); + const QRectF sourceRect = boundingRect(system); const QRect effectRect = item->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect(); if (offset) @@ -10052,13 +10064,10 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP QTransform sceneTransform = item->sceneTransform(); QTransform effectTransform = sceneTransform.inverted(); effectTransform *= translateTransform; - - QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); scened->draw(item, &pixmapPainter, 0, &sceneTransform, 0, 0, qreal(1.0), &effectTransform, false, true); } else if (deviceCoordinates) { // Device coordinates with info. - QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, info->exposedRegion, info->widget, info->opacity, &translateTransform, info->wasDirtySceneTransform, info->drawItem); @@ -10066,8 +10075,6 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP // Item coordinates with info. QTransform effectTransform = info->transformPtr->inverted(); effectTransform *= translateTransform; - - QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, info->exposedRegion, info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform, info->drawItem); -- cgit v0.12 From 2b5baa7d5eb68a908c392506d9f75a2bfdb0f720 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 30 Jul 2009 07:55:28 +0200 Subject: Make sure we don't create pixmaps that are bigger than the device rect. --- src/gui/graphicsview/qgraphicseffect.cpp | 6 +++++- src/gui/graphicsview/qgraphicseffect.h | 1 + src/gui/graphicsview/qgraphicseffect_p.h | 1 + src/gui/graphicsview/qgraphicsitem.cpp | 26 +++++++++++++++++++++++++- src/gui/graphicsview/qgraphicsitem_p.h | 9 +++++++++ 5 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index f9a99fc..76a3feb 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -108,6 +108,9 @@ QGraphicsEffectSource::QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, Q QGraphicsEffectSource::~QGraphicsEffectSource() {} +QRect QGraphicsEffectSource::deviceRect() const +{ return d_func()->deviceRect(); } + QRectF QGraphicsEffectSource::boundingRect(Qt::CoordinateSystem system) const { return d_func()->boundingRect(system); } @@ -709,7 +712,8 @@ void QGraphicsShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *sourc qreal delta = d->radius * 3; blurRect.adjust(-delta, -delta, delta, delta); blurRect |= sourceRect; - const QRect effectRect = blurRect.toAlignedRect(); + QRect effectRect = blurRect.toAlignedRect(); + effectRect &= source->deviceRect(); QPixmap pixmap(effectRect.size()); pixmap.fill(Qt::transparent); diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h index 8cf80b9..0125ebc 100644 --- a/src/gui/graphicsview/qgraphicseffect.h +++ b/src/gui/graphicsview/qgraphicseffect.h @@ -74,6 +74,7 @@ public: void update(); QRectF boundingRect(Qt::CoordinateSystem coordinateSystem = Qt::LogicalCoordinates) const; + QRect deviceRect() const; QPixmap pixmap(Qt::CoordinateSystem system = Qt::LogicalCoordinates, QPoint *offset = 0) const; protected: diff --git a/src/gui/graphicsview/qgraphicseffect_p.h b/src/gui/graphicsview/qgraphicseffect_p.h index 5348ae9..9e6e2a1 100644 --- a/src/gui/graphicsview/qgraphicseffect_p.h +++ b/src/gui/graphicsview/qgraphicseffect_p.h @@ -74,6 +74,7 @@ public: virtual ~QGraphicsEffectSourcePrivate() {} virtual void detach() = 0; virtual QRectF boundingRect(Qt::CoordinateSystem system) const = 0; + virtual QRect deviceRect() const = 0; virtual const QGraphicsItem *graphicsItem() const = 0; virtual const QStyleOption *styleOption() const = 0; virtual void draw(QPainter *p) = 0; diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 9d9c3af..976ffa3 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -10048,10 +10048,34 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); const QRectF sourceRect = boundingRect(system); - const QRect effectRect = item->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect(); + QRect effectRect = item->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect(); if (offset) *offset = sourceRect.toAlignedRect().topLeft(); + if (deviceCoordinates) { + // Clip to viewport rect. + int left, top, right, bottom; + effectRect.getCoords(&left, &top, &right, &bottom); + if (left < 0) { + if (offset) + offset->rx() += -left; + effectRect.setX(0); + } + if (top < 0) { + if (offset) + offset->ry() += -top; + effectRect.setY(0); + } + // NB! We use +-1 for historical reasons (see QRect documentation). + if (right + 1 > info->widget->width()) + effectRect.setRight(info->widget->width() - 1); + if (bottom + 1 > info->widget->height()) + effectRect.setBottom(info->widget->height() -1); + } + + if (effectRect.isEmpty()) + return QPixmap(); + QPixmap pixmap(effectRect.size()); pixmap.fill(Qt::transparent); QPainter pixmapPainter(&pixmap); diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 69d8b5f..8b7f5b5 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -557,6 +557,15 @@ public: inline const QStyleOption *styleOption() const { return info ? info->option : 0; } + inline QRect deviceRect() const + { + if (!info || !info->widget) { + qWarning("QGraphicsEffectSource::deviceRect: Not yet implemented, lacking device context"); + return QRect(); + } + return info->widget->rect(); + } + QRectF boundingRect(Qt::CoordinateSystem system) const; void draw(QPainter *); QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset) const; -- cgit v0.12 From 79672bc8164c199da096d645d3cb3390253a76cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 31 Jul 2009 01:13:06 +0200 Subject: Fix offset bug in QGraphicsShadowEffect. --- src/gui/graphicsview/qgraphicseffect.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index 76a3feb..6025537 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -706,21 +706,36 @@ void QGraphicsShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *sourc return; } + const QTransform &transform = painter->worldTransform(); + const QPointF offset(d->offset.x() * transform.m11(), d->offset.y() * transform.m22()); + const QPoint shadowOffset = offset.toPoint(); const QRectF sourceRect = source->boundingRect(Qt::DeviceCoordinates); - const QRectF shadowRect = sourceRect.translated(d->offset); + const QRectF shadowRect = sourceRect.translated(offset); + QRectF blurRect = shadowRect; qreal delta = d->radius * 3; blurRect.adjust(-delta, -delta, delta, delta); blurRect |= sourceRect; + QRect effectRect = blurRect.toAlignedRect(); - effectRect &= source->deviceRect(); + const QRect deviceRect = source->deviceRect(); + const bool fullyInsideDeviceRect = effectRect.x() >= deviceRect.x() + && effectRect.right() <= deviceRect.right() + && effectRect.y() >= deviceRect.y() + && effectRect.bottom() <= deviceRect.bottom(); + if (!fullyInsideDeviceRect) { + // Clip to device rect to avoid huge pixmaps. + effectRect &= source->deviceRect(); + effectRect |= effectRect.translated(-shadowOffset); + } QPixmap pixmap(effectRect.size()); pixmap.fill(Qt::transparent); QPainter pixmapPainter(&pixmap); pixmapPainter.setRenderHints(painter->renderHints()); pixmapPainter.setWorldTransform(painter->worldTransform()); - pixmapPainter.translate(-effectRect.topLeft()); + if (effectRect.x() != 0 || effectRect.y() != 0) + pixmapPainter.translate(-effectRect.topLeft()); source->draw(&pixmapPainter); pixmapPainter.end(); @@ -733,7 +748,7 @@ void QGraphicsShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *sourc // Draw using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - painter->drawImage(effectRect.topLeft() + d->offset, shadowImage); + painter->drawImage(effectRect.topLeft() + shadowOffset, shadowImage); painter->drawPixmap(effectRect.topLeft(), pixmap); painter->setWorldTransform(restoreTransform); } -- cgit v0.12 From c14927c3431017cb781045d8770888f1c2f9b5ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 31 Jul 2009 01:47:23 +0200 Subject: Compile fix. --- src/gui/graphicsview/qgraphicseffect.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h index 0125ebc..929ea19 100644 --- a/src/gui/graphicsview/qgraphicseffect.h +++ b/src/gui/graphicsview/qgraphicseffect.h @@ -58,6 +58,7 @@ class QStyleOption; class QColor; class QPainter; class QRectF; +class QRect; class QPixmap; class QGraphicsEffectSourcePrivate; -- cgit v0.12 From 0dc124e9eee0b44e331bfcb54d05a35e816f74a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 31 Jul 2009 02:22:39 +0200 Subject: Notify QGraphicsEffect about source bounding rect changes. --- src/gui/graphicsview/qgraphicseffect.cpp | 4 ++-- src/gui/graphicsview/qgraphicseffect.h | 1 + src/gui/graphicsview/qgraphicsitem.cpp | 6 +++++- src/gui/graphicsview/qgraphicsitem_p.h | 4 +++- src/gui/graphicsview/qgraphicsscene_p.h | 4 ++++ 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index 6025537..9196ee0 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -204,8 +204,8 @@ void QGraphicsEffect::updateBoundingRect() d->source->update(); } -void QGraphicsEffect::sourceChanged(QGraphicsEffectSource *) -{} +void QGraphicsEffect::sourceChanged(QGraphicsEffectSource *) {} +void QGraphicsEffect::sourceBoundingRectChanged() {} QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect() : QGraphicsEffect(*new QGraphicsGrayscaleEffectPrivate) diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h index 929ea19..37b6d23 100644 --- a/src/gui/graphicsview/qgraphicseffect.h +++ b/src/gui/graphicsview/qgraphicseffect.h @@ -117,6 +117,7 @@ protected: QGraphicsEffect(QGraphicsEffectPrivate &d); virtual void draw(QPainter *painter, QGraphicsEffectSource *source) = 0; virtual void sourceChanged(QGraphicsEffectSource *newSource); + virtual void sourceBoundingRectChanged(); void updateBoundingRect(); private: diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 976ffa3..9700965 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -6661,6 +6661,7 @@ void QGraphicsItem::prepareGeometryChange() d_ptr->scene->d_func()->dirtyGrowingItemsBoundingRect = true; d_ptr->geometryChanged = 1; d_ptr->paintedViewBoundingRectsNeedRepaint = 1; + d_ptr->notifyBoundingRectChanged = !d_ptr->inSetPosHelper; QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func(); scenePrivate->index->prepareBoundingRectChange(this); @@ -6684,8 +6685,11 @@ void QGraphicsItem::prepareGeometryChange() } QGraphicsItem *parent = this; - while ((parent = parent->d_ptr->parent)) + while ((parent = parent->d_ptr->parent)) { parent->d_ptr->dirtyChildrenBoundingRect = 1; + // ### Only do this if the parent's effect applies to the entire subtree. + parent->d_ptr->notifyBoundingRectChanged = 1; + } if (d_ptr->inSetPosHelper) return; diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 8b7f5b5..c01ee1a 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -164,6 +164,7 @@ public: acceptedTouchBeginEvent(0), filtersDescendantEvents(0), sceneTransformTranslateOnly(0), + notifyBoundingRectChanged(0), globalStackingOrder(-1), q_ptr(0) { @@ -457,7 +458,8 @@ public: quint32 acceptedTouchBeginEvent : 1; quint32 filtersDescendantEvents : 1; quint32 sceneTransformTranslateOnly : 1; - quint32 unused : 6; // feel free to use + quint32 notifyBoundingRectChanged : 1; + quint32 unused : 5; // feel free to use // Optional stacking order int globalStackingOrder; diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 56e6224..6223101 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -227,10 +227,14 @@ public: item->d_ptr->fullUpdatePending = 0; item->d_ptr->ignoreVisible = 0; item->d_ptr->ignoreOpacity = 0; + const bool notifyEffect = item->d_ptr->notifyBoundingRectChanged; + item->d_ptr->notifyBoundingRectChanged = 0; if (recursive) { for (int i = 0; i < item->d_ptr->children.size(); ++i) resetDirtyItem(item->d_ptr->children.at(i), recursive); } + if (notifyEffect && item->d_ptr->graphicsEffect) + item->d_ptr->graphicsEffect->sourceBoundingRectChanged(); } inline void ensureSortedTopLevelItems() -- cgit v0.12 From 72a6ac6e9a2f6f028994548670cb2c6524864186 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 31 Jul 2009 05:38:26 +0200 Subject: Compile examples/graphicsview/customshader. --- examples/graphicsview/customshader/blureffect.cpp | 6 +++--- examples/graphicsview/customshader/blureffect.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/graphicsview/customshader/blureffect.cpp b/examples/graphicsview/customshader/blureffect.cpp index 43791c6..042eea3 100644 --- a/examples/graphicsview/customshader/blureffect.cpp +++ b/examples/graphicsview/customshader/blureffect.cpp @@ -56,14 +56,14 @@ void BlurEffect::adjustForItem() setBlurRadius(radius); } -QRectF BlurEffect::boundingRect() const +QRectF BlurEffect::boundingRectFor(const QRectF &rect) const { const_cast(this)->adjustForItem(); return QGraphicsBlurEffect::boundingRect(); } -void BlurEffect::draw(QPainter *painter) +void BlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { adjustForItem(); - QGraphicsBlurEffect::draw(painter); + QGraphicsBlurEffect::draw(painter, source); } diff --git a/examples/graphicsview/customshader/blureffect.h b/examples/graphicsview/customshader/blureffect.h index 2aea8bf..bf72226 100644 --- a/examples/graphicsview/customshader/blureffect.h +++ b/examples/graphicsview/customshader/blureffect.h @@ -52,9 +52,9 @@ public: void setBaseLine(qreal y) { m_baseLine = y; } - QRectF boundingRect() const; + QRectF boundingRectFor(const QRectF &) const; - void draw(QPainter *painter); + void draw(QPainter *painter, QGraphicsEffectSource*); private: void adjustForItem(); -- cgit v0.12 From e241d607aba775d1ed0c8ff537ac69b9bacb18ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 31 Jul 2009 07:11:49 +0200 Subject: Fixes QGraphicsEffect offset bugs. --- src/gui/graphicsview/qgraphicseffect.cpp | 5 ++--- src/gui/graphicsview/qgraphicsitem.cpp | 2 +- src/gui/image/qpixmapfilter.cpp | 4 +++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index 9196ee0..37e3d8c 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -543,7 +543,6 @@ void QGraphicsBloomEffect::draw(QPainter *painter, QGraphicsEffectSource *source QPoint offset; const int radius = d->blurRadius; - const int delta = radius * 3; if (source->isPixmap()) { // No point in drawing in device coordinates (pixmap will be scaled anyways). @@ -555,7 +554,7 @@ void QGraphicsBloomEffect::draw(QPainter *painter, QGraphicsEffectSource *source overlay = brightened(overlay, 70); img = composited(img, overlay, d->opacity, QPainter::CompositionMode_Overlay); - painter->drawImage(offset - QPoint(delta, delta), img); + painter->drawImage(offset, img); return; } @@ -571,7 +570,7 @@ void QGraphicsBloomEffect::draw(QPainter *painter, QGraphicsEffectSource *source // Draw using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - painter->drawImage(offset - QPoint(radius * 3, radius * 3), img); + painter->drawImage(offset, img); painter->setWorldTransform(restoreTransform); } diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 9700965..991f2b2 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -10054,7 +10054,7 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP const QRectF sourceRect = boundingRect(system); QRect effectRect = item->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect(); if (offset) - *offset = sourceRect.toAlignedRect().topLeft(); + *offset = effectRect.topLeft(); if (deviceCoordinates) { // Clip to viewport rect. diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp index b7b3733..579d057 100644 --- a/src/gui/image/qpixmapfilter.cpp +++ b/src/gui/image/qpixmapfilter.cpp @@ -586,7 +586,9 @@ Qt::TransformationMode QPixmapBlurFilter::quality() const */ QRectF QPixmapBlurFilter::boundingRectFor(const QRectF &rect) const { - return rect; + Q_D(const QPixmapBlurFilter); + const qreal delta = d->radius * 2; + return rect.adjusted(-delta, -delta, delta, delta); } // Blur the image according to the blur radius -- cgit v0.12 From efdd45526ba5bcdaf2d6e95467347873a1f8c8aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 31 Jul 2009 07:15:23 +0200 Subject: Infinite recursion in examples/graphicsview/customshader --- examples/graphicsview/customshader/blureffect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/graphicsview/customshader/blureffect.cpp b/examples/graphicsview/customshader/blureffect.cpp index 042eea3..2b5237b 100644 --- a/examples/graphicsview/customshader/blureffect.cpp +++ b/examples/graphicsview/customshader/blureffect.cpp @@ -59,7 +59,7 @@ void BlurEffect::adjustForItem() QRectF BlurEffect::boundingRectFor(const QRectF &rect) const { const_cast(this)->adjustForItem(); - return QGraphicsBlurEffect::boundingRect(); + return QGraphicsBlurEffect::boundingRectFor(rect); } void BlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) -- cgit v0.12 From 2c277a362ff1961a4ffefe6f0787efbe40ebce1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Mon, 3 Aug 2009 09:55:33 +0200 Subject: QGraphicsItem leave traces when removing graphics effect. We have to update the view directly when removing an effect; otherwise we have no information about the effective bounding rect and only the item's bounding rect will be updated. --- src/gui/graphicsview/qgraphicsitem.cpp | 2 +- src/gui/graphicsview/qgraphicsscene.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 991f2b2..b1c19d8 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2238,7 +2238,7 @@ void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect) } if (d_ptr->scene) - d_ptr->scene->d_func()->markDirty(this); + d_ptr->scene->d_func()->markDirty(this, QRectF(), false, false, false, false, !effect); } /*! diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 5cd0ab2..b4674a5 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4324,7 +4324,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape); bool drawItem = itemHasContents && !itemIsFullyTransparent; if (drawItem) { - const QRectF brect = adjustedItemBoundingRect(item); + const QRectF brect = adjustedItemEffectiveBoundingRect(item); ENSURE_TRANSFORM_PTR QRect viewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy()).toRect() : transformPtr->mapRect(brect).toRect(); -- cgit v0.12 From 3fcc03fb2d4b629fb7f0a72a6aa45916086c6d06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Mon, 3 Aug 2009 10:12:09 +0200 Subject: Avoid painting on a null pixmap in QGraphicsShadowEffect. --- src/gui/graphicsview/qgraphicseffect.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index 37e3d8c..17506bc 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -726,6 +726,8 @@ void QGraphicsShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *sourc // Clip to device rect to avoid huge pixmaps. effectRect &= source->deviceRect(); effectRect |= effectRect.translated(-shadowOffset); + if (effectRect.isEmpty()) + return; // nothing to paint; } QPixmap pixmap(effectRect.size()); -- cgit v0.12 From 1c114fe03a6af18060529fe0604acf89dc595bcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Mon, 3 Aug 2009 12:56:55 +0200 Subject: Artifacts when moving a child when the parent has a graphics effect. We have to use the effectiveBoundingRect() when finding out which items to repaint within a specific area. However, we don't want items to be clickable on the shadow, so we shouldn't use effectiveBoundingRect for normal item-lookup. Solution to this is to only use effectiveBoundingRect() in the BSP (used by estimateTopLevels) and in drawSubtreeRecursive. Auto-test included. --- src/gui/graphicsview/qgraphicsitem.cpp | 27 +++++-- .../graphicsview/qgraphicsscenebsptreeindex.cpp | 4 +- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 90 ++++++++++++++++++++++ 3 files changed, 113 insertions(+), 8 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index b1c19d8..78a5410 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2227,8 +2227,11 @@ void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect) // Unset current effect. QGraphicsEffectPrivate *oldEffectPrivate = d_ptr->graphicsEffect->d_func(); d_ptr->graphicsEffect = 0; - if (oldEffectPrivate) + if (oldEffectPrivate) { oldEffectPrivate->setGraphicsEffectSource(0); // deletes the current source. + if (d_ptr->scene) // Update the views directly. + d_ptr->scene->d_func()->markDirty(this, QRectF(), false, false, false, false, true); + } } else { // Set new effect. QGraphicsEffectSourcePrivate *sourced = new QGraphicsItemEffectSourcePrivate(this); @@ -2237,8 +2240,7 @@ void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect) effect->d_func()->setGraphicsEffectSource(source); } - if (d_ptr->scene) - d_ptr->scene->d_func()->markDirty(this, QRectF(), false, false, false, false, !effect); + prepareGeometryChange(); } /*! @@ -2252,9 +2254,22 @@ void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect) */ QRectF QGraphicsItem::effectiveBoundingRect() const { - if (d_ptr->graphicsEffect && d_ptr->graphicsEffect->isEnabled()) - return d_ptr->graphicsEffect->boundingRect(); - return boundingRect(); + QGraphicsEffect *effect = d_ptr->graphicsEffect; + QRectF brect = effect && effect->isEnabled() ? effect->boundingRect() : boundingRect(); + if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) + return brect; + + const QGraphicsItem *effectParent = d_ptr->parent; + while (effectParent) { + effect = effectParent->d_ptr->graphicsEffect; + if (effect && effect->isEnabled()) + brect = effect->boundingRectFor(brect); + if (effectParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) + return brect; + effectParent = effectParent->d_ptr->parent; + } + + return brect; } /*! diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 3cb33d1..78a77aa 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -173,7 +173,7 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) continue; - bsp.insertItem(item, item->sceneBoundingRect()); + bsp.insertItem(item, item->sceneEffectiveBoundingRect()); } } unindexedItems.clear(); @@ -353,7 +353,7 @@ void QGraphicsSceneBspTreeIndexPrivate::removeItem(QGraphicsItem *item, bool rec purgePending = true; removedItems << item; } else if (!(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { - bsp.removeItem(item, item->sceneBoundingRect()); + bsp.removeItem(item, item->sceneEffectiveBoundingRect()); } } else { unindexedItems.removeOne(item); diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 011e480..ceb033e 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -57,6 +57,7 @@ #include #include #include +#include //TESTED_CLASS= //TESTED_FILES= @@ -274,6 +275,7 @@ private slots: void sorting(); void itemHasNoContents(); void hitTestUntransformableItem(); + void hitTestGraphicsEffectItem(); void focusProxy(); // task specific tests below me @@ -7385,6 +7387,94 @@ void tst_QGraphicsItem::hitTestUntransformableItem() QCOMPARE(items.at(0), static_cast(item3)); } +void tst_QGraphicsItem::hitTestGraphicsEffectItem() +{ + QGraphicsScene scene; + scene.setSceneRect(-100, -100, 200, 200); + + QGraphicsView view(&scene); + view.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&view); +#endif + QTest::qWait(100); + + // Confuse the BSP with dummy items. + QGraphicsRectItem *dummy = new QGraphicsRectItem(0, 0, 20, 20); + dummy->setPos(-100, -100); + scene.addItem(dummy); + for (int i = 0; i < 100; ++i) { + QGraphicsItem *parent = dummy; + dummy = new QGraphicsRectItem(0, 0, 20, 20); + dummy->setPos(-100 + i, -100 + i); + dummy->setParentItem(parent); + } + + const QRectF itemBoundingRect(0, 0, 20, 20); + EventTester *item1 = new EventTester; + item1->br = itemBoundingRect; + item1->setPos(-200, -200); + + EventTester *item2 = new EventTester; + item2->br = itemBoundingRect; + item2->setFlag(QGraphicsItem::ItemIgnoresTransformations); + item2->setParentItem(item1); + item2->setPos(200, 200); + + EventTester *item3 = new EventTester; + item3->br = itemBoundingRect; + item3->setParentItem(item2); + item3->setPos(80, 80); + + scene.addItem(item1); + QTest::qWait(100); + + item1->repaints = 0; + item2->repaints = 0; + item3->repaints = 0; + + // Apply shadow effect to the entire sub-tree. + QGraphicsShadowEffect *shadow = new QGraphicsShadowEffect; + shadow->setShadowOffset(-20, -20); + item1->setGraphicsEffect(shadow); + QTest::qWait(50); + + // Make sure all items are repainted. + QCOMPARE(item1->repaints, 1); + QCOMPARE(item2->repaints, 1); + QCOMPARE(item3->repaints, 1); + + // Make sure an item doesn't respond to a click on its shadow. + QList items = scene.items(QPointF(75, 75)); + QVERIFY(items.isEmpty()); + items = scene.items(QPointF(80, 80)); + QCOMPARE(items.size(), 1); + QCOMPARE(items.at(0), static_cast(item3)); + + item1->repaints = 0; + item2->repaints = 0; + item3->repaints = 0; + + view.viewport()->update(75, 75, 20, 20); + QTest::qWait(50); + + // item1 is the effect source and must therefore be repainted. + // item2 intersects with the exposed region + // item3 is just another child outside the exposed region + QCOMPARE(item1->repaints, 1); + QCOMPARE(item2->repaints, 1); + QCOMPARE(item3->repaints, 0); + + scene.setItemIndexMethod(QGraphicsScene::NoIndex); + QTest::qWait(100); + + items = scene.items(QPointF(75, 75)); + QVERIFY(items.isEmpty()); + items = scene.items(QPointF(80, 80)); + QCOMPARE(items.size(), 1); + QCOMPARE(items.at(0), static_cast(item3)); +} + void tst_QGraphicsItem::focusProxy() { QGraphicsScene scene; -- cgit v0.12 From 91ba3112b01dbb3f1a24556ac22782eedb5e4a13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 4 Aug 2009 11:18:12 +0200 Subject: More QGraphicsEffect API cleanup. Removing some left over from previous experiments. --- src/gui/graphicsview/qgraphicseffect.cpp | 21 +-------------------- src/gui/graphicsview/qgraphicseffect.h | 6 +----- src/gui/graphicsview/qgraphicseffect_p.h | 8 +++----- 3 files changed, 5 insertions(+), 30 deletions(-) diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index 17506bc..43ed86a 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -155,25 +155,6 @@ QRectF QGraphicsEffect::boundingRect() const return QRectF(); } -void QGraphicsEffect::setSourcePixmap(const QPixmap &pixmap) -{ - Q_D(QGraphicsEffect); - d->sourcePixmap = pixmap; - d->hasSourcePixmap = !pixmap.isNull(); -} - -QPixmap QGraphicsEffect::sourcePixmap() const -{ - Q_D(const QGraphicsEffect); - return d->sourcePixmap; -} - -bool QGraphicsEffect::hasSourcePixmap() const -{ - Q_D(const QGraphicsEffect); - return d->hasSourcePixmap; -} - QRectF QGraphicsEffect::boundingRectFor(const QRectF &rect) const { return rect; @@ -204,7 +185,7 @@ void QGraphicsEffect::updateBoundingRect() d->source->update(); } -void QGraphicsEffect::sourceChanged(QGraphicsEffectSource *) {} +void QGraphicsEffect::sourceChanged() {} void QGraphicsEffect::sourceBoundingRectChanged() {} QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect() diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h index 37b6d23..79e7c3d 100644 --- a/src/gui/graphicsview/qgraphicseffect.h +++ b/src/gui/graphicsview/qgraphicseffect.h @@ -102,10 +102,6 @@ public: virtual QRectF boundingRectFor(const QRectF &rect) const; QRectF boundingRect() const; - void setSourcePixmap(const QPixmap &pixmap); - QPixmap sourcePixmap() const; - bool hasSourcePixmap() const; - QGraphicsEffectSource *source() const; bool isEnabled() const; @@ -116,7 +112,7 @@ public Q_SLOTS: protected: QGraphicsEffect(QGraphicsEffectPrivate &d); virtual void draw(QPainter *painter, QGraphicsEffectSource *source) = 0; - virtual void sourceChanged(QGraphicsEffectSource *newSource); + virtual void sourceChanged(); virtual void sourceBoundingRectChanged(); void updateBoundingRect(); diff --git a/src/gui/graphicsview/qgraphicseffect_p.h b/src/gui/graphicsview/qgraphicseffect_p.h index 9e6e2a1..6664a03 100644 --- a/src/gui/graphicsview/qgraphicseffect_p.h +++ b/src/gui/graphicsview/qgraphicseffect_p.h @@ -90,7 +90,7 @@ class Q_GUI_EXPORT QGraphicsEffectPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QGraphicsEffect) public: - QGraphicsEffectPrivate() : source(0), hasSourcePixmap(0), isEnabled(1) {} + QGraphicsEffectPrivate() : source(0), isEnabled(1) {} inline void setGraphicsEffectSource(QGraphicsEffectSource *newSource) { @@ -99,15 +99,13 @@ public: delete source; } source = newSource; - q_func()->sourceChanged(newSource); + q_func()->sourceChanged(); } QGraphicsEffectSource *source; QRectF boundingRect; - QPixmap sourcePixmap; - quint32 hasSourcePixmap : 1; quint32 isEnabled : 1; - quint32 padding : 30; // feel free to use + quint32 padding : 31; // feel free to use }; class QGraphicsGrayscaleEffectPrivate : public QGraphicsEffectPrivate -- cgit v0.12 From 49e0dbfcdd5f1d8ed50efd62b2285cbddba832e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 4 Aug 2009 11:47:08 +0200 Subject: Add tests/auto/qgraphicseffect --- tests/auto/auto.pro | 1 + tests/auto/qgraphicseffect/qgraphicseffect.pro | 3 + tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp | 352 +++++++++++++++++++++ 3 files changed, 356 insertions(+) create mode 100644 tests/auto/qgraphicseffect/qgraphicseffect.pro create mode 100644 tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index b4a6600..0dfba50 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -140,6 +140,7 @@ SUBDIRS += _networkselftest \ qgetputenv \ qgl \ qglobal \ + qgraphicseffect \ qgraphicsitem \ qgraphicsitemanimation \ qgraphicslayout \ diff --git a/tests/auto/qgraphicseffect/qgraphicseffect.pro b/tests/auto/qgraphicseffect/qgraphicseffect.pro new file mode 100644 index 0000000..7effaca --- /dev/null +++ b/tests/auto/qgraphicseffect/qgraphicseffect.pro @@ -0,0 +1,3 @@ +load(qttest_p4) +SOURCES += tst_qgraphicseffect.cpp + diff --git a/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp b/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp new file mode 100644 index 0000000..ee8a973 --- /dev/null +++ b/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp @@ -0,0 +1,352 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include +#include +#include +#include +#include +#include + +//TESTED_CLASS= +//TESTED_FILES= + +class tst_QGraphicsEffect : public QObject +{ + Q_OBJECT +public slots: + void initTestCase(); + +private slots: + void setEnabled(); + void source(); + void boundingRectFor(); + void boundingRect(); + void draw(); +}; + +void tst_QGraphicsEffect::initTestCase() +{} + +class CustomItem : public QGraphicsRectItem +{ +public: + CustomItem(qreal x, qreal y, qreal width, qreal height) + : QGraphicsRectItem(x, y, width, height), numRepaints(0), + m_painter(0), m_styleOption(0) + {} + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) + { + m_painter = painter; + m_styleOption = option; + ++numRepaints; + QGraphicsRectItem::paint(painter, option, widget); + } + + void reset() + { + numRepaints = 0; + m_painter = 0; + m_styleOption = 0; + } + + int numRepaints; + QPainter *m_painter; + const QStyleOption *m_styleOption; +}; + +class CustomEffect : public QGraphicsEffect +{ +public: + CustomEffect() + : QGraphicsEffect(), numRepaints(0), m_margin(10), m_sourceChanged(false), + m_sourceBoundingRectChanged(false), doNothingInDraw(false), + m_painter(0), m_styleOption(0), m_source(0) + {} + + QRectF boundingRectFor(const QRectF &rect) const + { return rect.adjusted(-m_margin, -m_margin, m_margin, m_margin); } + + void reset() + { + numRepaints = 0; + m_sourceChanged = false; + m_sourceBoundingRectChanged = false; + m_painter = 0; + m_styleOption = 0; + m_source = 0; + } + + void setMargin(int margin) + { + m_margin = margin; + updateBoundingRect(); + } + + int margin() const + { return m_margin; } + + void draw(QPainter *painter, QGraphicsEffectSource *source) + { + ++numRepaints; + if (doNothingInDraw) + return; + m_source = source; + m_painter = painter; + m_styleOption = source->styleOption(); + source->draw(painter); + } + + void sourceChanged() + { m_sourceChanged = true; } + + void sourceBoundingRectChanged() + { m_sourceBoundingRectChanged = true; } + + int numRepaints; + int m_margin; + bool m_sourceChanged; + bool m_sourceBoundingRectChanged; + bool doNothingInDraw; + QPainter *m_painter; + const QStyleOption *m_styleOption; + QGraphicsEffectSource *m_source; +}; + +void tst_QGraphicsEffect::setEnabled() +{ + CustomEffect effect; + QVERIFY(effect.isEnabled()); + + effect.setEnabled(false); + QVERIFY(!effect.isEnabled()); +} + +void tst_QGraphicsEffect::source() +{ + QPointer effect = new CustomEffect; + QVERIFY(!effect->source()); + QVERIFY(!effect->m_sourceChanged); + + // Install effect on QGraphicsItem. + QGraphicsItem *item = new QGraphicsRectItem(0, 0, 10, 10); + item->setGraphicsEffect(effect); + QVERIFY(effect->source()); + QCOMPARE(effect->source()->graphicsItem(), item); + QVERIFY(effect->m_sourceChanged); + effect->reset(); + + // Make sure disabling/enabling the effect doesn't change the source. + effect->setEnabled(false); + QVERIFY(effect->source()); + QCOMPARE(effect->source()->graphicsItem(), item); + QVERIFY(!effect->m_sourceChanged); + effect->reset(); + + effect->setEnabled(true); + QVERIFY(effect->source()); + QCOMPARE(effect->source()->graphicsItem(), item); + QVERIFY(!effect->m_sourceChanged); + effect->reset(); + + // Uninstall effect on QGraphicsItem. + effect->reset(); + item->setGraphicsEffect(0); + QVERIFY(!effect->source()); + QVERIFY(effect->m_sourceChanged); + + // The item takes ownership and should delete the effect when destroyed. + item->setGraphicsEffect(effect); + QPointer source = effect->source(); + QVERIFY(source); + QCOMPARE(source->graphicsItem(), item); + delete item; + QVERIFY(!effect); + QVERIFY(!source); +} + +void tst_QGraphicsEffect::boundingRectFor() +{ + CustomEffect effect; + int margin = effect.margin(); + const QRectF source(0, 0, 100, 100); + QCOMPARE(effect.boundingRectFor(source), source.adjusted(-margin, -margin, margin, margin)); + + effect.setMargin(margin = 20); + QCOMPARE(effect.boundingRectFor(source), source.adjusted(-margin, -margin, margin, margin)); +} + +void tst_QGraphicsEffect::boundingRect() +{ + // No source; empty bounding rect. + CustomEffect *effect = new CustomEffect; + QCOMPARE(effect->boundingRect(), QRectF()); + + // Install effect on QGraphicsItem. + QRectF itemRect(0, 0, 100, 100); + QGraphicsRectItem *item = new QGraphicsRectItem; + item->setRect(itemRect); + item->setGraphicsEffect(effect); + int margin = effect->margin(); + QCOMPARE(effect->boundingRect(), itemRect.adjusted(-margin, -margin, margin, margin)); + QCOMPARE(effect->boundingRect(), effect->boundingRectFor(itemRect)); + + // Make sure disabling/enabling the effect doesn't change the bounding rect. + effect->setEnabled(false); + QCOMPARE(effect->boundingRect(), itemRect.adjusted(-margin, -margin, margin, margin)); + QCOMPARE(effect->boundingRect(), effect->boundingRectFor(itemRect)); + effect->setEnabled(true); + QCOMPARE(effect->boundingRect(), itemRect.adjusted(-margin, -margin, margin, margin)); + QCOMPARE(effect->boundingRect(), effect->boundingRectFor(itemRect)); + + // Change effect margins. + effect->setMargin(margin = 20); + QCOMPARE(effect->boundingRect(), itemRect.adjusted(-margin, -margin, margin, margin)); + QCOMPARE(effect->boundingRect(), effect->boundingRectFor(itemRect)); + + // Uninstall effect on QGraphicsItem. + item->setGraphicsEffect(0); + QCOMPARE(effect->boundingRect(), QRectF()); + + delete effect; + delete item; +} + +void tst_QGraphicsEffect::draw() +{ + QGraphicsScene scene; + CustomItem *item = new CustomItem(0, 0, 100, 100); + scene.addItem(item); + + QGraphicsView view(&scene); + view.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&view); +#endif + QTest::qWait(100); + item->reset(); + + // Make sure installing the effect triggers a repaint. + CustomEffect *effect = new CustomEffect; + item->setGraphicsEffect(effect); + QTest::qWait(50); + QCOMPARE(effect->numRepaints, 1); + QCOMPARE(item->numRepaints, 1); + + // Make sure QPainter* and QStyleOptionGraphicsItem* stays persistent + // during QGraphicsEffect::draw/QGraphicsItem::paint. + QVERIFY(effect->m_painter); + QCOMPARE(effect->m_painter, item->m_painter); + QCOMPARE(effect->m_styleOption, item->m_styleOption); + // Make sure QGraphicsEffect::source is persistent. + QCOMPARE(effect->m_source, effect->source()); + effect->reset(); + item->reset(); + + // Make sure updating the source triggers a repaint. + item->update(); + QTest::qWait(50); + QCOMPARE(effect->numRepaints, 1); + QCOMPARE(item->numRepaints, 1); + effect->reset(); + item->reset(); + + // Make sure changing the effect's bounding rect triggers a repaint. + effect->setMargin(20); + QTest::qWait(50); + QCOMPARE(effect->numRepaints, 1); + QCOMPARE(item->numRepaints, 1); + effect->reset(); + item->reset(); + + // Make sure change the item's bounding rect triggers a repaint. + item->setRect(0, 0, 50, 50); + QTest::qWait(50); + QCOMPARE(effect->numRepaints, 1); + QCOMPARE(item->numRepaints, 1); + QVERIFY(effect->m_sourceBoundingRectChanged); + effect->reset(); + item->reset(); + + // Make sure the effect is the one to issue a repaint of the item. + effect->doNothingInDraw = true; + item->update(); + QTest::qWait(50); + QCOMPARE(effect->numRepaints, 1); + QCOMPARE(item->numRepaints, 0); + effect->doNothingInDraw = false; + effect->reset(); + item->reset(); + + // Make sure we update the source when disabling/enabling the effect. + effect->setEnabled(false); + QTest::qWait(50); + QCOMPARE(effect->numRepaints, 0); + QCOMPARE(item->numRepaints, 1); + effect->reset(); + item->reset(); + + effect->setEnabled(true); + QTest::qWait(50); + QCOMPARE(effect->numRepaints, 1); + QCOMPARE(item->numRepaints, 1); + effect->reset(); + item->reset(); + + // Effect is already enabled; nothing should happen. + effect->setEnabled(true); + QTest::qWait(50); + QCOMPARE(effect->numRepaints, 0); + QCOMPARE(item->numRepaints, 0); + + // Make sure uninstalling an effect triggers a repaint. + item->setGraphicsEffect(0); + QTest::qWait(50); + QCOMPARE(effect->numRepaints, 0); + QCOMPARE(item->numRepaints, 1); + delete effect; +} + +QTEST_MAIN(tst_QGraphicsEffect) +#include "tst_qgraphicseffect.moc" + -- cgit v0.12 From 878789d3889d540bd9daad63b84181815d4589ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 4 Aug 2009 15:36:56 +0200 Subject: Toggling QGraphicsEffect's enabled property does not update the source. Makes tst_QGraphicsEffect::draw happy. --- src/gui/graphicsview/qgraphicseffect.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index 43ed86a..e63af3c 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -163,7 +163,13 @@ QRectF QGraphicsEffect::boundingRectFor(const QRectF &rect) const void QGraphicsEffect::setEnabled(bool enable) { Q_D(QGraphicsEffect); + if (d->isEnabled == enable) + return; + d->isEnabled = enable; + + if (d->source) + d->source->update(); } bool QGraphicsEffect::isEnabled() const -- cgit v0.12 From 00d1ee9ad0772fe7ee6d271141698030c4b0101a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 4 Aug 2009 18:17:54 +0200 Subject: Add tests/auto/qgraphicseffectsource. --- tests/auto/auto.pro | 1 + .../qgraphicseffectsource.pro | 3 + .../tst_qgraphicseffectsource.cpp | 323 +++++++++++++++++++++ 3 files changed, 327 insertions(+) create mode 100644 tests/auto/qgraphicseffectsource/qgraphicseffectsource.pro create mode 100644 tests/auto/qgraphicseffectsource/tst_qgraphicseffectsource.cpp diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 0dfba50..5ef38e8 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -141,6 +141,7 @@ SUBDIRS += _networkselftest \ qgl \ qglobal \ qgraphicseffect \ + qgraphicseffectsource \ qgraphicsitem \ qgraphicsitemanimation \ qgraphicslayout \ diff --git a/tests/auto/qgraphicseffectsource/qgraphicseffectsource.pro b/tests/auto/qgraphicseffectsource/qgraphicseffectsource.pro new file mode 100644 index 0000000..d506c6d --- /dev/null +++ b/tests/auto/qgraphicseffectsource/qgraphicseffectsource.pro @@ -0,0 +1,3 @@ +load(qttest_p4) +SOURCES += tst_qgraphicseffectsource.cpp + diff --git a/tests/auto/qgraphicseffectsource/tst_qgraphicseffectsource.cpp b/tests/auto/qgraphicseffectsource/tst_qgraphicseffectsource.cpp new file mode 100644 index 0000000..e7f7ba5 --- /dev/null +++ b/tests/auto/qgraphicseffectsource/tst_qgraphicseffectsource.cpp @@ -0,0 +1,323 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +//TESTED_CLASS= +//TESTED_FILES= + +class CustomItem : public QGraphicsRectItem +{ +public: + CustomItem(qreal x, qreal y, qreal width, qreal height) + : QGraphicsRectItem(x, y, width, height), numRepaints(0), + m_painter(0), m_styleOption(0) + {} + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) + { + m_painter = painter; + m_styleOption = option; + ++numRepaints; + QGraphicsRectItem::paint(painter, option, widget); + } + + void reset() + { + numRepaints = 0; + m_painter = 0; + m_styleOption = 0; + } + + int numRepaints; + QPainter *m_painter; + const QStyleOption *m_styleOption; +}; + +class CustomEffect : public QGraphicsEffect +{ +public: + CustomEffect() + : QGraphicsEffect(), numRepaints(0), m_margin(10), m_sourceChanged(false), + m_sourceBoundingRectChanged(false), doNothingInDraw(false), + storeDeviceDependentStuff(false), + m_painter(0), m_styleOption(0), m_source(0) + {} + + QRectF boundingRectFor(const QRectF &rect) const + { return rect.adjusted(-m_margin, -m_margin, m_margin, m_margin); } + + void reset() + { + numRepaints = 0; + m_sourceChanged = false; + m_sourceBoundingRectChanged = false; + m_painter = 0; + m_styleOption = 0; + m_source = 0; + deviceCoordinatesPixmap = QPixmap(); + deviceRect = QRect(); + sourceDeviceBoundingRect = QRectF(); + } + + void setMargin(int margin) + { + m_margin = margin; + updateBoundingRect(); + } + + int margin() const + { return m_margin; } + + void draw(QPainter *painter, QGraphicsEffectSource *source) + { + ++numRepaints; + if (storeDeviceDependentStuff) { + deviceCoordinatesPixmap = source->pixmap(Qt::DeviceCoordinates); + deviceRect = source->deviceRect(); + sourceDeviceBoundingRect = source->boundingRect(Qt::DeviceCoordinates); + } + if (doNothingInDraw) + return; + m_source = source; + m_painter = painter; + m_styleOption = source->styleOption(); + source->draw(painter); + } + + void sourceChanged() + { m_sourceChanged = true; } + + void sourceBoundingRectChanged() + { m_sourceBoundingRectChanged = true; } + + int numRepaints; + int m_margin; + bool m_sourceChanged; + bool m_sourceBoundingRectChanged; + bool doNothingInDraw; + bool storeDeviceDependentStuff; + QPainter *m_painter; + const QStyleOption *m_styleOption; + QGraphicsEffectSource *m_source; + QPixmap deviceCoordinatesPixmap; + QRect deviceRect; + QRectF sourceDeviceBoundingRect; +}; + +class tst_QGraphicsEffectSource : public QObject +{ + Q_OBJECT +public slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + +private slots: + void graphicsItem(); + void styleOption(); + void isPixmap(); + void draw(); + void update(); + void boundingRect(); + void deviceRect(); + void pixmap(); + +private: + QGraphicsView *view; + QGraphicsScene *scene; + CustomItem *item; + CustomEffect *effect; +}; + +void tst_QGraphicsEffectSource::initTestCase() +{ + scene = new QGraphicsScene; + item = new CustomItem(0, 0, 100, 100); + effect = new CustomEffect; + item->setGraphicsEffect(effect); + scene->addItem(item); + view = new QGraphicsView(scene); + view->show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(view); +#endif + QTest::qWait(200); +} + +void tst_QGraphicsEffectSource::cleanupTestCase() +{ + delete view; +} + +void tst_QGraphicsEffectSource::init() +{ + QVERIFY(effect); + QVERIFY(item); + QVERIFY(effect->source()); + effect->reset(); + effect->storeDeviceDependentStuff = false; + effect->doNothingInDraw = false; + item->reset(); +} + +void tst_QGraphicsEffectSource::graphicsItem() +{ + QVERIFY(effect->source()); + QCOMPARE(effect->source()->graphicsItem(), item); +} + +void tst_QGraphicsEffectSource::styleOption() +{ + // We don't have style options unless the source is drawing. + QVERIFY(effect->source()); + QVERIFY(!effect->source()->styleOption()); + + // Trigger an update and check that the style option in QGraphicsEffect::draw + // was the same as the one in QGraphicsItem::paint. + QCOMPARE(item->numRepaints, 0); + QCOMPARE(effect->numRepaints, 0); + item->update(); + QTest::qWait(50); + QCOMPARE(item->numRepaints, 1); + QCOMPARE(effect->numRepaints, 1); + QVERIFY(effect->m_styleOption); + QCOMPARE(effect->m_styleOption, item->m_styleOption); +} + +void tst_QGraphicsEffectSource::isPixmap() +{ + // Current source is a CustomItem (which is not a pixmap item). + QVERIFY(!effect->source()->isPixmap()); + + // Make sure isPixmap() returns true for QGraphicsPixmapItem. + QGraphicsPixmapItem *pixmapItem = new QGraphicsPixmapItem; + CustomEffect *anotherEffect = new CustomEffect; + pixmapItem->setGraphicsEffect(anotherEffect); + QVERIFY(anotherEffect->source()); + QCOMPARE(anotherEffect->source()->graphicsItem(), static_cast(pixmapItem)); + QVERIFY(anotherEffect->source()->isPixmap()); + delete pixmapItem; +} + +void tst_QGraphicsEffectSource::draw() +{ + // The source can only draw as a result of QGraphicsEffect::draw. + QTest::ignoreMessage(QtWarningMsg, "QGraphicsEffectSource::draw: Can only begin as a result of QGraphicsEffect::draw"); + QPixmap dummyPixmap(10, 10); + QPainter dummyPainter(&dummyPixmap); + effect->source()->draw(&dummyPainter); +} + +void tst_QGraphicsEffectSource::update() +{ + QCOMPARE(item->numRepaints, 0); + QCOMPARE(effect->numRepaints, 0); + + effect->source()->update(); + QTest::qWait(50); + + QCOMPARE(item->numRepaints, 1); + QCOMPARE(effect->numRepaints, 1); +} + +void tst_QGraphicsEffectSource::boundingRect() +{ + QTest::ignoreMessage(QtWarningMsg, "QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context"); + QCOMPARE(effect->source()->boundingRect(Qt::DeviceCoordinates), QRectF()); + + QRectF itemBoundingRect = item->boundingRect(); + if (!item->children().isEmpty()) + itemBoundingRect |= item->childrenBoundingRect(); + + // We can at least check that the device bounding rect was correct in QGraphicsEffect::draw. + effect->storeDeviceDependentStuff = true; + effect->source()->update(); + QTest::qWait(50); + const QTransform deviceTransform = item->deviceTransform(view->viewportTransform()); + QCOMPARE(effect->sourceDeviceBoundingRect, deviceTransform.mapRect(itemBoundingRect)); + + // Bounding rect in logical coordinates is of course fine. + QCOMPARE(effect->source()->boundingRect(Qt::LogicalCoordinates), itemBoundingRect); + // Make sure default value is Qt::LogicalCoordinates. + QCOMPARE(effect->source()->boundingRect(), itemBoundingRect); +} + +void tst_QGraphicsEffectSource::deviceRect() +{ + QTest::ignoreMessage(QtWarningMsg, "QGraphicsEffectSource::deviceRect: Not yet implemented, lacking device context"); + QCOMPARE(effect->source()->deviceRect(), QRect()); + + // We can at least check that the rect was correct in QGraphicsEffect::draw. + effect->storeDeviceDependentStuff = true; + effect->source()->update(); + QTest::qWait(50); + QCOMPARE(effect->deviceRect, view->viewport()->rect()); +} + +void tst_QGraphicsEffectSource::pixmap() +{ + QTest::ignoreMessage(QtWarningMsg, "QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context"); + QCOMPARE(effect->source()->pixmap(Qt::DeviceCoordinates), QPixmap()); + + // We can at least verify a valid pixmap from QGraphicsEffect::draw. + effect->storeDeviceDependentStuff = true; + effect->source()->update(); + QTest::qWait(50); + QVERIFY(!effect->deviceCoordinatesPixmap.isNull()); + + // Pixmaps in logical coordinates we can do fine. + QPixmap pixmap1 = effect->source()->pixmap(Qt::LogicalCoordinates); + QVERIFY(!pixmap1.isNull()); + + // Make sure default value is Qt::LogicalCoordinates. + QPixmap pixmap2 = effect->source()->pixmap(); + QCOMPARE(pixmap1, pixmap2); +} + +QTEST_MAIN(tst_QGraphicsEffectSource) +#include "tst_qgraphicseffectsource.moc" + -- cgit v0.12 From d7166584025d90dda52a859987f4dfaae12d6004 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 4 Aug 2009 19:12:50 +0200 Subject: Make tst_QGraphicsEffectSource happy. Doh, storing a stale pointer is not a good idea ;) --- src/gui/graphicsview/qgraphicsscene.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index b4674a5..ddd2550 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4358,6 +4358,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * painter->setWorldTransform(*transformPtr); item->d_ptr->graphicsEffect->draw(painter, source); painter->setWorldTransform(restoreTransform); + sourced->info = 0; } else { draw(item, painter, viewTransform, transformPtr, exposedRegion, widget, opacity, effectTransform, wasDirtyParentSceneTransform, drawItem); -- cgit v0.12 From e7c4967ec89cbc10dcc9127480532347264edca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 4 Aug 2009 19:50:07 +0200 Subject: Make tst_QGraphicsEffectSource::boundingRect happy. We cannot modify the transformPtr directly because we might want to use the original transform later. The problem in this particular case was that we called source->pixmap() (which modified the transformPtr), then source->boundingRect(Qt::DeviceCoordinates) which in turn used wrong transform to map the bounding rect. --- src/gui/graphicsview/qgraphicsitem_p.h | 4 ++-- src/gui/graphicsview/qgraphicsscene.cpp | 15 +++++++++------ src/gui/graphicsview/qgraphicsscene_p.h | 2 +- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index c01ee1a..76c9dab 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -516,7 +516,7 @@ struct QGraphicsItemPrivate::TransformData { struct QGraphicsItemPaintInfo { - inline QGraphicsItemPaintInfo(const QTransform *const xform1, QTransform *xform2, + inline QGraphicsItemPaintInfo(const QTransform *const xform1, const QTransform *const xform2, QRegion *r, QWidget *w, QStyleOptionGraphicsItem *opt, QPainter *p, qreal o, bool b1, bool b2) : viewTransform(xform1), transformPtr(xform2), exposedRegion(r), widget(w), @@ -524,7 +524,7 @@ struct QGraphicsItemPaintInfo {} const QTransform *viewTransform; - QTransform *transformPtr; + const QTransform *transformPtr; QRegion *exposedRegion; QWidget *widget; QStyleOptionGraphicsItem *option; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index ddd2550..c898a3e 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4366,8 +4366,9 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * } void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const QTransform *const viewTransform, - QTransform *transformPtr, QRegion *exposedRegion, QWidget *widget, qreal opacity, - const QTransform *effectTransform, bool wasDirtyParentSceneTransform, bool drawItem) + const QTransform *const transformPtr, QRegion *exposedRegion, QWidget *widget, + qreal opacity, const QTransform *effectTransform, + bool wasDirtyParentSceneTransform, bool drawItem) { const bool itemIsFullyTransparent = (opacity < 0.0001); const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape); @@ -4381,8 +4382,9 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q painter->save(); Q_ASSERT(transformPtr); if (effectTransform) - *transformPtr *= *effectTransform; - painter->setWorldTransform(*transformPtr); + painter->setWorldTransform(*transformPtr * *effectTransform); + else + painter->setWorldTransform(*transformPtr); painter->setClipPath(item->shape(), Qt::IntersectClip); } @@ -4414,8 +4416,9 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q if (!itemHasChildren || !itemClipsChildrenToShape) { if (effectTransform) - *transformPtr *= *effectTransform; - painter->setWorldTransform(*transformPtr); + painter->setWorldTransform(*transformPtr * *effectTransform); + else + painter->setWorldTransform(*transformPtr); } if (itemClipsToShape) diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 6223101..0422124 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -204,7 +204,7 @@ public: void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform *const, QRegion *exposedRegion, QWidget *widget, qreal parentOpacity = qreal(1.0), const QTransform *const effectTransform = 0); - void draw(QGraphicsItem *, QPainter *, const QTransform *const, QTransform *, + void draw(QGraphicsItem *, QPainter *, const QTransform *const, const QTransform *const, QRegion *, QWidget *, qreal, const QTransform *const, bool, bool); void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false, -- cgit v0.12 From befbee33497290b6e5448b1249e4ace83fcda27b Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Wed, 5 Aug 2009 15:14:25 +0200 Subject: First round of documentation for QGraphicsEffect. Discovered some weaknesses in the API; next round is to discuss and fix these. Reviewed-by: TrustMe --- src/gui/graphicsview/qgraphicseffect.cpp | 179 +++++++++++++++++++++++++++---- src/gui/graphicsview/qgraphicseffect.h | 2 + src/gui/graphicsview/qgraphicsitem.cpp | 1 + 3 files changed, 162 insertions(+), 20 deletions(-) diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index e63af3c..6f60ab9 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -39,6 +39,61 @@ ** ****************************************************************************/ +/*! + \class QGraphicsEffect + \brief The QGraphicsEffect class is the base class for all graphics effects. + \since 4.6 + \ingroup multimedia + \ingroup graphicsview-api + + Effects alter the appearance of elements by hooking into the rendering + pipeline and operating between the source (e.g., a QGraphicsPixmapItem), + and the destination device (e.g., QGraphicsView's viewport). Effects can be + disabled by calling setEnabled(); if the effect is disabled, the source is + rendered directly. + + If you want to add a visual effect to a QGraphicsItem, you can either use + one of the standard effects, or create your own effect by making a subclass + of QGraphicsEffect. + + Qt provides several standard effects, including: + + \list + \o QGraphicsGrayScaleEffect - renders the item in shades of gray + \o QGraphicsColorizeEffect - renders the item in shades of any given color + \o QGraphicsPixelizeEffect - pixelizes the item with any pixel size + \o QGraphicsBlurEffect - blurs the item by a given radius + \o QGraphicsBloomEffect - applies a blooming / glowing effect + \o QGraphicsFrameEffect - adds a frame to the item + \o QGraphicsShadowEffect - renders a dropshadow behind the item + \endlist + + If all you want is to add an effect to an item, you should visit the + documentation for the specific effect to learn more about how each effect + can be used. + + If you want to create your own custom effect, you can start by creating a + subclass of QGraphicsEffect (or any of the existing effects), and + reimplement the virtual function draw(). This function is called whenever + the effect needs to redraw. draw() has two arguments: the painter, and a + pointer to the source (QGraphicsEffectSource). The source provides extra + context information, such as a pointer to the item that is rendering the + effect, any cached pixmap data, and the device rect bounds. See the draw() + documentation for more details. You can also get a pointer to the current + source by calling source(). + + If your effect changes, you can call update() to request a redraw. If your + custom effect changes the bounding rectangle of the source (e.g., a radial + glow effect may need to apply an extra margin), you can reimplement the + virtual boundingRectFor() function, and call updateBoundingRect() to notify + the framework whenever this rectangle changes. The virtual + sourceBoundingRectChanged() function is called to notify the effects that + the source's bounding rectangle has changed (e.g., if the source is a + QGraphicsRectItem, then if the rectangle parameters have changed). + + \sa QGraphicsItem::setGraphicsEffect() +*/ + #include "qgraphicseffect_p.h" #ifndef QT_NO_GRAPHICSVIEW @@ -109,44 +164,78 @@ QGraphicsEffectSource::~QGraphicsEffectSource() {} QRect QGraphicsEffectSource::deviceRect() const -{ return d_func()->deviceRect(); } +{ + return d_func()->deviceRect(); +} QRectF QGraphicsEffectSource::boundingRect(Qt::CoordinateSystem system) const -{ return d_func()->boundingRect(system); } +{ + return d_func()->boundingRect(system); +} const QGraphicsItem *QGraphicsEffectSource::graphicsItem() const -{ return d_func()->graphicsItem(); } +{ + return d_func()->graphicsItem(); +} const QStyleOption *QGraphicsEffectSource::styleOption() const -{ return d_func()->styleOption(); } +{ + return d_func()->styleOption(); +} void QGraphicsEffectSource::draw(QPainter *painter) -{ d_func()->draw(painter); } +{ + d_func()->draw(painter); +} void QGraphicsEffectSource::update() -{ d_func()->update(); } +{ + d_func()->update(); +} bool QGraphicsEffectSource::isPixmap() const -{ return d_func()->isPixmap(); } +{ + return d_func()->isPixmap(); +} QPixmap QGraphicsEffectSource::pixmap(Qt::CoordinateSystem system, QPoint *offset) const -{ return d_func()->pixmap(system, offset); } - +{ + return d_func()->pixmap(system, offset); +} +/*! + Constructs a new QGraphicsEffect instance. +*/ QGraphicsEffect::QGraphicsEffect() : QObject(*new QGraphicsEffectPrivate, 0) -{} +{ + // ### parent? +} +/*! + \internal +*/ QGraphicsEffect::QGraphicsEffect(QGraphicsEffectPrivate &dd) : QObject(dd, 0) -{} +{ +} +/*! + Removes the effect from the source, and destroys the graphics effect. +*/ QGraphicsEffect::~QGraphicsEffect() { Q_D(QGraphicsEffect); d->setGraphicsEffectSource(0); } +/*! + Returns the bounding rectangle for this effect (i.e., the bounding + rectangle of the source, adjusted by any margins applied by the effect + itself). + + \sa boundingRectFor(), updateBoundingRect() +*/ QRectF QGraphicsEffect::boundingRect() const { Q_D(const QGraphicsEffect); @@ -155,11 +244,35 @@ QRectF QGraphicsEffect::boundingRect() const return QRectF(); } +/*! + Returns the bounding rectangle for this effect, given the provided source + \a rect. When writing you own custom effect, you must call + updateBoundingRect() whenever any parameters are changed that may cause + this this function to return a different value. + + \sa boundingRect() +*/ QRectF QGraphicsEffect::boundingRectFor(const QRectF &rect) const { return rect; } +/*! + \property QGraphicsEffect::enabled + \brief whether the effect is enabled or not. + + If an effect is disabled, the source will be rendered with as normal, with + no interference from the effect. If the effect is enabled (default), the + source will be rendered with the effect applied. + + This property is provided so that you can disable certain effects on slow + platforms, in order to ensure that the user interface is responsive. +*/ +bool QGraphicsEffect::isEnabled() const +{ + Q_D(const QGraphicsEffect); + return d->isEnabled; +} void QGraphicsEffect::setEnabled(bool enable) { Q_D(QGraphicsEffect); @@ -172,18 +285,26 @@ void QGraphicsEffect::setEnabled(bool enable) d->source->update(); } -bool QGraphicsEffect::isEnabled() const -{ - Q_D(const QGraphicsEffect); - return d->isEnabled; -} +/*! + Returns a pointer to the source, which provides extra context information + that can be useful for the effect. + \sa draw() +*/ QGraphicsEffectSource *QGraphicsEffect::source() const { Q_D(const QGraphicsEffect); return d->source; } +/*! + This function notifies the effect framework that the effect's bounding + rectangle has changed. As a custom effect author, you must call this + function whenever you change any parameters that will cause the virtual + boundingRectFor() function to return a different value. + + \sa boundingRectFor(), boundingRect() +*/ void QGraphicsEffect::updateBoundingRect() { Q_D(QGraphicsEffect); @@ -191,15 +312,33 @@ void QGraphicsEffect::updateBoundingRect() d->source->update(); } -void QGraphicsEffect::sourceChanged() {} -void QGraphicsEffect::sourceBoundingRectChanged() {} +/*! + This virtual function is called by QGraphicsEffect to notify the effect + that the source has changed. If the effect applies any cache, then this + cache must be purged in order to reflect the new appearance of the source. +*/ +void QGraphicsEffect::sourceChanged() +{ +} + +/*! + This virtual function is called by QGraphicsEffect to notify the effect + that the source's bounding rectangle has changed. If the effect applies any + cache, then this cache must be purged in order to reflect the new + appearance of the source. +*/ +void QGraphicsEffect::sourceBoundingRectChanged() +{ +} QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect() : QGraphicsEffect(*new QGraphicsGrayscaleEffectPrivate) -{} +{ +} QGraphicsGrayscaleEffect::~QGraphicsGrayscaleEffect() -{} +{ +} void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h index 79e7c3d..bb79563 100644 --- a/src/gui/graphicsview/qgraphicseffect.h +++ b/src/gui/graphicsview/qgraphicseffect.h @@ -99,6 +99,7 @@ public: QGraphicsEffect(); virtual ~QGraphicsEffect(); + // ### make protected? virtual QRectF boundingRectFor(const QRectF &rect) const; QRectF boundingRect() const; @@ -108,6 +109,7 @@ public: public Q_SLOTS: void setEnabled(bool enable); + // ### add update() slot protected: QGraphicsEffect(QGraphicsEffectPrivate &d); diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 78a5410..07a063e 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2218,6 +2218,7 @@ void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect) return; if (d_ptr->graphicsEffect && effect) { + // ### This seems wrong - the effect should automatically be deleted. qWarning("QGraphicsItem::setGraphicsEffect: Attempting to set QGraphicsEffect " "%p on %p, which already has an effect installed", effect, this); return; -- cgit v0.12 From 4909d2661d47a28c0ee932d9dfb5b8c47a376044 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 5 Aug 2009 17:29:23 +0200 Subject: Wrong caching of QGraphicsItem::childrenBoundingRect. We cannot cache the bounding rect on the fly for children, because the bounding rect is mapped to the callee's local coordinate system. Auto-test included. --- src/gui/graphicsview/qgraphicsitem.cpp | 24 ++++++++---------- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 34 ++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 07a063e..47f8a90 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1016,11 +1016,6 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) */ void QGraphicsItemPrivate::childrenBoundingRectHelper(QTransform *x, QRectF *rect) { - if (!dirtyChildrenBoundingRect) { - *rect |= x->mapRect(childrenBoundingRect); - return; - } - for (int i = 0; i < children.size(); ++i) { QGraphicsItem *child = children.at(i); QGraphicsItemPrivate *childd = child->d_ptr; @@ -1028,19 +1023,20 @@ void QGraphicsItemPrivate::childrenBoundingRectHelper(QTransform *x, QRectF *rec if (hasPos || childd->transformData) { // COMBINE QTransform matrix = childd->transformToParent(); - matrix *= *x; + if (x) + matrix *= *x; *rect |= matrix.mapRect(child->boundingRect()); if (!childd->children.isEmpty()) childd->childrenBoundingRectHelper(&matrix, rect); } else { - *rect |= x->mapRect(child->boundingRect()); + if (x) + *rect |= x->mapRect(child->boundingRect()); + else + *rect |= child->boundingRect(); if (!childd->children.isEmpty()) childd->childrenBoundingRectHelper(x, rect); } } - - childrenBoundingRect = *rect; - dirtyChildrenBoundingRect = 0; } void QGraphicsItemPrivate::initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform, @@ -3930,10 +3926,10 @@ QRectF QGraphicsItem::childrenBoundingRect() const if (!d_ptr->dirtyChildrenBoundingRect) return d_ptr->childrenBoundingRect; - QRectF childRect; - QTransform x; - d_ptr->childrenBoundingRectHelper(&x, &childRect); - return childRect; + d_ptr->childrenBoundingRect = QRectF(); + d_ptr->childrenBoundingRectHelper(0, &d_ptr->childrenBoundingRect); + d_ptr->dirtyChildrenBoundingRect = 0; + return d_ptr->childrenBoundingRect; } /*! diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index ceb033e..d07c6fd 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -215,6 +215,7 @@ private slots: void childrenBoundingRect(); void childrenBoundingRectTransformed(); void childrenBoundingRect2(); + void childrenBoundingRect3(); void group(); void setGroup(); void nestedGroups(); @@ -3052,6 +3053,39 @@ void tst_QGraphicsItem::childrenBoundingRect2() QCOMPARE(box.childrenBoundingRect(), QRectF(0, 0, 100, 100)); } +void tst_QGraphicsItem::childrenBoundingRect3() +{ + QGraphicsScene scene; + + QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100)); + QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 100, 100)); + QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 100, 100)); + QGraphicsRectItem *rect4 = scene.addRect(QRectF(0, 0, 100, 100)); + QGraphicsRectItem *rect5 = scene.addRect(QRectF(0, 0, 100, 100)); + rect2->setParentItem(rect); + rect3->setParentItem(rect2); + rect4->setParentItem(rect3); + rect5->setParentItem(rect4); + + rect2->setTransform(QTransform().translate(50, 50).rotate(45)); + rect2->setPos(25, 25); + rect3->setTransform(QTransform().translate(50, 50).rotate(45)); + rect3->setPos(25, 25); + rect4->setTransform(QTransform().translate(50, 50).rotate(45)); + rect4->setPos(25, 25); + rect5->setTransform(QTransform().translate(50, 50).rotate(45)); + rect5->setPos(25, 25); + + // Try to mess up the cached bounding rect. + (void)rect2->childrenBoundingRect(); + + QRectF subTreeRect = rect->childrenBoundingRect(); + QCOMPARE(subTreeRect.left(), qreal(-206.0660171779821)); + QCOMPARE(subTreeRect.top(), qreal(75.0)); + QCOMPARE(subTreeRect.width(), qreal(351.7766952966369)); + QCOMPARE(subTreeRect.height(), qreal(251.7766952966369)); +} + void tst_QGraphicsItem::group() { QGraphicsScene scene; -- cgit v0.12 From a0c12d54b8eef537ab8051e48b6d04617a91d170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 6 Aug 2009 10:56:58 +0200 Subject: Fix wrong transform when applying multiple QGraphicsEffects. --- src/gui/graphicsview/qgraphicsitem.cpp | 33 +++++++++++++++++++-------------- src/gui/graphicsview/qgraphicsitem_p.h | 4 +++- src/gui/graphicsview/qgraphicsscene.cpp | 7 +++++-- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 47f8a90..7a53598 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -10021,10 +10021,11 @@ QRectF QGraphicsItemEffectSourcePrivate::boundingRect(Qt::CoordinateSystem syste if (!item->d_ptr->children.isEmpty()) rect |= item->childrenBoundingRect(); - if (info && deviceCoordinates) { - Q_ASSERT(info->transformPtr); - rect = info->transformPtr->mapRect(rect); + if (deviceCoordinates) { + Q_ASSERT(info->painter); + rect = info->painter->worldTransform().mapRect(rect); } + return rect; } @@ -10039,11 +10040,13 @@ void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter) QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); if (painter == info->painter) { scened->draw(item, painter, info->viewTransform, info->transformPtr, info->exposedRegion, - info->widget, info->opacity, 0, info->wasDirtySceneTransform, + info->widget, info->opacity, info->effectTransform, info->wasDirtySceneTransform, info->drawItem); } else { QTransform effectTransform = painter->worldTransform(); - effectTransform *= info->transformPtr->inverted(); + effectTransform *= info->painter->worldTransform().inverted(); + if (info->effectTransform) + effectTransform *= *info->effectTransform; scened->draw(item, painter, info->viewTransform, info->transformPtr, info->exposedRegion, info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform, info->drawItem); @@ -10097,26 +10100,28 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP QPainter pixmapPainter(&pixmap); pixmapPainter.setRenderHints(info ? info->painter->renderHints() : QPainter::TextAntialiasing); - const QTransform translateTransform = QTransform::fromTranslate(-effectRect.x(), - -effectRect.y()); + QTransform effectTransform = QTransform::fromTranslate(-effectRect.x(), -effectRect.y()); + if (deviceCoordinates && info->effectTransform) + effectTransform *= *info->effectTransform; + if (!info) { // Logical coordinates without info. QTransform sceneTransform = item->sceneTransform(); - QTransform effectTransform = sceneTransform.inverted(); - effectTransform *= translateTransform; + QTransform newEffectTransform = sceneTransform.inverted(); + newEffectTransform *= effectTransform; scened->draw(item, &pixmapPainter, 0, &sceneTransform, 0, 0, qreal(1.0), - &effectTransform, false, true); + &newEffectTransform, false, true); } else if (deviceCoordinates) { // Device coordinates with info. scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, info->exposedRegion, - info->widget, info->opacity, &translateTransform, info->wasDirtySceneTransform, + info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform, info->drawItem); } else { // Item coordinates with info. - QTransform effectTransform = info->transformPtr->inverted(); - effectTransform *= translateTransform; + QTransform newEffectTransform = info->transformPtr->inverted(); + newEffectTransform *= effectTransform; scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, info->exposedRegion, - info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform, + info->widget, info->opacity, &newEffectTransform, info->wasDirtySceneTransform, info->drawItem); } return pixmap; diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 76c9dab..0d6946f 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -517,14 +517,16 @@ struct QGraphicsItemPrivate::TransformData { struct QGraphicsItemPaintInfo { inline QGraphicsItemPaintInfo(const QTransform *const xform1, const QTransform *const xform2, + const QTransform *const xform3, QRegion *r, QWidget *w, QStyleOptionGraphicsItem *opt, QPainter *p, qreal o, bool b1, bool b2) - : viewTransform(xform1), transformPtr(xform2), exposedRegion(r), widget(w), + : viewTransform(xform1), transformPtr(xform2), effectTransform(xform3), exposedRegion(r), widget(w), option(opt), painter(p), opacity(o), wasDirtySceneTransform(b1), drawItem(b2) {} const QTransform *viewTransform; const QTransform *transformPtr; + const QTransform *effectTransform; QRegion *exposedRegion; QWidget *widget; QStyleOptionGraphicsItem *option; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index c898a3e..5f214c9 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4348,14 +4348,17 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (item->d_ptr->graphicsEffect && item->d_ptr->graphicsEffect->isEnabled()) { ENSURE_TRANSFORM_PTR; - QGraphicsItemPaintInfo info(viewTransform, transformPtr, exposedRegion, widget, &styleOptionTmp, + QGraphicsItemPaintInfo info(viewTransform, transformPtr, effectTransform, exposedRegion, widget, &styleOptionTmp, painter, opacity, wasDirtyParentSceneTransform, drawItem); QGraphicsEffectSource *source = item->d_ptr->graphicsEffect->d_func()->source; QGraphicsItemEffectSourcePrivate *sourced = static_cast (source->d_func()); sourced->info = &info; const QTransform restoreTransform = painter->worldTransform(); - painter->setWorldTransform(*transformPtr); + if (effectTransform) + painter->setWorldTransform(*transformPtr * *effectTransform); + else + painter->setWorldTransform(*transformPtr); item->d_ptr->graphicsEffect->draw(painter, source); painter->setWorldTransform(restoreTransform); sourced->info = 0; -- cgit v0.12 From 525f585465029075bace5f68997bea07e64f7725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 7 Aug 2009 10:21:42 +0200 Subject: Add ChangeFlags to QGraphicsEffect and pass flags to sourceChanged. This is way more flexible as it allows for extension in the future. Instead of having several virtual functions, which in most cases when re-implemented have to do exactly the same, we now have one virtual function which takes a ChangedFlags parameter do describe what kind of changes that occurred to the source. --- src/gui/graphicsview/qgraphicseffect.cpp | 13 +++------- src/gui/graphicsview/qgraphicseffect.h | 12 +++++++-- src/gui/graphicsview/qgraphicseffect_p.h | 6 ++++- tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp | 30 +++++++++------------- 4 files changed, 30 insertions(+), 31 deletions(-) diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index 6f60ab9..b04af7a 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -316,19 +316,12 @@ void QGraphicsEffect::updateBoundingRect() This virtual function is called by QGraphicsEffect to notify the effect that the source has changed. If the effect applies any cache, then this cache must be purged in order to reflect the new appearance of the source. -*/ -void QGraphicsEffect::sourceChanged() -{ -} -/*! - This virtual function is called by QGraphicsEffect to notify the effect - that the source's bounding rectangle has changed. If the effect applies any - cache, then this cache must be purged in order to reflect the new - appearance of the source. + The \a flags describes what has changed. */ -void QGraphicsEffect::sourceBoundingRectChanged() +void QGraphicsEffect::sourceChanged(ChangeFlags flags) { + Q_UNUSED(flags); } QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect() diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h index bb79563..d171b1b 100644 --- a/src/gui/graphicsview/qgraphicseffect.h +++ b/src/gui/graphicsview/qgraphicseffect.h @@ -94,8 +94,17 @@ class QGraphicsEffectPrivate; class Q_GUI_EXPORT QGraphicsEffect : public QObject { Q_OBJECT + Q_FLAGS(ChangeFlags) Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) public: + enum ChangeFlag { + SourceAttached = 0x1, + SourceDetached = 0x2, + SourceBoundingRectChanged = 0x4, + SourceInvalidated = 0x8 + }; + Q_DECLARE_FLAGS(ChangeFlags, ChangeFlag); + QGraphicsEffect(); virtual ~QGraphicsEffect(); @@ -114,8 +123,7 @@ public Q_SLOTS: protected: QGraphicsEffect(QGraphicsEffectPrivate &d); virtual void draw(QPainter *painter, QGraphicsEffectSource *source) = 0; - virtual void sourceChanged(); - virtual void sourceBoundingRectChanged(); + virtual void sourceChanged(ChangeFlags flags); void updateBoundingRect(); private: diff --git a/src/gui/graphicsview/qgraphicseffect_p.h b/src/gui/graphicsview/qgraphicseffect_p.h index 6664a03..6d546cc 100644 --- a/src/gui/graphicsview/qgraphicseffect_p.h +++ b/src/gui/graphicsview/qgraphicseffect_p.h @@ -94,12 +94,16 @@ public: inline void setGraphicsEffectSource(QGraphicsEffectSource *newSource) { + QGraphicsEffect::ChangeFlags flags; if (source) { + flags |= QGraphicsEffect::SourceDetached; source->d_func()->detach(); delete source; } source = newSource; - q_func()->sourceChanged(); + if (newSource) + flags |= QGraphicsEffect::SourceAttached; + q_func()->sourceChanged(flags); } QGraphicsEffectSource *source; diff --git a/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp b/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp index ee8a973..b4c78f7 100644 --- a/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp +++ b/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp @@ -99,9 +99,8 @@ class CustomEffect : public QGraphicsEffect { public: CustomEffect() - : QGraphicsEffect(), numRepaints(0), m_margin(10), m_sourceChanged(false), - m_sourceBoundingRectChanged(false), doNothingInDraw(false), - m_painter(0), m_styleOption(0), m_source(0) + : QGraphicsEffect(), numRepaints(0), m_margin(10), + doNothingInDraw(false), m_painter(0), m_styleOption(0), m_source(0) {} QRectF boundingRectFor(const QRectF &rect) const @@ -110,8 +109,7 @@ public: void reset() { numRepaints = 0; - m_sourceChanged = false; - m_sourceBoundingRectChanged = false; + m_sourceChangedFlags = QGraphicsEffect::ChangeFlags(); m_painter = 0; m_styleOption = 0; m_source = 0; @@ -137,16 +135,12 @@ public: source->draw(painter); } - void sourceChanged() - { m_sourceChanged = true; } - - void sourceBoundingRectChanged() - { m_sourceBoundingRectChanged = true; } + void sourceChanged(QGraphicsEffect::ChangeFlags flags) + { m_sourceChangedFlags |= flags; } int numRepaints; int m_margin; - bool m_sourceChanged; - bool m_sourceBoundingRectChanged; + QGraphicsEffect::ChangeFlags m_sourceChangedFlags; bool doNothingInDraw; QPainter *m_painter; const QStyleOption *m_styleOption; @@ -166,34 +160,34 @@ void tst_QGraphicsEffect::source() { QPointer effect = new CustomEffect; QVERIFY(!effect->source()); - QVERIFY(!effect->m_sourceChanged); + QVERIFY(!effect->m_sourceChangedFlags); // Install effect on QGraphicsItem. QGraphicsItem *item = new QGraphicsRectItem(0, 0, 10, 10); item->setGraphicsEffect(effect); QVERIFY(effect->source()); QCOMPARE(effect->source()->graphicsItem(), item); - QVERIFY(effect->m_sourceChanged); + QVERIFY(effect->m_sourceChangedFlags & QGraphicsEffect::SourceAttached); effect->reset(); // Make sure disabling/enabling the effect doesn't change the source. effect->setEnabled(false); QVERIFY(effect->source()); QCOMPARE(effect->source()->graphicsItem(), item); - QVERIFY(!effect->m_sourceChanged); + QVERIFY(!effect->m_sourceChangedFlags); effect->reset(); effect->setEnabled(true); QVERIFY(effect->source()); QCOMPARE(effect->source()->graphicsItem(), item); - QVERIFY(!effect->m_sourceChanged); + QVERIFY(!effect->m_sourceChangedFlags); effect->reset(); // Uninstall effect on QGraphicsItem. effect->reset(); item->setGraphicsEffect(0); QVERIFY(!effect->source()); - QVERIFY(effect->m_sourceChanged); + QVERIFY(effect->m_sourceChangedFlags & QGraphicsEffect::SourceDetached); // The item takes ownership and should delete the effect when destroyed. item->setGraphicsEffect(effect); @@ -304,7 +298,7 @@ void tst_QGraphicsEffect::draw() QTest::qWait(50); QCOMPARE(effect->numRepaints, 1); QCOMPARE(item->numRepaints, 1); - QVERIFY(effect->m_sourceBoundingRectChanged); + QVERIFY(effect->m_sourceChangedFlags & QGraphicsEffect::SourceBoundingRectChanged); effect->reset(); item->reset(); -- cgit v0.12 From 7e2f40b8b98bab3cb5fd5343e496c3a268ce1c65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 7 Aug 2009 10:30:35 +0200 Subject: Notify QGraphicsEffect whenever the source is invalidated. In case of caching, the effect must be notified whenever the source has been invalidated; otherwise the cached pixmap will not be up-to-date. Auto-test included. --- src/gui/graphicsview/qgraphicsitem.cpp | 7 +++++++ src/gui/graphicsview/qgraphicsitem_p.h | 4 +++- src/gui/graphicsview/qgraphicsscene_p.h | 15 +++++++++++---- tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp | 1 + 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 7a53598..6fe4477 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -4811,6 +4811,13 @@ void QGraphicsItem::update(const QRectF &rect) if (rect.isEmpty() && !rect.isNull()) return; + // Make sure we notify effects about invalidated source. + QGraphicsItem *item = this; + do { + if (item->d_ptr->graphicsEffect) + item->d_ptr->notifyInvalidated = 1; + } while (item = item->d_ptr->parent); + if (CacheMode(d_ptr->cacheMode) != NoCache) { QGraphicsItemCache *cache = d_ptr->extraItemCache(); if (d_ptr->discardUpdateRequest(/* ignoreVisibleBit = */ false, diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 0d6946f..310d9ef 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -165,6 +165,7 @@ public: filtersDescendantEvents(0), sceneTransformTranslateOnly(0), notifyBoundingRectChanged(0), + notifyInvalidated(0), globalStackingOrder(-1), q_ptr(0) { @@ -459,7 +460,8 @@ public: quint32 filtersDescendantEvents : 1; quint32 sceneTransformTranslateOnly : 1; quint32 notifyBoundingRectChanged : 1; - quint32 unused : 5; // feel free to use + quint32 notifyInvalidated : 1; + quint32 unused : 4; // feel free to use // Optional stacking order int globalStackingOrder; diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 0422124..64ee785 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -227,14 +227,21 @@ public: item->d_ptr->fullUpdatePending = 0; item->d_ptr->ignoreVisible = 0; item->d_ptr->ignoreOpacity = 0; - const bool notifyEffect = item->d_ptr->notifyBoundingRectChanged; - item->d_ptr->notifyBoundingRectChanged = 0; + QGraphicsEffect::ChangeFlags flags; + if (item->d_ptr->notifyBoundingRectChanged) { + flags |= QGraphicsEffect::SourceBoundingRectChanged; + item->d_ptr->notifyBoundingRectChanged = 0; + } + if (item->d_ptr->notifyInvalidated) { + flags |= QGraphicsEffect::SourceInvalidated; + item->d_ptr->notifyInvalidated = 0; + } if (recursive) { for (int i = 0; i < item->d_ptr->children.size(); ++i) resetDirtyItem(item->d_ptr->children.at(i), recursive); } - if (notifyEffect && item->d_ptr->graphicsEffect) - item->d_ptr->graphicsEffect->sourceBoundingRectChanged(); + if (flags && item->d_ptr->graphicsEffect) + item->d_ptr->graphicsEffect->sourceChanged(flags); } inline void ensureSortedTopLevelItems() diff --git a/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp b/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp index b4c78f7..1e62bf8 100644 --- a/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp +++ b/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp @@ -282,6 +282,7 @@ void tst_QGraphicsEffect::draw() QTest::qWait(50); QCOMPARE(effect->numRepaints, 1); QCOMPARE(item->numRepaints, 1); + QVERIFY(effect->m_sourceChangedFlags & QGraphicsEffect::SourceInvalidated); effect->reset(); item->reset(); -- cgit v0.12 From 656551566c50705139535e36d5e5f3a784ab0fdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 7 Aug 2009 10:51:11 +0200 Subject: Fixes GCC compiler warning. warning: suggest parentheses around assignment used as truth value --- src/gui/graphicsview/qgraphicsitem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 6fe4477..240d791 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -4816,7 +4816,7 @@ void QGraphicsItem::update(const QRectF &rect) do { if (item->d_ptr->graphicsEffect) item->d_ptr->notifyInvalidated = 1; - } while (item = item->d_ptr->parent); + } while ((item = item->d_ptr->parent)); if (CacheMode(d_ptr->cacheMode) != NoCache) { QGraphicsItemCache *cache = d_ptr->extraItemCache(); -- cgit v0.12 From a4391dfd2aef38e3a3d37bee07900296ced2521c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 7 Aug 2009 11:05:43 +0200 Subject: Make sure caches are invalidated whenever a QGraphicsItem changes visual appearance. QGraphicsScenePrivate::markDirty does not invalidate the cache, it only schedules a repaint. QGraphicsItem::update however, invalidates the cache and then calls markDirty. Reviewed-by: Andreas --- src/gui/graphicsview/qgraphicsitem.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 240d791..9cb49af 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1972,8 +1972,8 @@ void QGraphicsItemPrivate::setEnabledHelper(bool newEnabled, bool explicitly, bo enabled = newEnabledVariant.toBool(); // Schedule redraw. - if (update && scene) - scene->d_func()->markDirty(q_ptr); + if (update) + q_ptr->update(); foreach (QGraphicsItem *child, children) { if (!newEnabled || !child->d_ptr->explicitlyDisabled) @@ -2077,8 +2077,8 @@ void QGraphicsItem::setSelected(bool selected) return; d_ptr->selected = newSelected; + update(); if (d_ptr->scene) { - d_ptr->scene->d_func()->markDirty(this); QGraphicsScenePrivate *sceneD = d_ptr->scene->d_func(); if (selected) { sceneD->selectedItems << this; @@ -6157,6 +6157,7 @@ void QGraphicsItem::dropEvent(QGraphicsSceneDragDropEvent *event) void QGraphicsItem::focusInEvent(QFocusEvent *event) { Q_UNUSED(event); + update(); } /*! @@ -6168,6 +6169,7 @@ void QGraphicsItem::focusInEvent(QFocusEvent *event) void QGraphicsItem::focusOutEvent(QFocusEvent *event) { Q_UNUSED(event); + update(); } /*! @@ -6182,8 +6184,7 @@ void QGraphicsItem::focusOutEvent(QFocusEvent *event) void QGraphicsItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { Q_UNUSED(event); - if (d_ptr->scene) - d_ptr->scene->d_func()->markDirty(this); + update(); } /*! @@ -6211,8 +6212,7 @@ void QGraphicsItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) void QGraphicsItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) { Q_UNUSED(event); - if (d_ptr->scene) - d_ptr->scene->d_func()->markDirty(this); + update(); } /*! -- cgit v0.12 From 19e01c93f9421a8db6c8a93ac103a7df2b93d9ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 19 Aug 2009 15:18:22 +0200 Subject: Move QGraphicsEffect from src/gui/graphicsview to src/gui/effects. --- src/gui/effects/qgraphicseffect.cpp | 876 +++++++++++++++++++++++++++++++ src/gui/effects/qgraphicseffect.h | 291 ++++++++++ src/gui/effects/qgraphicseffect_p.h | 195 +++++++ src/gui/graphicsview/graphicsview.pri | 5 +- src/gui/graphicsview/qgraphicseffect.cpp | 876 ------------------------------- src/gui/graphicsview/qgraphicseffect.h | 291 ---------- src/gui/graphicsview/qgraphicseffect_p.h | 195 ------- src/gui/graphicsview/qgraphicsitem_p.h | 3 +- src/gui/graphicsview/qgraphicsscene.cpp | 2 +- src/gui/gui.pro | 1 + 10 files changed, 1367 insertions(+), 1368 deletions(-) create mode 100644 src/gui/effects/qgraphicseffect.cpp create mode 100644 src/gui/effects/qgraphicseffect.h create mode 100644 src/gui/effects/qgraphicseffect_p.h delete mode 100644 src/gui/graphicsview/qgraphicseffect.cpp delete mode 100644 src/gui/graphicsview/qgraphicseffect.h delete mode 100644 src/gui/graphicsview/qgraphicseffect_p.h diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp new file mode 100644 index 0000000..b04af7a --- /dev/null +++ b/src/gui/effects/qgraphicseffect.cpp @@ -0,0 +1,876 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \class QGraphicsEffect + \brief The QGraphicsEffect class is the base class for all graphics effects. + \since 4.6 + \ingroup multimedia + \ingroup graphicsview-api + + Effects alter the appearance of elements by hooking into the rendering + pipeline and operating between the source (e.g., a QGraphicsPixmapItem), + and the destination device (e.g., QGraphicsView's viewport). Effects can be + disabled by calling setEnabled(); if the effect is disabled, the source is + rendered directly. + + If you want to add a visual effect to a QGraphicsItem, you can either use + one of the standard effects, or create your own effect by making a subclass + of QGraphicsEffect. + + Qt provides several standard effects, including: + + \list + \o QGraphicsGrayScaleEffect - renders the item in shades of gray + \o QGraphicsColorizeEffect - renders the item in shades of any given color + \o QGraphicsPixelizeEffect - pixelizes the item with any pixel size + \o QGraphicsBlurEffect - blurs the item by a given radius + \o QGraphicsBloomEffect - applies a blooming / glowing effect + \o QGraphicsFrameEffect - adds a frame to the item + \o QGraphicsShadowEffect - renders a dropshadow behind the item + \endlist + + If all you want is to add an effect to an item, you should visit the + documentation for the specific effect to learn more about how each effect + can be used. + + If you want to create your own custom effect, you can start by creating a + subclass of QGraphicsEffect (or any of the existing effects), and + reimplement the virtual function draw(). This function is called whenever + the effect needs to redraw. draw() has two arguments: the painter, and a + pointer to the source (QGraphicsEffectSource). The source provides extra + context information, such as a pointer to the item that is rendering the + effect, any cached pixmap data, and the device rect bounds. See the draw() + documentation for more details. You can also get a pointer to the current + source by calling source(). + + If your effect changes, you can call update() to request a redraw. If your + custom effect changes the bounding rectangle of the source (e.g., a radial + glow effect may need to apply an extra margin), you can reimplement the + virtual boundingRectFor() function, and call updateBoundingRect() to notify + the framework whenever this rectangle changes. The virtual + sourceBoundingRectChanged() function is called to notify the effects that + the source's bounding rectangle has changed (e.g., if the source is a + QGraphicsRectItem, then if the rectangle parameters have changed). + + \sa QGraphicsItem::setGraphicsEffect() +*/ + +#include "qgraphicseffect_p.h" + +#ifndef QT_NO_GRAPHICSVIEW + +#include +#include +#include + +/* + + List of known drawbacks which are being discussed: + + * No d-pointer yet. + + * No auto test yet. + + * No API documentation yet. + + * The API is far from being finalized. + + * Most of the effect implementation is not efficient, + as this is still a proof of concept only. + + * Painting artifacts occasionally occur when e.g. moving + an item over another item that has a large effective + bounding rect. + + * Item transformation is not taken into account. + For example, the effective bounding rect is calculated at + item coordinate (fast), but the painting is mostly + done at device coordinate. + + * Coordinate mode: item vs device. Most effects make sense only + in device coordinate. Should we keep both options open? + See also above transformation issue. + + * Right now the pixmap for effect drawing is stored in each item. + There can be problems with coordinates, see above. + + * There is a lot of duplication in drawItems() for each effect. + + * Port to use the new layer feature in QGraphicsView. + This should solve the above pixmap problem. + + * Frame effect is likely useless. However it is very useful + to check than the effective bounding rect is handled properly. + + * Proper exposed region and rect for style option are missing. + + * Pixelize effect is using raster only, because there is no + pixmap filter for it. We need to implement the missing pixmap filter. + + * Blur effect is using raster only, with exponential blur algorithm. + Perhaps use stack blur (better approximate Gaussian blur) instead? + QPixmapConvolutionFilter is too slow for this simple blur effect. + + * Bloom and shadow effect are also raster only. Same reason as above. + + * Make it work with widgets (QGraphicsWidget). + +*/ + +QGraphicsEffectSource::QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, QObject *parent) + : QObject(dd, parent) +{} + +QGraphicsEffectSource::~QGraphicsEffectSource() +{} + +QRect QGraphicsEffectSource::deviceRect() const +{ + return d_func()->deviceRect(); +} + +QRectF QGraphicsEffectSource::boundingRect(Qt::CoordinateSystem system) const +{ + return d_func()->boundingRect(system); +} + +const QGraphicsItem *QGraphicsEffectSource::graphicsItem() const +{ + return d_func()->graphicsItem(); +} + +const QStyleOption *QGraphicsEffectSource::styleOption() const +{ + return d_func()->styleOption(); +} + +void QGraphicsEffectSource::draw(QPainter *painter) +{ + d_func()->draw(painter); +} + +void QGraphicsEffectSource::update() +{ + d_func()->update(); +} + +bool QGraphicsEffectSource::isPixmap() const +{ + return d_func()->isPixmap(); +} + +QPixmap QGraphicsEffectSource::pixmap(Qt::CoordinateSystem system, QPoint *offset) const +{ + return d_func()->pixmap(system, offset); +} + +/*! + Constructs a new QGraphicsEffect instance. +*/ +QGraphicsEffect::QGraphicsEffect() + : QObject(*new QGraphicsEffectPrivate, 0) +{ + // ### parent? +} + +/*! + \internal +*/ +QGraphicsEffect::QGraphicsEffect(QGraphicsEffectPrivate &dd) + : QObject(dd, 0) +{ +} + +/*! + Removes the effect from the source, and destroys the graphics effect. +*/ +QGraphicsEffect::~QGraphicsEffect() +{ + Q_D(QGraphicsEffect); + d->setGraphicsEffectSource(0); +} + +/*! + Returns the bounding rectangle for this effect (i.e., the bounding + rectangle of the source, adjusted by any margins applied by the effect + itself). + + \sa boundingRectFor(), updateBoundingRect() +*/ +QRectF QGraphicsEffect::boundingRect() const +{ + Q_D(const QGraphicsEffect); + if (d->source) + return boundingRectFor(d->source->boundingRect()); + return QRectF(); +} + +/*! + Returns the bounding rectangle for this effect, given the provided source + \a rect. When writing you own custom effect, you must call + updateBoundingRect() whenever any parameters are changed that may cause + this this function to return a different value. + + \sa boundingRect() +*/ +QRectF QGraphicsEffect::boundingRectFor(const QRectF &rect) const +{ + return rect; +} + +/*! + \property QGraphicsEffect::enabled + \brief whether the effect is enabled or not. + + If an effect is disabled, the source will be rendered with as normal, with + no interference from the effect. If the effect is enabled (default), the + source will be rendered with the effect applied. + + This property is provided so that you can disable certain effects on slow + platforms, in order to ensure that the user interface is responsive. +*/ +bool QGraphicsEffect::isEnabled() const +{ + Q_D(const QGraphicsEffect); + return d->isEnabled; +} +void QGraphicsEffect::setEnabled(bool enable) +{ + Q_D(QGraphicsEffect); + if (d->isEnabled == enable) + return; + + d->isEnabled = enable; + + if (d->source) + d->source->update(); +} + +/*! + Returns a pointer to the source, which provides extra context information + that can be useful for the effect. + + \sa draw() +*/ +QGraphicsEffectSource *QGraphicsEffect::source() const +{ + Q_D(const QGraphicsEffect); + return d->source; +} + +/*! + This function notifies the effect framework that the effect's bounding + rectangle has changed. As a custom effect author, you must call this + function whenever you change any parameters that will cause the virtual + boundingRectFor() function to return a different value. + + \sa boundingRectFor(), boundingRect() +*/ +void QGraphicsEffect::updateBoundingRect() +{ + Q_D(QGraphicsEffect); + if (d->source) + d->source->update(); +} + +/*! + This virtual function is called by QGraphicsEffect to notify the effect + that the source has changed. If the effect applies any cache, then this + cache must be purged in order to reflect the new appearance of the source. + + The \a flags describes what has changed. +*/ +void QGraphicsEffect::sourceChanged(ChangeFlags flags) +{ + Q_UNUSED(flags); +} + +QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect() + : QGraphicsEffect(*new QGraphicsGrayscaleEffectPrivate) +{ +} + +QGraphicsGrayscaleEffect::~QGraphicsGrayscaleEffect() +{ +} + +void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *source) +{ + Q_D(QGraphicsGrayscaleEffect); + 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); + +} + +QGraphicsColorizeEffect::QGraphicsColorizeEffect() + : QGraphicsEffect(*new QGraphicsColorizeEffectPrivate) +{} + +QGraphicsColorizeEffect::~QGraphicsColorizeEffect() +{} + +QColor QGraphicsColorizeEffect::color() const +{ + Q_D(const QGraphicsColorizeEffect); + return d->filter->color(); +} + +void QGraphicsColorizeEffect::setColor(const QColor &c) +{ + Q_D(QGraphicsColorizeEffect); + d->filter->setColor(c); +} + +void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *source) +{ + Q_D(QGraphicsColorizeEffect); + 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 deviceCoordinates 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); +} + +QGraphicsPixelizeEffect::QGraphicsPixelizeEffect() + : QGraphicsEffect(*new QGraphicsPixelizeEffectPrivate) +{ +} + +QGraphicsPixelizeEffect::~QGraphicsPixelizeEffect() +{ +} + +int QGraphicsPixelizeEffect::pixelSize() const +{ + Q_D(const QGraphicsPixelizeEffect); + return d->pixelSize; +} + +void QGraphicsPixelizeEffect::setPixelSize(int size) +{ + Q_D(QGraphicsPixelizeEffect); + d->pixelSize = 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(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(image->scanLine(y + yi)); + for (int xi = 0; xi < qMin(pixelSize, width - x); ++xi) + buf[x + xi] = color; + } + } + } +} + +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); +} + +QGraphicsBlurEffect::QGraphicsBlurEffect() + : QGraphicsEffect(*new QGraphicsBlurEffectPrivate) +{ +} + +QGraphicsBlurEffect::~QGraphicsBlurEffect() +{ +} + +// Blur the image according to the blur radius +// Based on exponential blur algorithm by Jani Huhtanen +// (maximum radius is set to 16) +static QImage blurred(const QImage& image, const QRect& rect, int radius) +{ + int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 }; + int alpha = (radius < 1) ? 16 : (radius > 17) ? 1 : tab[radius-1]; + + QImage result = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); + int r1 = rect.top(); + int r2 = rect.bottom(); + int c1 = rect.left(); + int c2 = rect.right(); + + int bpl = result.bytesPerLine(); + int rgba[4]; + unsigned char* p; + + for (int col = c1; col <= c2; col++) { + p = result.scanLine(r1) + col * 4; + for (int i = 0; i < 4; i++) + rgba[i] = p[i] << 4; + + p += bpl; + for (int j = r1; j < r2; j++, p += bpl) + for (int i = 0; i < 4; i++) + p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; + } + + for (int row = r1; row <= r2; row++) { + p = result.scanLine(row) + c1 * 4; + for (int i = 0; i < 4; i++) + rgba[i] = p[i] << 4; + + p += 4; + for (int j = c1; j < c2; j++, p += 4) + for (int i = 0; i < 4; i++) + p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; + } + + for (int col = c1; col <= c2; col++) { + p = result.scanLine(r2) + col * 4; + for (int i = 0; i < 4; i++) + rgba[i] = p[i] << 4; + + p -= bpl; + for (int j = r1; j < r2; j++, p -= bpl) + for (int i = 0; i < 4; i++) + p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; + } + + for (int row = r1; row <= r2; row++) { + p = result.scanLine(row) + c2 * 4; + for (int i = 0; i < 4; i++) + rgba[i] = p[i] << 4; + + p -= 4; + for (int j = c1; j < c2; j++, p -= 4) + for (int i = 0; i < 4; i++) + p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; + } + + return result; +} + +int QGraphicsBlurEffect::blurRadius() const +{ + Q_D(const QGraphicsBlurEffect); + return d->filter->radius(); +} + +void QGraphicsBlurEffect::setBlurRadius(int radius) +{ + Q_D(QGraphicsBlurEffect); + d->filter->setRadius(radius); + updateBoundingRect(); +} + +QRectF QGraphicsBlurEffect::boundingRectFor(const QRectF &rect) const +{ + Q_D(const QGraphicsBlurEffect); + return d->filter->boundingRectFor(rect); +} + +void QGraphicsBlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) +{ + Q_D(QGraphicsBlurEffect); + if (d->filter->radius() <= 0) { + 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); +} + +QGraphicsBloomEffect::QGraphicsBloomEffect() + : QGraphicsEffect(*new QGraphicsBloomEffectPrivate) +{ +} + +QGraphicsBloomEffect::~QGraphicsBloomEffect() +{ +} + +int QGraphicsBloomEffect::blurRadius() const +{ + Q_D(const QGraphicsBloomEffect); + return d->blurRadius; +} + +void QGraphicsBloomEffect::setBlurRadius(int radius) +{ + Q_D(QGraphicsBloomEffect); + d->blurRadius = radius; + updateBoundingRect(); +} + +qreal QGraphicsBloomEffect::opacity() const +{ + Q_D(const QGraphicsBloomEffect); + return d->opacity; +} + +void QGraphicsBloomEffect::setOpacity(qreal alpha) +{ + Q_D(QGraphicsBloomEffect); + d->opacity = alpha; +} + +QRectF QGraphicsBloomEffect::boundingRectFor(const QRectF &rect) const +{ + Q_D(const QGraphicsBloomEffect); + const qreal delta = d->blurRadius * 3; + return rect.adjusted(-delta, -delta, delta, delta); +} + +// Change brightness (positive integer) of each pixel +static QImage brightened(const QImage& image, int brightness) +{ + int tab[ 256 ]; + for (int i = 0; i < 256; ++i) + tab[i] = qMin(i + brightness, 255); + + QImage img = image.convertToFormat(QImage::Format_ARGB32); + for (int y = 0; y < img.height(); y++) { + QRgb* line = (QRgb*)(img.scanLine(y)); + for (int x = 0; x < img.width(); x++) { + QRgb c = line[x]; + line[x] = qRgba(tab[qRed(c)], tab[qGreen(c)], tab[qBlue(c)], qAlpha(c)); + } + } + + return img; +} + +// Composite two QImages using given composition mode and opacity +static QImage composited(const QImage& img1, const QImage& img2, qreal opacity, QPainter::CompositionMode mode) +{ + QImage result = img1.convertToFormat(QImage::Format_ARGB32_Premultiplied); + QPainter painter(&result); + painter.setCompositionMode(mode); + painter.setOpacity(opacity); + painter.drawImage(0, 0, img2); + painter.end(); + return result; +} + +void QGraphicsBloomEffect::draw(QPainter *painter, QGraphicsEffectSource *source) +{ + Q_D(QGraphicsBloomEffect); + if (d->blurRadius <= 0) { + source->draw(painter); + return; + } + + QPoint offset; + const int radius = d->blurRadius; + + if (source->isPixmap()) { + // No point in drawing in device coordinates (pixmap will be scaled anyways). + const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset); + + // bloom routine + QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); + QImage overlay = blurred(img, img.rect(), radius); + overlay = brightened(overlay, 70); + img = composited(img, overlay, d->opacity, QPainter::CompositionMode_Overlay); + + painter->drawImage(offset, img); + return; + } + + // Draw pixmap in device coordinates to avoid pixmap scaling. + const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); + + // bloom routine + QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); + QImage overlay = blurred(img, img.rect(), radius); + overlay = brightened(overlay, 70); + img = composited(img, overlay, d->opacity, QPainter::CompositionMode_Overlay); + + // Draw using an untransformed painter. + QTransform restoreTransform = painter->worldTransform(); + painter->setWorldTransform(QTransform()); + painter->drawImage(offset, img); + painter->setWorldTransform(restoreTransform); +} + +QGraphicsFrameEffect::QGraphicsFrameEffect() + : QGraphicsEffect(*new QGraphicsFrameEffectPrivate) +{ +} + +QGraphicsFrameEffect::~QGraphicsFrameEffect() +{ +} + +QColor QGraphicsFrameEffect::frameColor() const +{ + Q_D(const QGraphicsFrameEffect); + return d->color; +} + +void QGraphicsFrameEffect::setFrameColor(const QColor &c) +{ + Q_D(QGraphicsFrameEffect); + d->color = c; +} + +qreal QGraphicsFrameEffect::frameWidth() const +{ + Q_D(const QGraphicsFrameEffect); + return d->width; +} + +void QGraphicsFrameEffect::setFrameWidth(qreal frameWidth) +{ + Q_D(QGraphicsFrameEffect); + d->width = frameWidth; + updateBoundingRect(); +} + +qreal QGraphicsFrameEffect::frameOpacity() const +{ + Q_D(const QGraphicsFrameEffect); + return d->alpha; +} + +void QGraphicsFrameEffect::setFrameOpacity(qreal opacity) +{ + Q_D(QGraphicsFrameEffect); + d->alpha = opacity; +} + +QRectF QGraphicsFrameEffect::boundingRectFor(const QRectF &rect) const +{ + Q_D(const QGraphicsFrameEffect); + return rect.adjusted(-d->width, -d->width, d->width, d->width); +} + +void QGraphicsFrameEffect::draw(QPainter *painter, QGraphicsEffectSource *source) +{ + Q_D(QGraphicsFrameEffect); + painter->save(); + painter->setOpacity(painter->opacity() * d->alpha); + painter->setPen(Qt::NoPen); + painter->setBrush(d->color); + painter->drawRoundedRect(boundingRect(), 20, 20, Qt::RelativeSize); + painter->restore(); + + source->draw(painter); +} + +QGraphicsShadowEffect::QGraphicsShadowEffect() + : QGraphicsEffect(*new QGraphicsShadowEffectPrivate) +{ +} + +QGraphicsShadowEffect::~QGraphicsShadowEffect() +{ +} + +QPointF QGraphicsShadowEffect::shadowOffset() const +{ + Q_D(const QGraphicsShadowEffect); + return d->offset; +} + +void QGraphicsShadowEffect::setShadowOffset(const QPointF &ofs) +{ + Q_D(QGraphicsShadowEffect); + d->offset = ofs; + updateBoundingRect(); +} + +int QGraphicsShadowEffect::blurRadius() const +{ + Q_D(const QGraphicsShadowEffect); + return d->radius; +} + +void QGraphicsShadowEffect::setBlurRadius(int blurRadius) +{ + Q_D(QGraphicsShadowEffect); + d->radius = blurRadius; + updateBoundingRect(); +} + +qreal QGraphicsShadowEffect::opacity() const +{ + Q_D(const QGraphicsShadowEffect); + return d->alpha; +} + +void QGraphicsShadowEffect::setOpacity(qreal opacity) +{ + Q_D(QGraphicsShadowEffect); + d->alpha = opacity; +} + +QRectF QGraphicsShadowEffect::boundingRectFor(const QRectF &rect) const +{ + Q_D(const QGraphicsShadowEffect); + QRectF shadowRect = rect.translated(d->offset); + QRectF blurRect = shadowRect; + qreal delta = d->radius * 3; + blurRect.adjust(-delta, -delta, delta, delta); + blurRect |= rect; + return blurRect; +} + +void QGraphicsShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *source) +{ + Q_D(QGraphicsShadowEffect); + if (d->radius <= 0 && d->offset.isNull()) { + source->draw(painter); + return; + } + + const QTransform &transform = painter->worldTransform(); + const QPointF offset(d->offset.x() * transform.m11(), d->offset.y() * transform.m22()); + const QPoint shadowOffset = offset.toPoint(); + const QRectF sourceRect = source->boundingRect(Qt::DeviceCoordinates); + const QRectF shadowRect = sourceRect.translated(offset); + + QRectF blurRect = shadowRect; + qreal delta = d->radius * 3; + blurRect.adjust(-delta, -delta, delta, delta); + blurRect |= sourceRect; + + QRect effectRect = blurRect.toAlignedRect(); + const QRect deviceRect = source->deviceRect(); + const bool fullyInsideDeviceRect = effectRect.x() >= deviceRect.x() + && effectRect.right() <= deviceRect.right() + && effectRect.y() >= deviceRect.y() + && effectRect.bottom() <= deviceRect.bottom(); + if (!fullyInsideDeviceRect) { + // Clip to device rect to avoid huge pixmaps. + effectRect &= source->deviceRect(); + effectRect |= effectRect.translated(-shadowOffset); + if (effectRect.isEmpty()) + return; // nothing to paint; + } + + QPixmap pixmap(effectRect.size()); + pixmap.fill(Qt::transparent); + QPainter pixmapPainter(&pixmap); + pixmapPainter.setRenderHints(painter->renderHints()); + pixmapPainter.setWorldTransform(painter->worldTransform()); + if (effectRect.x() != 0 || effectRect.y() != 0) + pixmapPainter.translate(-effectRect.topLeft()); + source->draw(&pixmapPainter); + pixmapPainter.end(); + + QImage img = pixmap.toImage(); + QImage shadowImage(img.size(), QImage::Format_ARGB32); + shadowImage.fill(qRgba(0, 0, 0, d->alpha * 255)); + shadowImage.setAlphaChannel(img.alphaChannel()); + shadowImage = blurred(shadowImage, shadowImage.rect(), d->radius); + + // Draw using an untransformed painter. + QTransform restoreTransform = painter->worldTransform(); + painter->setWorldTransform(QTransform()); + painter->drawImage(effectRect.topLeft() + shadowOffset, shadowImage); + painter->drawPixmap(effectRect.topLeft(), pixmap); + painter->setWorldTransform(restoreTransform); +} + +#endif diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h new file mode 100644 index 0000000..d171b1b --- /dev/null +++ b/src/gui/effects/qgraphicseffect.h @@ -0,0 +1,291 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSEFFECT_H +#define QGRAPHICSEFFECT_H + +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + +class QGraphicsItem; +class QStyleOption; +class QColor; +class QPainter; +class QRectF; +class QRect; +class QPixmap; + +class QGraphicsEffectSourcePrivate; +class Q_GUI_EXPORT QGraphicsEffectSource : public QObject +{ + Q_OBJECT +public: + ~QGraphicsEffectSource(); + const QGraphicsItem *graphicsItem() const; + const QStyleOption *styleOption() const; + + bool isPixmap() const; + void draw(QPainter *painter); + void update(); + + QRectF boundingRect(Qt::CoordinateSystem coordinateSystem = Qt::LogicalCoordinates) const; + QRect deviceRect() const; + QPixmap pixmap(Qt::CoordinateSystem system = Qt::LogicalCoordinates, QPoint *offset = 0) const; + +protected: + QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, QObject *parent = 0); + +private: + Q_DECLARE_PRIVATE(QGraphicsEffectSource); + Q_DISABLE_COPY(QGraphicsEffectSource); + friend class QGraphicsEffect; + friend class QGraphicsEffectPrivate; + friend class QGraphicsScenePrivate; + friend class QGraphicsItem; +}; + +class QGraphicsEffectPrivate; +class Q_GUI_EXPORT QGraphicsEffect : public QObject +{ + Q_OBJECT + Q_FLAGS(ChangeFlags) + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) +public: + enum ChangeFlag { + SourceAttached = 0x1, + SourceDetached = 0x2, + SourceBoundingRectChanged = 0x4, + SourceInvalidated = 0x8 + }; + Q_DECLARE_FLAGS(ChangeFlags, ChangeFlag); + + QGraphicsEffect(); + virtual ~QGraphicsEffect(); + + // ### make protected? + virtual QRectF boundingRectFor(const QRectF &rect) const; + QRectF boundingRect() const; + + QGraphicsEffectSource *source() const; + + bool isEnabled() const; + +public Q_SLOTS: + void setEnabled(bool enable); + // ### add update() slot + +protected: + QGraphicsEffect(QGraphicsEffectPrivate &d); + virtual void draw(QPainter *painter, QGraphicsEffectSource *source) = 0; + virtual void sourceChanged(ChangeFlags flags); + void updateBoundingRect(); + +private: + Q_DECLARE_PRIVATE(QGraphicsEffect) + Q_DISABLE_COPY(QGraphicsEffect) + friend class QGraphicsItem; + friend class QGraphicsItemPrivate; + friend class QGraphicsScenePrivate; +}; + +class QGraphicsGrayscaleEffectPrivate; +class Q_GUI_EXPORT QGraphicsGrayscaleEffect: public QGraphicsEffect +{ + Q_OBJECT +public: + QGraphicsGrayscaleEffect(); + ~QGraphicsGrayscaleEffect(); + +protected: + void draw(QPainter *painter, QGraphicsEffectSource *source); + +private: + Q_DECLARE_PRIVATE(QGraphicsGrayscaleEffect) + Q_DISABLE_COPY(QGraphicsGrayscaleEffect) +}; + +class QGraphicsColorizeEffectPrivate; +class Q_GUI_EXPORT QGraphicsColorizeEffect: public QGraphicsEffect { + Q_OBJECT +public: + QGraphicsColorizeEffect(); + ~QGraphicsColorizeEffect(); + + QColor color() const; + void setColor(const QColor &c); + +protected: + void draw(QPainter *painter, QGraphicsEffectSource *source); + +private: + Q_DECLARE_PRIVATE(QGraphicsColorizeEffect) + Q_DISABLE_COPY(QGraphicsColorizeEffect) +}; + +class QGraphicsPixelizeEffectPrivate; +class Q_GUI_EXPORT QGraphicsPixelizeEffect: public QGraphicsEffect { + Q_OBJECT +public: + QGraphicsPixelizeEffect(); + ~QGraphicsPixelizeEffect(); + + int pixelSize() const; + void setPixelSize(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 +public: + QGraphicsBlurEffect(); + ~QGraphicsBlurEffect(); + + int blurRadius() const; + void setBlurRadius(int blurRadius); + +protected: + QRectF boundingRectFor(const QRectF &rect) const; + void draw(QPainter *painter, QGraphicsEffectSource *source); + +private: + Q_DECLARE_PRIVATE(QGraphicsBlurEffect) + Q_DISABLE_COPY(QGraphicsBlurEffect) +}; + +class QGraphicsBloomEffectPrivate; +class Q_GUI_EXPORT QGraphicsBloomEffect: public QGraphicsEffect { + Q_OBJECT +public: + QGraphicsBloomEffect(); + ~QGraphicsBloomEffect(); + + int blurRadius() const; + void setBlurRadius(int blurRadius); + + qreal opacity() const; + void setOpacity(qreal opacity); + +protected: + QRectF boundingRectFor(const QRectF &rect) const; + void draw(QPainter *painter, QGraphicsEffectSource *source); + +private: + Q_DECLARE_PRIVATE(QGraphicsBloomEffect) + Q_DISABLE_COPY(QGraphicsBloomEffect) +}; + +class QGraphicsFrameEffectPrivate; +class Q_GUI_EXPORT QGraphicsFrameEffect: public QGraphicsEffect { + Q_OBJECT +public: + QGraphicsFrameEffect(); + ~QGraphicsFrameEffect(); + + QColor frameColor() const; + void setFrameColor(const QColor &c); + + qreal frameWidth() const; + void setFrameWidth(qreal frameWidth); + + qreal frameOpacity() const; + void setFrameOpacity(qreal opacity); + +protected: + QRectF boundingRectFor(const QRectF &rect) const; + void draw(QPainter *painter, QGraphicsEffectSource *source); + +private: + Q_DECLARE_PRIVATE(QGraphicsFrameEffect) + Q_DISABLE_COPY(QGraphicsFrameEffect) +}; + +class QGraphicsShadowEffectPrivate; +class Q_GUI_EXPORT QGraphicsShadowEffect: public QGraphicsEffect { + Q_OBJECT +public: + QGraphicsShadowEffect(); + ~QGraphicsShadowEffect(); + + QPointF shadowOffset() const; + void setShadowOffset(const QPointF &ofs); + inline void setShadowOffset(qreal dx, qreal dy) + { setShadowOffset(QPointF(dx, dy)); } + inline void setShadowOffset(qreal d) + { setShadowOffset(QPointF(d, d)); } + + int blurRadius() const; + void setBlurRadius(int blurRadius); + + qreal opacity() const; + void setOpacity(qreal opacity); + +protected: + QRectF boundingRectFor(const QRectF &rect) const; + void draw(QPainter *painter, QGraphicsEffectSource *source); + +private: + Q_DECLARE_PRIVATE(QGraphicsShadowEffect) + Q_DISABLE_COPY(QGraphicsShadowEffect) +}; + +#endif // QT_NO_GRAPHICSVIEW + +QT_END_NAMESPACE + +QT_END_HEADER + + +#endif // QGRAPHICSEFFECT_H diff --git a/src/gui/effects/qgraphicseffect_p.h b/src/gui/effects/qgraphicseffect_p.h new file mode 100644 index 0000000..6d546cc --- /dev/null +++ b/src/gui/effects/qgraphicseffect_p.h @@ -0,0 +1,195 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSEFFECT_P_H +#define QGRAPHICSEFFECT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +#include "qgraphicseffect.h" + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + +#include +#include + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGraphicsEffectSourcePrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsEffectSource) +public: + QGraphicsEffectSourcePrivate() : QObjectPrivate() {} + virtual ~QGraphicsEffectSourcePrivate() {} + virtual void detach() = 0; + virtual QRectF boundingRect(Qt::CoordinateSystem system) const = 0; + virtual QRect deviceRect() const = 0; + virtual const QGraphicsItem *graphicsItem() const = 0; + virtual const QStyleOption *styleOption() const = 0; + 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; + friend class QGraphicsScenePrivate; + friend class QGraphicsItem; + friend class QGraphicsItemPrivate; +}; + +class Q_GUI_EXPORT QGraphicsEffectPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsEffect) +public: + QGraphicsEffectPrivate() : source(0), isEnabled(1) {} + + inline void setGraphicsEffectSource(QGraphicsEffectSource *newSource) + { + QGraphicsEffect::ChangeFlags flags; + if (source) { + flags |= QGraphicsEffect::SourceDetached; + source->d_func()->detach(); + delete source; + } + source = newSource; + if (newSource) + flags |= QGraphicsEffect::SourceAttached; + q_func()->sourceChanged(flags); + } + + QGraphicsEffectSource *source; + QRectF boundingRect; + quint32 isEnabled : 1; + quint32 padding : 31; // feel free to use +}; + +class QGraphicsGrayscaleEffectPrivate : public QGraphicsEffectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsGrayscaleEffect) +public: + QGraphicsGrayscaleEffectPrivate() + { + filter = new QPixmapColorizeFilter; + filter->setColor(Qt::black); + } + ~QGraphicsGrayscaleEffectPrivate() { delete filter; } + + QPixmapColorizeFilter *filter; +}; + +class QGraphicsColorizeEffectPrivate : public QGraphicsEffectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsColorizeEffect) +public: + QGraphicsColorizeEffectPrivate() { filter = new QPixmapColorizeFilter; } + ~QGraphicsColorizeEffectPrivate() { delete filter; } + + QPixmapColorizeFilter *filter; +}; + +class QGraphicsPixelizeEffectPrivate : public QGraphicsEffectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsPixelizeEffect) +public: + QGraphicsPixelizeEffectPrivate() : pixelSize(3) {} + + int pixelSize; +}; + +class QGraphicsBlurEffectPrivate : public QGraphicsEffectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsBlurEffect) +public: + QGraphicsBlurEffectPrivate() : filter(new QPixmapBlurFilter), blurRadius(4) {} + ~QGraphicsBlurEffectPrivate() { delete filter; } + + QPixmapBlurFilter *filter; + int blurRadius; +}; + +class QGraphicsBloomEffectPrivate : public QGraphicsEffectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsBlurEffect) +public: + QGraphicsBloomEffectPrivate() : blurRadius(6), opacity(0.7) {} + + int blurRadius; + qreal opacity; +}; + +class QGraphicsFrameEffectPrivate : public QGraphicsEffectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsFrameEffect) +public: + QGraphicsFrameEffectPrivate() : color(Qt::blue), width(5), alpha(0.6) {} + + QColor color; + qreal width; + qreal alpha; +}; + +class QGraphicsShadowEffectPrivate : public QGraphicsEffectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsShadowEffect) +public: + QGraphicsShadowEffectPrivate() : offset(4, 4), radius(8), alpha(0.7) {} + + QPointF offset; + int radius; + qreal alpha; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_GRAPHICSVIEW + +#endif // QGRAPHICSEFFECT_P_H diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri index a3095e7..15b86b5 100644 --- a/src/gui/graphicsview/graphicsview.pri +++ b/src/gui/graphicsview/graphicsview.pri @@ -22,8 +22,6 @@ HEADERS += graphicsview/qgraphicsgridlayout.h \ graphicsview/qgraphicsview_p.h \ graphicsview/qgraphicswidget.h \ graphicsview/qgraphicswidget_p.h \ - graphicsview/qgraphicseffect.h \ - graphicsview/qgraphicseffect_p.h \ graphicsview/qgridlayoutengine_p.h SOURCES += graphicsview/qgraphicsgridlayout.cpp \ @@ -44,5 +42,4 @@ SOURCES += graphicsview/qgraphicsgridlayout.cpp \ graphicsview/qgraphicsview.cpp \ graphicsview/qgraphicswidget.cpp \ graphicsview/qgraphicswidget_p.cpp \ - graphicsview/qgridlayoutengine.cpp \ - graphicsview/qgraphicseffect.cpp + graphicsview/qgridlayoutengine.cpp diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp deleted file mode 100644 index b04af7a..0000000 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ /dev/null @@ -1,876 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \class QGraphicsEffect - \brief The QGraphicsEffect class is the base class for all graphics effects. - \since 4.6 - \ingroup multimedia - \ingroup graphicsview-api - - Effects alter the appearance of elements by hooking into the rendering - pipeline and operating between the source (e.g., a QGraphicsPixmapItem), - and the destination device (e.g., QGraphicsView's viewport). Effects can be - disabled by calling setEnabled(); if the effect is disabled, the source is - rendered directly. - - If you want to add a visual effect to a QGraphicsItem, you can either use - one of the standard effects, or create your own effect by making a subclass - of QGraphicsEffect. - - Qt provides several standard effects, including: - - \list - \o QGraphicsGrayScaleEffect - renders the item in shades of gray - \o QGraphicsColorizeEffect - renders the item in shades of any given color - \o QGraphicsPixelizeEffect - pixelizes the item with any pixel size - \o QGraphicsBlurEffect - blurs the item by a given radius - \o QGraphicsBloomEffect - applies a blooming / glowing effect - \o QGraphicsFrameEffect - adds a frame to the item - \o QGraphicsShadowEffect - renders a dropshadow behind the item - \endlist - - If all you want is to add an effect to an item, you should visit the - documentation for the specific effect to learn more about how each effect - can be used. - - If you want to create your own custom effect, you can start by creating a - subclass of QGraphicsEffect (or any of the existing effects), and - reimplement the virtual function draw(). This function is called whenever - the effect needs to redraw. draw() has two arguments: the painter, and a - pointer to the source (QGraphicsEffectSource). The source provides extra - context information, such as a pointer to the item that is rendering the - effect, any cached pixmap data, and the device rect bounds. See the draw() - documentation for more details. You can also get a pointer to the current - source by calling source(). - - If your effect changes, you can call update() to request a redraw. If your - custom effect changes the bounding rectangle of the source (e.g., a radial - glow effect may need to apply an extra margin), you can reimplement the - virtual boundingRectFor() function, and call updateBoundingRect() to notify - the framework whenever this rectangle changes. The virtual - sourceBoundingRectChanged() function is called to notify the effects that - the source's bounding rectangle has changed (e.g., if the source is a - QGraphicsRectItem, then if the rectangle parameters have changed). - - \sa QGraphicsItem::setGraphicsEffect() -*/ - -#include "qgraphicseffect_p.h" - -#ifndef QT_NO_GRAPHICSVIEW - -#include -#include -#include - -/* - - List of known drawbacks which are being discussed: - - * No d-pointer yet. - - * No auto test yet. - - * No API documentation yet. - - * The API is far from being finalized. - - * Most of the effect implementation is not efficient, - as this is still a proof of concept only. - - * Painting artifacts occasionally occur when e.g. moving - an item over another item that has a large effective - bounding rect. - - * Item transformation is not taken into account. - For example, the effective bounding rect is calculated at - item coordinate (fast), but the painting is mostly - done at device coordinate. - - * Coordinate mode: item vs device. Most effects make sense only - in device coordinate. Should we keep both options open? - See also above transformation issue. - - * Right now the pixmap for effect drawing is stored in each item. - There can be problems with coordinates, see above. - - * There is a lot of duplication in drawItems() for each effect. - - * Port to use the new layer feature in QGraphicsView. - This should solve the above pixmap problem. - - * Frame effect is likely useless. However it is very useful - to check than the effective bounding rect is handled properly. - - * Proper exposed region and rect for style option are missing. - - * Pixelize effect is using raster only, because there is no - pixmap filter for it. We need to implement the missing pixmap filter. - - * Blur effect is using raster only, with exponential blur algorithm. - Perhaps use stack blur (better approximate Gaussian blur) instead? - QPixmapConvolutionFilter is too slow for this simple blur effect. - - * Bloom and shadow effect are also raster only. Same reason as above. - - * Make it work with widgets (QGraphicsWidget). - -*/ - -QGraphicsEffectSource::QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, QObject *parent) - : QObject(dd, parent) -{} - -QGraphicsEffectSource::~QGraphicsEffectSource() -{} - -QRect QGraphicsEffectSource::deviceRect() const -{ - return d_func()->deviceRect(); -} - -QRectF QGraphicsEffectSource::boundingRect(Qt::CoordinateSystem system) const -{ - return d_func()->boundingRect(system); -} - -const QGraphicsItem *QGraphicsEffectSource::graphicsItem() const -{ - return d_func()->graphicsItem(); -} - -const QStyleOption *QGraphicsEffectSource::styleOption() const -{ - return d_func()->styleOption(); -} - -void QGraphicsEffectSource::draw(QPainter *painter) -{ - d_func()->draw(painter); -} - -void QGraphicsEffectSource::update() -{ - d_func()->update(); -} - -bool QGraphicsEffectSource::isPixmap() const -{ - return d_func()->isPixmap(); -} - -QPixmap QGraphicsEffectSource::pixmap(Qt::CoordinateSystem system, QPoint *offset) const -{ - return d_func()->pixmap(system, offset); -} - -/*! - Constructs a new QGraphicsEffect instance. -*/ -QGraphicsEffect::QGraphicsEffect() - : QObject(*new QGraphicsEffectPrivate, 0) -{ - // ### parent? -} - -/*! - \internal -*/ -QGraphicsEffect::QGraphicsEffect(QGraphicsEffectPrivate &dd) - : QObject(dd, 0) -{ -} - -/*! - Removes the effect from the source, and destroys the graphics effect. -*/ -QGraphicsEffect::~QGraphicsEffect() -{ - Q_D(QGraphicsEffect); - d->setGraphicsEffectSource(0); -} - -/*! - Returns the bounding rectangle for this effect (i.e., the bounding - rectangle of the source, adjusted by any margins applied by the effect - itself). - - \sa boundingRectFor(), updateBoundingRect() -*/ -QRectF QGraphicsEffect::boundingRect() const -{ - Q_D(const QGraphicsEffect); - if (d->source) - return boundingRectFor(d->source->boundingRect()); - return QRectF(); -} - -/*! - Returns the bounding rectangle for this effect, given the provided source - \a rect. When writing you own custom effect, you must call - updateBoundingRect() whenever any parameters are changed that may cause - this this function to return a different value. - - \sa boundingRect() -*/ -QRectF QGraphicsEffect::boundingRectFor(const QRectF &rect) const -{ - return rect; -} - -/*! - \property QGraphicsEffect::enabled - \brief whether the effect is enabled or not. - - If an effect is disabled, the source will be rendered with as normal, with - no interference from the effect. If the effect is enabled (default), the - source will be rendered with the effect applied. - - This property is provided so that you can disable certain effects on slow - platforms, in order to ensure that the user interface is responsive. -*/ -bool QGraphicsEffect::isEnabled() const -{ - Q_D(const QGraphicsEffect); - return d->isEnabled; -} -void QGraphicsEffect::setEnabled(bool enable) -{ - Q_D(QGraphicsEffect); - if (d->isEnabled == enable) - return; - - d->isEnabled = enable; - - if (d->source) - d->source->update(); -} - -/*! - Returns a pointer to the source, which provides extra context information - that can be useful for the effect. - - \sa draw() -*/ -QGraphicsEffectSource *QGraphicsEffect::source() const -{ - Q_D(const QGraphicsEffect); - return d->source; -} - -/*! - This function notifies the effect framework that the effect's bounding - rectangle has changed. As a custom effect author, you must call this - function whenever you change any parameters that will cause the virtual - boundingRectFor() function to return a different value. - - \sa boundingRectFor(), boundingRect() -*/ -void QGraphicsEffect::updateBoundingRect() -{ - Q_D(QGraphicsEffect); - if (d->source) - d->source->update(); -} - -/*! - This virtual function is called by QGraphicsEffect to notify the effect - that the source has changed. If the effect applies any cache, then this - cache must be purged in order to reflect the new appearance of the source. - - The \a flags describes what has changed. -*/ -void QGraphicsEffect::sourceChanged(ChangeFlags flags) -{ - Q_UNUSED(flags); -} - -QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect() - : QGraphicsEffect(*new QGraphicsGrayscaleEffectPrivate) -{ -} - -QGraphicsGrayscaleEffect::~QGraphicsGrayscaleEffect() -{ -} - -void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *source) -{ - Q_D(QGraphicsGrayscaleEffect); - 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); - -} - -QGraphicsColorizeEffect::QGraphicsColorizeEffect() - : QGraphicsEffect(*new QGraphicsColorizeEffectPrivate) -{} - -QGraphicsColorizeEffect::~QGraphicsColorizeEffect() -{} - -QColor QGraphicsColorizeEffect::color() const -{ - Q_D(const QGraphicsColorizeEffect); - return d->filter->color(); -} - -void QGraphicsColorizeEffect::setColor(const QColor &c) -{ - Q_D(QGraphicsColorizeEffect); - d->filter->setColor(c); -} - -void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *source) -{ - Q_D(QGraphicsColorizeEffect); - 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 deviceCoordinates 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); -} - -QGraphicsPixelizeEffect::QGraphicsPixelizeEffect() - : QGraphicsEffect(*new QGraphicsPixelizeEffectPrivate) -{ -} - -QGraphicsPixelizeEffect::~QGraphicsPixelizeEffect() -{ -} - -int QGraphicsPixelizeEffect::pixelSize() const -{ - Q_D(const QGraphicsPixelizeEffect); - return d->pixelSize; -} - -void QGraphicsPixelizeEffect::setPixelSize(int size) -{ - Q_D(QGraphicsPixelizeEffect); - d->pixelSize = 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(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(image->scanLine(y + yi)); - for (int xi = 0; xi < qMin(pixelSize, width - x); ++xi) - buf[x + xi] = color; - } - } - } -} - -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); -} - -QGraphicsBlurEffect::QGraphicsBlurEffect() - : QGraphicsEffect(*new QGraphicsBlurEffectPrivate) -{ -} - -QGraphicsBlurEffect::~QGraphicsBlurEffect() -{ -} - -// Blur the image according to the blur radius -// Based on exponential blur algorithm by Jani Huhtanen -// (maximum radius is set to 16) -static QImage blurred(const QImage& image, const QRect& rect, int radius) -{ - int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 }; - int alpha = (radius < 1) ? 16 : (radius > 17) ? 1 : tab[radius-1]; - - QImage result = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); - int r1 = rect.top(); - int r2 = rect.bottom(); - int c1 = rect.left(); - int c2 = rect.right(); - - int bpl = result.bytesPerLine(); - int rgba[4]; - unsigned char* p; - - for (int col = c1; col <= c2; col++) { - p = result.scanLine(r1) + col * 4; - for (int i = 0; i < 4; i++) - rgba[i] = p[i] << 4; - - p += bpl; - for (int j = r1; j < r2; j++, p += bpl) - for (int i = 0; i < 4; i++) - p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; - } - - for (int row = r1; row <= r2; row++) { - p = result.scanLine(row) + c1 * 4; - for (int i = 0; i < 4; i++) - rgba[i] = p[i] << 4; - - p += 4; - for (int j = c1; j < c2; j++, p += 4) - for (int i = 0; i < 4; i++) - p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; - } - - for (int col = c1; col <= c2; col++) { - p = result.scanLine(r2) + col * 4; - for (int i = 0; i < 4; i++) - rgba[i] = p[i] << 4; - - p -= bpl; - for (int j = r1; j < r2; j++, p -= bpl) - for (int i = 0; i < 4; i++) - p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; - } - - for (int row = r1; row <= r2; row++) { - p = result.scanLine(row) + c2 * 4; - for (int i = 0; i < 4; i++) - rgba[i] = p[i] << 4; - - p -= 4; - for (int j = c1; j < c2; j++, p -= 4) - for (int i = 0; i < 4; i++) - p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; - } - - return result; -} - -int QGraphicsBlurEffect::blurRadius() const -{ - Q_D(const QGraphicsBlurEffect); - return d->filter->radius(); -} - -void QGraphicsBlurEffect::setBlurRadius(int radius) -{ - Q_D(QGraphicsBlurEffect); - d->filter->setRadius(radius); - updateBoundingRect(); -} - -QRectF QGraphicsBlurEffect::boundingRectFor(const QRectF &rect) const -{ - Q_D(const QGraphicsBlurEffect); - return d->filter->boundingRectFor(rect); -} - -void QGraphicsBlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) -{ - Q_D(QGraphicsBlurEffect); - if (d->filter->radius() <= 0) { - 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); -} - -QGraphicsBloomEffect::QGraphicsBloomEffect() - : QGraphicsEffect(*new QGraphicsBloomEffectPrivate) -{ -} - -QGraphicsBloomEffect::~QGraphicsBloomEffect() -{ -} - -int QGraphicsBloomEffect::blurRadius() const -{ - Q_D(const QGraphicsBloomEffect); - return d->blurRadius; -} - -void QGraphicsBloomEffect::setBlurRadius(int radius) -{ - Q_D(QGraphicsBloomEffect); - d->blurRadius = radius; - updateBoundingRect(); -} - -qreal QGraphicsBloomEffect::opacity() const -{ - Q_D(const QGraphicsBloomEffect); - return d->opacity; -} - -void QGraphicsBloomEffect::setOpacity(qreal alpha) -{ - Q_D(QGraphicsBloomEffect); - d->opacity = alpha; -} - -QRectF QGraphicsBloomEffect::boundingRectFor(const QRectF &rect) const -{ - Q_D(const QGraphicsBloomEffect); - const qreal delta = d->blurRadius * 3; - return rect.adjusted(-delta, -delta, delta, delta); -} - -// Change brightness (positive integer) of each pixel -static QImage brightened(const QImage& image, int brightness) -{ - int tab[ 256 ]; - for (int i = 0; i < 256; ++i) - tab[i] = qMin(i + brightness, 255); - - QImage img = image.convertToFormat(QImage::Format_ARGB32); - for (int y = 0; y < img.height(); y++) { - QRgb* line = (QRgb*)(img.scanLine(y)); - for (int x = 0; x < img.width(); x++) { - QRgb c = line[x]; - line[x] = qRgba(tab[qRed(c)], tab[qGreen(c)], tab[qBlue(c)], qAlpha(c)); - } - } - - return img; -} - -// Composite two QImages using given composition mode and opacity -static QImage composited(const QImage& img1, const QImage& img2, qreal opacity, QPainter::CompositionMode mode) -{ - QImage result = img1.convertToFormat(QImage::Format_ARGB32_Premultiplied); - QPainter painter(&result); - painter.setCompositionMode(mode); - painter.setOpacity(opacity); - painter.drawImage(0, 0, img2); - painter.end(); - return result; -} - -void QGraphicsBloomEffect::draw(QPainter *painter, QGraphicsEffectSource *source) -{ - Q_D(QGraphicsBloomEffect); - if (d->blurRadius <= 0) { - source->draw(painter); - return; - } - - QPoint offset; - const int radius = d->blurRadius; - - if (source->isPixmap()) { - // No point in drawing in device coordinates (pixmap will be scaled anyways). - const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset); - - // bloom routine - QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); - QImage overlay = blurred(img, img.rect(), radius); - overlay = brightened(overlay, 70); - img = composited(img, overlay, d->opacity, QPainter::CompositionMode_Overlay); - - painter->drawImage(offset, img); - return; - } - - // Draw pixmap in device coordinates to avoid pixmap scaling. - const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); - - // bloom routine - QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); - QImage overlay = blurred(img, img.rect(), radius); - overlay = brightened(overlay, 70); - img = composited(img, overlay, d->opacity, QPainter::CompositionMode_Overlay); - - // Draw using an untransformed painter. - QTransform restoreTransform = painter->worldTransform(); - painter->setWorldTransform(QTransform()); - painter->drawImage(offset, img); - painter->setWorldTransform(restoreTransform); -} - -QGraphicsFrameEffect::QGraphicsFrameEffect() - : QGraphicsEffect(*new QGraphicsFrameEffectPrivate) -{ -} - -QGraphicsFrameEffect::~QGraphicsFrameEffect() -{ -} - -QColor QGraphicsFrameEffect::frameColor() const -{ - Q_D(const QGraphicsFrameEffect); - return d->color; -} - -void QGraphicsFrameEffect::setFrameColor(const QColor &c) -{ - Q_D(QGraphicsFrameEffect); - d->color = c; -} - -qreal QGraphicsFrameEffect::frameWidth() const -{ - Q_D(const QGraphicsFrameEffect); - return d->width; -} - -void QGraphicsFrameEffect::setFrameWidth(qreal frameWidth) -{ - Q_D(QGraphicsFrameEffect); - d->width = frameWidth; - updateBoundingRect(); -} - -qreal QGraphicsFrameEffect::frameOpacity() const -{ - Q_D(const QGraphicsFrameEffect); - return d->alpha; -} - -void QGraphicsFrameEffect::setFrameOpacity(qreal opacity) -{ - Q_D(QGraphicsFrameEffect); - d->alpha = opacity; -} - -QRectF QGraphicsFrameEffect::boundingRectFor(const QRectF &rect) const -{ - Q_D(const QGraphicsFrameEffect); - return rect.adjusted(-d->width, -d->width, d->width, d->width); -} - -void QGraphicsFrameEffect::draw(QPainter *painter, QGraphicsEffectSource *source) -{ - Q_D(QGraphicsFrameEffect); - painter->save(); - painter->setOpacity(painter->opacity() * d->alpha); - painter->setPen(Qt::NoPen); - painter->setBrush(d->color); - painter->drawRoundedRect(boundingRect(), 20, 20, Qt::RelativeSize); - painter->restore(); - - source->draw(painter); -} - -QGraphicsShadowEffect::QGraphicsShadowEffect() - : QGraphicsEffect(*new QGraphicsShadowEffectPrivate) -{ -} - -QGraphicsShadowEffect::~QGraphicsShadowEffect() -{ -} - -QPointF QGraphicsShadowEffect::shadowOffset() const -{ - Q_D(const QGraphicsShadowEffect); - return d->offset; -} - -void QGraphicsShadowEffect::setShadowOffset(const QPointF &ofs) -{ - Q_D(QGraphicsShadowEffect); - d->offset = ofs; - updateBoundingRect(); -} - -int QGraphicsShadowEffect::blurRadius() const -{ - Q_D(const QGraphicsShadowEffect); - return d->radius; -} - -void QGraphicsShadowEffect::setBlurRadius(int blurRadius) -{ - Q_D(QGraphicsShadowEffect); - d->radius = blurRadius; - updateBoundingRect(); -} - -qreal QGraphicsShadowEffect::opacity() const -{ - Q_D(const QGraphicsShadowEffect); - return d->alpha; -} - -void QGraphicsShadowEffect::setOpacity(qreal opacity) -{ - Q_D(QGraphicsShadowEffect); - d->alpha = opacity; -} - -QRectF QGraphicsShadowEffect::boundingRectFor(const QRectF &rect) const -{ - Q_D(const QGraphicsShadowEffect); - QRectF shadowRect = rect.translated(d->offset); - QRectF blurRect = shadowRect; - qreal delta = d->radius * 3; - blurRect.adjust(-delta, -delta, delta, delta); - blurRect |= rect; - return blurRect; -} - -void QGraphicsShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *source) -{ - Q_D(QGraphicsShadowEffect); - if (d->radius <= 0 && d->offset.isNull()) { - source->draw(painter); - return; - } - - const QTransform &transform = painter->worldTransform(); - const QPointF offset(d->offset.x() * transform.m11(), d->offset.y() * transform.m22()); - const QPoint shadowOffset = offset.toPoint(); - const QRectF sourceRect = source->boundingRect(Qt::DeviceCoordinates); - const QRectF shadowRect = sourceRect.translated(offset); - - QRectF blurRect = shadowRect; - qreal delta = d->radius * 3; - blurRect.adjust(-delta, -delta, delta, delta); - blurRect |= sourceRect; - - QRect effectRect = blurRect.toAlignedRect(); - const QRect deviceRect = source->deviceRect(); - const bool fullyInsideDeviceRect = effectRect.x() >= deviceRect.x() - && effectRect.right() <= deviceRect.right() - && effectRect.y() >= deviceRect.y() - && effectRect.bottom() <= deviceRect.bottom(); - if (!fullyInsideDeviceRect) { - // Clip to device rect to avoid huge pixmaps. - effectRect &= source->deviceRect(); - effectRect |= effectRect.translated(-shadowOffset); - if (effectRect.isEmpty()) - return; // nothing to paint; - } - - QPixmap pixmap(effectRect.size()); - pixmap.fill(Qt::transparent); - QPainter pixmapPainter(&pixmap); - pixmapPainter.setRenderHints(painter->renderHints()); - pixmapPainter.setWorldTransform(painter->worldTransform()); - if (effectRect.x() != 0 || effectRect.y() != 0) - pixmapPainter.translate(-effectRect.topLeft()); - source->draw(&pixmapPainter); - pixmapPainter.end(); - - QImage img = pixmap.toImage(); - QImage shadowImage(img.size(), QImage::Format_ARGB32); - shadowImage.fill(qRgba(0, 0, 0, d->alpha * 255)); - shadowImage.setAlphaChannel(img.alphaChannel()); - shadowImage = blurred(shadowImage, shadowImage.rect(), d->radius); - - // Draw using an untransformed painter. - QTransform restoreTransform = painter->worldTransform(); - painter->setWorldTransform(QTransform()); - painter->drawImage(effectRect.topLeft() + shadowOffset, shadowImage); - painter->drawPixmap(effectRect.topLeft(), pixmap); - painter->setWorldTransform(restoreTransform); -} - -#endif diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h deleted file mode 100644 index d171b1b..0000000 --- a/src/gui/graphicsview/qgraphicseffect.h +++ /dev/null @@ -1,291 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSEFFECT_H -#define QGRAPHICSEFFECT_H - -#include -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -class QGraphicsItem; -class QStyleOption; -class QColor; -class QPainter; -class QRectF; -class QRect; -class QPixmap; - -class QGraphicsEffectSourcePrivate; -class Q_GUI_EXPORT QGraphicsEffectSource : public QObject -{ - Q_OBJECT -public: - ~QGraphicsEffectSource(); - const QGraphicsItem *graphicsItem() const; - const QStyleOption *styleOption() const; - - bool isPixmap() const; - void draw(QPainter *painter); - void update(); - - QRectF boundingRect(Qt::CoordinateSystem coordinateSystem = Qt::LogicalCoordinates) const; - QRect deviceRect() const; - QPixmap pixmap(Qt::CoordinateSystem system = Qt::LogicalCoordinates, QPoint *offset = 0) const; - -protected: - QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, QObject *parent = 0); - -private: - Q_DECLARE_PRIVATE(QGraphicsEffectSource); - Q_DISABLE_COPY(QGraphicsEffectSource); - friend class QGraphicsEffect; - friend class QGraphicsEffectPrivate; - friend class QGraphicsScenePrivate; - friend class QGraphicsItem; -}; - -class QGraphicsEffectPrivate; -class Q_GUI_EXPORT QGraphicsEffect : public QObject -{ - Q_OBJECT - Q_FLAGS(ChangeFlags) - Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) -public: - enum ChangeFlag { - SourceAttached = 0x1, - SourceDetached = 0x2, - SourceBoundingRectChanged = 0x4, - SourceInvalidated = 0x8 - }; - Q_DECLARE_FLAGS(ChangeFlags, ChangeFlag); - - QGraphicsEffect(); - virtual ~QGraphicsEffect(); - - // ### make protected? - virtual QRectF boundingRectFor(const QRectF &rect) const; - QRectF boundingRect() const; - - QGraphicsEffectSource *source() const; - - bool isEnabled() const; - -public Q_SLOTS: - void setEnabled(bool enable); - // ### add update() slot - -protected: - QGraphicsEffect(QGraphicsEffectPrivate &d); - virtual void draw(QPainter *painter, QGraphicsEffectSource *source) = 0; - virtual void sourceChanged(ChangeFlags flags); - void updateBoundingRect(); - -private: - Q_DECLARE_PRIVATE(QGraphicsEffect) - Q_DISABLE_COPY(QGraphicsEffect) - friend class QGraphicsItem; - friend class QGraphicsItemPrivate; - friend class QGraphicsScenePrivate; -}; - -class QGraphicsGrayscaleEffectPrivate; -class Q_GUI_EXPORT QGraphicsGrayscaleEffect: public QGraphicsEffect -{ - Q_OBJECT -public: - QGraphicsGrayscaleEffect(); - ~QGraphicsGrayscaleEffect(); - -protected: - void draw(QPainter *painter, QGraphicsEffectSource *source); - -private: - Q_DECLARE_PRIVATE(QGraphicsGrayscaleEffect) - Q_DISABLE_COPY(QGraphicsGrayscaleEffect) -}; - -class QGraphicsColorizeEffectPrivate; -class Q_GUI_EXPORT QGraphicsColorizeEffect: public QGraphicsEffect { - Q_OBJECT -public: - QGraphicsColorizeEffect(); - ~QGraphicsColorizeEffect(); - - QColor color() const; - void setColor(const QColor &c); - -protected: - void draw(QPainter *painter, QGraphicsEffectSource *source); - -private: - Q_DECLARE_PRIVATE(QGraphicsColorizeEffect) - Q_DISABLE_COPY(QGraphicsColorizeEffect) -}; - -class QGraphicsPixelizeEffectPrivate; -class Q_GUI_EXPORT QGraphicsPixelizeEffect: public QGraphicsEffect { - Q_OBJECT -public: - QGraphicsPixelizeEffect(); - ~QGraphicsPixelizeEffect(); - - int pixelSize() const; - void setPixelSize(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 -public: - QGraphicsBlurEffect(); - ~QGraphicsBlurEffect(); - - int blurRadius() const; - void setBlurRadius(int blurRadius); - -protected: - QRectF boundingRectFor(const QRectF &rect) const; - void draw(QPainter *painter, QGraphicsEffectSource *source); - -private: - Q_DECLARE_PRIVATE(QGraphicsBlurEffect) - Q_DISABLE_COPY(QGraphicsBlurEffect) -}; - -class QGraphicsBloomEffectPrivate; -class Q_GUI_EXPORT QGraphicsBloomEffect: public QGraphicsEffect { - Q_OBJECT -public: - QGraphicsBloomEffect(); - ~QGraphicsBloomEffect(); - - int blurRadius() const; - void setBlurRadius(int blurRadius); - - qreal opacity() const; - void setOpacity(qreal opacity); - -protected: - QRectF boundingRectFor(const QRectF &rect) const; - void draw(QPainter *painter, QGraphicsEffectSource *source); - -private: - Q_DECLARE_PRIVATE(QGraphicsBloomEffect) - Q_DISABLE_COPY(QGraphicsBloomEffect) -}; - -class QGraphicsFrameEffectPrivate; -class Q_GUI_EXPORT QGraphicsFrameEffect: public QGraphicsEffect { - Q_OBJECT -public: - QGraphicsFrameEffect(); - ~QGraphicsFrameEffect(); - - QColor frameColor() const; - void setFrameColor(const QColor &c); - - qreal frameWidth() const; - void setFrameWidth(qreal frameWidth); - - qreal frameOpacity() const; - void setFrameOpacity(qreal opacity); - -protected: - QRectF boundingRectFor(const QRectF &rect) const; - void draw(QPainter *painter, QGraphicsEffectSource *source); - -private: - Q_DECLARE_PRIVATE(QGraphicsFrameEffect) - Q_DISABLE_COPY(QGraphicsFrameEffect) -}; - -class QGraphicsShadowEffectPrivate; -class Q_GUI_EXPORT QGraphicsShadowEffect: public QGraphicsEffect { - Q_OBJECT -public: - QGraphicsShadowEffect(); - ~QGraphicsShadowEffect(); - - QPointF shadowOffset() const; - void setShadowOffset(const QPointF &ofs); - inline void setShadowOffset(qreal dx, qreal dy) - { setShadowOffset(QPointF(dx, dy)); } - inline void setShadowOffset(qreal d) - { setShadowOffset(QPointF(d, d)); } - - int blurRadius() const; - void setBlurRadius(int blurRadius); - - qreal opacity() const; - void setOpacity(qreal opacity); - -protected: - QRectF boundingRectFor(const QRectF &rect) const; - void draw(QPainter *painter, QGraphicsEffectSource *source); - -private: - Q_DECLARE_PRIVATE(QGraphicsShadowEffect) - Q_DISABLE_COPY(QGraphicsShadowEffect) -}; - -#endif // QT_NO_GRAPHICSVIEW - -QT_END_NAMESPACE - -QT_END_HEADER - - -#endif // QGRAPHICSEFFECT_H diff --git a/src/gui/graphicsview/qgraphicseffect_p.h b/src/gui/graphicsview/qgraphicseffect_p.h deleted file mode 100644 index 6d546cc..0000000 --- a/src/gui/graphicsview/qgraphicseffect_p.h +++ /dev/null @@ -1,195 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://www.qtsoftware.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSEFFECT_P_H -#define QGRAPHICSEFFECT_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header -// file may change from version to version without notice, or even be removed. -// -// We mean it. -// - -#include "qgraphicseffect.h" - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -#include -#include - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class QGraphicsEffectSourcePrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsEffectSource) -public: - QGraphicsEffectSourcePrivate() : QObjectPrivate() {} - virtual ~QGraphicsEffectSourcePrivate() {} - virtual void detach() = 0; - virtual QRectF boundingRect(Qt::CoordinateSystem system) const = 0; - virtual QRect deviceRect() const = 0; - virtual const QGraphicsItem *graphicsItem() const = 0; - virtual const QStyleOption *styleOption() const = 0; - 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; - friend class QGraphicsScenePrivate; - friend class QGraphicsItem; - friend class QGraphicsItemPrivate; -}; - -class Q_GUI_EXPORT QGraphicsEffectPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsEffect) -public: - QGraphicsEffectPrivate() : source(0), isEnabled(1) {} - - inline void setGraphicsEffectSource(QGraphicsEffectSource *newSource) - { - QGraphicsEffect::ChangeFlags flags; - if (source) { - flags |= QGraphicsEffect::SourceDetached; - source->d_func()->detach(); - delete source; - } - source = newSource; - if (newSource) - flags |= QGraphicsEffect::SourceAttached; - q_func()->sourceChanged(flags); - } - - QGraphicsEffectSource *source; - QRectF boundingRect; - quint32 isEnabled : 1; - quint32 padding : 31; // feel free to use -}; - -class QGraphicsGrayscaleEffectPrivate : public QGraphicsEffectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsGrayscaleEffect) -public: - QGraphicsGrayscaleEffectPrivate() - { - filter = new QPixmapColorizeFilter; - filter->setColor(Qt::black); - } - ~QGraphicsGrayscaleEffectPrivate() { delete filter; } - - QPixmapColorizeFilter *filter; -}; - -class QGraphicsColorizeEffectPrivate : public QGraphicsEffectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsColorizeEffect) -public: - QGraphicsColorizeEffectPrivate() { filter = new QPixmapColorizeFilter; } - ~QGraphicsColorizeEffectPrivate() { delete filter; } - - QPixmapColorizeFilter *filter; -}; - -class QGraphicsPixelizeEffectPrivate : public QGraphicsEffectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsPixelizeEffect) -public: - QGraphicsPixelizeEffectPrivate() : pixelSize(3) {} - - int pixelSize; -}; - -class QGraphicsBlurEffectPrivate : public QGraphicsEffectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsBlurEffect) -public: - QGraphicsBlurEffectPrivate() : filter(new QPixmapBlurFilter), blurRadius(4) {} - ~QGraphicsBlurEffectPrivate() { delete filter; } - - QPixmapBlurFilter *filter; - int blurRadius; -}; - -class QGraphicsBloomEffectPrivate : public QGraphicsEffectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsBlurEffect) -public: - QGraphicsBloomEffectPrivate() : blurRadius(6), opacity(0.7) {} - - int blurRadius; - qreal opacity; -}; - -class QGraphicsFrameEffectPrivate : public QGraphicsEffectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsFrameEffect) -public: - QGraphicsFrameEffectPrivate() : color(Qt::blue), width(5), alpha(0.6) {} - - QColor color; - qreal width; - qreal alpha; -}; - -class QGraphicsShadowEffectPrivate : public QGraphicsEffectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsShadowEffect) -public: - QGraphicsShadowEffectPrivate() : offset(4, 4), radius(8), alpha(0.7) {} - - QPointF offset; - int radius; - qreal alpha; -}; - -QT_END_NAMESPACE - -#endif // QT_NO_GRAPHICSVIEW - -#endif // QGRAPHICSEFFECT_P_H diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index a5854b1..a7b48fc 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -57,10 +57,11 @@ #include "qset.h" #include "qpixmapcache.h" #include "qgraphicsview_p.h" -#include "qgraphicseffect_p.h" #include "qgraphicstransform.h" #include "qgraphicstransform_p.h" +#include + #include #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index db783ad..ff8445f 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -207,7 +207,6 @@ #ifndef QT_NO_GRAPHICSVIEW -#include "qgraphicseffect_p.h" #include "qgraphicsitem.h" #include "qgraphicsitem_p.h" #include "qgraphicslayout.h" @@ -250,6 +249,7 @@ #ifdef Q_WS_X11 #include #endif +#include QT_BEGIN_NAMESPACE diff --git a/src/gui/gui.pro b/src/gui/gui.pro index a49d680..90ac3ce 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -34,6 +34,7 @@ include(graphicsview/graphicsview.pri) include(util/util.pri) include(statemachine/statemachine.pri) include(math3d/math3d.pri) +include(effects/effects.pri) contains(QT_CONFIG, egl): include(egl/egl.pri) -- cgit v0.12 From 1c9a28ea64cc53e61a64644dc5a4ff121b475bc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 19 Aug 2009 15:30:32 +0200 Subject: Remove QGraphicsBloomEffect and QGraphicsFrameEffect. These belong to the examples directory as discussed with Andreas. --- src/gui/effects/qgraphicseffect.cpp | 180 ------------------------------------ src/gui/effects/qgraphicseffect.h | 47 ---------- src/gui/effects/qgraphicseffect_p.h | 21 ----- 3 files changed, 248 deletions(-) diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index b04af7a..c1f8f06 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -63,8 +63,6 @@ \o QGraphicsColorizeEffect - renders the item in shades of any given color \o QGraphicsPixelizeEffect - pixelizes the item with any pixel size \o QGraphicsBlurEffect - blurs the item by a given radius - \o QGraphicsBloomEffect - applies a blooming / glowing effect - \o QGraphicsFrameEffect - adds a frame to the item \o QGraphicsShadowEffect - renders a dropshadow behind the item \endlist @@ -580,184 +578,6 @@ void QGraphicsBlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) painter->setWorldTransform(restoreTransform); } -QGraphicsBloomEffect::QGraphicsBloomEffect() - : QGraphicsEffect(*new QGraphicsBloomEffectPrivate) -{ -} - -QGraphicsBloomEffect::~QGraphicsBloomEffect() -{ -} - -int QGraphicsBloomEffect::blurRadius() const -{ - Q_D(const QGraphicsBloomEffect); - return d->blurRadius; -} - -void QGraphicsBloomEffect::setBlurRadius(int radius) -{ - Q_D(QGraphicsBloomEffect); - d->blurRadius = radius; - updateBoundingRect(); -} - -qreal QGraphicsBloomEffect::opacity() const -{ - Q_D(const QGraphicsBloomEffect); - return d->opacity; -} - -void QGraphicsBloomEffect::setOpacity(qreal alpha) -{ - Q_D(QGraphicsBloomEffect); - d->opacity = alpha; -} - -QRectF QGraphicsBloomEffect::boundingRectFor(const QRectF &rect) const -{ - Q_D(const QGraphicsBloomEffect); - const qreal delta = d->blurRadius * 3; - return rect.adjusted(-delta, -delta, delta, delta); -} - -// Change brightness (positive integer) of each pixel -static QImage brightened(const QImage& image, int brightness) -{ - int tab[ 256 ]; - for (int i = 0; i < 256; ++i) - tab[i] = qMin(i + brightness, 255); - - QImage img = image.convertToFormat(QImage::Format_ARGB32); - for (int y = 0; y < img.height(); y++) { - QRgb* line = (QRgb*)(img.scanLine(y)); - for (int x = 0; x < img.width(); x++) { - QRgb c = line[x]; - line[x] = qRgba(tab[qRed(c)], tab[qGreen(c)], tab[qBlue(c)], qAlpha(c)); - } - } - - return img; -} - -// Composite two QImages using given composition mode and opacity -static QImage composited(const QImage& img1, const QImage& img2, qreal opacity, QPainter::CompositionMode mode) -{ - QImage result = img1.convertToFormat(QImage::Format_ARGB32_Premultiplied); - QPainter painter(&result); - painter.setCompositionMode(mode); - painter.setOpacity(opacity); - painter.drawImage(0, 0, img2); - painter.end(); - return result; -} - -void QGraphicsBloomEffect::draw(QPainter *painter, QGraphicsEffectSource *source) -{ - Q_D(QGraphicsBloomEffect); - if (d->blurRadius <= 0) { - source->draw(painter); - return; - } - - QPoint offset; - const int radius = d->blurRadius; - - if (source->isPixmap()) { - // No point in drawing in device coordinates (pixmap will be scaled anyways). - const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset); - - // bloom routine - QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); - QImage overlay = blurred(img, img.rect(), radius); - overlay = brightened(overlay, 70); - img = composited(img, overlay, d->opacity, QPainter::CompositionMode_Overlay); - - painter->drawImage(offset, img); - return; - } - - // Draw pixmap in device coordinates to avoid pixmap scaling. - const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); - - // bloom routine - QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); - QImage overlay = blurred(img, img.rect(), radius); - overlay = brightened(overlay, 70); - img = composited(img, overlay, d->opacity, QPainter::CompositionMode_Overlay); - - // Draw using an untransformed painter. - QTransform restoreTransform = painter->worldTransform(); - painter->setWorldTransform(QTransform()); - painter->drawImage(offset, img); - painter->setWorldTransform(restoreTransform); -} - -QGraphicsFrameEffect::QGraphicsFrameEffect() - : QGraphicsEffect(*new QGraphicsFrameEffectPrivate) -{ -} - -QGraphicsFrameEffect::~QGraphicsFrameEffect() -{ -} - -QColor QGraphicsFrameEffect::frameColor() const -{ - Q_D(const QGraphicsFrameEffect); - return d->color; -} - -void QGraphicsFrameEffect::setFrameColor(const QColor &c) -{ - Q_D(QGraphicsFrameEffect); - d->color = c; -} - -qreal QGraphicsFrameEffect::frameWidth() const -{ - Q_D(const QGraphicsFrameEffect); - return d->width; -} - -void QGraphicsFrameEffect::setFrameWidth(qreal frameWidth) -{ - Q_D(QGraphicsFrameEffect); - d->width = frameWidth; - updateBoundingRect(); -} - -qreal QGraphicsFrameEffect::frameOpacity() const -{ - Q_D(const QGraphicsFrameEffect); - return d->alpha; -} - -void QGraphicsFrameEffect::setFrameOpacity(qreal opacity) -{ - Q_D(QGraphicsFrameEffect); - d->alpha = opacity; -} - -QRectF QGraphicsFrameEffect::boundingRectFor(const QRectF &rect) const -{ - Q_D(const QGraphicsFrameEffect); - return rect.adjusted(-d->width, -d->width, d->width, d->width); -} - -void QGraphicsFrameEffect::draw(QPainter *painter, QGraphicsEffectSource *source) -{ - Q_D(QGraphicsFrameEffect); - painter->save(); - painter->setOpacity(painter->opacity() * d->alpha); - painter->setPen(Qt::NoPen); - painter->setBrush(d->color); - painter->drawRoundedRect(boundingRect(), 20, 20, Qt::RelativeSize); - painter->restore(); - - source->draw(painter); -} - QGraphicsShadowEffect::QGraphicsShadowEffect() : QGraphicsEffect(*new QGraphicsShadowEffectPrivate) { diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h index d171b1b..19399d3 100644 --- a/src/gui/effects/qgraphicseffect.h +++ b/src/gui/effects/qgraphicseffect.h @@ -205,53 +205,6 @@ private: Q_DISABLE_COPY(QGraphicsBlurEffect) }; -class QGraphicsBloomEffectPrivate; -class Q_GUI_EXPORT QGraphicsBloomEffect: public QGraphicsEffect { - Q_OBJECT -public: - QGraphicsBloomEffect(); - ~QGraphicsBloomEffect(); - - int blurRadius() const; - void setBlurRadius(int blurRadius); - - qreal opacity() const; - void setOpacity(qreal opacity); - -protected: - QRectF boundingRectFor(const QRectF &rect) const; - void draw(QPainter *painter, QGraphicsEffectSource *source); - -private: - Q_DECLARE_PRIVATE(QGraphicsBloomEffect) - Q_DISABLE_COPY(QGraphicsBloomEffect) -}; - -class QGraphicsFrameEffectPrivate; -class Q_GUI_EXPORT QGraphicsFrameEffect: public QGraphicsEffect { - Q_OBJECT -public: - QGraphicsFrameEffect(); - ~QGraphicsFrameEffect(); - - QColor frameColor() const; - void setFrameColor(const QColor &c); - - qreal frameWidth() const; - void setFrameWidth(qreal frameWidth); - - qreal frameOpacity() const; - void setFrameOpacity(qreal opacity); - -protected: - QRectF boundingRectFor(const QRectF &rect) const; - void draw(QPainter *painter, QGraphicsEffectSource *source); - -private: - Q_DECLARE_PRIVATE(QGraphicsFrameEffect) - Q_DISABLE_COPY(QGraphicsFrameEffect) -}; - class QGraphicsShadowEffectPrivate; class Q_GUI_EXPORT QGraphicsShadowEffect: public QGraphicsEffect { Q_OBJECT diff --git a/src/gui/effects/qgraphicseffect_p.h b/src/gui/effects/qgraphicseffect_p.h index 6d546cc..a92e7ae 100644 --- a/src/gui/effects/qgraphicseffect_p.h +++ b/src/gui/effects/qgraphicseffect_p.h @@ -156,27 +156,6 @@ public: int blurRadius; }; -class QGraphicsBloomEffectPrivate : public QGraphicsEffectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsBlurEffect) -public: - QGraphicsBloomEffectPrivate() : blurRadius(6), opacity(0.7) {} - - int blurRadius; - qreal opacity; -}; - -class QGraphicsFrameEffectPrivate : public QGraphicsEffectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsFrameEffect) -public: - QGraphicsFrameEffectPrivate() : color(Qt::blue), width(5), alpha(0.6) {} - - QColor color; - qreal width; - qreal alpha; -}; - class QGraphicsShadowEffectPrivate : public QGraphicsEffectPrivate { Q_DECLARE_PUBLIC(QGraphicsShadowEffect) -- cgit v0.12 From eb277fd3e9e1b1a3f2fdb0ae18f92f608c584816 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 19 Aug 2009 16:23:16 +0200 Subject: Add Q_PROPERTY to all qgraphics effects. --- src/gui/effects/qgraphicseffect.cpp | 27 ++++++++++++++++++++++++++- src/gui/effects/qgraphicseffect.h | 25 ++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index c1f8f06..ba13b25 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -271,6 +271,7 @@ bool QGraphicsEffect::isEnabled() const Q_D(const QGraphicsEffect); return d->isEnabled; } + void QGraphicsEffect::setEnabled(bool enable) { Q_D(QGraphicsEffect); @@ -278,9 +279,9 @@ void QGraphicsEffect::setEnabled(bool enable) return; d->isEnabled = enable; - if (d->source) d->source->update(); + emit enabledChanged(enable); } /*! @@ -367,7 +368,11 @@ QColor QGraphicsColorizeEffect::color() const void QGraphicsColorizeEffect::setColor(const QColor &c) { Q_D(QGraphicsColorizeEffect); + if (d->filter->color() == c) + return; + d->filter->setColor(c); + emit colorChanged(c); } void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *source) @@ -407,7 +412,11 @@ int QGraphicsPixelizeEffect::pixelSize() const void QGraphicsPixelizeEffect::setPixelSize(int size) { Q_D(QGraphicsPixelizeEffect); + if (d->pixelSize == size) + return; + d->pixelSize = size; + emit pixelSizeChanged(size); } static inline void pixelize(QImage *image, int pixelSize) @@ -544,8 +553,12 @@ int QGraphicsBlurEffect::blurRadius() const void QGraphicsBlurEffect::setBlurRadius(int radius) { Q_D(QGraphicsBlurEffect); + if (d->filter->radius() == radius) + return; + d->filter->setRadius(radius); updateBoundingRect(); + emit blurRadiusChanged(radius); } QRectF QGraphicsBlurEffect::boundingRectFor(const QRectF &rect) const @@ -596,8 +609,12 @@ QPointF QGraphicsShadowEffect::shadowOffset() const void QGraphicsShadowEffect::setShadowOffset(const QPointF &ofs) { Q_D(QGraphicsShadowEffect); + if (d->offset == ofs) + return; + d->offset = ofs; updateBoundingRect(); + emit shadowOffsetChanged(ofs); } int QGraphicsShadowEffect::blurRadius() const @@ -609,8 +626,12 @@ int QGraphicsShadowEffect::blurRadius() const void QGraphicsShadowEffect::setBlurRadius(int blurRadius) { Q_D(QGraphicsShadowEffect); + if (d->radius == blurRadius) + return; + d->radius = blurRadius; updateBoundingRect(); + emit blurRadiusChanged(blurRadius); } qreal QGraphicsShadowEffect::opacity() const @@ -622,7 +643,11 @@ qreal QGraphicsShadowEffect::opacity() const void QGraphicsShadowEffect::setOpacity(qreal opacity) { Q_D(QGraphicsShadowEffect); + if (qFuzzyCompare(d->alpha, opacity)) + return; + d->alpha = opacity; + emit opacityChanged(opacity); } QRectF QGraphicsShadowEffect::boundingRectFor(const QRectF &rect) const diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h index 19399d3..0692cda 100644 --- a/src/gui/effects/qgraphicseffect.h +++ b/src/gui/effects/qgraphicseffect.h @@ -95,7 +95,7 @@ class Q_GUI_EXPORT QGraphicsEffect : public QObject { Q_OBJECT Q_FLAGS(ChangeFlags) - Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged) public: enum ChangeFlag { SourceAttached = 0x1, @@ -116,6 +116,9 @@ public: bool isEnabled() const; +Q_SIGNALS: + void enabledChanged(bool enabled); + public Q_SLOTS: void setEnabled(bool enable); // ### add update() slot @@ -153,6 +156,7 @@ private: class QGraphicsColorizeEffectPrivate; class Q_GUI_EXPORT QGraphicsColorizeEffect: public QGraphicsEffect { Q_OBJECT + Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) public: QGraphicsColorizeEffect(); ~QGraphicsColorizeEffect(); @@ -160,6 +164,9 @@ public: QColor color() const; void setColor(const QColor &c); +Q_SIGNALS: + void colorChanged(const QColor &color); + protected: void draw(QPainter *painter, QGraphicsEffectSource *source); @@ -171,6 +178,7 @@ private: class QGraphicsPixelizeEffectPrivate; class Q_GUI_EXPORT QGraphicsPixelizeEffect: public QGraphicsEffect { Q_OBJECT + Q_PROPERTY(int pixelSize READ pixelSize WRITE setPixelSize NOTIFY pixelSizeChanged) public: QGraphicsPixelizeEffect(); ~QGraphicsPixelizeEffect(); @@ -178,6 +186,9 @@ public: int pixelSize() const; void setPixelSize(int pixelSize); +Q_SIGNALS: + void pixelSizeChanged(int pixelSize); + protected: void draw(QPainter *painter, QGraphicsEffectSource *source); @@ -189,6 +200,7 @@ private: class QGraphicsBlurEffectPrivate; class Q_GUI_EXPORT QGraphicsBlurEffect: public QGraphicsEffect { Q_OBJECT + Q_PROPERTY(int blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) public: QGraphicsBlurEffect(); ~QGraphicsBlurEffect(); @@ -196,6 +208,9 @@ public: int blurRadius() const; void setBlurRadius(int blurRadius); +Q_SIGNALS: + void blurRadiusChanged(int blurRadius); + protected: QRectF boundingRectFor(const QRectF &rect) const; void draw(QPainter *painter, QGraphicsEffectSource *source); @@ -208,6 +223,9 @@ private: class QGraphicsShadowEffectPrivate; class Q_GUI_EXPORT QGraphicsShadowEffect: public QGraphicsEffect { Q_OBJECT + Q_PROPERTY(QPointF shadowOffset READ shadowOffset WRITE setShadowOffset NOTIFY shadowOffsetChanged) + Q_PROPERTY(int blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) + Q_PROPERTY(int opacity READ opacity WRITE setOpacity NOTIFY opacityChanged) public: QGraphicsShadowEffect(); ~QGraphicsShadowEffect(); @@ -225,6 +243,11 @@ public: qreal opacity() const; void setOpacity(qreal opacity); +Q_SIGNALS: + void shadowOffsetChanged(const QPointF &offset); + void blurRadiusChanged(int blurRadius); + void opacityChanged(int opacity); + protected: QRectF boundingRectFor(const QRectF &rect) const; void draw(QPainter *painter, QGraphicsEffectSource *source); -- cgit v0.12 From 19ae511027367c890cda0df4dd1364a3219aafd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 19 Aug 2009 16:28:46 +0200 Subject: Make all graphics effect setters Q_SLOTS. --- src/gui/effects/qgraphicseffect.h | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h index 0692cda..74839cd 100644 --- a/src/gui/effects/qgraphicseffect.h +++ b/src/gui/effects/qgraphicseffect.h @@ -116,13 +116,13 @@ public: bool isEnabled() const; -Q_SIGNALS: - void enabledChanged(bool enabled); - public Q_SLOTS: void setEnabled(bool enable); // ### add update() slot +Q_SIGNALS: + void enabledChanged(bool enabled); + protected: QGraphicsEffect(QGraphicsEffectPrivate &d); virtual void draw(QPainter *painter, QGraphicsEffectSource *source) = 0; @@ -162,6 +162,8 @@ public: ~QGraphicsColorizeEffect(); QColor color() const; + +public Q_SLOTS: void setColor(const QColor &c); Q_SIGNALS: @@ -184,6 +186,8 @@ public: ~QGraphicsPixelizeEffect(); int pixelSize() const; + +public Q_SLOTS: void setPixelSize(int pixelSize); Q_SIGNALS: @@ -206,6 +210,8 @@ public: ~QGraphicsBlurEffect(); int blurRadius() const; + +public Q_SLOTS: void setBlurRadius(int blurRadius); Q_SIGNALS: @@ -231,16 +237,16 @@ public: ~QGraphicsShadowEffect(); QPointF shadowOffset() const; + int blurRadius() const; + qreal opacity() const; + +public Q_SLOTS: void setShadowOffset(const QPointF &ofs); inline void setShadowOffset(qreal dx, qreal dy) { setShadowOffset(QPointF(dx, dy)); } inline void setShadowOffset(qreal d) { setShadowOffset(QPointF(d, d)); } - - int blurRadius() const; void setBlurRadius(int blurRadius); - - qreal opacity() const; void setOpacity(qreal opacity); Q_SIGNALS: -- cgit v0.12 From ae1b9c676dc9c590008de58ce0ab51bff3ef0f9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 19 Aug 2009 16:44:50 +0200 Subject: Move examples/graphicsview/blurpicker|lighting to examples/effects. --- examples/effects/blurpicker/blureffect.cpp | 69 +++++++++++ examples/effects/blurpicker/blureffect.h | 67 +++++++++++ examples/effects/blurpicker/blurpicker.cpp | 132 +++++++++++++++++++++ examples/effects/blurpicker/blurpicker.h | 74 ++++++++++++ examples/effects/blurpicker/blurpicker.pro | 9 ++ examples/effects/blurpicker/blurpicker.qrc | 14 +++ examples/effects/blurpicker/images/README.txt | 5 + .../blurpicker/images/accessories-calculator.png | Bin 0 -> 3760 bytes .../blurpicker/images/accessories-text-editor.png | Bin 0 -> 4746 bytes examples/effects/blurpicker/images/background.jpg | Bin 0 -> 16259 bytes .../effects/blurpicker/images/help-browser.png | Bin 0 -> 5392 bytes .../blurpicker/images/internet-group-chat.png | Bin 0 -> 2809 bytes .../effects/blurpicker/images/internet-mail.png | Bin 0 -> 3899 bytes .../blurpicker/images/internet-web-browser.png | Bin 0 -> 6376 bytes .../effects/blurpicker/images/office-calendar.png | Bin 0 -> 4010 bytes .../effects/blurpicker/images/system-users.png | Bin 0 -> 5353 bytes examples/effects/blurpicker/main.cpp | 55 +++++++++ examples/effects/effects.pro | 12 ++ examples/effects/lighting/lighting.cpp | 119 +++++++++++++++++++ examples/effects/lighting/lighting.h | 70 +++++++++++ examples/effects/lighting/lighting.pro | 8 ++ examples/effects/lighting/main.cpp | 55 +++++++++ examples/effects/lighting/shadoweffect.cpp | 74 ++++++++++++ examples/effects/lighting/shadoweffect.h | 65 ++++++++++ examples/examples.pro | 1 + examples/graphicsview/blurpicker/blureffect.cpp | 69 ----------- examples/graphicsview/blurpicker/blureffect.h | 67 ----------- examples/graphicsview/blurpicker/blurpicker.cpp | 132 --------------------- examples/graphicsview/blurpicker/blurpicker.h | 74 ------------ examples/graphicsview/blurpicker/blurpicker.pro | 9 -- examples/graphicsview/blurpicker/blurpicker.qrc | 14 --- examples/graphicsview/blurpicker/images/README.txt | 5 - .../blurpicker/images/accessories-calculator.png | Bin 3760 -> 0 bytes .../blurpicker/images/accessories-text-editor.png | Bin 4746 -> 0 bytes .../graphicsview/blurpicker/images/background.jpg | Bin 16259 -> 0 bytes .../blurpicker/images/help-browser.png | Bin 5392 -> 0 bytes .../blurpicker/images/internet-group-chat.png | Bin 2809 -> 0 bytes .../blurpicker/images/internet-mail.png | Bin 3899 -> 0 bytes .../blurpicker/images/internet-web-browser.png | Bin 6376 -> 0 bytes .../blurpicker/images/office-calendar.png | Bin 4010 -> 0 bytes .../blurpicker/images/system-users.png | Bin 5353 -> 0 bytes examples/graphicsview/blurpicker/main.cpp | 55 --------- examples/graphicsview/graphicsview.pro | 2 - examples/graphicsview/lighting/lighting.cpp | 119 ------------------- examples/graphicsview/lighting/lighting.h | 70 ----------- examples/graphicsview/lighting/lighting.pro | 8 -- examples/graphicsview/lighting/main.cpp | 55 --------- examples/graphicsview/lighting/shadoweffect.cpp | 74 ------------ examples/graphicsview/lighting/shadoweffect.h | 65 ---------- 49 files changed, 829 insertions(+), 818 deletions(-) create mode 100644 examples/effects/blurpicker/blureffect.cpp create mode 100644 examples/effects/blurpicker/blureffect.h create mode 100644 examples/effects/blurpicker/blurpicker.cpp create mode 100644 examples/effects/blurpicker/blurpicker.h create mode 100644 examples/effects/blurpicker/blurpicker.pro create mode 100644 examples/effects/blurpicker/blurpicker.qrc create mode 100644 examples/effects/blurpicker/images/README.txt create mode 100644 examples/effects/blurpicker/images/accessories-calculator.png create mode 100644 examples/effects/blurpicker/images/accessories-text-editor.png create mode 100644 examples/effects/blurpicker/images/background.jpg create mode 100644 examples/effects/blurpicker/images/help-browser.png create mode 100644 examples/effects/blurpicker/images/internet-group-chat.png create mode 100644 examples/effects/blurpicker/images/internet-mail.png create mode 100644 examples/effects/blurpicker/images/internet-web-browser.png create mode 100644 examples/effects/blurpicker/images/office-calendar.png create mode 100644 examples/effects/blurpicker/images/system-users.png create mode 100644 examples/effects/blurpicker/main.cpp create mode 100644 examples/effects/effects.pro create mode 100644 examples/effects/lighting/lighting.cpp create mode 100644 examples/effects/lighting/lighting.h create mode 100644 examples/effects/lighting/lighting.pro create mode 100644 examples/effects/lighting/main.cpp create mode 100644 examples/effects/lighting/shadoweffect.cpp create mode 100644 examples/effects/lighting/shadoweffect.h delete mode 100644 examples/graphicsview/blurpicker/blureffect.cpp delete mode 100644 examples/graphicsview/blurpicker/blureffect.h delete mode 100644 examples/graphicsview/blurpicker/blurpicker.cpp delete mode 100644 examples/graphicsview/blurpicker/blurpicker.h delete mode 100644 examples/graphicsview/blurpicker/blurpicker.pro delete mode 100644 examples/graphicsview/blurpicker/blurpicker.qrc delete mode 100644 examples/graphicsview/blurpicker/images/README.txt delete mode 100644 examples/graphicsview/blurpicker/images/accessories-calculator.png delete mode 100644 examples/graphicsview/blurpicker/images/accessories-text-editor.png delete mode 100644 examples/graphicsview/blurpicker/images/background.jpg delete mode 100644 examples/graphicsview/blurpicker/images/help-browser.png delete mode 100644 examples/graphicsview/blurpicker/images/internet-group-chat.png delete mode 100644 examples/graphicsview/blurpicker/images/internet-mail.png delete mode 100644 examples/graphicsview/blurpicker/images/internet-web-browser.png delete mode 100644 examples/graphicsview/blurpicker/images/office-calendar.png delete mode 100644 examples/graphicsview/blurpicker/images/system-users.png delete mode 100644 examples/graphicsview/blurpicker/main.cpp delete mode 100644 examples/graphicsview/lighting/lighting.cpp delete mode 100644 examples/graphicsview/lighting/lighting.h delete mode 100644 examples/graphicsview/lighting/lighting.pro delete mode 100644 examples/graphicsview/lighting/main.cpp delete mode 100644 examples/graphicsview/lighting/shadoweffect.cpp delete mode 100644 examples/graphicsview/lighting/shadoweffect.h diff --git a/examples/effects/blurpicker/blureffect.cpp b/examples/effects/blurpicker/blureffect.cpp new file mode 100644 index 0000000..82be44f --- /dev/null +++ b/examples/effects/blurpicker/blureffect.cpp @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "blureffect.h" + +#include + +BlurEffect::BlurEffect(QGraphicsItem *item) + : QGraphicsBlurEffect() + , m_baseLine(200), item(item) +{ +} + +void BlurEffect::adjustForItem() +{ + qreal y = m_baseLine - item->pos().y(); + qreal radius = qBound(0.0, y / 32, 16.0); + setBlurRadius(radius); +} + +QRectF BlurEffect::boundingRect() const +{ + const_cast(this)->adjustForItem(); + return QGraphicsBlurEffect::boundingRect(); +} + +void BlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) +{ + adjustForItem(); + QGraphicsBlurEffect::draw(painter, source); +} diff --git a/examples/effects/blurpicker/blureffect.h b/examples/effects/blurpicker/blureffect.h new file mode 100644 index 0000000..89694b6 --- /dev/null +++ b/examples/effects/blurpicker/blureffect.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BLUREFFECT_H +#define BLUREFFECT_H + +#include +#include + +class BlurEffect: public QGraphicsBlurEffect +{ +public: + BlurEffect(QGraphicsItem *item); + + void setBaseLine(qreal y) { m_baseLine = y; } + + QRectF boundingRect() const; + + void draw(QPainter *painter, QGraphicsEffectSource *source); + +private: + void adjustForItem(); + +private: + qreal m_baseLine; + QGraphicsItem *item; +}; + +#endif // BLUREFFECT_H diff --git a/examples/effects/blurpicker/blurpicker.cpp b/examples/effects/blurpicker/blurpicker.cpp new file mode 100644 index 0000000..9904dfa --- /dev/null +++ b/examples/effects/blurpicker/blurpicker.cpp @@ -0,0 +1,132 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "blurpicker.h" + +#include + +#include "blureffect.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +BlurPicker::BlurPicker(QWidget *parent): QGraphicsView(parent), m_index(0.0) +{ + setBackgroundBrush(QPixmap(":/images/background.jpg")); + setScene(&m_scene); + + setupScene(); + updateIconPositions(); + + connect(&m_timeLine, SIGNAL(valueChanged(qreal)), SLOT(updateIconPositions())); + m_timeLine.setDuration(400); + + setRenderHint(QPainter::Antialiasing, true); + setFrameStyle(QFrame::NoFrame); +} + +void BlurPicker::updateIconPositions() +{ + m_index = m_timeLine.currentFrame() / 1000.0; + + qreal baseline = 0; + for (int i = 0; i < m_icons.count(); ++i) { + QGraphicsItem *icon = m_icons[i]; + qreal a = ((i + m_index) * 2 * M_PI) / m_icons.count(); + qreal xs = 170 * sin(a); + qreal ys = 100 * cos(a); + QPointF pos(xs, ys); + pos = QTransform().rotate(-20).map(pos); + pos -= QPointF(40, 40); + icon->setPos(pos); + baseline = qMax(baseline, ys); + static_cast(icon->graphicsEffect())->setBaseLine(baseline); + } + + m_scene.update(); +} + +void BlurPicker::setupScene() +{ + m_scene.setSceneRect(-200, -120, 400, 240); + + QStringList names; + names << ":/images/accessories-calculator.png"; + names << ":/images/accessories-text-editor.png"; + names << ":/images/help-browser.png"; + names << ":/images/internet-group-chat.png"; + names << ":/images/internet-mail.png"; + names << ":/images/internet-web-browser.png"; + names << ":/images/office-calendar.png"; + names << ":/images/system-users.png"; + + for (int i = 0; i < names.count(); i++) { + QPixmap pixmap(names[i]); + QGraphicsPixmapItem *icon = m_scene.addPixmap(pixmap); + icon->setZValue(1); + icon->setGraphicsEffect(new BlurEffect(icon)); + m_icons << icon; + } + + QGraphicsPixmapItem *bg = m_scene.addPixmap(QPixmap(":/images/background.jpg")); + bg->setZValue(0); + bg->setPos(-200, -150); +} + +void BlurPicker::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_Left) { + if (m_timeLine.state() == QTimeLine::NotRunning) { + m_timeLine.setFrameRange(m_index * 1000, m_index * 1000 - 1000); + m_timeLine.start(); + event->accept(); + } + } + + if (event->key() == Qt::Key_Right) { + if (m_timeLine.state() == QTimeLine::NotRunning) { + m_timeLine.setFrameRange(m_index * 1000, m_index * 1000 + 1000); + m_timeLine.start(); + event->accept(); + } + } +} diff --git a/examples/effects/blurpicker/blurpicker.h b/examples/effects/blurpicker/blurpicker.h new file mode 100644 index 0000000..b7ea3b4 --- /dev/null +++ b/examples/effects/blurpicker/blurpicker.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BLURPICKER_H +#define BLURPICKER_H + +#include +#include +#include + +#include "blureffect.h" + +class BlurPicker: public QGraphicsView +{ + Q_OBJECT + +public: + BlurPicker(QWidget *parent = 0); + +protected: + void keyPressEvent(QKeyEvent *event); + +private slots: + void updateIconPositions(); + +private: + void setupScene(); + +private: + qreal m_index; + QGraphicsScene m_scene; + QList m_icons; + QTimeLine m_timeLine; +}; + +#endif // BLURPICKER_H diff --git a/examples/effects/blurpicker/blurpicker.pro b/examples/effects/blurpicker/blurpicker.pro new file mode 100644 index 0000000..76537a9 --- /dev/null +++ b/examples/effects/blurpicker/blurpicker.pro @@ -0,0 +1,9 @@ +SOURCES += main.cpp blurpicker.cpp blureffect.cpp +HEADERS += blurpicker.h blureffect.h +RESOURCES += blurpicker.qrc + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/effects/blurpicker +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS blurpicker.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/effects/blurpicker +INSTALLS += target sources diff --git a/examples/effects/blurpicker/blurpicker.qrc b/examples/effects/blurpicker/blurpicker.qrc new file mode 100644 index 0000000..e88eaca --- /dev/null +++ b/examples/effects/blurpicker/blurpicker.qrc @@ -0,0 +1,14 @@ + + + images/background.jpg + images/accessories-calculator.png + images/accessories-text-editor.png + images/help-browser.png + images/internet-group-chat.png + images/internet-mail.png + images/internet-web-browser.png + images/office-calendar.png + images/system-users.png + + + diff --git a/examples/effects/blurpicker/images/README.txt b/examples/effects/blurpicker/images/README.txt new file mode 100644 index 0000000..0927e17 --- /dev/null +++ b/examples/effects/blurpicker/images/README.txt @@ -0,0 +1,5 @@ +The background is taken from a public domain photo at: +http://www.photos8.com/view/computer_board2-800x600.html + +All other icons are from the Tango Desktop project: +http://tango.freedesktop.org/Tango_Desktop_Project diff --git a/examples/effects/blurpicker/images/accessories-calculator.png b/examples/effects/blurpicker/images/accessories-calculator.png new file mode 100644 index 0000000..4e7661f Binary files /dev/null and b/examples/effects/blurpicker/images/accessories-calculator.png differ diff --git a/examples/effects/blurpicker/images/accessories-text-editor.png b/examples/effects/blurpicker/images/accessories-text-editor.png new file mode 100644 index 0000000..33bef0b Binary files /dev/null and b/examples/effects/blurpicker/images/accessories-text-editor.png differ diff --git a/examples/effects/blurpicker/images/background.jpg b/examples/effects/blurpicker/images/background.jpg new file mode 100644 index 0000000..e75b388 Binary files /dev/null and b/examples/effects/blurpicker/images/background.jpg differ diff --git a/examples/effects/blurpicker/images/help-browser.png b/examples/effects/blurpicker/images/help-browser.png new file mode 100644 index 0000000..8ef4fae Binary files /dev/null and b/examples/effects/blurpicker/images/help-browser.png differ diff --git a/examples/effects/blurpicker/images/internet-group-chat.png b/examples/effects/blurpicker/images/internet-group-chat.png new file mode 100644 index 0000000..dd92d93 Binary files /dev/null and b/examples/effects/blurpicker/images/internet-group-chat.png differ diff --git a/examples/effects/blurpicker/images/internet-mail.png b/examples/effects/blurpicker/images/internet-mail.png new file mode 100644 index 0000000..7e6b93b Binary files /dev/null and b/examples/effects/blurpicker/images/internet-mail.png differ diff --git a/examples/effects/blurpicker/images/internet-web-browser.png b/examples/effects/blurpicker/images/internet-web-browser.png new file mode 100644 index 0000000..a979a92 Binary files /dev/null and b/examples/effects/blurpicker/images/internet-web-browser.png differ diff --git a/examples/effects/blurpicker/images/office-calendar.png b/examples/effects/blurpicker/images/office-calendar.png new file mode 100644 index 0000000..e095906 Binary files /dev/null and b/examples/effects/blurpicker/images/office-calendar.png differ diff --git a/examples/effects/blurpicker/images/system-users.png b/examples/effects/blurpicker/images/system-users.png new file mode 100644 index 0000000..a7f630a Binary files /dev/null and b/examples/effects/blurpicker/images/system-users.png differ diff --git a/examples/effects/blurpicker/main.cpp b/examples/effects/blurpicker/main.cpp new file mode 100644 index 0000000..b88a51d --- /dev/null +++ b/examples/effects/blurpicker/main.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "blurpicker.h" +#include + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + BlurPicker blurPicker; + blurPicker.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Application Picker")); + blurPicker.setFixedSize(400, 300); + blurPicker.show(); + + return app.exec(); +} diff --git a/examples/effects/effects.pro b/examples/effects/effects.pro new file mode 100644 index 0000000..8ba0324 --- /dev/null +++ b/examples/effects/effects.pro @@ -0,0 +1,12 @@ +TEMPLATE = \ + subdirs +SUBDIRS = \ + blurpicker \ + lighting + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/effects +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS effects.pro README +sources.path = $$[QT_INSTALL_EXAMPLES]/effects +INSTALLS += target sources + diff --git a/examples/effects/lighting/lighting.cpp b/examples/effects/lighting/lighting.cpp new file mode 100644 index 0000000..63f0a6c --- /dev/null +++ b/examples/effects/lighting/lighting.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "lighting.h" + +#include + +#include "shadoweffect.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +Lighting::Lighting(QWidget *parent): QGraphicsView(parent), angle(0.0) +{ + setScene(&m_scene); + + setupScene(); + + QTimer *timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), SLOT(animate())); + timer->setInterval(30); + timer->start(); + + setRenderHint(QPainter::Antialiasing, true); + setFrameStyle(QFrame::NoFrame); +} + +void Lighting::setupScene() +{ + m_scene.setSceneRect(-300, -200, 600, 460); + + QLinearGradient linearGrad(QPointF(-100, -100), QPointF(100, 100)); + linearGrad.setColorAt(0, QColor(255, 255, 255)); + linearGrad.setColorAt(1, QColor(192, 192, 255)); + setBackgroundBrush(linearGrad); + + QRadialGradient radialGrad(30, 30, 30); + radialGrad.setColorAt(0, Qt::yellow); + radialGrad.setColorAt(0.2, Qt::yellow); + radialGrad.setColorAt(1, Qt::transparent); + QPixmap pixmap(60, 60); + pixmap.fill(Qt::transparent); + QPainter painter(&pixmap); + painter.setPen(Qt::NoPen); + painter.setBrush(radialGrad); + painter.drawEllipse(0, 0, 60, 60); + painter.end(); + + m_lightSource = m_scene.addPixmap(pixmap); + m_lightSource->setZValue(2); + + for (int i = -2; i < 3; ++i) + for (int j = -2; j < 3; ++j) { + QAbstractGraphicsShapeItem *item; + if ((i + j) & 1) + item = new QGraphicsEllipseItem(0, 0, 50, 50); + else + item = new QGraphicsRectItem(0, 0, 50, 50); + + item->setPen(QPen(Qt::black)); + item->setBrush(QBrush(Qt::white)); + item->setGraphicsEffect(new ShadowEffect(item, m_lightSource)); + item->setZValue(1); + item->setPos(i * 80, j * 80); + m_scene.addItem(item); + m_items << item; + } + + +} + +void Lighting::animate() +{ + angle += (M_PI / 30); + qreal xs = 200 * sin(angle) - 40 + 25; + qreal ys = 200 * cos(angle) - 40 + 25; + m_lightSource->setPos(xs, ys); + m_scene.update(); +} + diff --git a/examples/effects/lighting/lighting.h b/examples/effects/lighting/lighting.h new file mode 100644 index 0000000..70a4d48 --- /dev/null +++ b/examples/effects/lighting/lighting.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LIGHTING_H +#define LIGHTING_H + +#include +#include + +#include "shadoweffect.h" + +class Lighting: public QGraphicsView +{ + Q_OBJECT + +public: + Lighting(QWidget *parent = 0); + +private slots: + void animate(); + +private: + void setupScene(); + +private: + qreal angle; + QGraphicsScene m_scene; + QGraphicsItem *m_lightSource; + QList m_items; +}; + +#endif // LIGHTING_H diff --git a/examples/effects/lighting/lighting.pro b/examples/effects/lighting/lighting.pro new file mode 100644 index 0000000..ea9d5f6 --- /dev/null +++ b/examples/effects/lighting/lighting.pro @@ -0,0 +1,8 @@ +SOURCES += main.cpp lighting.cpp shadoweffect.cpp +HEADERS += lighting.h shadoweffect.h + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/effects/lighting +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS lighting.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/effects/lighting +INSTALLS += target sources diff --git a/examples/effects/lighting/main.cpp b/examples/effects/lighting/main.cpp new file mode 100644 index 0000000..07415f6 --- /dev/null +++ b/examples/effects/lighting/main.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "lighting.h" +#include + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + Lighting lighting; + lighting.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Lighting and Shadows")); + lighting.resize(640, 480); + lighting.show(); + + return app.exec(); +} diff --git a/examples/effects/lighting/shadoweffect.cpp b/examples/effects/lighting/shadoweffect.cpp new file mode 100644 index 0000000..f447531 --- /dev/null +++ b/examples/effects/lighting/shadoweffect.cpp @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "shadoweffect.h" + +#include + +ShadowEffect::ShadowEffect(QGraphicsItem *item, QGraphicsItem *source) + : QGraphicsShadowEffect() + , item(item), m_lightSource(source) +{ + setBlurRadius(8); +} + +void ShadowEffect::adjustForItem() +{ + QPointF delta = item->pos() - m_lightSource->pos(); + setShadowOffset(delta.toPoint() / 30); + + qreal dx = delta.x(); + qreal dy = delta.y(); + qreal dd = sqrt(dx * dx + dy * dy); + setOpacity(qBound(0.4, 1 - dd / 200.0, 0.7)); +} + +QRectF ShadowEffect::boundingRectFor(const QRectF &rect) const +{ + const_cast(this)->adjustForItem(); + return QGraphicsShadowEffect::boundingRectFor(rect); +} + +void ShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *source) +{ + adjustForItem(); + QGraphicsShadowEffect::draw(painter, source); +} diff --git a/examples/effects/lighting/shadoweffect.h b/examples/effects/lighting/shadoweffect.h new file mode 100644 index 0000000..68318b0 --- /dev/null +++ b/examples/effects/lighting/shadoweffect.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SHADOWEFFECT_H +#define SHADOWEFFECT_H + +#include +#include + +class ShadowEffect: public QGraphicsShadowEffect +{ +public: + ShadowEffect(QGraphicsItem *item, QGraphicsItem *source); + + QRectF boundingRectFor(const QRectF &rect) const; + + void draw(QPainter *painter, QGraphicsEffectSource *source); + +private: + void adjustForItem(); + +private: + QGraphicsItem *item; + QGraphicsItem *m_lightSource; +}; + +#endif // SHADOWEFFECT_H diff --git a/examples/examples.pro b/examples/examples.pro index e6cece9..197e80f 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -4,6 +4,7 @@ SUBDIRS = \ desktop \ dialogs \ draganddrop \ + effects \ graphicsview \ ipc \ itemviews \ diff --git a/examples/graphicsview/blurpicker/blureffect.cpp b/examples/graphicsview/blurpicker/blureffect.cpp deleted file mode 100644 index 82be44f..0000000 --- a/examples/graphicsview/blurpicker/blureffect.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "blureffect.h" - -#include - -BlurEffect::BlurEffect(QGraphicsItem *item) - : QGraphicsBlurEffect() - , m_baseLine(200), item(item) -{ -} - -void BlurEffect::adjustForItem() -{ - qreal y = m_baseLine - item->pos().y(); - qreal radius = qBound(0.0, y / 32, 16.0); - setBlurRadius(radius); -} - -QRectF BlurEffect::boundingRect() const -{ - const_cast(this)->adjustForItem(); - return QGraphicsBlurEffect::boundingRect(); -} - -void BlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) -{ - adjustForItem(); - QGraphicsBlurEffect::draw(painter, source); -} diff --git a/examples/graphicsview/blurpicker/blureffect.h b/examples/graphicsview/blurpicker/blureffect.h deleted file mode 100644 index 89694b6..0000000 --- a/examples/graphicsview/blurpicker/blureffect.h +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef BLUREFFECT_H -#define BLUREFFECT_H - -#include -#include - -class BlurEffect: public QGraphicsBlurEffect -{ -public: - BlurEffect(QGraphicsItem *item); - - void setBaseLine(qreal y) { m_baseLine = y; } - - QRectF boundingRect() const; - - void draw(QPainter *painter, QGraphicsEffectSource *source); - -private: - void adjustForItem(); - -private: - qreal m_baseLine; - QGraphicsItem *item; -}; - -#endif // BLUREFFECT_H diff --git a/examples/graphicsview/blurpicker/blurpicker.cpp b/examples/graphicsview/blurpicker/blurpicker.cpp deleted file mode 100644 index 9904dfa..0000000 --- a/examples/graphicsview/blurpicker/blurpicker.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "blurpicker.h" - -#include - -#include "blureffect.h" - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -BlurPicker::BlurPicker(QWidget *parent): QGraphicsView(parent), m_index(0.0) -{ - setBackgroundBrush(QPixmap(":/images/background.jpg")); - setScene(&m_scene); - - setupScene(); - updateIconPositions(); - - connect(&m_timeLine, SIGNAL(valueChanged(qreal)), SLOT(updateIconPositions())); - m_timeLine.setDuration(400); - - setRenderHint(QPainter::Antialiasing, true); - setFrameStyle(QFrame::NoFrame); -} - -void BlurPicker::updateIconPositions() -{ - m_index = m_timeLine.currentFrame() / 1000.0; - - qreal baseline = 0; - for (int i = 0; i < m_icons.count(); ++i) { - QGraphicsItem *icon = m_icons[i]; - qreal a = ((i + m_index) * 2 * M_PI) / m_icons.count(); - qreal xs = 170 * sin(a); - qreal ys = 100 * cos(a); - QPointF pos(xs, ys); - pos = QTransform().rotate(-20).map(pos); - pos -= QPointF(40, 40); - icon->setPos(pos); - baseline = qMax(baseline, ys); - static_cast(icon->graphicsEffect())->setBaseLine(baseline); - } - - m_scene.update(); -} - -void BlurPicker::setupScene() -{ - m_scene.setSceneRect(-200, -120, 400, 240); - - QStringList names; - names << ":/images/accessories-calculator.png"; - names << ":/images/accessories-text-editor.png"; - names << ":/images/help-browser.png"; - names << ":/images/internet-group-chat.png"; - names << ":/images/internet-mail.png"; - names << ":/images/internet-web-browser.png"; - names << ":/images/office-calendar.png"; - names << ":/images/system-users.png"; - - for (int i = 0; i < names.count(); i++) { - QPixmap pixmap(names[i]); - QGraphicsPixmapItem *icon = m_scene.addPixmap(pixmap); - icon->setZValue(1); - icon->setGraphicsEffect(new BlurEffect(icon)); - m_icons << icon; - } - - QGraphicsPixmapItem *bg = m_scene.addPixmap(QPixmap(":/images/background.jpg")); - bg->setZValue(0); - bg->setPos(-200, -150); -} - -void BlurPicker::keyPressEvent(QKeyEvent *event) -{ - if (event->key() == Qt::Key_Left) { - if (m_timeLine.state() == QTimeLine::NotRunning) { - m_timeLine.setFrameRange(m_index * 1000, m_index * 1000 - 1000); - m_timeLine.start(); - event->accept(); - } - } - - if (event->key() == Qt::Key_Right) { - if (m_timeLine.state() == QTimeLine::NotRunning) { - m_timeLine.setFrameRange(m_index * 1000, m_index * 1000 + 1000); - m_timeLine.start(); - event->accept(); - } - } -} diff --git a/examples/graphicsview/blurpicker/blurpicker.h b/examples/graphicsview/blurpicker/blurpicker.h deleted file mode 100644 index b7ea3b4..0000000 --- a/examples/graphicsview/blurpicker/blurpicker.h +++ /dev/null @@ -1,74 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef BLURPICKER_H -#define BLURPICKER_H - -#include -#include -#include - -#include "blureffect.h" - -class BlurPicker: public QGraphicsView -{ - Q_OBJECT - -public: - BlurPicker(QWidget *parent = 0); - -protected: - void keyPressEvent(QKeyEvent *event); - -private slots: - void updateIconPositions(); - -private: - void setupScene(); - -private: - qreal m_index; - QGraphicsScene m_scene; - QList m_icons; - QTimeLine m_timeLine; -}; - -#endif // BLURPICKER_H diff --git a/examples/graphicsview/blurpicker/blurpicker.pro b/examples/graphicsview/blurpicker/blurpicker.pro deleted file mode 100644 index e42cc0f..0000000 --- a/examples/graphicsview/blurpicker/blurpicker.pro +++ /dev/null @@ -1,9 +0,0 @@ -SOURCES += main.cpp blurpicker.cpp blureffect.cpp -HEADERS += blurpicker.h blureffect.h -RESOURCES += blurpicker.qrc - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/graphicsview/blurpicker -sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS blurpicker.pro -sources.path = $$[QT_INSTALL_EXAMPLES]/graphicsview/blurpicker -INSTALLS += target sources diff --git a/examples/graphicsview/blurpicker/blurpicker.qrc b/examples/graphicsview/blurpicker/blurpicker.qrc deleted file mode 100644 index e88eaca..0000000 --- a/examples/graphicsview/blurpicker/blurpicker.qrc +++ /dev/null @@ -1,14 +0,0 @@ - - - images/background.jpg - images/accessories-calculator.png - images/accessories-text-editor.png - images/help-browser.png - images/internet-group-chat.png - images/internet-mail.png - images/internet-web-browser.png - images/office-calendar.png - images/system-users.png - - - diff --git a/examples/graphicsview/blurpicker/images/README.txt b/examples/graphicsview/blurpicker/images/README.txt deleted file mode 100644 index 0927e17..0000000 --- a/examples/graphicsview/blurpicker/images/README.txt +++ /dev/null @@ -1,5 +0,0 @@ -The background is taken from a public domain photo at: -http://www.photos8.com/view/computer_board2-800x600.html - -All other icons are from the Tango Desktop project: -http://tango.freedesktop.org/Tango_Desktop_Project diff --git a/examples/graphicsview/blurpicker/images/accessories-calculator.png b/examples/graphicsview/blurpicker/images/accessories-calculator.png deleted file mode 100644 index 4e7661f..0000000 Binary files a/examples/graphicsview/blurpicker/images/accessories-calculator.png and /dev/null differ diff --git a/examples/graphicsview/blurpicker/images/accessories-text-editor.png b/examples/graphicsview/blurpicker/images/accessories-text-editor.png deleted file mode 100644 index 33bef0b..0000000 Binary files a/examples/graphicsview/blurpicker/images/accessories-text-editor.png and /dev/null differ diff --git a/examples/graphicsview/blurpicker/images/background.jpg b/examples/graphicsview/blurpicker/images/background.jpg deleted file mode 100644 index e75b388..0000000 Binary files a/examples/graphicsview/blurpicker/images/background.jpg and /dev/null differ diff --git a/examples/graphicsview/blurpicker/images/help-browser.png b/examples/graphicsview/blurpicker/images/help-browser.png deleted file mode 100644 index 8ef4fae..0000000 Binary files a/examples/graphicsview/blurpicker/images/help-browser.png and /dev/null differ diff --git a/examples/graphicsview/blurpicker/images/internet-group-chat.png b/examples/graphicsview/blurpicker/images/internet-group-chat.png deleted file mode 100644 index dd92d93..0000000 Binary files a/examples/graphicsview/blurpicker/images/internet-group-chat.png and /dev/null differ diff --git a/examples/graphicsview/blurpicker/images/internet-mail.png b/examples/graphicsview/blurpicker/images/internet-mail.png deleted file mode 100644 index 7e6b93b..0000000 Binary files a/examples/graphicsview/blurpicker/images/internet-mail.png and /dev/null differ diff --git a/examples/graphicsview/blurpicker/images/internet-web-browser.png b/examples/graphicsview/blurpicker/images/internet-web-browser.png deleted file mode 100644 index a979a92..0000000 Binary files a/examples/graphicsview/blurpicker/images/internet-web-browser.png and /dev/null differ diff --git a/examples/graphicsview/blurpicker/images/office-calendar.png b/examples/graphicsview/blurpicker/images/office-calendar.png deleted file mode 100644 index e095906..0000000 Binary files a/examples/graphicsview/blurpicker/images/office-calendar.png and /dev/null differ diff --git a/examples/graphicsview/blurpicker/images/system-users.png b/examples/graphicsview/blurpicker/images/system-users.png deleted file mode 100644 index a7f630a..0000000 Binary files a/examples/graphicsview/blurpicker/images/system-users.png and /dev/null differ diff --git a/examples/graphicsview/blurpicker/main.cpp b/examples/graphicsview/blurpicker/main.cpp deleted file mode 100644 index b88a51d..0000000 --- a/examples/graphicsview/blurpicker/main.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "blurpicker.h" -#include - -int main(int argc, char **argv) -{ - QApplication app(argc, argv); - - BlurPicker blurPicker; - blurPicker.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Application Picker")); - blurPicker.setFixedSize(400, 300); - blurPicker.show(); - - return app.exec(); -} diff --git a/examples/graphicsview/graphicsview.pro b/examples/graphicsview/graphicsview.pro index 4dd0b13..7c8e787 100644 --- a/examples/graphicsview/graphicsview.pro +++ b/examples/graphicsview/graphicsview.pro @@ -6,8 +6,6 @@ SUBDIRS = \ diagramscene \ dragdroprobot \ padnavigator \ - lighting \ - blurpicker \ basicgraphicslayouts contains(QT_CONFIG, qt3support):SUBDIRS += portedcanvas portedasteroids diff --git a/examples/graphicsview/lighting/lighting.cpp b/examples/graphicsview/lighting/lighting.cpp deleted file mode 100644 index 63f0a6c..0000000 --- a/examples/graphicsview/lighting/lighting.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "lighting.h" - -#include - -#include "shadoweffect.h" - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -Lighting::Lighting(QWidget *parent): QGraphicsView(parent), angle(0.0) -{ - setScene(&m_scene); - - setupScene(); - - QTimer *timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), SLOT(animate())); - timer->setInterval(30); - timer->start(); - - setRenderHint(QPainter::Antialiasing, true); - setFrameStyle(QFrame::NoFrame); -} - -void Lighting::setupScene() -{ - m_scene.setSceneRect(-300, -200, 600, 460); - - QLinearGradient linearGrad(QPointF(-100, -100), QPointF(100, 100)); - linearGrad.setColorAt(0, QColor(255, 255, 255)); - linearGrad.setColorAt(1, QColor(192, 192, 255)); - setBackgroundBrush(linearGrad); - - QRadialGradient radialGrad(30, 30, 30); - radialGrad.setColorAt(0, Qt::yellow); - radialGrad.setColorAt(0.2, Qt::yellow); - radialGrad.setColorAt(1, Qt::transparent); - QPixmap pixmap(60, 60); - pixmap.fill(Qt::transparent); - QPainter painter(&pixmap); - painter.setPen(Qt::NoPen); - painter.setBrush(radialGrad); - painter.drawEllipse(0, 0, 60, 60); - painter.end(); - - m_lightSource = m_scene.addPixmap(pixmap); - m_lightSource->setZValue(2); - - for (int i = -2; i < 3; ++i) - for (int j = -2; j < 3; ++j) { - QAbstractGraphicsShapeItem *item; - if ((i + j) & 1) - item = new QGraphicsEllipseItem(0, 0, 50, 50); - else - item = new QGraphicsRectItem(0, 0, 50, 50); - - item->setPen(QPen(Qt::black)); - item->setBrush(QBrush(Qt::white)); - item->setGraphicsEffect(new ShadowEffect(item, m_lightSource)); - item->setZValue(1); - item->setPos(i * 80, j * 80); - m_scene.addItem(item); - m_items << item; - } - - -} - -void Lighting::animate() -{ - angle += (M_PI / 30); - qreal xs = 200 * sin(angle) - 40 + 25; - qreal ys = 200 * cos(angle) - 40 + 25; - m_lightSource->setPos(xs, ys); - m_scene.update(); -} - diff --git a/examples/graphicsview/lighting/lighting.h b/examples/graphicsview/lighting/lighting.h deleted file mode 100644 index 70a4d48..0000000 --- a/examples/graphicsview/lighting/lighting.h +++ /dev/null @@ -1,70 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef LIGHTING_H -#define LIGHTING_H - -#include -#include - -#include "shadoweffect.h" - -class Lighting: public QGraphicsView -{ - Q_OBJECT - -public: - Lighting(QWidget *parent = 0); - -private slots: - void animate(); - -private: - void setupScene(); - -private: - qreal angle; - QGraphicsScene m_scene; - QGraphicsItem *m_lightSource; - QList m_items; -}; - -#endif // LIGHTING_H diff --git a/examples/graphicsview/lighting/lighting.pro b/examples/graphicsview/lighting/lighting.pro deleted file mode 100644 index 440bb53..0000000 --- a/examples/graphicsview/lighting/lighting.pro +++ /dev/null @@ -1,8 +0,0 @@ -SOURCES += main.cpp lighting.cpp shadoweffect.cpp -HEADERS += lighting.h shadoweffect.h - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/graphicsview/lighting -sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS lighting.pro -sources.path = $$[QT_INSTALL_EXAMPLES]/graphicsview/lighting -INSTALLS += target sources diff --git a/examples/graphicsview/lighting/main.cpp b/examples/graphicsview/lighting/main.cpp deleted file mode 100644 index 07415f6..0000000 --- a/examples/graphicsview/lighting/main.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "lighting.h" -#include - -int main(int argc, char **argv) -{ - QApplication app(argc, argv); - - Lighting lighting; - lighting.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Lighting and Shadows")); - lighting.resize(640, 480); - lighting.show(); - - return app.exec(); -} diff --git a/examples/graphicsview/lighting/shadoweffect.cpp b/examples/graphicsview/lighting/shadoweffect.cpp deleted file mode 100644 index f447531..0000000 --- a/examples/graphicsview/lighting/shadoweffect.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "shadoweffect.h" - -#include - -ShadowEffect::ShadowEffect(QGraphicsItem *item, QGraphicsItem *source) - : QGraphicsShadowEffect() - , item(item), m_lightSource(source) -{ - setBlurRadius(8); -} - -void ShadowEffect::adjustForItem() -{ - QPointF delta = item->pos() - m_lightSource->pos(); - setShadowOffset(delta.toPoint() / 30); - - qreal dx = delta.x(); - qreal dy = delta.y(); - qreal dd = sqrt(dx * dx + dy * dy); - setOpacity(qBound(0.4, 1 - dd / 200.0, 0.7)); -} - -QRectF ShadowEffect::boundingRectFor(const QRectF &rect) const -{ - const_cast(this)->adjustForItem(); - return QGraphicsShadowEffect::boundingRectFor(rect); -} - -void ShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *source) -{ - adjustForItem(); - QGraphicsShadowEffect::draw(painter, source); -} diff --git a/examples/graphicsview/lighting/shadoweffect.h b/examples/graphicsview/lighting/shadoweffect.h deleted file mode 100644 index 68318b0..0000000 --- a/examples/graphicsview/lighting/shadoweffect.h +++ /dev/null @@ -1,65 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SHADOWEFFECT_H -#define SHADOWEFFECT_H - -#include -#include - -class ShadowEffect: public QGraphicsShadowEffect -{ -public: - ShadowEffect(QGraphicsItem *item, QGraphicsItem *source); - - QRectF boundingRectFor(const QRectF &rect) const; - - void draw(QPainter *painter, QGraphicsEffectSource *source); - -private: - void adjustForItem(); - -private: - QGraphicsItem *item; - QGraphicsItem *m_lightSource; -}; - -#endif // SHADOWEFFECT_H -- cgit v0.12 From 457b34bbac3b9e7f9154ac2d729c9f7e8cdee8b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 19 Aug 2009 17:00:17 +0200 Subject: Cleanup after 19e01c93f9421a8db6c8a93ac103a7df2b93d9ec QGraphicsEffect is no longer dependent on the Graphics View module. --- src/gui/effects/qgraphicseffect.cpp | 3 --- src/gui/effects/qgraphicseffect.h | 18 +++++++++--------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index ba13b25..1d604b5 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -94,8 +94,6 @@ #include "qgraphicseffect_p.h" -#ifndef QT_NO_GRAPHICSVIEW - #include #include #include @@ -718,4 +716,3 @@ void QGraphicsShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *sourc painter->setWorldTransform(restoreTransform); } -#endif diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h index 74839cd..8890a48 100644 --- a/src/gui/effects/qgraphicseffect.h +++ b/src/gui/effects/qgraphicseffect.h @@ -51,8 +51,6 @@ QT_BEGIN_NAMESPACE QT_MODULE(Gui) -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - class QGraphicsItem; class QStyleOption; class QColor; @@ -154,7 +152,8 @@ private: }; class QGraphicsColorizeEffectPrivate; -class Q_GUI_EXPORT QGraphicsColorizeEffect: public QGraphicsEffect { +class Q_GUI_EXPORT QGraphicsColorizeEffect: public QGraphicsEffect +{ Q_OBJECT Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) public: @@ -178,7 +177,8 @@ private: }; class QGraphicsPixelizeEffectPrivate; -class Q_GUI_EXPORT QGraphicsPixelizeEffect: public QGraphicsEffect { +class Q_GUI_EXPORT QGraphicsPixelizeEffect: public QGraphicsEffect +{ Q_OBJECT Q_PROPERTY(int pixelSize READ pixelSize WRITE setPixelSize NOTIFY pixelSizeChanged) public: @@ -202,7 +202,8 @@ private: }; class QGraphicsBlurEffectPrivate; -class Q_GUI_EXPORT QGraphicsBlurEffect: public QGraphicsEffect { +class Q_GUI_EXPORT QGraphicsBlurEffect: public QGraphicsEffect +{ Q_OBJECT Q_PROPERTY(int blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) public: @@ -227,7 +228,8 @@ private: }; class QGraphicsShadowEffectPrivate; -class Q_GUI_EXPORT QGraphicsShadowEffect: public QGraphicsEffect { +class Q_GUI_EXPORT QGraphicsShadowEffect: public QGraphicsEffect +{ Q_OBJECT Q_PROPERTY(QPointF shadowOffset READ shadowOffset WRITE setShadowOffset NOTIFY shadowOffsetChanged) Q_PROPERTY(int blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) @@ -263,11 +265,9 @@ private: Q_DISABLE_COPY(QGraphicsShadowEffect) }; -#endif // QT_NO_GRAPHICSVIEW - QT_END_NAMESPACE QT_END_HEADER - #endif // QGRAPHICSEFFECT_H + -- cgit v0.12 From 39f5298ef2c0424e7b4916d8d1de1d46e534daee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 20 Aug 2009 11:55:23 +0200 Subject: Add "QObject *parent = 0" to all graphics effect constructors. --- src/gui/effects/qgraphicseffect.cpp | 28 ++++++++++++++-------------- src/gui/effects/qgraphicseffect.h | 14 +++++++------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index 1d604b5..a1845a6 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -202,8 +202,8 @@ QPixmap QGraphicsEffectSource::pixmap(Qt::CoordinateSystem system, QPoint *offse /*! Constructs a new QGraphicsEffect instance. */ -QGraphicsEffect::QGraphicsEffect() - : QObject(*new QGraphicsEffectPrivate, 0) +QGraphicsEffect::QGraphicsEffect(QObject *parent) + : QObject(*new QGraphicsEffectPrivate, parent) { // ### parent? } @@ -211,8 +211,8 @@ QGraphicsEffect::QGraphicsEffect() /*! \internal */ -QGraphicsEffect::QGraphicsEffect(QGraphicsEffectPrivate &dd) - : QObject(dd, 0) +QGraphicsEffect::QGraphicsEffect(QGraphicsEffectPrivate &dd, QObject *parent) + : QObject(dd, parent) { } @@ -321,8 +321,8 @@ void QGraphicsEffect::sourceChanged(ChangeFlags flags) Q_UNUSED(flags); } -QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect() - : QGraphicsEffect(*new QGraphicsGrayscaleEffectPrivate) +QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect(QObject *parent) + : QGraphicsEffect(*new QGraphicsGrayscaleEffectPrivate, parent) { } @@ -350,8 +350,8 @@ void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *so } -QGraphicsColorizeEffect::QGraphicsColorizeEffect() - : QGraphicsEffect(*new QGraphicsColorizeEffectPrivate) +QGraphicsColorizeEffect::QGraphicsColorizeEffect(QObject *parent) + : QGraphicsEffect(*new QGraphicsColorizeEffectPrivate, parent) {} QGraphicsColorizeEffect::~QGraphicsColorizeEffect() @@ -392,8 +392,8 @@ void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou painter->setWorldTransform(restoreTransform); } -QGraphicsPixelizeEffect::QGraphicsPixelizeEffect() - : QGraphicsEffect(*new QGraphicsPixelizeEffectPrivate) +QGraphicsPixelizeEffect::QGraphicsPixelizeEffect(QObject *parent) + : QGraphicsEffect(*new QGraphicsPixelizeEffectPrivate, parent) { } @@ -468,8 +468,8 @@ void QGraphicsPixelizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou painter->setWorldTransform(restoreTransform); } -QGraphicsBlurEffect::QGraphicsBlurEffect() - : QGraphicsEffect(*new QGraphicsBlurEffectPrivate) +QGraphicsBlurEffect::QGraphicsBlurEffect(QObject *parent) + : QGraphicsEffect(*new QGraphicsBlurEffectPrivate, parent) { } @@ -589,8 +589,8 @@ void QGraphicsBlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) painter->setWorldTransform(restoreTransform); } -QGraphicsShadowEffect::QGraphicsShadowEffect() - : QGraphicsEffect(*new QGraphicsShadowEffectPrivate) +QGraphicsShadowEffect::QGraphicsShadowEffect(QObject *parent) + : QGraphicsEffect(*new QGraphicsShadowEffectPrivate, parent) { } diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h index 8890a48..d5ec19e 100644 --- a/src/gui/effects/qgraphicseffect.h +++ b/src/gui/effects/qgraphicseffect.h @@ -103,7 +103,7 @@ public: }; Q_DECLARE_FLAGS(ChangeFlags, ChangeFlag); - QGraphicsEffect(); + QGraphicsEffect(QObject *parent = 0); virtual ~QGraphicsEffect(); // ### make protected? @@ -122,7 +122,7 @@ Q_SIGNALS: void enabledChanged(bool enabled); protected: - QGraphicsEffect(QGraphicsEffectPrivate &d); + QGraphicsEffect(QGraphicsEffectPrivate &d, QObject *parent = 0); virtual void draw(QPainter *painter, QGraphicsEffectSource *source) = 0; virtual void sourceChanged(ChangeFlags flags); void updateBoundingRect(); @@ -140,7 +140,7 @@ class Q_GUI_EXPORT QGraphicsGrayscaleEffect: public QGraphicsEffect { Q_OBJECT public: - QGraphicsGrayscaleEffect(); + QGraphicsGrayscaleEffect(QObject *parent = 0); ~QGraphicsGrayscaleEffect(); protected: @@ -157,7 +157,7 @@ class Q_GUI_EXPORT QGraphicsColorizeEffect: public QGraphicsEffect Q_OBJECT Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) public: - QGraphicsColorizeEffect(); + QGraphicsColorizeEffect(QObject *parent = 0); ~QGraphicsColorizeEffect(); QColor color() const; @@ -182,7 +182,7 @@ class Q_GUI_EXPORT QGraphicsPixelizeEffect: public QGraphicsEffect Q_OBJECT Q_PROPERTY(int pixelSize READ pixelSize WRITE setPixelSize NOTIFY pixelSizeChanged) public: - QGraphicsPixelizeEffect(); + QGraphicsPixelizeEffect(QObject *parent = 0); ~QGraphicsPixelizeEffect(); int pixelSize() const; @@ -207,7 +207,7 @@ class Q_GUI_EXPORT QGraphicsBlurEffect: public QGraphicsEffect Q_OBJECT Q_PROPERTY(int blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) public: - QGraphicsBlurEffect(); + QGraphicsBlurEffect(QObject *parent = 0); ~QGraphicsBlurEffect(); int blurRadius() const; @@ -235,7 +235,7 @@ class Q_GUI_EXPORT QGraphicsShadowEffect: public QGraphicsEffect Q_PROPERTY(int blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) Q_PROPERTY(int opacity READ opacity WRITE setOpacity NOTIFY opacityChanged) public: - QGraphicsShadowEffect(); + QGraphicsShadowEffect(QObject *parent = 0); ~QGraphicsShadowEffect(); QPointF shadowOffset() const; -- cgit v0.12 From c84219af1301d4422e7877315b1c20fc41d5464f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 20 Aug 2009 12:01:04 +0200 Subject: Add QT_BEGIN_NAMESPACE and QT_END_NAMESPACE --- src/gui/effects/qgraphicseffect.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index a1845a6..73668ec 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -98,6 +98,8 @@ #include #include +QT_BEGIN_NAMESPACE + /* List of known drawbacks which are being discussed: @@ -716,3 +718,5 @@ void QGraphicsShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *sourc painter->setWorldTransform(restoreTransform); } +QT_END_NAMESPACE + -- cgit v0.12 From e25fd5980236044a05acbf9c4440f2221de44f75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 20 Aug 2009 12:06:30 +0200 Subject: Compile graphics effect. We have to include QColor and QRect rather than forward declare them. --- src/gui/effects/qgraphicseffect.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h index d5ec19e..fe31ae8 100644 --- a/src/gui/effects/qgraphicseffect.h +++ b/src/gui/effects/qgraphicseffect.h @@ -44,6 +44,8 @@ #include #include +#include +#include QT_BEGIN_HEADER @@ -53,10 +55,7 @@ QT_MODULE(Gui) class QGraphicsItem; class QStyleOption; -class QColor; class QPainter; -class QRectF; -class QRect; class QPixmap; class QGraphicsEffectSourcePrivate; -- cgit v0.12 From 068aed9aa59998dd69b181f508a5b2fdbd14b598 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 20 Aug 2009 12:14:01 +0200 Subject: Add Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsEffect::ChangeFlags) --- src/gui/effects/qgraphicseffect.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h index fe31ae8..40d206d 100644 --- a/src/gui/effects/qgraphicseffect.h +++ b/src/gui/effects/qgraphicseffect.h @@ -133,6 +133,7 @@ private: friend class QGraphicsItemPrivate; friend class QGraphicsScenePrivate; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsEffect::ChangeFlags); class QGraphicsGrayscaleEffectPrivate; class Q_GUI_EXPORT QGraphicsGrayscaleEffect: public QGraphicsEffect -- cgit v0.12 From 6b7460b6b519122b78dfef598a100169dc6a074b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 20 Aug 2009 12:24:19 +0200 Subject: Graphics Effect cleanup: Remove old comments; not valid anymore. --- src/gui/effects/qgraphicseffect.cpp | 61 +++---------------------------------- src/gui/effects/qgraphicseffect.h | 1 - 2 files changed, 4 insertions(+), 58 deletions(-) diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index 73668ec..0747046 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -100,60 +100,6 @@ QT_BEGIN_NAMESPACE -/* - - List of known drawbacks which are being discussed: - - * No d-pointer yet. - - * No auto test yet. - - * No API documentation yet. - - * The API is far from being finalized. - - * Most of the effect implementation is not efficient, - as this is still a proof of concept only. - - * Painting artifacts occasionally occur when e.g. moving - an item over another item that has a large effective - bounding rect. - - * Item transformation is not taken into account. - For example, the effective bounding rect is calculated at - item coordinate (fast), but the painting is mostly - done at device coordinate. - - * Coordinate mode: item vs device. Most effects make sense only - in device coordinate. Should we keep both options open? - See also above transformation issue. - - * Right now the pixmap for effect drawing is stored in each item. - There can be problems with coordinates, see above. - - * There is a lot of duplication in drawItems() for each effect. - - * Port to use the new layer feature in QGraphicsView. - This should solve the above pixmap problem. - - * Frame effect is likely useless. However it is very useful - to check than the effective bounding rect is handled properly. - - * Proper exposed region and rect for style option are missing. - - * Pixelize effect is using raster only, because there is no - pixmap filter for it. We need to implement the missing pixmap filter. - - * Blur effect is using raster only, with exponential blur algorithm. - Perhaps use stack blur (better approximate Gaussian blur) instead? - QPixmapConvolutionFilter is too slow for this simple blur effect. - - * Bloom and shadow effect are also raster only. Same reason as above. - - * Make it work with widgets (QGraphicsWidget). - -*/ - QGraphicsEffectSource::QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, QObject *parent) : QObject(dd, parent) {} @@ -207,7 +153,6 @@ QPixmap QGraphicsEffectSource::pixmap(Qt::CoordinateSystem system, QPoint *offse QGraphicsEffect::QGraphicsEffect(QObject *parent) : QObject(*new QGraphicsEffectPrivate, parent) { - // ### parent? } /*! @@ -354,10 +299,12 @@ void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *so QGraphicsColorizeEffect::QGraphicsColorizeEffect(QObject *parent) : QGraphicsEffect(*new QGraphicsColorizeEffectPrivate, parent) -{} +{ +} QGraphicsColorizeEffect::~QGraphicsColorizeEffect() -{} +{ +} QColor QGraphicsColorizeEffect::color() const { diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h index 40d206d..1f0e4de 100644 --- a/src/gui/effects/qgraphicseffect.h +++ b/src/gui/effects/qgraphicseffect.h @@ -105,7 +105,6 @@ public: QGraphicsEffect(QObject *parent = 0); virtual ~QGraphicsEffect(); - // ### make protected? virtual QRectF boundingRectFor(const QRectF &rect) const; QRectF boundingRect() const; -- cgit v0.12 From bd24e3f06e0df6f17f620a722baeea170e29972f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 20 Aug 2009 12:35:46 +0200 Subject: Make QGraphicsXXXEffect::boundingRectFor public. --- src/gui/effects/qgraphicseffect.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h index 1f0e4de..e92a4f4 100644 --- a/src/gui/effects/qgraphicseffect.h +++ b/src/gui/effects/qgraphicseffect.h @@ -209,6 +209,7 @@ public: QGraphicsBlurEffect(QObject *parent = 0); ~QGraphicsBlurEffect(); + QRectF boundingRectFor(const QRectF &rect) const; int blurRadius() const; public Q_SLOTS: @@ -218,7 +219,6 @@ Q_SIGNALS: void blurRadiusChanged(int blurRadius); protected: - QRectF boundingRectFor(const QRectF &rect) const; void draw(QPainter *painter, QGraphicsEffectSource *source); private: @@ -237,6 +237,7 @@ public: QGraphicsShadowEffect(QObject *parent = 0); ~QGraphicsShadowEffect(); + QRectF boundingRectFor(const QRectF &rect) const; QPointF shadowOffset() const; int blurRadius() const; qreal opacity() const; @@ -256,7 +257,6 @@ Q_SIGNALS: void opacityChanged(int opacity); protected: - QRectF boundingRectFor(const QRectF &rect) const; void draw(QPainter *painter, QGraphicsEffectSource *source); private: -- cgit v0.12 From f385c3897f00bc40201f35ae7eb61e8de71671af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 20 Aug 2009 12:41:34 +0200 Subject: Header cleanup. Graphics effects is no longer dependent of graphics view. --- src/gui/effects/qgraphicseffect_p.h | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/gui/effects/qgraphicseffect_p.h b/src/gui/effects/qgraphicseffect_p.h index a92e7ae..705b442 100644 --- a/src/gui/effects/qgraphicseffect_p.h +++ b/src/gui/effects/qgraphicseffect_p.h @@ -55,15 +55,9 @@ #include "qgraphicseffect.h" -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - #include #include -#include -#include -#include - QT_BEGIN_NAMESPACE class QGraphicsEffectSourcePrivate : public QObjectPrivate @@ -169,6 +163,5 @@ public: QT_END_NAMESPACE -#endif // QT_NO_GRAPHICSVIEW - #endif // QGRAPHICSEFFECT_P_H + -- cgit v0.12 From 98d9206fe788e7d00c9e7cb5513b449dbed9e853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 20 Aug 2009 12:44:43 +0200 Subject: Compile graphics effect on all platforms. Looks like we need to include graphicseffect.h even though it should have been included by the _p.h. --- src/gui/graphicsview/qgraphicsitem.cpp | 1 + src/gui/graphicsview/qgraphicsscene.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 50b5b9e..b9b4180 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -581,6 +581,7 @@ #include #include #include +#include #include #include diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index ff8445f..767c8a2 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -244,6 +244,7 @@ #include #include #include +#include #include #include #ifdef Q_WS_X11 -- cgit v0.12 From f6fdb0f10a3525205fc7143e5db61087058daf73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 20 Aug 2009 13:52:35 +0200 Subject: Add missing effects.pri file in src/gui/effects --- src/gui/effects/effects.pri | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/gui/effects/effects.pri diff --git a/src/gui/effects/effects.pri b/src/gui/effects/effects.pri new file mode 100644 index 0000000..0ebf96f --- /dev/null +++ b/src/gui/effects/effects.pri @@ -0,0 +1,4 @@ +HEADERS += effects/qgraphicseffect.h \ + effects/qgraphicseffect_p.h + +SOURCES += effects/qgraphicseffect.cpp -- cgit v0.12 From 5c7c4b9a0c95f5e97d73547e830a4e4bf87d2fca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 20 Aug 2009 14:11:40 +0200 Subject: Rename QGraphicsShadowEffect to QGraphicsDropShadowEffect. Discussed with Andreas. --- examples/effects/lighting/shadoweffect.cpp | 6 ++-- examples/effects/lighting/shadoweffect.h | 2 +- src/gui/effects/qgraphicseffect.cpp | 40 +++++++++++++------------- src/gui/effects/qgraphicseffect.h | 12 ++++---- src/gui/effects/qgraphicseffect_p.h | 6 ++-- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 2 +- 6 files changed, 34 insertions(+), 34 deletions(-) diff --git a/examples/effects/lighting/shadoweffect.cpp b/examples/effects/lighting/shadoweffect.cpp index f447531..9545815 100644 --- a/examples/effects/lighting/shadoweffect.cpp +++ b/examples/effects/lighting/shadoweffect.cpp @@ -44,7 +44,7 @@ #include ShadowEffect::ShadowEffect(QGraphicsItem *item, QGraphicsItem *source) - : QGraphicsShadowEffect() + : QGraphicsDropShadowEffect() , item(item), m_lightSource(source) { setBlurRadius(8); @@ -64,11 +64,11 @@ void ShadowEffect::adjustForItem() QRectF ShadowEffect::boundingRectFor(const QRectF &rect) const { const_cast(this)->adjustForItem(); - return QGraphicsShadowEffect::boundingRectFor(rect); + return QGraphicsDropShadowEffect::boundingRectFor(rect); } void ShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { adjustForItem(); - QGraphicsShadowEffect::draw(painter, source); + QGraphicsDropShadowEffect::draw(painter, source); } diff --git a/examples/effects/lighting/shadoweffect.h b/examples/effects/lighting/shadoweffect.h index 68318b0..b20f647 100644 --- a/examples/effects/lighting/shadoweffect.h +++ b/examples/effects/lighting/shadoweffect.h @@ -45,7 +45,7 @@ #include #include -class ShadowEffect: public QGraphicsShadowEffect +class ShadowEffect: public QGraphicsDropShadowEffect { public: ShadowEffect(QGraphicsItem *item, QGraphicsItem *source); diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index 0747046..c6f2871 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -63,7 +63,7 @@ \o QGraphicsColorizeEffect - renders the item in shades of any given color \o QGraphicsPixelizeEffect - pixelizes the item with any pixel size \o QGraphicsBlurEffect - blurs the item by a given radius - \o QGraphicsShadowEffect - renders a dropshadow behind the item + \o QGraphicsDropShadowEffect - renders a dropshadow behind the item \endlist If all you want is to add an effect to an item, you should visit the @@ -538,24 +538,24 @@ void QGraphicsBlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) painter->setWorldTransform(restoreTransform); } -QGraphicsShadowEffect::QGraphicsShadowEffect(QObject *parent) - : QGraphicsEffect(*new QGraphicsShadowEffectPrivate, parent) +QGraphicsDropShadowEffect::QGraphicsDropShadowEffect(QObject *parent) + : QGraphicsEffect(*new QGraphicsDropShadowEffectPrivate, parent) { } -QGraphicsShadowEffect::~QGraphicsShadowEffect() +QGraphicsDropShadowEffect::~QGraphicsDropShadowEffect() { } -QPointF QGraphicsShadowEffect::shadowOffset() const +QPointF QGraphicsDropShadowEffect::shadowOffset() const { - Q_D(const QGraphicsShadowEffect); + Q_D(const QGraphicsDropShadowEffect); return d->offset; } -void QGraphicsShadowEffect::setShadowOffset(const QPointF &ofs) +void QGraphicsDropShadowEffect::setShadowOffset(const QPointF &ofs) { - Q_D(QGraphicsShadowEffect); + Q_D(QGraphicsDropShadowEffect); if (d->offset == ofs) return; @@ -564,15 +564,15 @@ void QGraphicsShadowEffect::setShadowOffset(const QPointF &ofs) emit shadowOffsetChanged(ofs); } -int QGraphicsShadowEffect::blurRadius() const +int QGraphicsDropShadowEffect::blurRadius() const { - Q_D(const QGraphicsShadowEffect); + Q_D(const QGraphicsDropShadowEffect); return d->radius; } -void QGraphicsShadowEffect::setBlurRadius(int blurRadius) +void QGraphicsDropShadowEffect::setBlurRadius(int blurRadius) { - Q_D(QGraphicsShadowEffect); + Q_D(QGraphicsDropShadowEffect); if (d->radius == blurRadius) return; @@ -581,15 +581,15 @@ void QGraphicsShadowEffect::setBlurRadius(int blurRadius) emit blurRadiusChanged(blurRadius); } -qreal QGraphicsShadowEffect::opacity() const +qreal QGraphicsDropShadowEffect::opacity() const { - Q_D(const QGraphicsShadowEffect); + Q_D(const QGraphicsDropShadowEffect); return d->alpha; } -void QGraphicsShadowEffect::setOpacity(qreal opacity) +void QGraphicsDropShadowEffect::setOpacity(qreal opacity) { - Q_D(QGraphicsShadowEffect); + Q_D(QGraphicsDropShadowEffect); if (qFuzzyCompare(d->alpha, opacity)) return; @@ -597,9 +597,9 @@ void QGraphicsShadowEffect::setOpacity(qreal opacity) emit opacityChanged(opacity); } -QRectF QGraphicsShadowEffect::boundingRectFor(const QRectF &rect) const +QRectF QGraphicsDropShadowEffect::boundingRectFor(const QRectF &rect) const { - Q_D(const QGraphicsShadowEffect); + Q_D(const QGraphicsDropShadowEffect); QRectF shadowRect = rect.translated(d->offset); QRectF blurRect = shadowRect; qreal delta = d->radius * 3; @@ -608,9 +608,9 @@ QRectF QGraphicsShadowEffect::boundingRectFor(const QRectF &rect) const return blurRect; } -void QGraphicsShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *source) +void QGraphicsDropShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { - Q_D(QGraphicsShadowEffect); + Q_D(QGraphicsDropShadowEffect); if (d->radius <= 0 && d->offset.isNull()) { source->draw(painter); return; diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h index e92a4f4..4344e2d 100644 --- a/src/gui/effects/qgraphicseffect.h +++ b/src/gui/effects/qgraphicseffect.h @@ -226,16 +226,16 @@ private: Q_DISABLE_COPY(QGraphicsBlurEffect) }; -class QGraphicsShadowEffectPrivate; -class Q_GUI_EXPORT QGraphicsShadowEffect: public QGraphicsEffect +class QGraphicsDropShadowEffectPrivate; +class Q_GUI_EXPORT QGraphicsDropShadowEffect: public QGraphicsEffect { Q_OBJECT Q_PROPERTY(QPointF shadowOffset READ shadowOffset WRITE setShadowOffset NOTIFY shadowOffsetChanged) Q_PROPERTY(int blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) Q_PROPERTY(int opacity READ opacity WRITE setOpacity NOTIFY opacityChanged) public: - QGraphicsShadowEffect(QObject *parent = 0); - ~QGraphicsShadowEffect(); + QGraphicsDropShadowEffect(QObject *parent = 0); + ~QGraphicsDropShadowEffect(); QRectF boundingRectFor(const QRectF &rect) const; QPointF shadowOffset() const; @@ -260,8 +260,8 @@ protected: void draw(QPainter *painter, QGraphicsEffectSource *source); private: - Q_DECLARE_PRIVATE(QGraphicsShadowEffect) - Q_DISABLE_COPY(QGraphicsShadowEffect) + Q_DECLARE_PRIVATE(QGraphicsDropShadowEffect) + Q_DISABLE_COPY(QGraphicsDropShadowEffect) }; QT_END_NAMESPACE diff --git a/src/gui/effects/qgraphicseffect_p.h b/src/gui/effects/qgraphicseffect_p.h index 705b442..309b382 100644 --- a/src/gui/effects/qgraphicseffect_p.h +++ b/src/gui/effects/qgraphicseffect_p.h @@ -150,11 +150,11 @@ public: int blurRadius; }; -class QGraphicsShadowEffectPrivate : public QGraphicsEffectPrivate +class QGraphicsDropShadowEffectPrivate : public QGraphicsEffectPrivate { - Q_DECLARE_PUBLIC(QGraphicsShadowEffect) + Q_DECLARE_PUBLIC(QGraphicsDropShadowEffect) public: - QGraphicsShadowEffectPrivate() : offset(4, 4), radius(8), alpha(0.7) {} + QGraphicsDropShadowEffectPrivate() : offset(4, 4), radius(8), alpha(0.7) {} QPointF offset; int radius; diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 976f57d..184bfe2 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -7418,7 +7418,7 @@ void tst_QGraphicsItem::hitTestGraphicsEffectItem() item3->repaints = 0; // Apply shadow effect to the entire sub-tree. - QGraphicsShadowEffect *shadow = new QGraphicsShadowEffect; + QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect; shadow->setShadowOffset(-20, -20); item1->setGraphicsEffect(shadow); QTest::qWait(50); -- cgit v0.12 From 181c9774791b6f581598389337f9af0fa4658e6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 20 Aug 2009 16:09:47 +0200 Subject: Make QGraphicsItem::effectiveBoundingRect/sceneEffectiveBoundingRect internal. These shouldn't be in public API unless someone ask for it. The same information is accessible via public functions in QGraphicsEffect and QGraphicsEffectSource, so they are only convenience functions after all. --- src/gui/graphicsview/qgraphicsitem.cpp | 16 +++++++++------- src/gui/graphicsview/qgraphicsitem.h | 2 -- src/gui/graphicsview/qgraphicsitem_p.h | 2 ++ src/gui/graphicsview/qgraphicsscene_p.h | 2 +- src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp | 4 ++-- 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index b9b4180..5fa1748 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2284,6 +2284,7 @@ void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect) } /*! + \internal \since 4.6 Returns the effective bounding rect of the item. If the item has no effect, this is the same as the item's bounding rect. @@ -2292,14 +2293,14 @@ void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect) \sa boundingRect() */ -QRectF QGraphicsItem::effectiveBoundingRect() const +QRectF QGraphicsItemPrivate::effectiveBoundingRect() const { - QGraphicsEffect *effect = d_ptr->graphicsEffect; - QRectF brect = effect && effect->isEnabled() ? effect->boundingRect() : boundingRect(); - if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) + QGraphicsEffect *effect = graphicsEffect; + QRectF brect = effect && effect->isEnabled() ? effect->boundingRect() : q_ptr->boundingRect(); + if (ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) return brect; - const QGraphicsItem *effectParent = d_ptr->parent; + const QGraphicsItem *effectParent = parent; while (effectParent) { effect = effectParent->d_ptr->graphicsEffect; if (effect && effect->isEnabled()) @@ -2313,6 +2314,7 @@ QRectF QGraphicsItem::effectiveBoundingRect() const } /*! + \internal \since 4.6 Returns the effective bounding rect of this item in scene coordinates, by combining sceneTransform() with boundingRect(), taking into account @@ -2322,12 +2324,12 @@ QRectF QGraphicsItem::effectiveBoundingRect() const \sa effectiveBoundingRect(), sceneBoundingRect() */ -QRectF QGraphicsItem::sceneEffectiveBoundingRect() const +QRectF QGraphicsItemPrivate::sceneEffectiveBoundingRect() const { // Find translate-only offset // COMBINE QPointF offset; - const QGraphicsItem *parentItem = this; + const QGraphicsItem *parentItem = q_ptr; const QGraphicsItemPrivate *itemd; do { itemd = parentItem->d_ptr; diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index b4c7ed8..216053d 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -213,8 +213,6 @@ public: // Effect QGraphicsEffect *graphicsEffect() const; void setGraphicsEffect(QGraphicsEffect *effect); - QRectF effectiveBoundingRect() const; - QRectF sceneEffectiveBoundingRect() const; Qt::MouseButtons acceptedMouseButtons() const; void setAcceptedMouseButtons(Qt::MouseButtons buttons); diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index a7b48fc..a798a3b 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -222,6 +222,8 @@ public: void childrenBoundingRectHelper(QTransform *x, QRectF *rect); void initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform, const QRegion &exposedRegion, bool allItems = false) const; + QRectF effectiveBoundingRect() const; + QRectF sceneEffectiveBoundingRect() const; virtual void resolveFont(uint inheritedMask) { diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index a405f31..119d9de 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -298,7 +298,7 @@ static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item) static inline QRectF adjustedItemEffectiveBoundingRect(const QGraphicsItem *item) { Q_ASSERT(item); - QRectF boundingRect(item->effectiveBoundingRect()); + QRectF boundingRect(QGraphicsItemPrivate::get(item)->effectiveBoundingRect()); _q_adjustRect(&boundingRect); return boundingRect; } diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 2d2ce02..1f5d106 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -172,7 +172,7 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) continue; - bsp.insertItem(item, item->sceneEffectiveBoundingRect()); + bsp.insertItem(item, item->d_ptr->sceneEffectiveBoundingRect()); } } unindexedItems.clear(); @@ -352,7 +352,7 @@ void QGraphicsSceneBspTreeIndexPrivate::removeItem(QGraphicsItem *item, bool rec purgePending = true; removedItems << item; } else if (!(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { - bsp.removeItem(item, item->sceneEffectiveBoundingRect()); + bsp.removeItem(item, item->d_ptr->sceneEffectiveBoundingRect()); } } else { unindexedItems.removeOne(item); -- cgit v0.12 From 1ffed52434741aa31b1549a931f6b446b2aaabd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 18 Aug 2009 15:28:09 +0200 Subject: Add support for graphics effects on QWidget. --- src/gui/effects/qgraphicseffect.cpp | 6 ++ src/gui/effects/qgraphicseffect.h | 5 ++ src/gui/effects/qgraphicseffect_p.h | 1 + src/gui/graphicsview/qgraphicsitem_p.h | 3 + src/gui/kernel/qwidget.cpp | 109 ++++++++++++++++++++++++++++++++- src/gui/kernel/qwidget.h | 4 ++ src/gui/kernel/qwidget_p.h | 66 ++++++++++++++++++++ src/gui/painting/qpaintengine_p.h | 4 +- 8 files changed, 192 insertions(+), 6 deletions(-) diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index c6f2871..3d363f1 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -97,6 +97,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -122,6 +123,11 @@ const QGraphicsItem *QGraphicsEffectSource::graphicsItem() const return d_func()->graphicsItem(); } +const QWidget *QGraphicsEffectSource::widget() const +{ + return d_func()->widget(); +} + const QStyleOption *QGraphicsEffectSource::styleOption() const { return d_func()->styleOption(); diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h index 4344e2d..f6c47d7 100644 --- a/src/gui/effects/qgraphicseffect.h +++ b/src/gui/effects/qgraphicseffect.h @@ -65,6 +65,7 @@ class Q_GUI_EXPORT QGraphicsEffectSource : public QObject public: ~QGraphicsEffectSource(); const QGraphicsItem *graphicsItem() const; + const QWidget *widget() const; const QStyleOption *styleOption() const; bool isPixmap() const; @@ -85,6 +86,8 @@ private: friend class QGraphicsEffectPrivate; friend class QGraphicsScenePrivate; friend class QGraphicsItem; + friend class QWidget; + friend class QWidgetPrivate; }; class QGraphicsEffectPrivate; @@ -131,6 +134,8 @@ private: friend class QGraphicsItem; friend class QGraphicsItemPrivate; friend class QGraphicsScenePrivate; + friend class QWidget; + friend class QWidgetPrivate; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsEffect::ChangeFlags); diff --git a/src/gui/effects/qgraphicseffect_p.h b/src/gui/effects/qgraphicseffect_p.h index 309b382..25397c3 100644 --- a/src/gui/effects/qgraphicseffect_p.h +++ b/src/gui/effects/qgraphicseffect_p.h @@ -70,6 +70,7 @@ public: virtual QRectF boundingRect(Qt::CoordinateSystem system) const = 0; virtual QRect deviceRect() const = 0; virtual const QGraphicsItem *graphicsItem() const = 0; + virtual const QWidget *widget() const = 0; virtual const QStyleOption *styleOption() const = 0; virtual void draw(QPainter *p) = 0; virtual void update() = 0; diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index a798a3b..cd5c595 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -559,6 +559,9 @@ public: inline const QGraphicsItem *graphicsItem() const { return item; } + inline const QWidget *widget() const + { return 0; } + inline void update() { item->update(); } diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 515eed9..a314cf19 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -182,6 +182,7 @@ QWidgetPrivate::QWidgetPrivate(int version) , widgetItem(0) , extraPaintEngine(0) , polished(0) + , graphicsEffect(0) , inheritedFontResolveMask(0) , inheritedPaletteResolveMask(0) , leftmargin(0) @@ -237,6 +238,8 @@ QWidgetPrivate::~QWidgetPrivate() if (extra) deleteExtra(); + + delete graphicsEffect; } QWindowSurface *QWidgetPrivate::createDefaultWindowSurface() @@ -1649,7 +1652,7 @@ QRect QWidgetPrivate::clipRect() const const QWidget * w = q; if (!w->isVisible()) return QRect(); - QRect r = q->rect(); + QRect r = effectiveRectFor(q->rect()); int ox = 0; int oy = 0; while (w @@ -1891,6 +1894,12 @@ void QWidgetPrivate::updateIsOpaque() // hw: todo: only needed if opacity actually changed setDirtyOpaqueRegion(); + if (graphicsEffect) { + // ### We should probably add QGraphicsEffect::isOpaque at some point. + setOpaque(false); + return; + } + Q_Q(QWidget); #ifdef Q_WS_X11 if (q->testAttribute(Qt::WA_X11OpenGLOverlay)) { @@ -4847,6 +4856,43 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset, d->extra->inRenderWithPainter = false; } +QGraphicsEffect *QWidget::graphicsEffect() const +{ + Q_D(const QWidget); + return d->graphicsEffect; +} + +void QWidget::setGraphicsEffect(QGraphicsEffect *effect) +{ + Q_D(QWidget); + if (d->graphicsEffect == effect) + return; + + if (d->graphicsEffect && effect) { + // ### This seems wrong - the effect should automatically be deleted. + qWarning("already set"); + return; + } + + if (!effect) { + // Unset current effect. + QGraphicsEffectPrivate *oldEffectPrivate = d->graphicsEffect->d_func(); + d->graphicsEffect = 0; + if (oldEffectPrivate) { + oldEffectPrivate->setGraphicsEffectSource(0); // deletes the current source. + } + } else { + // Set new effect. + QGraphicsEffectSourcePrivate *sourced = new QWidgetEffectSourcePrivate(this); + QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced); + d->graphicsEffect = effect; + effect->d_func()->setGraphicsEffectSource(source); + } + + d->updateIsOpaque(); + update(); +} + bool QWidgetPrivate::isAboutToShow() const { if (data.in_show) @@ -4991,6 +5037,30 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP return; Q_Q(QWidget); + if (graphicsEffect && graphicsEffect->isEnabled()) { + QGraphicsEffectSource *source = graphicsEffect->d_func()->source; + QWidgetEffectSourcePrivate *sourced = static_cast + (source->d_func()); + if (!sourced->context) { + QWidgetPaintContext context(pdev, rgn, offset, flags, sharedPainter, backingStore); + sourced->context = &context; + if (!sharedPainter) { + QPaintEngine *paintEngine = pdev->paintEngine(); + paintEngine->d_func()->systemClip = clipRect().translated(offset); + QPainter p(pdev); + p.translate(offset); + context.painter = &p; + graphicsEffect->draw(&p, source); + paintEngine->d_func()->systemClip = QRegion(); + } else { + context.painter = sharedPainter; + graphicsEffect->draw(sharedPainter, source); + } + sourced->context = 0; + return; + } + } + const bool asRoot = flags & DrawAsRoot; const bool alsoOnScreen = flags & DrawPaintOnScreen; const bool recursive = flags & DrawRecursive; @@ -5023,7 +5093,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP if (sharedPainter) paintEngine->d_func()->systemClip = toBePainted; else - paintEngine->setSystemRect(q->data->crect); + paintEngine->d_func()->systemRect = q->data->crect; //paint the background if ((asRoot || q->autoFillBackground() || onScreen || q->testAttribute(Qt::WA_StyledBackground)) @@ -5062,7 +5132,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP if (paintEngine) { restoreRedirected(); if (!sharedPainter) - paintEngine->setSystemRect(QRect()); + paintEngine->d_func()->systemRect = QRect(); else paintEngine->d_func()->currentClipWidget = 0; paintEngine->d_func()->systemClip = QRegion(); @@ -5166,6 +5236,39 @@ void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectLis } } +void QWidgetEffectSourcePrivate::draw(QPainter *painter) +{ + if (!context || context->painter != painter) { + m_widget->render(painter); + return; + } + + qt_widget_private(m_widget)->drawWidget(context->pdev, context->rgn, context->offset, context->flags, + context->sharedPainter, context->backingStore); +} + +QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset) const +{ + const bool deviceCoordinates = (system == Qt::DeviceCoordinates); + QPoint pixmapOffset; + + QRect sourceRect(m_widget->rect()); + if (deviceCoordinates) { + pixmapOffset = m_widget->mapTo(m_widget->window(), QPoint()); + sourceRect.translate(pixmapOffset); + } + + QRect effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect(); + if (offset) + *offset = effectRect.topLeft(); + pixmapOffset -= effectRect.topLeft(); + + QPixmap pixmap(effectRect.size()); + pixmap.fill(Qt::transparent); + m_widget->render(&pixmap, pixmapOffset); + return pixmap; +} + /*! \internal diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h index 6f30883..4f14a53 100644 --- a/src/gui/kernel/qwidget.h +++ b/src/gui/kernel/qwidget.h @@ -96,6 +96,7 @@ class QWindowSurface; class QLocale; class QGraphicsProxyWidget; class QGestureManager; +class QGraphicsEffect; #if defined(Q_WS_X11) class QX11Info; #endif @@ -352,6 +353,9 @@ public: const QRegion &sourceRegion = QRegion(), RenderFlags renderFlags = RenderFlags(DrawWindowBackground | DrawChildren)); + QGraphicsEffect *graphicsEffect() const; + void setGraphicsEffect(QGraphicsEffect *effect); + public Q_SLOTS: void setWindowTitle(const QString &); #ifndef QT_NO_STYLE_STYLESHEET diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index a3f4f6f..acfb6c3 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -61,6 +61,7 @@ #include "QtGui/qregion.h" #include "QtGui/qsizepolicy.h" #include "QtGui/qstyle.h" +#include #ifdef Q_WS_WIN #include "QtCore/qt_windows.h" @@ -443,6 +444,13 @@ public: return extra ? extra->nativeChildrenForced : false; } + inline QRect effectiveRectFor(const QRect &rect) const + { + if (graphicsEffect && graphicsEffect->isEnabled()) + return graphicsEffect->boundingRectFor(rect).toAlignedRect(); + return rect; + } + QSize adjustedSize() const; #ifndef Q_WS_QWS // Almost cross-platform :-) @@ -473,6 +481,7 @@ public: QWidgetItemV2 *widgetItem; QPaintEngine *extraPaintEngine; mutable const QMetaObject *polished; + QGraphicsEffect *graphicsEffect; // All widgets are initially added into the uncreatedWidgets set. Once // they receive a window id they are removed and added to the mapper static QWidgetMapper *mapper; @@ -642,6 +651,63 @@ public: #endif }; +struct QWidgetPaintContext +{ + inline QWidgetPaintContext(QPaintDevice *d, const QRegion &r, const QPoint &o, int f, + QPainter *p, QWidgetBackingStore *b) + : pdev(d), rgn(r), offset(o), flags(f), sharedPainter(p), backingStore(b), painter(0) {} + + QPaintDevice *pdev; + QRegion rgn; + QPoint offset; + int flags; + QPainter *sharedPainter; + QWidgetBackingStore *backingStore; + QPainter *painter; +}; + +class QWidgetEffectSourcePrivate : public QGraphicsEffectSourcePrivate +{ +public: + QWidgetEffectSourcePrivate(QWidget *widget) + : QGraphicsEffectSourcePrivate(), m_widget(widget), context(0) + {} + + inline void detach() + { m_widget->setGraphicsEffect(0); } + + inline const QGraphicsItem *graphicsItem() const + { return 0; } + + inline const QWidget *widget() const + { return m_widget; } + + inline void update() + { m_widget->update(); } + + inline bool isPixmap() const + { return false; } + + inline const QStyleOption *styleOption() const + { return 0; } + + inline QRect deviceRect() const + { return m_widget->window()->rect(); } + + inline QRectF boundingRect(Qt::CoordinateSystem system) const + { + if (system == Qt::LogicalCoordinates) + return m_widget->rect(); + return m_widget->rect().translated(m_widget->mapTo(m_widget->window(), QPoint())); + } + + void draw(QPainter *p); + QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset) const; + + QWidget *m_widget; + QWidgetPaintContext *context; +}; + inline QWExtra *QWidgetPrivate::extraData() const { return extra; diff --git a/src/gui/painting/qpaintengine_p.h b/src/gui/painting/qpaintengine_p.h index 7ea68d2..d3cd6f9 100644 --- a/src/gui/painting/qpaintengine_p.h +++ b/src/gui/painting/qpaintengine_p.h @@ -72,6 +72,7 @@ public: QPaintDevice *pdev; QPaintEngine *q_ptr; QRegion systemClip; + QRect systemRect; QRegion systemViewport; QTransform systemTransform; QWidget *currentClipWidget; @@ -117,9 +118,6 @@ public: virtual void systemStateChanged() { } void drawBoxTextItem(const QPointF &p, const QTextItemInt &ti); - -private: - QRect systemRect; }; QT_END_NAMESPACE -- cgit v0.12 From ee2670460af760bf07c47950a8cca37bd6814f2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 20 Aug 2009 20:29:56 +0200 Subject: Fix the most obvious rendering bugs when applying an effect to QWidget. --- src/gui/kernel/qwidget.cpp | 95 ++++++++++++++++++++++++++++++++------ src/gui/kernel/qwidget_p.h | 8 +--- src/gui/kernel/qwidget_qws.cpp | 8 ++-- src/gui/kernel/qwidget_win.cpp | 4 +- src/gui/kernel/qwidget_x11.cpp | 4 +- src/gui/painting/qbackingstore.cpp | 37 +++++++++------ src/gui/painting/qbackingstore_p.h | 8 +++- 7 files changed, 118 insertions(+), 46 deletions(-) diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index a314cf19..a9ef6aa 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -1551,9 +1551,9 @@ bool QWidgetPrivate::isOverlapped(const QRect &rect) const continue; } - if (qRectIntersects(sibling->data->crect, r)) { + if (qRectIntersects(sibling->d_func()->effectiveRectFor(sibling->data->crect), r)) { const QWExtra *siblingExtra = sibling->d_func()->extra; - if (siblingExtra && siblingExtra->hasMask + if (siblingExtra && siblingExtra->hasMask && !sibling->d_func()->graphicsEffect && !siblingExtra->mask.translated(sibling->data->crect.topLeft()).intersects(r)) { continue; } @@ -1794,12 +1794,14 @@ void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirt break; QWidgetPrivate *pd = w->parentWidget()->d_func(); const int myIndex = pd->children.indexOf(const_cast(w)); + const QRect widgetGeometry = w->d_func()->effectiveRectFor(w->data->crect); for (int i = myIndex + 1; i < pd->children.size(); ++i) { QWidget *sibling = qobject_cast(pd->children.at(i)); if (!sibling || !sibling->isVisible() || sibling->isWindow()) continue; - if (!qRectIntersects(sibling->data->crect, w->data->crect)) + const QRect siblingGeometry = sibling->d_func()->effectiveRectFor(sibling->data->crect); + if (!qRectIntersects(siblingGeometry, widgetGeometry)) continue; if (dirtyClipBoundingRect) { @@ -1807,7 +1809,7 @@ void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirt dirtyClipBoundingRect = false; } - if (!qRectIntersects(sibling->data->crect, clipBoundingRect.translated(parentOffset))) + if (!qRectIntersects(siblingGeometry, clipBoundingRect.translated(parentOffset))) continue; if (dirtyParentClip) { @@ -1819,7 +1821,8 @@ void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirt const QRect siblingClipRect(sibling->d_func()->clipRect()); QRegion siblingDirty(parentClip); siblingDirty &= (siblingClipRect.translated(siblingPos)); - const bool hasMask = sibling->d_func()->extra && sibling->d_func()->extra->hasMask; + const bool hasMask = sibling->d_func()->extra && sibling->d_func()->extra->hasMask + && !sibling->d_func()->graphicsEffect; if (hasMask) siblingDirty &= sibling->d_func()->extra->mask.translated(siblingPos); if (siblingDirty.isEmpty()) @@ -1830,7 +1833,7 @@ void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirt siblingDirty.translate(-parentOffset); sourceRegion -= siblingDirty; } else { - sourceRegion -= sibling->data->crect.translated(-parentOffset); + sourceRegion -= siblingGeometry.translated(-parentOffset); } } else { if (hasDirtySiblingsAbove) @@ -1861,6 +1864,11 @@ void QWidgetPrivate::clipToEffectiveMask(QRegion ®ion) const const QWidget *w = q; QPoint offset; + if (graphicsEffect) { + w = q->parentWidget(); + offset -= data.crect.topLeft(); + } + while (w) { const QWidgetPrivate *wd = w->d_func(); if (wd->extra && wd->extra->hasMask) @@ -5046,7 +5054,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP sourced->context = &context; if (!sharedPainter) { QPaintEngine *paintEngine = pdev->paintEngine(); - paintEngine->d_func()->systemClip = clipRect().translated(offset); + paintEngine->d_func()->systemClip = rgn.translated(offset); QPainter p(pdev); p.translate(offset); context.painter = &p; @@ -5054,7 +5062,10 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP paintEngine->d_func()->systemClip = QRegion(); } else { context.painter = sharedPainter; + sharedPainter->save(); + sharedPainter->translate(offset); graphicsEffect->draw(sharedPainter, source); + sharedPainter->restore(); } sourced->context = 0; return; @@ -5195,7 +5206,7 @@ void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectLis dirtyBoundingRect = false; } - if (qRectIntersects(boundingRect, x->data->crect)) { + if (qRectIntersects(boundingRect, x->d_func()->effectiveRectFor(x->data->crect))) { #ifdef Q_BACKINGSTORE_SUBSURFACES if (x->windowSurface() == currentSurface) #endif @@ -5213,7 +5224,7 @@ void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectLis QWidgetPrivate *wd = w->d_func(); const QPoint widgetPos(w->data->crect.topLeft()); - const bool hasMask = wd->extra && wd->extra->hasMask; + const bool hasMask = wd->extra && wd->extra->hasMask && !wd->graphicsEffect; if (index > 0) { QRegion wr(rgn); @@ -5228,7 +5239,7 @@ void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectLis if (w->updatesEnabled() && (!w->d_func()->extra || !w->d_func()->extra->proxyWidget)) { QRegion wRegion(rgn); - wRegion &= w->data->crect; + wRegion &= wd->effectiveRectFor(w->data->crect); wRegion.translate(-widgetPos); if (hasMask) wRegion &= wd->extra->mask; @@ -5236,6 +5247,20 @@ void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectLis } } +QRectF QWidgetEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const +{ + if (system != Qt::DeviceCoordinates) + return m_widget->rect(); + + if (!context) { + // Device coordinates without context not yet supported. + qWarning("QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context"); + return QRectF(); + } + + return context->painter->worldTransform().mapRect(m_widget->rect()); +} + void QWidgetEffectSourcePrivate::draw(QPainter *painter) { if (!context || context->painter != painter) { @@ -5243,24 +5268,64 @@ void QWidgetEffectSourcePrivate::draw(QPainter *painter) return; } - qt_widget_private(m_widget)->drawWidget(context->pdev, context->rgn, context->offset, context->flags, - context->sharedPainter, context->backingStore); + // The region saved in the context is neither clipped to the rect + // nor the mask, so we have to clip it here before calling drawWidget. + QRegion toBePainted = context->rgn; + toBePainted &= m_widget->rect(); + QWidgetPrivate *wd = qt_widget_private(m_widget); + if (wd->extra && wd->extra->hasMask) + toBePainted &= wd->extra->mask; + + wd->drawWidget(context->pdev, toBePainted, context->offset, context->flags, + context->sharedPainter, context->backingStore); } QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset) const { const bool deviceCoordinates = (system == Qt::DeviceCoordinates); + if (!context && deviceCoordinates) { + // Device coordinates without context not yet supported. + qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context"); + return QPixmap(); + } + QPoint pixmapOffset; + QRectF sourceRect = m_widget->rect(); - QRect sourceRect(m_widget->rect()); if (deviceCoordinates) { - pixmapOffset = m_widget->mapTo(m_widget->window(), QPoint()); - sourceRect.translate(pixmapOffset); + const QTransform &painterTransform = context->painter->worldTransform(); + sourceRect = painterTransform.mapRect(sourceRect); + pixmapOffset = painterTransform.map(pixmapOffset); } QRect effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect(); if (offset) *offset = effectRect.topLeft(); + + if (deviceCoordinates) { + // Clip to device rect. + int left, top, right, bottom; + effectRect.getCoords(&left, &top, &right, &bottom); + if (left < 0) { + if (offset) + offset->rx() += -left; + effectRect.setX(0); + } + if (top < 0) { + if (offset) + offset->ry() += -top; + effectRect.setY(0); + } + // NB! We use +-1 for historical reasons (see QRect documentation). + QPaintDevice *device = context->painter->device(); + const int deviceWidth = device->width(); + const int deviceHeight = device->height(); + if (right + 1 > deviceWidth) + effectRect.setRight(deviceWidth - 1); + if (bottom + 1 > deviceHeight) + effectRect.setBottom(deviceHeight -1); + } + pixmapOffset -= effectRect.topLeft(); QPixmap pixmap(effectRect.size()); diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index acfb6c3..69fcbbc 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -694,13 +694,7 @@ public: inline QRect deviceRect() const { return m_widget->window()->rect(); } - inline QRectF boundingRect(Qt::CoordinateSystem system) const - { - if (system == Qt::LogicalCoordinates) - return m_widget->rect(); - return m_widget->rect().translated(m_widget->mapTo(m_widget->window(), QPoint())); - } - + QRectF boundingRect(Qt::CoordinateSystem system) const; void draw(QPainter *p); QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset) const; diff --git a/src/gui/kernel/qwidget_qws.cpp b/src/gui/kernel/qwidget_qws.cpp index ea3cef2..98d48de 100644 --- a/src/gui/kernel/qwidget_qws.cpp +++ b/src/gui/kernel/qwidget_qws.cpp @@ -258,7 +258,7 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows) Q_D(QWidget); if (!isWindow() && parentWidget()) - parentWidget()->d_func()->invalidateBuffer(geometry()); + parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry())); d->deactivateWidgetCleanup(); if (testAttribute(Qt::WA_WState_Created)) { @@ -312,7 +312,7 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f) Q_Q(QWidget); bool wasCreated = q->testAttribute(Qt::WA_WState_Created); if (q->isVisible() && q->parentWidget() && parent != q->parentWidget()) - q->parentWidget()->d_func()->invalidateBuffer(q->geometry()); + q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(q->geometry())); #ifndef QT_NO_CURSOR QCursor oldcurs; bool setcurs=q->testAttribute(Qt::WA_SetCursor); @@ -805,7 +805,7 @@ void QWidgetPrivate::lower_sys() QWSChangeAltitudeCommand::Lower); } else if (QWidget *p = q->parentWidget()) { setDirtyOpaqueRegion(); - p->d_func()->invalidateBuffer(q->geometry()); + p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry())); } } @@ -814,7 +814,7 @@ void QWidgetPrivate::stackUnder_sys(QWidget*) Q_Q(QWidget); if (QWidget *p = q->parentWidget()) { setDirtyOpaqueRegion(); - p->d_func()->invalidateBuffer(q->geometry()); + p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry())); } } diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index 77ab590..5f7bb5a 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -535,7 +535,7 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows) { Q_D(QWidget); if (!isWindow() && parentWidget()) - parentWidget()->d_func()->invalidateBuffer(geometry()); + parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry())); d->deactivateWidgetCleanup(); if (testAttribute(Qt::WA_WState_Created)) { setAttribute(Qt::WA_WState_Created, false); @@ -597,7 +597,7 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) Q_Q(QWidget); bool wasCreated = q->testAttribute(Qt::WA_WState_Created); if (q->isVisible() && q->parentWidget() && parent != q->parentWidget()) - q->parentWidget()->d_func()->invalidateBuffer(q->geometry()); + q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(q->geometry())); WId old_winid = data.winid; // hide and reparent our own window away. Otherwise we might get diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp index de38b4c..a4ee21b 100644 --- a/src/gui/kernel/qwidget_x11.cpp +++ b/src/gui/kernel/qwidget_x11.cpp @@ -971,7 +971,7 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows) { Q_D(QWidget); if (!isWindow() && parentWidget()) - parentWidget()->d_func()->invalidateBuffer(geometry()); + parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry())); d->deactivateWidgetCleanup(); if (testAttribute(Qt::WA_WState_Created)) { setAttribute(Qt::WA_WState_Created, false); @@ -1050,7 +1050,7 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) QTLWExtra *topData = maybeTopData(); bool wasCreated = q->testAttribute(Qt::WA_WState_Created); if (q->isVisible() && q->parentWidget() && parent != q->parentWidget()) - q->parentWidget()->d_func()->invalidateBuffer(q->geometry()); + q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(q->geometry())); extern void qPRCreate(const QWidget *, Window); #ifndef QT_NO_CURSOR QCursor oldcurs; diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index fdbdef0..1c31e33 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -559,7 +559,8 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up } const QPoint offset = widget->mapTo(tlw, QPoint()); - if (qt_region_strictContains(dirty, widget->rect().translated(offset))) { + const QRect widgetRect = widget->d_func()->effectiveRectFor(widget->rect()); + if (qt_region_strictContains(dirty, widgetRect.translated(offset))) { if (updateImmediately) sendUpdateRequest(tlw, updateImmediately); return; // Already dirty. @@ -567,7 +568,10 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up if (invalidateBuffer) { const bool eventAlreadyPosted = !dirty.isEmpty(); - dirty += rgn.translated(offset); + if (widget->d_func()->graphicsEffect) + dirty += widget->d_func()->effectiveRectFor(rgn.boundingRect()).translated(offset); + else + dirty += rgn.translated(offset); if (!eventAlreadyPosted || updateImmediately) sendUpdateRequest(tlw, updateImmediately); return; @@ -580,8 +584,12 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up } if (widget->d_func()->inDirtyList) { - if (!qt_region_strictContains(widget->d_func()->dirty, widget->rect())) - widget->d_func()->dirty += rgn; + if (!qt_region_strictContains(widget->d_func()->dirty, widgetRect)) { + if (widget->d_func()->graphicsEffect) + widget->d_func()->dirty += widget->d_func()->effectiveRectFor(rgn.boundingRect()); + else + widget->d_func()->dirty += rgn; + } } else { addDirtyWidget(widget, rgn); } @@ -625,7 +633,8 @@ void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget, bool upd return; } - const QRect translatedRect(rect.translated(widget->mapTo(tlw, QPoint()))); + const QRect widgetRect = widget->d_func()->effectiveRectFor(rect); + const QRect translatedRect(widgetRect.translated(widget->mapTo(tlw, QPoint()))); if (qt_region_strictContains(dirty, translatedRect)) { if (updateImmediately) sendUpdateRequest(tlw, updateImmediately); @@ -647,8 +656,8 @@ void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget, bool upd } if (widget->d_func()->inDirtyList) { - if (!qt_region_strictContains(widget->d_func()->dirty, rect)) - widget->d_func()->dirty += rect; + if (!qt_region_strictContains(widget->d_func()->dirty, widgetRect)) + widget->d_func()->dirty += widgetRect; } else { addDirtyWidget(widget, rect); } @@ -880,7 +889,7 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy) && !isOverlapped(sourceRect) && !isOverlapped(destRect); if (!accelerateMove) { - QRegion parentR(parentRect); + QRegion parentR(effectiveRectFor(parentRect)); if (!extra || !extra->hasMask) { parentR -= newRect; } else { @@ -1384,7 +1393,7 @@ void QWidgetPrivate::invalidateBuffer_resizeHelper(const QPoint &oldPos, const Q const QRect newWidgetRect(q->rect()); const QRect oldWidgetRect(0, 0, oldSize.width(), oldSize.height()); - if (!staticContents) { + if (!staticContents || graphicsEffect) { QRegion staticChildren; QWidgetBackingStore *bs = 0; if (offset.isNull() && (bs = maybeBackingStore())) @@ -1404,19 +1413,19 @@ void QWidgetPrivate::invalidateBuffer_resizeHelper(const QPoint &oldPos, const Q return; // Invalidate newly exposed area of the parent. - if (extra && extra->hasMask) { + if (!graphicsEffect && extra && extra->hasMask) { QRegion parentExpose(extra->mask.translated(oldPos)); parentExpose &= QRect(oldPos, oldSize); if (hasStaticChildren) parentExpose -= data.crect; // Offset is unchanged, safe to do this. q->parentWidget()->d_func()->invalidateBuffer(parentExpose); } else { - if (hasStaticChildren) { + if (hasStaticChildren && !graphicsEffect) { QRegion parentExpose(QRect(oldPos, oldSize)); parentExpose -= data.crect; // Offset is unchanged, safe to do this. q->parentWidget()->d_func()->invalidateBuffer(parentExpose); } else { - q->parentWidget()->d_func()->invalidateBuffer(QRect(oldPos, oldSize)); + q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(QRect(oldPos, oldSize))); } } return; @@ -1474,7 +1483,7 @@ void QWidgetPrivate::invalidateBuffer(const QRegion &rgn) QRegion wrgn(rgn); wrgn &= clipRect(); - if (extra && extra->hasMask) + if (!graphicsEffect && extra && extra->hasMask) wrgn &= extra->mask; if (wrgn.isEmpty()) return; @@ -1502,7 +1511,7 @@ void QWidgetPrivate::invalidateBuffer(const QRect &rect) if (wRect.isEmpty()) return; - if (!extra || !extra->hasMask) { + if (graphicsEffect || !extra || !extra->hasMask) { tlwExtra->backingStore->markDirty(wRect, q, false, true); return; } diff --git a/src/gui/painting/qbackingstore_p.h b/src/gui/painting/qbackingstore_p.h index ddc0a59..b21d504 100644 --- a/src/gui/painting/qbackingstore_p.h +++ b/src/gui/painting/qbackingstore_p.h @@ -144,9 +144,13 @@ private: inline void addDirtyWidget(QWidget *widget, const QRegion &rgn) { if (widget && !widget->d_func()->inDirtyList && !widget->data->in_destructor) { - widget->d_func()->dirty = rgn; + QWidgetPrivate *widgetPrivate = widget->d_func(); + if (widgetPrivate->graphicsEffect) + widgetPrivate->dirty = widgetPrivate->effectiveRectFor(rgn.boundingRect()); + else + widgetPrivate->dirty = rgn; dirtyWidgets.append(widget); - widget->d_func()->inDirtyList = true; + widgetPrivate->inDirtyList = true; } } -- cgit v0.12 From 547224c750a090222836f90532ff405ed5171358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 20 Aug 2009 22:16:42 +0200 Subject: Add "QObject *parent = 0" to QGraphicsShaderEffect constructor. See also 39f5298ef2c0424e7b4916d8d1de1d46e534daee --- src/opengl/qgraphicsshadereffect.cpp | 4 ++-- src/opengl/qgraphicsshadereffect.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/opengl/qgraphicsshadereffect.cpp b/src/opengl/qgraphicsshadereffect.cpp index e8d9ae3..e8741b5 100644 --- a/src/opengl/qgraphicsshadereffect.cpp +++ b/src/opengl/qgraphicsshadereffect.cpp @@ -182,8 +182,8 @@ public: /*! Constructs a shader effect and attaches it to \a parent. */ -QGraphicsShaderEffect::QGraphicsShaderEffect() - : QGraphicsEffect(*new QGraphicsShaderEffectPrivate()) +QGraphicsShaderEffect::QGraphicsShaderEffect(QObject *parent) + : QGraphicsEffect(*new QGraphicsShaderEffectPrivate(), parent) { } diff --git a/src/opengl/qgraphicsshadereffect.h b/src/opengl/qgraphicsshadereffect.h index 29b7c9f..1612431 100644 --- a/src/opengl/qgraphicsshadereffect.h +++ b/src/opengl/qgraphicsshadereffect.h @@ -60,7 +60,7 @@ class Q_OPENGL_EXPORT QGraphicsShaderEffect : public QGraphicsEffect { Q_OBJECT public: - QGraphicsShaderEffect(); + QGraphicsShaderEffect(QObject *parent = 0); virtual ~QGraphicsShaderEffect(); QByteArray pixelShaderFragment() const; -- cgit v0.12 From de69a7c1dd558b4e9a119f2c63479d11cdbcaaf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 20 Aug 2009 22:30:48 +0200 Subject: Delete existing graphics effect when setting a new one. Before we had to delete the existing effect before setting a new one (in the same fashion as QLayout behaves). This feels wrong and we should automatically delete it instead. --- src/gui/graphicsview/qgraphicsitem.cpp | 11 ++++------- src/gui/kernel/qwidget.cpp | 17 ++++++++++++++--- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 5fa1748..b8187e7 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2240,9 +2240,8 @@ QGraphicsEffect *QGraphicsItem::graphicsEffect() const /*! Sets \a effect as the item's effect. If there already is an effect installed - on this item, QGraphicsItem won't let you install another. You must first - delete the existing effect (returned by graphicsEffect()) before you can call - setGraphicsEffect() with the new effect. + on this item, QGraphicsItem will delete the existing effect before installing + the new \a effect. If \a effect is the installed on a different item, setGraphicsEffect() will remove the effect from the item and install it on this item. @@ -2257,10 +2256,8 @@ void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect) return; if (d_ptr->graphicsEffect && effect) { - // ### This seems wrong - the effect should automatically be deleted. - qWarning("QGraphicsItem::setGraphicsEffect: Attempting to set QGraphicsEffect " - "%p on %p, which already has an effect installed", effect, this); - return; + delete d_ptr->graphicsEffect; + d_ptr->graphicsEffect = 0; } if (!effect) { diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index a9ef6aa..6928761 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -4870,6 +4870,18 @@ QGraphicsEffect *QWidget::graphicsEffect() const return d->graphicsEffect; } +/*! + Sets \a effect as the widget's effect. If there already is an effect installed + on this widget, QWidget will delete the existing effect before installing + the new \a effect. + + If \a effect is the installed on a different widget, setGraphicsEffect() will remove + the effect from the widget and install it on this widget. + + \note This function will apply the effect on itself and all its children. + + \since 4.6 +*/ void QWidget::setGraphicsEffect(QGraphicsEffect *effect) { Q_D(QWidget); @@ -4877,9 +4889,8 @@ void QWidget::setGraphicsEffect(QGraphicsEffect *effect) return; if (d->graphicsEffect && effect) { - // ### This seems wrong - the effect should automatically be deleted. - qWarning("already set"); - return; + delete d->graphicsEffect; + d->graphicsEffect = 0; } if (!effect) { -- cgit v0.12 From ae7a891627787e7925fecaa1e3430f1d31684688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 20 Aug 2009 22:44:23 +0200 Subject: Fix some rendering bugs on the Mac when applying an effect to QWidget. --- src/gui/kernel/qwidget_mac.mm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 999faeb..a10117d 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -2567,7 +2567,7 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows) { Q_D(QWidget); if (!isWindow() && parentWidget()) - parentWidget()->d_func()->invalidateBuffer(geometry()); + parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry())); d->deactivateWidgetCleanup(); qt_mac_event_release(this); if(testAttribute(Qt::WA_WState_Created)) { @@ -2669,7 +2669,7 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) OSViewRef old_id = 0; if (q->isVisible() && q->parentWidget() && parent != q->parentWidget()) - q->parentWidget()->d_func()->invalidateBuffer(q->geometry()); + q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(q->geometry())); // Maintain the glWidgets list on parent change: remove "our" gl widgets // from the list on the old parent and grandparents. @@ -4165,12 +4165,12 @@ void QWidgetPrivate::setGeometry_sys_helper(int x, int y, int w, int h, bool isM setWSGeometry(false, oldRect); if (isResize && QApplicationPrivate::graphicsSystem()) { invalidateBuffer(q->rect()); - if (extra && !extra->mask.isEmpty()) { + if (extra && !graphicsEffect && !extra->mask.isEmpty()) { QRegion oldRegion(extra->mask.translated(oldp)); oldRegion &= oldRect; q->parentWidget()->d_func()->invalidateBuffer(oldRegion); } else { - q->parentWidget()->d_func()->invalidateBuffer(oldRect); + q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(oldRect)); } } } -- cgit v0.12 From 487f636523dfded4c07a39e4d96ab3e83c64f95e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 21 Aug 2009 12:05:33 +0200 Subject: Add auto-tests for QGraphicsItem/QWidget::setGraphicsEffect. --- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 32 ++++++++++++++++++++++++++ tests/auto/qwidget/tst_qwidget.cpp | 32 ++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 184bfe2..931e2d3 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -285,6 +285,7 @@ private slots: void reverseCreateAutoFocusProxy(); void focusProxyDeletion(); void negativeZStacksBehindParent(); + void setGraphicsEffect(); // task specific tests below me void task141694_textItemEnsureVisible(); @@ -7708,5 +7709,36 @@ void tst_QGraphicsItem::negativeZStacksBehindParent() QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent); } +void tst_QGraphicsItem::setGraphicsEffect() +{ + // Check that we don't have any effect by default. + QGraphicsItem *item = new QGraphicsRectItem(0, 0, 10, 10); + QVERIFY(!item->graphicsEffect()); + + // SetGet check. + QPointer blurEffect = new QGraphicsBlurEffect; + item->setGraphicsEffect(blurEffect); + QCOMPARE(item->graphicsEffect(), static_cast(blurEffect)); + + // Ensure the existing effect is deleted when setting a new one. + QPointer shadowEffect = new QGraphicsDropShadowEffect; + item->setGraphicsEffect(shadowEffect); + QVERIFY(!blurEffect); + QCOMPARE(item->graphicsEffect(), static_cast(shadowEffect)); + blurEffect = new QGraphicsBlurEffect; + + // Ensure the effect is uninstalled when setting it on a new target. + QGraphicsItem *anotherItem = new QGraphicsRectItem(0, 0, 10, 10); + anotherItem->setGraphicsEffect(blurEffect); + item->setGraphicsEffect(blurEffect); + QVERIFY(!anotherItem->graphicsEffect()); + QVERIFY(!shadowEffect); + + // Ensure the existing effect is deleted when deleting the item. + delete item; + QVERIFY(!blurEffect); + delete anotherItem; +} + QTEST_MAIN(tst_QGraphicsItem) #include "tst_qgraphicsitem.moc" diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp index 34971a9..36f4ddf 100644 --- a/tests/auto/qwidget/tst_qwidget.cpp +++ b/tests/auto/qwidget/tst_qwidget.cpp @@ -355,6 +355,7 @@ private slots: void focusWidget_task254563(); void rectOutsideCoordinatesLimit_task144779(); + void setGraphicsEffect(); private: bool ensureScreenSize(int width, int height); @@ -9169,5 +9170,36 @@ void tst_QWidget::inputFocus_task257832() delete widget; } +void tst_QWidget::setGraphicsEffect() +{ + // Check that we don't have any effect by default. + QWidget *widget = new QWidget; + QVERIFY(!widget->graphicsEffect()); + + // SetGet check. + QPointer blurEffect = new QGraphicsBlurEffect; + widget->setGraphicsEffect(blurEffect); + QCOMPARE(widget->graphicsEffect(), static_cast(blurEffect)); + + // Ensure the existing effect is deleted when setting a new one. + QPointer shadowEffect = new QGraphicsDropShadowEffect; + widget->setGraphicsEffect(shadowEffect); + QVERIFY(!blurEffect); + QCOMPARE(widget->graphicsEffect(), static_cast(shadowEffect)); + blurEffect = new QGraphicsBlurEffect; + + // Ensure the effect is uninstalled when setting it on a new target. + QWidget *anotherWidget = new QWidget; + anotherWidget->setGraphicsEffect(blurEffect); + widget->setGraphicsEffect(blurEffect); + QVERIFY(!anotherWidget->graphicsEffect()); + QVERIFY(!shadowEffect); + + // Ensure the existing effect is deleted when deleting the widget. + delete widget; + QVERIFY(!blurEffect); + delete anotherWidget; +} + QTEST_MAIN(tst_QWidget) #include "tst_qwidget.moc" -- cgit v0.12 From 00d7d50cde5d1e491039149d58502e17dba9b3b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 21 Aug 2009 11:33:44 +0200 Subject: Use pixmap filter for the drop shadow effect. --- examples/effects/lighting/shadoweffect.cpp | 6 +- examples/effects/lighting/shadoweffect.h | 1 + src/gui/effects/qgraphicseffect.cpp | 155 +++++-------------------- src/gui/effects/qgraphicseffect.h | 24 ++-- src/gui/effects/qgraphicseffect_p.h | 10 +- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 2 +- 6 files changed, 48 insertions(+), 150 deletions(-) diff --git a/examples/effects/lighting/shadoweffect.cpp b/examples/effects/lighting/shadoweffect.cpp index 9545815..8a41aaa 100644 --- a/examples/effects/lighting/shadoweffect.cpp +++ b/examples/effects/lighting/shadoweffect.cpp @@ -48,17 +48,19 @@ ShadowEffect::ShadowEffect(QGraphicsItem *item, QGraphicsItem *source) , item(item), m_lightSource(source) { setBlurRadius(8); + m_color = color(); } void ShadowEffect::adjustForItem() { QPointF delta = item->pos() - m_lightSource->pos(); - setShadowOffset(delta.toPoint() / 30); + setOffset(delta.toPoint() / 30); qreal dx = delta.x(); qreal dy = delta.y(); qreal dd = sqrt(dx * dx + dy * dy); - setOpacity(qBound(0.4, 1 - dd / 200.0, 0.7)); + m_color.setAlphaF(qBound(0.4, 1 - dd / 200.0, 0.7)); + setColor(m_color); } QRectF ShadowEffect::boundingRectFor(const QRectF &rect) const diff --git a/examples/effects/lighting/shadoweffect.h b/examples/effects/lighting/shadoweffect.h index b20f647..7ea409e 100644 --- a/examples/effects/lighting/shadoweffect.h +++ b/examples/effects/lighting/shadoweffect.h @@ -58,6 +58,7 @@ private: void adjustForItem(); private: + QColor m_color; QGraphicsItem *item; QGraphicsItem *m_lightSource; }; diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index 3d363f1..949922a 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -432,71 +432,6 @@ QGraphicsBlurEffect::~QGraphicsBlurEffect() { } -// Blur the image according to the blur radius -// Based on exponential blur algorithm by Jani Huhtanen -// (maximum radius is set to 16) -static QImage blurred(const QImage& image, const QRect& rect, int radius) -{ - int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 }; - int alpha = (radius < 1) ? 16 : (radius > 17) ? 1 : tab[radius-1]; - - QImage result = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); - int r1 = rect.top(); - int r2 = rect.bottom(); - int c1 = rect.left(); - int c2 = rect.right(); - - int bpl = result.bytesPerLine(); - int rgba[4]; - unsigned char* p; - - for (int col = c1; col <= c2; col++) { - p = result.scanLine(r1) + col * 4; - for (int i = 0; i < 4; i++) - rgba[i] = p[i] << 4; - - p += bpl; - for (int j = r1; j < r2; j++, p += bpl) - for (int i = 0; i < 4; i++) - p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; - } - - for (int row = r1; row <= r2; row++) { - p = result.scanLine(row) + c1 * 4; - for (int i = 0; i < 4; i++) - rgba[i] = p[i] << 4; - - p += 4; - for (int j = c1; j < c2; j++, p += 4) - for (int i = 0; i < 4; i++) - p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; - } - - for (int col = c1; col <= c2; col++) { - p = result.scanLine(r2) + col * 4; - for (int i = 0; i < 4; i++) - rgba[i] = p[i] << 4; - - p -= bpl; - for (int j = r1; j < r2; j++, p -= bpl) - for (int i = 0; i < 4; i++) - p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; - } - - for (int row = r1; row <= r2; row++) { - p = result.scanLine(row) + c2 * 4; - for (int i = 0; i < 4; i++) - rgba[i] = p[i] << 4; - - p -= 4; - for (int j = c1; j < c2; j++, p -= 4) - for (int i = 0; i < 4; i++) - p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; - } - - return result; -} - int QGraphicsBlurEffect::blurRadius() const { Q_D(const QGraphicsBlurEffect); @@ -553,121 +488,83 @@ QGraphicsDropShadowEffect::~QGraphicsDropShadowEffect() { } -QPointF QGraphicsDropShadowEffect::shadowOffset() const +QPointF QGraphicsDropShadowEffect::offset() const { Q_D(const QGraphicsDropShadowEffect); - return d->offset; + return d->filter->offset(); } -void QGraphicsDropShadowEffect::setShadowOffset(const QPointF &ofs) +void QGraphicsDropShadowEffect::setOffset(const QPointF &ofs) { Q_D(QGraphicsDropShadowEffect); - if (d->offset == ofs) + if (d->filter->offset() == ofs) return; - d->offset = ofs; + d->filter->setOffset(ofs); updateBoundingRect(); - emit shadowOffsetChanged(ofs); + emit offsetChanged(ofs); } int QGraphicsDropShadowEffect::blurRadius() const { Q_D(const QGraphicsDropShadowEffect); - return d->radius; + return d->filter->blurRadius(); } void QGraphicsDropShadowEffect::setBlurRadius(int blurRadius) { Q_D(QGraphicsDropShadowEffect); - if (d->radius == blurRadius) + if (d->filter->blurRadius() == blurRadius) return; - d->radius = blurRadius; + d->filter->setBlurRadius(blurRadius); updateBoundingRect(); emit blurRadiusChanged(blurRadius); } -qreal QGraphicsDropShadowEffect::opacity() const +QColor QGraphicsDropShadowEffect::color() const { Q_D(const QGraphicsDropShadowEffect); - return d->alpha; + return d->filter->color(); } -void QGraphicsDropShadowEffect::setOpacity(qreal opacity) +void QGraphicsDropShadowEffect::setColor(const QColor &color) { Q_D(QGraphicsDropShadowEffect); - if (qFuzzyCompare(d->alpha, opacity)) + if (d->filter->color() == color) return; - d->alpha = opacity; - emit opacityChanged(opacity); + d->filter->setColor(color); + emit colorChanged(color); } QRectF QGraphicsDropShadowEffect::boundingRectFor(const QRectF &rect) const { Q_D(const QGraphicsDropShadowEffect); - QRectF shadowRect = rect.translated(d->offset); - QRectF blurRect = shadowRect; - qreal delta = d->radius * 3; - blurRect.adjust(-delta, -delta, delta, delta); - blurRect |= rect; - return blurRect; + return d->filter->boundingRectFor(rect); } void QGraphicsDropShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsDropShadowEffect); - if (d->radius <= 0 && d->offset.isNull()) { + if (d->filter->blurRadius() <= 0 && d->filter->offset().isNull()) { source->draw(painter); return; } - const QTransform &transform = painter->worldTransform(); - const QPointF offset(d->offset.x() * transform.m11(), d->offset.y() * transform.m22()); - const QPoint shadowOffset = offset.toPoint(); - const QRectF sourceRect = source->boundingRect(Qt::DeviceCoordinates); - const QRectF shadowRect = sourceRect.translated(offset); - - QRectF blurRect = shadowRect; - qreal delta = d->radius * 3; - blurRect.adjust(-delta, -delta, delta, delta); - blurRect |= sourceRect; - - QRect effectRect = blurRect.toAlignedRect(); - const QRect deviceRect = source->deviceRect(); - const bool fullyInsideDeviceRect = effectRect.x() >= deviceRect.x() - && effectRect.right() <= deviceRect.right() - && effectRect.y() >= deviceRect.y() - && effectRect.bottom() <= deviceRect.bottom(); - if (!fullyInsideDeviceRect) { - // Clip to device rect to avoid huge pixmaps. - effectRect &= source->deviceRect(); - effectRect |= effectRect.translated(-shadowOffset); - if (effectRect.isEmpty()) - return; // nothing to paint; + 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; } - QPixmap pixmap(effectRect.size()); - pixmap.fill(Qt::transparent); - QPainter pixmapPainter(&pixmap); - pixmapPainter.setRenderHints(painter->renderHints()); - pixmapPainter.setWorldTransform(painter->worldTransform()); - if (effectRect.x() != 0 || effectRect.y() != 0) - pixmapPainter.translate(-effectRect.topLeft()); - source->draw(&pixmapPainter); - pixmapPainter.end(); - - QImage img = pixmap.toImage(); - QImage shadowImage(img.size(), QImage::Format_ARGB32); - shadowImage.fill(qRgba(0, 0, 0, d->alpha * 255)); - shadowImage.setAlphaChannel(img.alphaChannel()); - shadowImage = blurred(shadowImage, shadowImage.rect(), d->radius); - - // Draw using an untransformed painter. + // Draw pixmap in device coordinates to avoid pixmap scaling. + const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - painter->drawImage(effectRect.topLeft() + shadowOffset, shadowImage); - painter->drawPixmap(effectRect.topLeft(), pixmap); + d->filter->draw(painter, offset, pixmap); painter->setWorldTransform(restoreTransform); } diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h index f6c47d7..99d8548 100644 --- a/src/gui/effects/qgraphicseffect.h +++ b/src/gui/effects/qgraphicseffect.h @@ -235,31 +235,31 @@ class QGraphicsDropShadowEffectPrivate; class Q_GUI_EXPORT QGraphicsDropShadowEffect: public QGraphicsEffect { Q_OBJECT - Q_PROPERTY(QPointF shadowOffset READ shadowOffset WRITE setShadowOffset NOTIFY shadowOffsetChanged) + Q_PROPERTY(QPointF offset READ offset WRITE setOffset NOTIFY offsetChanged) Q_PROPERTY(int blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) - Q_PROPERTY(int opacity READ opacity WRITE setOpacity NOTIFY opacityChanged) + Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) public: QGraphicsDropShadowEffect(QObject *parent = 0); ~QGraphicsDropShadowEffect(); QRectF boundingRectFor(const QRectF &rect) const; - QPointF shadowOffset() const; + QPointF offset() const; int blurRadius() const; - qreal opacity() const; + QColor color() const; public Q_SLOTS: - void setShadowOffset(const QPointF &ofs); - inline void setShadowOffset(qreal dx, qreal dy) - { setShadowOffset(QPointF(dx, dy)); } - inline void setShadowOffset(qreal d) - { setShadowOffset(QPointF(d, d)); } + void setOffset(const QPointF &ofs); + inline void setOffset(qreal dx, qreal dy) + { setOffset(QPointF(dx, dy)); } + inline void setOffset(qreal d) + { setOffset(QPointF(d, d)); } void setBlurRadius(int blurRadius); - void setOpacity(qreal opacity); + void setColor(const QColor &color); Q_SIGNALS: - void shadowOffsetChanged(const QPointF &offset); + void offsetChanged(const QPointF &offset); void blurRadiusChanged(int blurRadius); - void opacityChanged(int opacity); + void colorChanged(const QColor &color); protected: void draw(QPainter *painter, QGraphicsEffectSource *source); diff --git a/src/gui/effects/qgraphicseffect_p.h b/src/gui/effects/qgraphicseffect_p.h index 25397c3..35f2d40 100644 --- a/src/gui/effects/qgraphicseffect_p.h +++ b/src/gui/effects/qgraphicseffect_p.h @@ -144,22 +144,20 @@ class QGraphicsBlurEffectPrivate : public QGraphicsEffectPrivate { Q_DECLARE_PUBLIC(QGraphicsBlurEffect) public: - QGraphicsBlurEffectPrivate() : filter(new QPixmapBlurFilter), blurRadius(4) {} + QGraphicsBlurEffectPrivate() : filter(new QPixmapBlurFilter) {} ~QGraphicsBlurEffectPrivate() { delete filter; } QPixmapBlurFilter *filter; - int blurRadius; }; class QGraphicsDropShadowEffectPrivate : public QGraphicsEffectPrivate { Q_DECLARE_PUBLIC(QGraphicsDropShadowEffect) public: - QGraphicsDropShadowEffectPrivate() : offset(4, 4), radius(8), alpha(0.7) {} + QGraphicsDropShadowEffectPrivate() : filter(new QPixmapDropShadowFilter) {} + ~QGraphicsDropShadowEffectPrivate() { delete filter; } - QPointF offset; - int radius; - qreal alpha; + QPixmapDropShadowFilter *filter; }; QT_END_NAMESPACE diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 931e2d3..c335f16 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -7420,7 +7420,7 @@ void tst_QGraphicsItem::hitTestGraphicsEffectItem() // Apply shadow effect to the entire sub-tree. QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect; - shadow->setShadowOffset(-20, -20); + shadow->setOffset(-20, -20); item1->setGraphicsEffect(shadow); QTest::qWait(50); -- cgit v0.12 From 9d639659f2334bb5f3ea9b16b23bcb0127752f64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 21 Aug 2009 12:27:17 +0200 Subject: Fix broken drop shadow pixmap filter on X11. Xrender is not rocket science when it comes to composition modes, so we have to use the raster engine for the fill. toImage/fromImage is a no-op on QWS and Windows, and on other platforms it is required, so we don't have to add any ifdefs or clever checks. Reviewed-by: Gunnar --- src/gui/image/qpixmapfilter.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp index e95cf89..f7de80d 100644 --- a/src/gui/image/qpixmapfilter.cpp +++ b/src/gui/image/qpixmapfilter.cpp @@ -1047,7 +1047,7 @@ void QPixmapDropShadowFilter::draw(QPainter *p, { Q_D(const QPixmapDropShadowFilter); - QPixmap tmp = src.isNull() ? px : px.copy(src.toRect()); + QImage tmp = src.isNull() ? px : px.copy(src.toRect()).toImage(); QPainter tmpPainter(&tmp); // blacken the image... @@ -1055,8 +1055,10 @@ void QPixmapDropShadowFilter::draw(QPainter *p, tmpPainter.fillRect(0, 0, tmp.width(), tmp.height(), d->color); tmpPainter.end(); + const QPixmap pixTmp = QPixmap::fromImage(tmp); + // draw the blurred drop shadow... - d->convolution->draw(p, pos + d->offset, tmp); + d->convolution->draw(p, pos + d->offset, pixTmp); // Draw the actual pixmap... p->drawPixmap(pos, px, src); -- cgit v0.12 From a23dab51f5f0bce3294cc814efc3db402ea92116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 21 Aug 2009 12:37:15 +0200 Subject: Add an alpha to the drop shadow pixmap filter by the default. Shadows looks much nicer with an alpha, so we should use it by default. Reviewed-by: Gunnar --- src/gui/image/qpixmapfilter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp index f7de80d..4b08227 100644 --- a/src/gui/image/qpixmapfilter.cpp +++ b/src/gui/image/qpixmapfilter.cpp @@ -852,7 +852,7 @@ public: QPixmapDropShadowFilterPrivate() : offset(8, 8), radius(1), - color(63, 63, 63, 255) { + color(63, 63, 63, 180) { } QPointF offset; -- cgit v0.12 From 97cec103793a4b9aae8337ffc2ce9a2bd98fb5fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 21 Aug 2009 13:43:53 +0200 Subject: Improve performance of the drop shadow pixmap filter. The convolution filter is horrible slow. Instead we use a custom blur filter which is much more efficient. Reviewed-by: Samuel --- src/gui/image/qpixmapfilter.cpp | 42 ++++++++++++++--------------------------- src/gui/image/qpixmapfilter_p.h | 4 ++-- 2 files changed, 16 insertions(+), 30 deletions(-) diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp index 4b08227..0bb948b 100644 --- a/src/gui/image/qpixmapfilter.cpp +++ b/src/gui/image/qpixmapfilter.cpp @@ -850,16 +850,11 @@ class QPixmapDropShadowFilterPrivate : public QPixmapFilterPrivate { public: QPixmapDropShadowFilterPrivate() - : offset(8, 8), - radius(1), - color(63, 63, 63, 180) { - } + : offset(8, 8), color(63, 63, 63, 180), blurFilter(new QPixmapBlurFilter) {} QPointF offset; - qreal radius; QColor color; - - QPixmapConvolutionFilter *convolution; + QPixmapBlurFilter *blurFilter; }; /*! @@ -904,9 +899,7 @@ QPixmapDropShadowFilter::QPixmapDropShadowFilter(QObject *parent) : QPixmapFilter(*new QPixmapDropShadowFilterPrivate, DropShadowFilter, parent) { Q_D(QPixmapDropShadowFilter); - d->convolution = new QPixmapConvolutionFilter; - - setBlurRadius(1); + d->blurFilter->setRadius(1); } /*! @@ -917,7 +910,7 @@ QPixmapDropShadowFilter::QPixmapDropShadowFilter(QObject *parent) QPixmapDropShadowFilter::~QPixmapDropShadowFilter() { Q_D(QPixmapDropShadowFilter); - delete d->convolution; + delete d->blurFilter; } /*! @@ -929,10 +922,10 @@ QPixmapDropShadowFilter::~QPixmapDropShadowFilter() \internal */ -qreal QPixmapDropShadowFilter::blurRadius() const +int QPixmapDropShadowFilter::blurRadius() const { Q_D(const QPixmapDropShadowFilter); - return d->radius; + return d->blurFilter->radius(); } /*! @@ -944,18 +937,10 @@ qreal QPixmapDropShadowFilter::blurRadius() const \internal */ -void QPixmapDropShadowFilter::setBlurRadius(qreal radius) +void QPixmapDropShadowFilter::setBlurRadius(int radius) { Q_D(QPixmapDropShadowFilter); - - d->radius = radius; - - int dim = 2 * qRound(radius) + 1; - QVarLengthArray arr(dim * dim); - qreal f = 1 / qreal(dim * dim); - for (int i = 0; i < dim * dim; ++i) - arr[i] = f; - d->convolution->setConvolutionKernel(arr.data(), dim, dim); + d->blurFilter->setRadius(radius); } /*! @@ -1029,10 +1014,11 @@ QRectF QPixmapDropShadowFilter::boundingRectFor(const QRectF &rect) const { Q_D(const QPixmapDropShadowFilter); - qreal x1 = qMin(rect.left(), rect.left() + d->offset.x() - d->radius); - qreal y1 = qMin(rect.top(), rect.top() + d->offset.y() - d->radius); - qreal x2 = qMax(rect.right(), rect.right() + d->offset.x() + d->radius); - qreal y2 = qMax(rect.bottom(), rect.bottom() + d->offset.y() + d->radius); + const qreal delta = qreal(d->blurFilter->radius() * 2); + qreal x1 = qMin(rect.left(), rect.left() + d->offset.x() - delta); + qreal y1 = qMin(rect.top(), rect.top() + d->offset.y() - delta); + qreal x2 = qMax(rect.right(), rect.right() + d->offset.x() + delta); + qreal y2 = qMax(rect.bottom(), rect.bottom() + d->offset.y() + delta); return QRectF(x1, y1, x2 - x1, y2 - y1); } @@ -1058,7 +1044,7 @@ void QPixmapDropShadowFilter::draw(QPainter *p, const QPixmap pixTmp = QPixmap::fromImage(tmp); // draw the blurred drop shadow... - d->convolution->draw(p, pos + d->offset, pixTmp); + d->blurFilter->draw(p, pos + d->offset, pixTmp); // Draw the actual pixmap... p->drawPixmap(pos, px, src); diff --git a/src/gui/image/qpixmapfilter_p.h b/src/gui/image/qpixmapfilter_p.h index 8456cdd..29d919d 100644 --- a/src/gui/image/qpixmapfilter_p.h +++ b/src/gui/image/qpixmapfilter_p.h @@ -172,8 +172,8 @@ public: QRectF boundingRectFor(const QRectF &rect) const; void draw(QPainter *p, const QPointF &pos, const QPixmap &px, const QRectF &src = QRectF()) const; - qreal blurRadius() const; - void setBlurRadius(qreal radius); + int blurRadius() const; + void setBlurRadius(int radius); QColor color() const; void setColor(const QColor &color); -- cgit v0.12 From ceb4df5262ca41ff9314b36af9a3be19ffe24a76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 21 Aug 2009 14:33:07 +0200 Subject: Move shader effect example from examples/graphicsview to examples/effects --- examples/effects/customshader/blureffect.cpp | 69 +++++++++++ examples/effects/customshader/blureffect.h | 67 ++++++++++ examples/effects/customshader/blurpicker.cpp | 137 +++++++++++++++++++++ examples/effects/customshader/blurpicker.h | 74 +++++++++++ examples/effects/customshader/blurpicker.qrc | 14 +++ examples/effects/customshader/customshader.pro | 10 ++ .../effects/customshader/customshadereffect.cpp | 72 +++++++++++ examples/effects/customshader/customshadereffect.h | 64 ++++++++++ examples/effects/customshader/images/README.txt | 5 + .../customshader/images/accessories-calculator.png | Bin 0 -> 3760 bytes .../images/accessories-text-editor.png | Bin 0 -> 4746 bytes .../effects/customshader/images/background.jpg | Bin 0 -> 16259 bytes .../effects/customshader/images/help-browser.png | Bin 0 -> 5392 bytes .../customshader/images/internet-group-chat.png | Bin 0 -> 2809 bytes .../effects/customshader/images/internet-mail.png | Bin 0 -> 3899 bytes .../customshader/images/internet-web-browser.png | Bin 0 -> 6376 bytes .../customshader/images/office-calendar.png | Bin 0 -> 4010 bytes .../effects/customshader/images/system-users.png | Bin 0 -> 5353 bytes examples/effects/customshader/main.cpp | 55 +++++++++ examples/effects/effects.pro | 3 +- examples/graphicsview/customshader/blureffect.cpp | 69 ----------- examples/graphicsview/customshader/blureffect.h | 67 ---------- examples/graphicsview/customshader/blurpicker.cpp | 137 --------------------- examples/graphicsview/customshader/blurpicker.h | 74 ----------- examples/graphicsview/customshader/blurpicker.qrc | 14 --- .../graphicsview/customshader/customshader.pro | 10 -- .../customshader/customshadereffect.cpp | 72 ----------- .../graphicsview/customshader/customshadereffect.h | 64 ---------- examples/graphicsview/customshader/main.cpp | 55 --------- 29 files changed, 569 insertions(+), 563 deletions(-) create mode 100644 examples/effects/customshader/blureffect.cpp create mode 100644 examples/effects/customshader/blureffect.h create mode 100644 examples/effects/customshader/blurpicker.cpp create mode 100644 examples/effects/customshader/blurpicker.h create mode 100644 examples/effects/customshader/blurpicker.qrc create mode 100644 examples/effects/customshader/customshader.pro create mode 100644 examples/effects/customshader/customshadereffect.cpp create mode 100644 examples/effects/customshader/customshadereffect.h create mode 100644 examples/effects/customshader/images/README.txt create mode 100644 examples/effects/customshader/images/accessories-calculator.png create mode 100644 examples/effects/customshader/images/accessories-text-editor.png create mode 100644 examples/effects/customshader/images/background.jpg create mode 100644 examples/effects/customshader/images/help-browser.png create mode 100644 examples/effects/customshader/images/internet-group-chat.png create mode 100644 examples/effects/customshader/images/internet-mail.png create mode 100644 examples/effects/customshader/images/internet-web-browser.png create mode 100644 examples/effects/customshader/images/office-calendar.png create mode 100644 examples/effects/customshader/images/system-users.png create mode 100644 examples/effects/customshader/main.cpp delete mode 100644 examples/graphicsview/customshader/blureffect.cpp delete mode 100644 examples/graphicsview/customshader/blureffect.h delete mode 100644 examples/graphicsview/customshader/blurpicker.cpp delete mode 100644 examples/graphicsview/customshader/blurpicker.h delete mode 100644 examples/graphicsview/customshader/blurpicker.qrc delete mode 100644 examples/graphicsview/customshader/customshader.pro delete mode 100644 examples/graphicsview/customshader/customshadereffect.cpp delete mode 100644 examples/graphicsview/customshader/customshadereffect.h delete mode 100644 examples/graphicsview/customshader/main.cpp diff --git a/examples/effects/customshader/blureffect.cpp b/examples/effects/customshader/blureffect.cpp new file mode 100644 index 0000000..2b5237b --- /dev/null +++ b/examples/effects/customshader/blureffect.cpp @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "blureffect.h" + +#include + +BlurEffect::BlurEffect(QGraphicsItem *item) + : QGraphicsBlurEffect() + , m_baseLine(200), item(item) +{ +} + +void BlurEffect::adjustForItem() +{ + qreal y = m_baseLine - item->pos().y(); + qreal radius = qBound(0.0, y / 32, 16.0); + setBlurRadius(radius); +} + +QRectF BlurEffect::boundingRectFor(const QRectF &rect) const +{ + const_cast(this)->adjustForItem(); + return QGraphicsBlurEffect::boundingRectFor(rect); +} + +void BlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) +{ + adjustForItem(); + QGraphicsBlurEffect::draw(painter, source); +} diff --git a/examples/effects/customshader/blureffect.h b/examples/effects/customshader/blureffect.h new file mode 100644 index 0000000..bf72226 --- /dev/null +++ b/examples/effects/customshader/blureffect.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BLUREFFECT_H +#define BLUREFFECT_H + +#include +#include + +class BlurEffect: public QGraphicsBlurEffect +{ +public: + BlurEffect(QGraphicsItem *item); + + void setBaseLine(qreal y) { m_baseLine = y; } + + QRectF boundingRectFor(const QRectF &) const; + + void draw(QPainter *painter, QGraphicsEffectSource*); + +private: + void adjustForItem(); + +private: + qreal m_baseLine; + QGraphicsItem *item; +}; + +#endif // BLUREFFECT_H diff --git a/examples/effects/customshader/blurpicker.cpp b/examples/effects/customshader/blurpicker.cpp new file mode 100644 index 0000000..de80312 --- /dev/null +++ b/examples/effects/customshader/blurpicker.cpp @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "blurpicker.h" + +#include + +#include "blureffect.h" +#include "customshadereffect.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +BlurPicker::BlurPicker(QWidget *parent): QGraphicsView(parent), m_index(0.0) +{ + setBackgroundBrush(QPixmap(":/images/background.jpg")); + setScene(&m_scene); + + setupScene(); + updateIconPositions(); + + connect(&m_timeLine, SIGNAL(valueChanged(qreal)), SLOT(updateIconPositions())); + m_timeLine.setDuration(400); + + setRenderHint(QPainter::Antialiasing, true); + setFrameStyle(QFrame::NoFrame); +} + +void BlurPicker::updateIconPositions() +{ + m_index = m_timeLine.currentFrame() / 1000.0; + + qreal baseline = 0; + for (int i = 0; i < m_icons.count(); ++i) { + QGraphicsItem *icon = m_icons[i]; + qreal a = ((i + m_index) * 2 * M_PI) / m_icons.count(); + qreal xs = 170 * sin(a); + qreal ys = 100 * cos(a); + QPointF pos(xs, ys); + pos = QTransform().rotate(-20).map(pos); + pos -= QPointF(40, 40); + icon->setPos(pos); + baseline = qMax(baseline, ys); + if (i != 3) + static_cast(icon->graphicsEffect())->setBaseLine(baseline); + } + + m_scene.update(); +} + +void BlurPicker::setupScene() +{ + m_scene.setSceneRect(-200, -120, 400, 240); + + QStringList names; + names << ":/images/accessories-calculator.png"; + names << ":/images/accessories-text-editor.png"; + names << ":/images/help-browser.png"; + names << ":/images/internet-group-chat.png"; + names << ":/images/internet-mail.png"; + names << ":/images/internet-web-browser.png"; + names << ":/images/office-calendar.png"; + names << ":/images/system-users.png"; + + for (int i = 0; i < names.count(); i++) { + QPixmap pixmap(names[i]); + QGraphicsPixmapItem *icon = m_scene.addPixmap(pixmap); + icon->setZValue(1); + if (i == 3) + icon->setGraphicsEffect(new CustomShaderEffect()); + else + icon->setGraphicsEffect(new BlurEffect(icon)); + m_icons << icon; + } + + QGraphicsPixmapItem *bg = m_scene.addPixmap(QPixmap(":/images/background.jpg")); + bg->setZValue(0); + bg->setPos(-200, -150); +} + +void BlurPicker::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_Left) { + if (m_timeLine.state() == QTimeLine::NotRunning) { + m_timeLine.setFrameRange(m_index * 1000, m_index * 1000 - 1000); + m_timeLine.start(); + event->accept(); + } + } + + if (event->key() == Qt::Key_Right) { + if (m_timeLine.state() == QTimeLine::NotRunning) { + m_timeLine.setFrameRange(m_index * 1000, m_index * 1000 + 1000); + m_timeLine.start(); + event->accept(); + } + } +} diff --git a/examples/effects/customshader/blurpicker.h b/examples/effects/customshader/blurpicker.h new file mode 100644 index 0000000..b7ea3b4 --- /dev/null +++ b/examples/effects/customshader/blurpicker.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BLURPICKER_H +#define BLURPICKER_H + +#include +#include +#include + +#include "blureffect.h" + +class BlurPicker: public QGraphicsView +{ + Q_OBJECT + +public: + BlurPicker(QWidget *parent = 0); + +protected: + void keyPressEvent(QKeyEvent *event); + +private slots: + void updateIconPositions(); + +private: + void setupScene(); + +private: + qreal m_index; + QGraphicsScene m_scene; + QList m_icons; + QTimeLine m_timeLine; +}; + +#endif // BLURPICKER_H diff --git a/examples/effects/customshader/blurpicker.qrc b/examples/effects/customshader/blurpicker.qrc new file mode 100644 index 0000000..e88eaca --- /dev/null +++ b/examples/effects/customshader/blurpicker.qrc @@ -0,0 +1,14 @@ + + + images/background.jpg + images/accessories-calculator.png + images/accessories-text-editor.png + images/help-browser.png + images/internet-group-chat.png + images/internet-mail.png + images/internet-web-browser.png + images/office-calendar.png + images/system-users.png + + + diff --git a/examples/effects/customshader/customshader.pro b/examples/effects/customshader/customshader.pro new file mode 100644 index 0000000..4ce5d2b --- /dev/null +++ b/examples/effects/customshader/customshader.pro @@ -0,0 +1,10 @@ +SOURCES += main.cpp blurpicker.cpp blureffect.cpp customshadereffect.cpp +HEADERS += blurpicker.h blureffect.h customshadereffect.h +RESOURCES += blurpicker.qrc +QT += opengl + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/effects/customshader +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS customshader.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/effects/customshader +INSTALLS += target sources diff --git a/examples/effects/customshader/customshadereffect.cpp b/examples/effects/customshader/customshadereffect.cpp new file mode 100644 index 0000000..293123c --- /dev/null +++ b/examples/effects/customshader/customshadereffect.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "customshadereffect.h" +#include + +static char const colorizeShaderCode[] = + "varying highp vec2 textureCoords;\n" + "uniform sampler2D imageTexture;\n" + "uniform lowp vec4 effectColor;\n" + "lowp vec4 srcPixel() {\n" + " vec4 src = texture2D(imageTexture, textureCoords);\n" + " float gray = dot(src.rgb, vec3(0.212671, 0.715160, 0.072169));\n" + " vec4 colorize = 1.0-((1.0-gray)*(1.0-effectColor));\n" + " return vec4(colorize.rgb, src.a);\n" + "}"; + +CustomShaderEffect::CustomShaderEffect() + : QGraphicsShaderEffect(), + color(Qt::red) +{ + setPixelShaderFragment(colorizeShaderCode); +} + +void CustomShaderEffect::setEffectColor(const QColor& c) +{ + color = c; + setUniformsDirty(); +} + +void CustomShaderEffect::setUniforms(QGLShaderProgram *program) +{ + program->setUniformValue("effectColor", color); +} diff --git a/examples/effects/customshader/customshadereffect.h b/examples/effects/customshader/customshadereffect.h new file mode 100644 index 0000000..6482bd5 --- /dev/null +++ b/examples/effects/customshader/customshadereffect.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CUSTOMSHADEREFFECT_H +#define CUSTOMSHADEREFFECT_H + +#include +#include +#include + +class CustomShaderEffect: public QGraphicsShaderEffect +{ +public: + CustomShaderEffect(); + + QColor effectColor() const { return color; } + void setEffectColor(const QColor& c); + +protected: + void setUniforms(QGLShaderProgram *program); + +private: + QColor color; +}; + +#endif // CUSTOMSHADEREFFECT_H diff --git a/examples/effects/customshader/images/README.txt b/examples/effects/customshader/images/README.txt new file mode 100644 index 0000000..0927e17 --- /dev/null +++ b/examples/effects/customshader/images/README.txt @@ -0,0 +1,5 @@ +The background is taken from a public domain photo at: +http://www.photos8.com/view/computer_board2-800x600.html + +All other icons are from the Tango Desktop project: +http://tango.freedesktop.org/Tango_Desktop_Project diff --git a/examples/effects/customshader/images/accessories-calculator.png b/examples/effects/customshader/images/accessories-calculator.png new file mode 100644 index 0000000..4e7661f Binary files /dev/null and b/examples/effects/customshader/images/accessories-calculator.png differ diff --git a/examples/effects/customshader/images/accessories-text-editor.png b/examples/effects/customshader/images/accessories-text-editor.png new file mode 100644 index 0000000..33bef0b Binary files /dev/null and b/examples/effects/customshader/images/accessories-text-editor.png differ diff --git a/examples/effects/customshader/images/background.jpg b/examples/effects/customshader/images/background.jpg new file mode 100644 index 0000000..e75b388 Binary files /dev/null and b/examples/effects/customshader/images/background.jpg differ diff --git a/examples/effects/customshader/images/help-browser.png b/examples/effects/customshader/images/help-browser.png new file mode 100644 index 0000000..8ef4fae Binary files /dev/null and b/examples/effects/customshader/images/help-browser.png differ diff --git a/examples/effects/customshader/images/internet-group-chat.png b/examples/effects/customshader/images/internet-group-chat.png new file mode 100644 index 0000000..dd92d93 Binary files /dev/null and b/examples/effects/customshader/images/internet-group-chat.png differ diff --git a/examples/effects/customshader/images/internet-mail.png b/examples/effects/customshader/images/internet-mail.png new file mode 100644 index 0000000..7e6b93b Binary files /dev/null and b/examples/effects/customshader/images/internet-mail.png differ diff --git a/examples/effects/customshader/images/internet-web-browser.png b/examples/effects/customshader/images/internet-web-browser.png new file mode 100644 index 0000000..a979a92 Binary files /dev/null and b/examples/effects/customshader/images/internet-web-browser.png differ diff --git a/examples/effects/customshader/images/office-calendar.png b/examples/effects/customshader/images/office-calendar.png new file mode 100644 index 0000000..e095906 Binary files /dev/null and b/examples/effects/customshader/images/office-calendar.png differ diff --git a/examples/effects/customshader/images/system-users.png b/examples/effects/customshader/images/system-users.png new file mode 100644 index 0000000..a7f630a Binary files /dev/null and b/examples/effects/customshader/images/system-users.png differ diff --git a/examples/effects/customshader/main.cpp b/examples/effects/customshader/main.cpp new file mode 100644 index 0000000..b88a51d --- /dev/null +++ b/examples/effects/customshader/main.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "blurpicker.h" +#include + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + BlurPicker blurPicker; + blurPicker.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Application Picker")); + blurPicker.setFixedSize(400, 300); + blurPicker.show(); + + return app.exec(); +} diff --git a/examples/effects/effects.pro b/examples/effects/effects.pro index 8ba0324..4a6c8de 100644 --- a/examples/effects/effects.pro +++ b/examples/effects/effects.pro @@ -2,7 +2,8 @@ TEMPLATE = \ subdirs SUBDIRS = \ blurpicker \ - lighting + lighting \ + customshader # install target.path = $$[QT_INSTALL_EXAMPLES]/effects diff --git a/examples/graphicsview/customshader/blureffect.cpp b/examples/graphicsview/customshader/blureffect.cpp deleted file mode 100644 index 2b5237b..0000000 --- a/examples/graphicsview/customshader/blureffect.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "blureffect.h" - -#include - -BlurEffect::BlurEffect(QGraphicsItem *item) - : QGraphicsBlurEffect() - , m_baseLine(200), item(item) -{ -} - -void BlurEffect::adjustForItem() -{ - qreal y = m_baseLine - item->pos().y(); - qreal radius = qBound(0.0, y / 32, 16.0); - setBlurRadius(radius); -} - -QRectF BlurEffect::boundingRectFor(const QRectF &rect) const -{ - const_cast(this)->adjustForItem(); - return QGraphicsBlurEffect::boundingRectFor(rect); -} - -void BlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) -{ - adjustForItem(); - QGraphicsBlurEffect::draw(painter, source); -} diff --git a/examples/graphicsview/customshader/blureffect.h b/examples/graphicsview/customshader/blureffect.h deleted file mode 100644 index bf72226..0000000 --- a/examples/graphicsview/customshader/blureffect.h +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef BLUREFFECT_H -#define BLUREFFECT_H - -#include -#include - -class BlurEffect: public QGraphicsBlurEffect -{ -public: - BlurEffect(QGraphicsItem *item); - - void setBaseLine(qreal y) { m_baseLine = y; } - - QRectF boundingRectFor(const QRectF &) const; - - void draw(QPainter *painter, QGraphicsEffectSource*); - -private: - void adjustForItem(); - -private: - qreal m_baseLine; - QGraphicsItem *item; -}; - -#endif // BLUREFFECT_H diff --git a/examples/graphicsview/customshader/blurpicker.cpp b/examples/graphicsview/customshader/blurpicker.cpp deleted file mode 100644 index de80312..0000000 --- a/examples/graphicsview/customshader/blurpicker.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "blurpicker.h" - -#include - -#include "blureffect.h" -#include "customshadereffect.h" - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -BlurPicker::BlurPicker(QWidget *parent): QGraphicsView(parent), m_index(0.0) -{ - setBackgroundBrush(QPixmap(":/images/background.jpg")); - setScene(&m_scene); - - setupScene(); - updateIconPositions(); - - connect(&m_timeLine, SIGNAL(valueChanged(qreal)), SLOT(updateIconPositions())); - m_timeLine.setDuration(400); - - setRenderHint(QPainter::Antialiasing, true); - setFrameStyle(QFrame::NoFrame); -} - -void BlurPicker::updateIconPositions() -{ - m_index = m_timeLine.currentFrame() / 1000.0; - - qreal baseline = 0; - for (int i = 0; i < m_icons.count(); ++i) { - QGraphicsItem *icon = m_icons[i]; - qreal a = ((i + m_index) * 2 * M_PI) / m_icons.count(); - qreal xs = 170 * sin(a); - qreal ys = 100 * cos(a); - QPointF pos(xs, ys); - pos = QTransform().rotate(-20).map(pos); - pos -= QPointF(40, 40); - icon->setPos(pos); - baseline = qMax(baseline, ys); - if (i != 3) - static_cast(icon->graphicsEffect())->setBaseLine(baseline); - } - - m_scene.update(); -} - -void BlurPicker::setupScene() -{ - m_scene.setSceneRect(-200, -120, 400, 240); - - QStringList names; - names << ":/images/accessories-calculator.png"; - names << ":/images/accessories-text-editor.png"; - names << ":/images/help-browser.png"; - names << ":/images/internet-group-chat.png"; - names << ":/images/internet-mail.png"; - names << ":/images/internet-web-browser.png"; - names << ":/images/office-calendar.png"; - names << ":/images/system-users.png"; - - for (int i = 0; i < names.count(); i++) { - QPixmap pixmap(names[i]); - QGraphicsPixmapItem *icon = m_scene.addPixmap(pixmap); - icon->setZValue(1); - if (i == 3) - icon->setGraphicsEffect(new CustomShaderEffect()); - else - icon->setGraphicsEffect(new BlurEffect(icon)); - m_icons << icon; - } - - QGraphicsPixmapItem *bg = m_scene.addPixmap(QPixmap(":/images/background.jpg")); - bg->setZValue(0); - bg->setPos(-200, -150); -} - -void BlurPicker::keyPressEvent(QKeyEvent *event) -{ - if (event->key() == Qt::Key_Left) { - if (m_timeLine.state() == QTimeLine::NotRunning) { - m_timeLine.setFrameRange(m_index * 1000, m_index * 1000 - 1000); - m_timeLine.start(); - event->accept(); - } - } - - if (event->key() == Qt::Key_Right) { - if (m_timeLine.state() == QTimeLine::NotRunning) { - m_timeLine.setFrameRange(m_index * 1000, m_index * 1000 + 1000); - m_timeLine.start(); - event->accept(); - } - } -} diff --git a/examples/graphicsview/customshader/blurpicker.h b/examples/graphicsview/customshader/blurpicker.h deleted file mode 100644 index b7ea3b4..0000000 --- a/examples/graphicsview/customshader/blurpicker.h +++ /dev/null @@ -1,74 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef BLURPICKER_H -#define BLURPICKER_H - -#include -#include -#include - -#include "blureffect.h" - -class BlurPicker: public QGraphicsView -{ - Q_OBJECT - -public: - BlurPicker(QWidget *parent = 0); - -protected: - void keyPressEvent(QKeyEvent *event); - -private slots: - void updateIconPositions(); - -private: - void setupScene(); - -private: - qreal m_index; - QGraphicsScene m_scene; - QList m_icons; - QTimeLine m_timeLine; -}; - -#endif // BLURPICKER_H diff --git a/examples/graphicsview/customshader/blurpicker.qrc b/examples/graphicsview/customshader/blurpicker.qrc deleted file mode 100644 index e88eaca..0000000 --- a/examples/graphicsview/customshader/blurpicker.qrc +++ /dev/null @@ -1,14 +0,0 @@ - - - images/background.jpg - images/accessories-calculator.png - images/accessories-text-editor.png - images/help-browser.png - images/internet-group-chat.png - images/internet-mail.png - images/internet-web-browser.png - images/office-calendar.png - images/system-users.png - - - diff --git a/examples/graphicsview/customshader/customshader.pro b/examples/graphicsview/customshader/customshader.pro deleted file mode 100644 index bc07d7a..0000000 --- a/examples/graphicsview/customshader/customshader.pro +++ /dev/null @@ -1,10 +0,0 @@ -SOURCES += main.cpp blurpicker.cpp blureffect.cpp customshadereffect.cpp -HEADERS += blurpicker.h blureffect.h customshadereffect.h -RESOURCES += blurpicker.qrc -QT += opengl - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/graphicsview/blurpicker -sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS blurpicker.pro -sources.path = $$[QT_INSTALL_EXAMPLES]/graphicsview/blurpicker -INSTALLS += target sources diff --git a/examples/graphicsview/customshader/customshadereffect.cpp b/examples/graphicsview/customshader/customshadereffect.cpp deleted file mode 100644 index 293123c..0000000 --- a/examples/graphicsview/customshader/customshadereffect.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "customshadereffect.h" -#include - -static char const colorizeShaderCode[] = - "varying highp vec2 textureCoords;\n" - "uniform sampler2D imageTexture;\n" - "uniform lowp vec4 effectColor;\n" - "lowp vec4 srcPixel() {\n" - " vec4 src = texture2D(imageTexture, textureCoords);\n" - " float gray = dot(src.rgb, vec3(0.212671, 0.715160, 0.072169));\n" - " vec4 colorize = 1.0-((1.0-gray)*(1.0-effectColor));\n" - " return vec4(colorize.rgb, src.a);\n" - "}"; - -CustomShaderEffect::CustomShaderEffect() - : QGraphicsShaderEffect(), - color(Qt::red) -{ - setPixelShaderFragment(colorizeShaderCode); -} - -void CustomShaderEffect::setEffectColor(const QColor& c) -{ - color = c; - setUniformsDirty(); -} - -void CustomShaderEffect::setUniforms(QGLShaderProgram *program) -{ - program->setUniformValue("effectColor", color); -} diff --git a/examples/graphicsview/customshader/customshadereffect.h b/examples/graphicsview/customshader/customshadereffect.h deleted file mode 100644 index 6482bd5..0000000 --- a/examples/graphicsview/customshader/customshadereffect.h +++ /dev/null @@ -1,64 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef CUSTOMSHADEREFFECT_H -#define CUSTOMSHADEREFFECT_H - -#include -#include -#include - -class CustomShaderEffect: public QGraphicsShaderEffect -{ -public: - CustomShaderEffect(); - - QColor effectColor() const { return color; } - void setEffectColor(const QColor& c); - -protected: - void setUniforms(QGLShaderProgram *program); - -private: - QColor color; -}; - -#endif // CUSTOMSHADEREFFECT_H diff --git a/examples/graphicsview/customshader/main.cpp b/examples/graphicsview/customshader/main.cpp deleted file mode 100644 index b88a51d..0000000 --- a/examples/graphicsview/customshader/main.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "blurpicker.h" -#include - -int main(int argc, char **argv) -{ - QApplication app(argc, argv); - - BlurPicker blurPicker; - blurPicker.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Application Picker")); - blurPicker.setFixedSize(400, 300); - blurPicker.show(); - - return app.exec(); -} -- cgit v0.12 From 1959b56b331286b4d7d2cc560736992535f06042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 21 Aug 2009 14:37:16 +0200 Subject: Only compile shader effect example when having OpenGL. --- examples/effects/effects.pro | 5 +++-- examples/graphicsview/graphicsview.pro | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/effects/effects.pro b/examples/effects/effects.pro index 4a6c8de..60b5baf 100644 --- a/examples/effects/effects.pro +++ b/examples/effects/effects.pro @@ -2,8 +2,9 @@ TEMPLATE = \ subdirs SUBDIRS = \ blurpicker \ - lighting \ - customshader + lighting + +contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles2):SUBDIRS += customshader # install target.path = $$[QT_INSTALL_EXAMPLES]/effects diff --git a/examples/graphicsview/graphicsview.pro b/examples/graphicsview/graphicsview.pro index 627f9d4..7238995 100644 --- a/examples/graphicsview/graphicsview.pro +++ b/examples/graphicsview/graphicsview.pro @@ -11,7 +11,6 @@ SUBDIRS = \ contains(QT_CONFIG, qt3support):SUBDIRS += portedcanvas portedasteroids contains(DEFINES, QT_NO_CURSOR): SUBDIRS -= dragdroprobot -contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles2):SUBDIRS += customshader # install target.path = $$[QT_INSTALL_EXAMPLES]/graphicsview -- cgit v0.12 From 1b305c739979f7d0e8cb6ebbac6d29ca2e6b060d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 21 Aug 2009 14:49:44 +0200 Subject: Cleanup after wrong merge. ExtraGestures is not in the master branch, and gestures has not been touched in the kinetic-graphicseffect branch so this must be a result of a wrong merge at some point. Remove it. --- src/gui/graphicsview/qgraphicsitem_p.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 5838fc0..77f203f 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -106,8 +106,7 @@ public: ExtraCursor, ExtraCacheData, ExtraMaxDeviceCoordCacheSize, - ExtraBoundingRegionGranularity, - ExtraGestures + ExtraBoundingRegionGranularity }; enum AncestorFlag { -- cgit v0.12