summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/graphicsview/blurpicker/blureffect.cpp70
-rw-r--r--examples/graphicsview/blurpicker/blureffect.h68
-rw-r--r--examples/graphicsview/blurpicker/blurpicker.cpp134
-rw-r--r--examples/graphicsview/blurpicker/blurpicker.h75
-rw-r--r--examples/graphicsview/blurpicker/blurpicker.pro9
-rw-r--r--examples/graphicsview/blurpicker/blurpicker.qrc14
-rw-r--r--examples/graphicsview/blurpicker/images/README.txt5
-rw-r--r--examples/graphicsview/blurpicker/images/accessories-calculator.pngbin0 -> 3760 bytes
-rw-r--r--examples/graphicsview/blurpicker/images/accessories-text-editor.pngbin0 -> 4746 bytes
-rw-r--r--examples/graphicsview/blurpicker/images/background.jpgbin0 -> 16259 bytes
-rw-r--r--examples/graphicsview/blurpicker/images/help-browser.pngbin0 -> 5392 bytes
-rw-r--r--examples/graphicsview/blurpicker/images/internet-group-chat.pngbin0 -> 2809 bytes
-rw-r--r--examples/graphicsview/blurpicker/images/internet-mail.pngbin0 -> 3899 bytes
-rw-r--r--examples/graphicsview/blurpicker/images/internet-web-browser.pngbin0 -> 6376 bytes
-rw-r--r--examples/graphicsview/blurpicker/images/office-calendar.pngbin0 -> 4010 bytes
-rw-r--r--examples/graphicsview/blurpicker/images/system-users.pngbin0 -> 5353 bytes
-rw-r--r--examples/graphicsview/blurpicker/main.cpp55
-rw-r--r--examples/graphicsview/graphicsview.pro2
-rw-r--r--examples/graphicsview/lighting/lighting.cpp121
-rw-r--r--examples/graphicsview/lighting/lighting.h71
-rw-r--r--examples/graphicsview/lighting/lighting.pro8
-rw-r--r--examples/graphicsview/lighting/main.cpp55
-rw-r--r--examples/graphicsview/lighting/shadoweffect.cpp75
-rw-r--r--examples/graphicsview/lighting/shadoweffect.h66
-rw-r--r--src/gui/graphicsview/graphicsview.pri6
-rw-r--r--src/gui/graphicsview/qgraphicseffect.cpp823
-rw-r--r--src/gui/graphicsview/qgraphicseffect.h279
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp120
-rw-r--r--src/gui/graphicsview/qgraphicsitem.h9
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h9
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp72
-rw-r--r--src/gui/graphicsview/qgraphicsscene.h6
-rw-r--r--src/gui/graphicsview/qgraphicsscene_p.h8
-rw-r--r--src/gui/image/qpixmapfilter.cpp235
-rw-r--r--src/gui/image/qpixmapfilter_p.h28
35 files changed, 2418 insertions, 5 deletions
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 <QDebug>
+
+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 <QGraphicsEffect>
+#include <QGraphicsItem>
+
+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..887d7ef
--- /dev/null
+++ b/examples/graphicsview/blurpicker/blurpicker.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** 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 <QtGui>
+
+#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);
+
+ 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..e41c608
--- /dev/null
+++ b/examples/graphicsview/blurpicker/blurpicker.h
@@ -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$
+**
+****************************************************************************/
+
+#ifndef BLURPICKER_H
+#define BLURPICKER_H
+
+#include <QGraphicsEffect>
+#include <QGraphicsView>
+#include <QTimeLine>
+
+#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;
+ BlurEffect *m_blurEffect;
+ QList<QGraphicsItem*> 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 @@
+<RCC>
+ <qresource prefix="/" >
+ <file>images/background.jpg</file>
+ <file>images/accessories-calculator.png</file>
+ <file>images/accessories-text-editor.png</file>
+ <file>images/help-browser.png</file>
+ <file>images/internet-group-chat.png</file>
+ <file>images/internet-mail.png</file>
+ <file>images/internet-web-browser.png</file>
+ <file>images/office-calendar.png</file>
+ <file>images/system-users.png</file>
+ </qresource>
+</RCC>
+
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
--- /dev/null
+++ b/examples/graphicsview/blurpicker/images/accessories-calculator.png
Binary files 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
--- /dev/null
+++ b/examples/graphicsview/blurpicker/images/accessories-text-editor.png
Binary files differ
diff --git a/examples/graphicsview/blurpicker/images/background.jpg b/examples/graphicsview/blurpicker/images/background.jpg
new file mode 100644
index 0000000..e75b388
--- /dev/null
+++ b/examples/graphicsview/blurpicker/images/background.jpg
Binary files 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
--- /dev/null
+++ b/examples/graphicsview/blurpicker/images/help-browser.png
Binary files 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
--- /dev/null
+++ b/examples/graphicsview/blurpicker/images/internet-group-chat.png
Binary files 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
--- /dev/null
+++ b/examples/graphicsview/blurpicker/images/internet-mail.png
Binary files 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
--- /dev/null
+++ b/examples/graphicsview/blurpicker/images/internet-web-browser.png
Binary files 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
--- /dev/null
+++ b/examples/graphicsview/blurpicker/images/office-calendar.png
Binary files 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
--- /dev/null
+++ b/examples/graphicsview/blurpicker/images/system-users.png
Binary files differ
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 <QApplication>
+
+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 66eb0b4..185c856 100644
--- a/examples/graphicsview/graphicsview.pro
+++ b/examples/graphicsview/graphicsview.pro
@@ -6,6 +6,8 @@ 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
new file mode 100644
index 0000000..445d7f9
--- /dev/null
+++ b/examples/graphicsview/lighting/lighting.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** 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 <QtGui>
+
+#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);
+
+ m_shadowEffect = new ShadowEffect(m_lightSource, this);
+
+ 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..66237f6
--- /dev/null
+++ b/examples/graphicsview/lighting/lighting.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** 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 <QGraphicsEffect>
+#include <QGraphicsView>
+
+#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;
+ ShadowEffect *m_shadowEffect;
+ QList<QGraphicsItem*> 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 <QApplication>
+
+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..726cbd0
--- /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 <math.h>
+
+ShadowEffect::ShadowEffect(QGraphicsItem *source, QObject *parent)
+ : QGraphicsShadowEffect(parent)
+ , 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..02d0bf1
--- /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 <QGraphicsEffect>
+#include <QGraphicsItem>
+
+class ShadowEffect: public QGraphicsShadowEffect
+{
+public:
+ ShadowEffect(QGraphicsItem *source, QObject *parent = 0);
+
+ 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
diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri
index 0c0747e..c3cb574 100644
--- a/src/gui/graphicsview/graphicsview.pri
+++ b/src/gui/graphicsview/graphicsview.pri
@@ -20,7 +20,8 @@ HEADERS += graphicsview/qgraphicsgridlayout.h \
graphicsview/qgraphicsview_p.h \
graphicsview/qgraphicswidget.h \
graphicsview/qgraphicswidget_p.h \
- graphicsview/qgridlayoutengine_p.h
+ graphicsview/qgridlayoutengine_p.h \
+ graphicsview/qgraphicseffect.h
SOURCES += graphicsview/qgraphicsgridlayout.cpp \
graphicsview/qgraphicsitem.cpp \
@@ -39,4 +40,5 @@ SOURCES += graphicsview/qgraphicsgridlayout.cpp \
graphicsview/qgraphicsview.cpp \
graphicsview/qgraphicswidget.cpp \
graphicsview/qgraphicswidget_p.cpp \
- graphicsview/qgridlayoutengine.cpp
+ graphicsview/qgridlayoutengine.cpp \
+ graphicsview/qgraphicseffect.cpp
diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp
new file mode 100644
index 0000000..6b1f12a
--- /dev/null
+++ b/src/gui/graphicsview/qgraphicseffect.cpp
@@ -0,0 +1,823 @@
+/****************************************************************************
+**
+** 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 <QtGui/qimage.h>
+#include <QtGui/qgraphicsitem.h>
+#include <QtGui/qgraphicsscene.h>
+#include <QtGui/qpainter.h>
+
+#include <private/qobject_p.h>
+#include <private/qpixmapfilter_p.h>
+
+/*
+
+ 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).
+
+*/
+
+/*!
+ \internal
+*/
+class QGraphicsEffectPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QGraphicsEffect)
+public:
+ QGraphicsEffectPrivate() {}
+};
+
+QGraphicsEffect::QGraphicsEffect(QObject *parent)
+ : QObject(*new QGraphicsEffectPrivate, parent)
+{
+}
+
+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();
+}
+
+/*! \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
+// (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);
+}
+
+/*!
+ \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()
+{
+}
+
+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);
+ 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());
+ d->filter->draw(painter, deviceRect.topLeft(), *pixmap, pixmap->rect());
+ 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()
+{
+}
+
+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::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);
+ 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());
+ d->filter->draw(painter, deviceRect.topLeft(), *pixmap, pixmap->rect());
+ 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()
+{
+}
+
+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);
+ 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 (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<QRgb*>(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<QRgb*>(img.scanLine(y + yi));
+ for (int xi = 0; xi < qMin(d->pixelSize, 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);
+}
+
+/*!
+ \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()
+{
+}
+
+// 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 int(d->filter->blurRadius());
+}
+
+void QGraphicsBlurEffect::setBlurRadius(int radius)
+{
+ Q_D(QGraphicsBlurEffect);
+ d->filter->setBlurRadius(radius);
+}
+
+QRectF QGraphicsBlurEffect::boundingRectFor(const QGraphicsItem *item)
+{
+ Q_D(const QGraphicsBlurEffect);
+ return d->filter->boundingRectFor(item->boundingRect());
+}
+
+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);
+ 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());
+ d->filter->draw(painter, deviceRect.topLeft(), *pixmap, pixmap->rect());
+ 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()
+{
+}
+
+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)
+{
+ Q_D(QGraphicsBloomEffect);
+ qreal delta = d->blurRadius * 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)
+{
+ 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);
+ if (deviceRect.isEmpty())
+ return;
+
+ QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0);
+ if (!pixmap)
+ 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, d->opacity, 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);
+}
+
+/*!
+ \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()
+{
+}
+
+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(-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);
+ if (deviceRect.isEmpty())
+ return;
+
+ QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0);
+ if (!pixmap)
+ return;
+
+ QRectF frameRect = deviceBounds;
+ frameRect.adjust(-d->width, -d->width, d->width, d->width);
+
+ 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->restore();
+
+ painter->drawPixmap(frameRect.topLeft(), *pixmap);
+
+ 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()
+{
+}
+
+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(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());
+ return totalRect;
+}
+
+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);
+ if (deviceRect.isEmpty())
+ return;
+
+ QRectF shadowRect = deviceBounds;
+ 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(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, 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());
+
+ QRect shadowAlignedRect = shadowRect.toAlignedRect();
+
+ 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())
+ 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());
+ 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..29d97a6
--- /dev/null
+++ b/src/gui/graphicsview/qgraphicseffect.h
@@ -0,0 +1,279 @@
+/****************************************************************************
+**
+** 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 <QtCore/qobject.h>
+#include <QtCore/qglobal.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qvariant.h>
+#include <QtGui/qcolor.h>
+
+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 QGraphicsEffectPrivate;
+class Q_GUI_EXPORT QGraphicsEffect : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ QGraphicsEffect(QObject *parent = 0);
+ virtual ~QGraphicsEffect();
+
+ virtual QRectF boundingRectFor(const QGraphicsItem *item);
+
+ virtual void drawItem(QGraphicsItem *item, QPainter *painter,
+ const QStyleOptionGraphicsItem *option = 0,
+ 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_DECLARE_PRIVATE(QGraphicsEffect)
+ Q_DISABLE_COPY(QGraphicsEffect)
+};
+
+class QGraphicsGrayscaleEffectPrivate;
+class Q_GUI_EXPORT QGraphicsGrayscaleEffect: public QGraphicsEffect
+{
+ Q_OBJECT
+
+public:
+
+ QGraphicsGrayscaleEffect(QObject *parent = 0);
+ ~QGraphicsGrayscaleEffect();
+
+ void drawItem(QGraphicsItem *item, QPainter *painter,
+ const QStyleOptionGraphicsItem *option = 0,
+ QWidget *widget = 0);
+
+private:
+ Q_DECLARE_PRIVATE(QGraphicsGrayscaleEffect)
+ Q_DISABLE_COPY(QGraphicsGrayscaleEffect)
+};
+
+class QGraphicsColorizeEffectPrivate;
+class Q_GUI_EXPORT QGraphicsColorizeEffect: public QGraphicsEffect {
+ Q_OBJECT
+
+public:
+
+ QGraphicsColorizeEffect(QObject *parent = 0);
+ ~QGraphicsColorizeEffect();
+
+ QColor color() const;
+ void setColor(const QColor &c);
+
+ void drawItem(QGraphicsItem *item, QPainter *painter,
+ const QStyleOptionGraphicsItem *option = 0,
+ QWidget *widget = 0);
+
+private:
+ Q_DECLARE_PRIVATE(QGraphicsColorizeEffect)
+ Q_DISABLE_COPY(QGraphicsColorizeEffect)
+};
+
+class QGraphicsPixelizeEffectPrivate;
+class Q_GUI_EXPORT QGraphicsPixelizeEffect: public QGraphicsEffect {
+ Q_OBJECT
+
+public:
+
+ QGraphicsPixelizeEffect(QObject *parent = 0);
+ ~QGraphicsPixelizeEffect();
+
+ int pixelSize() const;
+ void setPixelSize(int pixelSize);
+
+ void drawItem(QGraphicsItem *item, QPainter *painter,
+ const QStyleOptionGraphicsItem *option = 0,
+ QWidget *widget = 0);
+
+private:
+ Q_DECLARE_PRIVATE(QGraphicsPixelizeEffect)
+ Q_DISABLE_COPY(QGraphicsPixelizeEffect)
+};
+
+class QGraphicsBlurEffectPrivate;
+class Q_GUI_EXPORT QGraphicsBlurEffect: public QGraphicsEffect {
+ Q_OBJECT
+
+public:
+
+ QGraphicsBlurEffect(QObject *parent = 0);
+ ~QGraphicsBlurEffect();
+
+ int blurRadius() const;
+ void setBlurRadius(int blurRadius);
+
+ QRectF boundingRectFor(const QGraphicsItem *item);
+
+ void drawItem(QGraphicsItem *item, QPainter *painter,
+ const QStyleOptionGraphicsItem *option = 0,
+ QWidget *widget = 0);
+
+private:
+ Q_DECLARE_PRIVATE(QGraphicsBlurEffect)
+ Q_DISABLE_COPY(QGraphicsBlurEffect)
+};
+
+class QGraphicsBloomEffectPrivate;
+class Q_GUI_EXPORT QGraphicsBloomEffect: public QGraphicsEffect {
+ Q_OBJECT
+
+public:
+
+ QGraphicsBloomEffect(QObject *parent = 0);
+ ~QGraphicsBloomEffect();
+
+ int blurRadius() const;
+ void setBlurRadius(int blurRadius);
+
+ qreal opacity() const;
+ void setOpacity(qreal opacity);
+
+ QRectF boundingRectFor(const QGraphicsItem *item);
+
+ void drawItem(QGraphicsItem *item, QPainter *painter,
+ const QStyleOptionGraphicsItem *option = 0,
+ QWidget *widget = 0);
+
+private:
+ Q_DECLARE_PRIVATE(QGraphicsBloomEffect)
+ Q_DISABLE_COPY(QGraphicsBloomEffect)
+};
+
+class QGraphicsFrameEffectPrivate;
+class Q_GUI_EXPORT QGraphicsFrameEffect: public QGraphicsEffect {
+ Q_OBJECT
+
+public:
+
+ QGraphicsFrameEffect(QObject *parent = 0);
+ ~QGraphicsFrameEffect();
+
+ QColor frameColor() const;
+ void setFrameColor(const QColor &c);
+
+ qreal frameWidth() const;
+ void setFrameWidth(qreal frameWidth);
+
+ qreal frameOpacity() const;
+ void setFrameOpacity(qreal opacity);
+
+ QRectF boundingRectFor(const QGraphicsItem *item);
+
+ void drawItem(QGraphicsItem *item, QPainter *painter,
+ const QStyleOptionGraphicsItem *option = 0,
+ QWidget *widget = 0);
+private:
+ Q_DECLARE_PRIVATE(QGraphicsFrameEffect)
+ Q_DISABLE_COPY(QGraphicsFrameEffect)
+};
+
+class QGraphicsShadowEffectPrivate;
+class Q_GUI_EXPORT QGraphicsShadowEffect: public QGraphicsEffect {
+ Q_OBJECT
+
+public:
+
+ QGraphicsShadowEffect(QObject *parent = 0);
+ ~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);
+
+ QRectF boundingRectFor(const QGraphicsItem *item);
+
+ void drawItem(QGraphicsItem *item, QPainter *painter,
+ const QStyleOptionGraphicsItem *option = 0,
+ QWidget *widget = 0);
+
+protected:
+
+private:
+ Q_DECLARE_PRIVATE(QGraphicsShadowEffect)
+ 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 4e3677a..c395e21 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -552,6 +552,7 @@
#ifndef QT_NO_GRAPHICSVIEW
+#include "qgraphicseffect.h"
#include "qgraphicsscene.h"
#include "qgraphicsscene_p.h"
#include "qgraphicssceneevent.h"
@@ -2189,6 +2190,125 @@ 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<QGraphicsEffect*>();
+
+ 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<void*>();
+ QPixmap *pixmap = reinterpret_cast<QPixmap*>(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
+ // COMBINE
+ QPointF offset;
+ const QGraphicsItem *parentItem = this;
+ const QGraphicsItemPrivate *itemd;
+ do {
+ itemd = parentItem->d_ptr;
+ if (itemd->transformData)
+ 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<void*>();
+ QPixmap *pixmap = reinterpret_cast<QPixmap*>(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<void*>(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 5c9297f..4cb94bf 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 QGraphicsObject;
class QGraphicsSceneContextMenuEvent;
@@ -206,6 +207,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);
@@ -436,6 +443,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 1cf188e..3f02560 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -102,7 +102,10 @@ public:
ExtraCursor,
ExtraCacheData,
ExtraMaxDeviceCoordCacheSize,
- ExtraBoundingRegionGranularity
+ ExtraBoundingRegionGranularity,
+ ExtraEffect,
+ ExtraEffectPixmap,
+ ExtraGestures
};
enum AncestorFlag {
@@ -149,6 +152,7 @@ public:
allChildrenDirty(0),
fullUpdatePending(0),
flags(0),
+ hasEffect(0),
dirtyChildrenBoundingRect(1),
paintedViewBoundingRectsNeedRepaint(0),
dirtySceneTransform(1),
@@ -440,7 +444,8 @@ public:
// New 32 bits
quint32 fullUpdatePending : 1;
- quint32 flags : 13;
+ quint32 flags : 12;
+ quint32 hasEffect : 1;
quint32 dirtyChildrenBoundingRect : 1;
quint32 paintedViewBoundingRectsNeedRepaint : 1;
quint32 dirtySceneTransform : 1;
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 4796436..b2b9ebd 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -208,6 +208,7 @@
#ifndef QT_NO_GRAPHICSVIEW
+#include "qgraphicseffect.h"
#include "qgraphicsitem.h"
#include "qgraphicsitem_p.h"
#include "qgraphicslayout.h"
@@ -3962,6 +3963,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
@@ -4257,6 +4271,62 @@ 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)
{
@@ -4385,7 +4455,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);
diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h
index c0c6e75..6292afa 100644
--- a/src/gui/graphicsview/qgraphicsscene.h
+++ b/src/gui/graphicsview/qgraphicsscene.h
@@ -282,6 +282,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);
@@ -302,6 +307,7 @@ private:
friend class QGraphicsViewPrivate;
friend class QGraphicsWidget;
friend class QGraphicsWidgetPrivate;
+ friend class QGraphicsEffect;
friend class QGraphicsSceneIndex;
friend class QGraphicsSceneIndexPrivate;
friend class QGraphicsSceneBspTreeIndex;
diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h
index a4bbdd2..7e95f70 100644
--- a/src/gui/graphicsview/qgraphicsscene_p.h
+++ b/src/gui/graphicsview/qgraphicsscene_p.h
@@ -280,6 +280,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
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<QPaintEngineEx *>(painter->paintEngine())->createPixmapFilter(type()) : 0;
+ QPixmapBlurFilter *blurFilter = static_cast<QPixmapBlurFilter*>(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