diff options
Diffstat (limited to 'demos/composition')
-rw-r--r-- | demos/composition/composition.cpp | 511 | ||||
-rw-r--r-- | demos/composition/composition.h | 190 | ||||
-rw-r--r-- | demos/composition/composition.html | 23 | ||||
-rw-r--r-- | demos/composition/composition.pro | 27 | ||||
-rw-r--r-- | demos/composition/composition.qrc | 8 | ||||
-rw-r--r-- | demos/composition/flower.jpg | bin | 0 -> 49616 bytes | |||
-rw-r--r-- | demos/composition/flower_alpha.jpg | bin | 0 -> 67326 bytes | |||
-rw-r--r-- | demos/composition/main.cpp | 62 |
8 files changed, 821 insertions, 0 deletions
diff --git a/demos/composition/composition.cpp b/demos/composition/composition.cpp new file mode 100644 index 0000000..b43c66b --- /dev/null +++ b/demos/composition/composition.cpp @@ -0,0 +1,511 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "composition.h" +#include <QBoxLayout> +#include <QRadioButton> +#include <QTimer> +#include <QDateTime> +#include <QSlider> +#include <QMouseEvent> +#include <qmath.h> + +CompositionWidget::CompositionWidget(QWidget *parent) + : QWidget(parent) +{ + CompositionRenderer *view = new CompositionRenderer(this); + + QGroupBox *mainGroup = new QGroupBox(parent); + mainGroup->setTitle(tr("Composition Modes")); + + QGroupBox *modesGroup = new QGroupBox(mainGroup); + modesGroup->setTitle(tr("Mode")); + + rbClear = new QRadioButton(tr("Clear"), modesGroup); + connect(rbClear, SIGNAL(clicked()), view, SLOT(setClearMode())); + rbSource = new QRadioButton(tr("Source"), modesGroup); + connect(rbSource, SIGNAL(clicked()), view, SLOT(setSourceMode())); + rbDest = new QRadioButton(tr("Destination"), modesGroup); + connect(rbDest, SIGNAL(clicked()), view, SLOT(setDestMode())); + rbSourceOver = new QRadioButton(tr("Source Over"), modesGroup); + connect(rbSourceOver, SIGNAL(clicked()), view, SLOT(setSourceOverMode())); + rbDestOver = new QRadioButton(tr("Destination Over"), modesGroup); + connect(rbDestOver, SIGNAL(clicked()), view, SLOT(setDestOverMode())); + rbSourceIn = new QRadioButton(tr("Source In"), modesGroup); + connect(rbSourceIn, SIGNAL(clicked()), view, SLOT(setSourceInMode())); + rbDestIn = new QRadioButton(tr("Dest In"), modesGroup); + connect(rbDestIn, SIGNAL(clicked()), view, SLOT(setDestInMode())); + rbSourceOut = new QRadioButton(tr("Source Out"), modesGroup); + connect(rbSourceOut, SIGNAL(clicked()), view, SLOT(setSourceOutMode())); + rbDestOut = new QRadioButton(tr("Dest Out"), modesGroup); + connect(rbDestOut, SIGNAL(clicked()), view, SLOT(setDestOutMode())); + rbSourceAtop = new QRadioButton(tr("Source Atop"), modesGroup); + connect(rbSourceAtop, SIGNAL(clicked()), view, SLOT(setSourceAtopMode())); + rbDestAtop = new QRadioButton(tr("Dest Atop"), modesGroup); + connect(rbDestAtop, SIGNAL(clicked()), view, SLOT(setDestAtopMode())); + rbXor = new QRadioButton(tr("Xor"), modesGroup); + connect(rbXor, SIGNAL(clicked()), view, SLOT(setXorMode())); + + rbPlus = new QRadioButton(tr("Plus"), modesGroup); + connect(rbPlus, SIGNAL(clicked()), view, SLOT(setPlusMode())); + rbMultiply = new QRadioButton(tr("Multiply"), modesGroup); + connect(rbMultiply, SIGNAL(clicked()), view, SLOT(setMultiplyMode())); + rbScreen = new QRadioButton(tr("Screen"), modesGroup); + connect(rbScreen, SIGNAL(clicked()), view, SLOT(setScreenMode())); + rbOverlay = new QRadioButton(tr("Overlay"), modesGroup); + connect(rbOverlay, SIGNAL(clicked()), view, SLOT(setOverlayMode())); + rbDarken = new QRadioButton(tr("Darken"), modesGroup); + connect(rbDarken, SIGNAL(clicked()), view, SLOT(setDarkenMode())); + rbLighten = new QRadioButton(tr("Lighten"), modesGroup); + connect(rbLighten, SIGNAL(clicked()), view, SLOT(setLightenMode())); + rbColorDodge = new QRadioButton(tr("Color Dodge"), modesGroup); + connect(rbColorDodge, SIGNAL(clicked()), view, SLOT(setColorDodgeMode())); + rbColorBurn = new QRadioButton(tr("Color Burn"), modesGroup); + connect(rbColorBurn, SIGNAL(clicked()), view, SLOT(setColorBurnMode())); + rbHardLight = new QRadioButton(tr("Hard Light"), modesGroup); + connect(rbHardLight, SIGNAL(clicked()), view, SLOT(setHardLightMode())); + rbSoftLight = new QRadioButton(tr("Soft Light"), modesGroup); + connect(rbSoftLight, SIGNAL(clicked()), view, SLOT(setSoftLightMode())); + rbDifference = new QRadioButton(tr("Difference"), modesGroup); + connect(rbDifference, SIGNAL(clicked()), view, SLOT(setDifferenceMode())); + rbExclusion = new QRadioButton(tr("Exclusion"), modesGroup); + connect(rbExclusion, SIGNAL(clicked()), view, SLOT(setExclusionMode())); + + QGroupBox *circleColorGroup = new QGroupBox(mainGroup); + circleColorGroup->setTitle(tr("Circle color")); + QSlider *circleColorSlider = new QSlider(Qt::Horizontal, circleColorGroup); + circleColorSlider->setRange(0, 359); + circleColorSlider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + connect(circleColorSlider, SIGNAL(valueChanged(int)), view, SLOT(setCircleColor(int))); + + QGroupBox *circleAlphaGroup = new QGroupBox(mainGroup); + circleAlphaGroup->setTitle(tr("Circle alpha")); + QSlider *circleAlphaSlider = new QSlider(Qt::Horizontal, circleAlphaGroup); + circleAlphaSlider->setRange(0, 255); + circleAlphaSlider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + connect(circleAlphaSlider, SIGNAL(valueChanged(int)), view, SLOT(setCircleAlpha(int))); + + QPushButton *showSourceButton = new QPushButton(mainGroup); + showSourceButton->setText(tr("Show Source")); +#if defined(QT_OPENGL_SUPPORT) && !defined(QT_OPENGL_ES) + QPushButton *enableOpenGLButton = new QPushButton(mainGroup); + enableOpenGLButton->setText(tr("Use OpenGL")); + enableOpenGLButton->setCheckable(true); + enableOpenGLButton->setChecked(view->usesOpenGL()); + + if (!QGLFormat::hasOpenGL() || !QGLPixelBuffer::hasOpenGLPbuffers()) + enableOpenGLButton->hide(); +#endif + QPushButton *whatsThisButton = new QPushButton(mainGroup); + whatsThisButton->setText(tr("What's This?")); + whatsThisButton->setCheckable(true); + + QPushButton *animateButton = new QPushButton(mainGroup); + animateButton->setText(tr("Animated")); + animateButton->setCheckable(true); + animateButton->setChecked(true); + + QHBoxLayout *viewLayout = new QHBoxLayout(this); + viewLayout->addWidget(view); + viewLayout->addWidget(mainGroup); + + QVBoxLayout *mainGroupLayout = new QVBoxLayout(mainGroup); + mainGroupLayout->addWidget(circleColorGroup); + mainGroupLayout->addWidget(circleAlphaGroup); + mainGroupLayout->addWidget(modesGroup); + mainGroupLayout->addStretch(); + mainGroupLayout->addWidget(animateButton); + mainGroupLayout->addWidget(whatsThisButton); + mainGroupLayout->addWidget(showSourceButton); +#if defined(QT_OPENGL_SUPPORT) && !defined(QT_OPENGL_ES) + mainGroupLayout->addWidget(enableOpenGLButton); +#endif + + QGridLayout *modesLayout = new QGridLayout(modesGroup); + modesLayout->addWidget(rbClear, 0, 0); + modesLayout->addWidget(rbSource, 1, 0); + modesLayout->addWidget(rbDest, 2, 0); + modesLayout->addWidget(rbSourceOver, 3, 0); + modesLayout->addWidget(rbDestOver, 4, 0); + modesLayout->addWidget(rbSourceIn, 5, 0); + modesLayout->addWidget(rbDestIn, 6, 0); + modesLayout->addWidget(rbSourceOut, 7, 0); + modesLayout->addWidget(rbDestOut, 8, 0); + modesLayout->addWidget(rbSourceAtop, 9, 0); + modesLayout->addWidget(rbDestAtop, 10, 0); + modesLayout->addWidget(rbXor, 11, 0); + + modesLayout->addWidget(rbPlus, 0, 1); + modesLayout->addWidget(rbMultiply, 1, 1); + modesLayout->addWidget(rbScreen, 2, 1); + modesLayout->addWidget(rbOverlay, 3, 1); + modesLayout->addWidget(rbDarken, 4, 1); + modesLayout->addWidget(rbLighten, 5, 1); + modesLayout->addWidget(rbColorDodge, 6, 1); + modesLayout->addWidget(rbColorBurn, 7, 1); + modesLayout->addWidget(rbHardLight, 8, 1); + modesLayout->addWidget(rbSoftLight, 9, 1); + modesLayout->addWidget(rbDifference, 10, 1); + modesLayout->addWidget(rbExclusion, 11, 1); + + + QVBoxLayout *circleColorLayout = new QVBoxLayout(circleColorGroup); + circleColorLayout->addWidget(circleColorSlider); + + QVBoxLayout *circleAlphaLayout = new QVBoxLayout(circleAlphaGroup); + circleAlphaLayout->addWidget(circleAlphaSlider); + + view->loadDescription(":res/composition/composition.html"); + view->loadSourceFile(":res/composition/composition.cpp"); + + connect(whatsThisButton, SIGNAL(clicked(bool)), view, SLOT(setDescriptionEnabled(bool))); + connect(view, SIGNAL(descriptionEnabledChanged(bool)), whatsThisButton, SLOT(setChecked(bool))); + connect(showSourceButton, SIGNAL(clicked()), view, SLOT(showSource())); +#if defined(QT_OPENGL_SUPPORT) && !defined(QT_OPENGL_ES) + connect(enableOpenGLButton, SIGNAL(clicked(bool)), view, SLOT(enableOpenGL(bool))); +#endif + connect(animateButton, SIGNAL(toggled(bool)), view, SLOT(setAnimationEnabled(bool))); + + circleColorSlider->setValue(270); + circleAlphaSlider->setValue(200); + rbSourceOut->animateClick(); + + setWindowTitle(tr("Composition Modes")); +} + + +void CompositionWidget::nextMode() +{ + /* + if (!m_animation_enabled) + return; + if (rbClear->isChecked()) rbSource->animateClick(); + if (rbSource->isChecked()) rbDest->animateClick(); + if (rbDest->isChecked()) rbSourceOver->animateClick(); + if (rbSourceOver->isChecked()) rbDestOver->animateClick(); + if (rbDestOver->isChecked()) rbSourceIn->animateClick(); + if (rbSourceIn->isChecked()) rbDestIn->animateClick(); + if (rbDestIn->isChecked()) rbSourceOut->animateClick(); + if (rbSourceOut->isChecked()) rbDestOut->animateClick(); + if (rbDestOut->isChecked()) rbSourceAtop->animateClick(); + if (rbSourceAtop->isChecked()) rbDestAtop->animateClick(); + if (rbDestAtop->isChecked()) rbXor->animateClick(); + if (rbXor->isChecked()) rbClear->animateClick(); + */ +} + +CompositionRenderer::CompositionRenderer(QWidget *parent) + : ArthurFrame(parent) +{ + m_animation_enabled = true; +#ifdef Q_WS_QWS + m_image = QPixmap(":res/composition/flower.jpg"); + m_image.setAlphaChannel(QPixmap(":res/composition/flower_alpha.jpg")); +#else + m_image = QImage(":res/composition/flower.jpg"); + m_image.setAlphaChannel(QImage(":res/composition/flower_alpha.jpg")); +#endif + m_circle_alpha = 127; + m_circle_hue = 255; + m_current_object = NoObject; + m_composition_mode = QPainter::CompositionMode_SourceOut; + + m_circle_pos = QPoint(200, 100); + + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); +#ifdef QT_OPENGL_SUPPORT + m_pbuffer = 0; + m_pbuffer_size = 1024; +#endif +} + +QRectF rectangle_around(const QPointF &p, const QSizeF &size = QSize(250, 200)) +{ + QRectF rect(p, size); + rect.translate(-size.width()/2, -size.height()/2); + return rect; +} + +void CompositionRenderer::updateCirclePos() +{ + if (m_current_object != NoObject) + return; + QDateTime dt = QDateTime::currentDateTime(); + qreal t = (dt.toTime_t() * 1000 + dt.time().msec()) / 1000.0; + + qreal x = width() / qreal(2) + (qCos(t*8/11) + qSin(-t)) * width() / qreal(4); + qreal y = height() / qreal(2) + (qSin(t*6/7) + qCos(t * qreal(1.5))) * height() / qreal(4); + + setCirclePos(QLineF(m_circle_pos, QPointF(x, y)).pointAt(0.02)); +} + +void CompositionRenderer::drawBase(QPainter &p) +{ + p.setPen(Qt::NoPen); + + QLinearGradient rect_gradient(0, 0, 0, height()); + rect_gradient.setColorAt(0, Qt::red); + rect_gradient.setColorAt(.17, Qt::yellow); + rect_gradient.setColorAt(.33, Qt::green); + rect_gradient.setColorAt(.50, Qt::cyan); + rect_gradient.setColorAt(.66, Qt::blue); + rect_gradient.setColorAt(.81, Qt::magenta); + rect_gradient.setColorAt(1, Qt::red); + p.setBrush(rect_gradient); + p.drawRect(width() / 2, 0, width() / 2, height()); + + QLinearGradient alpha_gradient(0, 0, width(), 0); + alpha_gradient.setColorAt(0, Qt::white); + alpha_gradient.setColorAt(0.2, Qt::white); + alpha_gradient.setColorAt(0.5, Qt::transparent); + alpha_gradient.setColorAt(0.8, Qt::white); + alpha_gradient.setColorAt(1, Qt::white); + + p.setCompositionMode(QPainter::CompositionMode_DestinationIn); + p.setBrush(alpha_gradient); + p.drawRect(0, 0, width(), height()); + + p.setCompositionMode(QPainter::CompositionMode_DestinationOver); + + p.setPen(Qt::NoPen); + p.setRenderHint(QPainter::SmoothPixmapTransform); +#ifdef Q_WS_QWS + p.drawPixmap(rect(), m_image); +#else + p.drawImage(rect(), m_image); +#endif +} + +void CompositionRenderer::drawSource(QPainter &p) +{ + p.setPen(Qt::NoPen); + p.setRenderHint(QPainter::Antialiasing); + p.setCompositionMode(m_composition_mode); + + QRectF circle_rect = rectangle_around(m_circle_pos); + QColor color = QColor::fromHsvF(m_circle_hue / 360.0, 1, 1, m_circle_alpha / 255.0); + QLinearGradient circle_gradient(circle_rect.topLeft(), circle_rect.bottomRight()); + circle_gradient.setColorAt(0, color.light()); + circle_gradient.setColorAt(0.5, color); + circle_gradient.setColorAt(1, color.dark()); + p.setBrush(circle_gradient); + + p.drawEllipse(circle_rect); +} + +void CompositionRenderer::paint(QPainter *painter) +{ +#if defined(QT_OPENGL_SUPPORT) && !defined(QT_OPENGL_ES) + if (usesOpenGL()) { + + int new_pbuf_size = m_pbuffer_size; + if (size().width() > m_pbuffer_size || + size().height() > m_pbuffer_size) + new_pbuf_size *= 2; + + if (size().width() < m_pbuffer_size/2 && + size().height() < m_pbuffer_size/2) + new_pbuf_size /= 2; + + if (!m_pbuffer || new_pbuf_size != m_pbuffer_size) { + if (m_pbuffer) { + m_pbuffer->deleteTexture(m_base_tex); + m_pbuffer->deleteTexture(m_compositing_tex); + delete m_pbuffer; + } + + m_pbuffer = new QGLPixelBuffer(QSize(new_pbuf_size, new_pbuf_size), QGLFormat::defaultFormat(), glWidget()); + m_pbuffer->makeCurrent(); + m_base_tex = m_pbuffer->generateDynamicTexture(); + m_compositing_tex = m_pbuffer->generateDynamicTexture(); + m_pbuffer_size = new_pbuf_size; + } + + if (size() != m_previous_size) { + m_previous_size = size(); + QPainter p(m_pbuffer); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.fillRect(QRect(0, 0, m_pbuffer->width(), m_pbuffer->height()), Qt::transparent); + drawBase(p); + p.end(); + m_pbuffer->updateDynamicTexture(m_base_tex); + } + + qreal x_fraction = width()/float(m_pbuffer->width()); + qreal y_fraction = height()/float(m_pbuffer->height()); + + { + QPainter p(m_pbuffer); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.fillRect(QRect(0, 0, m_pbuffer->width(), m_pbuffer->height()), Qt::transparent); + + p.save(); + glBindTexture(GL_TEXTURE_2D, m_base_tex); + glEnable(GL_TEXTURE_2D); + glColor4f(1.,1.,1.,1.); + + glBegin(GL_QUADS); + { + glTexCoord2f(0, 1.0); + glVertex2f(0, 0); + + glTexCoord2f(x_fraction, 1.0); + glVertex2f(width(), 0); + + glTexCoord2f(x_fraction, 1.0-y_fraction); + glVertex2f(width(), height()); + + glTexCoord2f(0, 1.0-y_fraction); + glVertex2f(0, height()); + } + glEnd(); + + glDisable(GL_TEXTURE_2D); + p.restore(); + + drawSource(p); + p.end(); + m_pbuffer->updateDynamicTexture(m_compositing_tex); + } + + glWidget()->makeCurrent(); + glBindTexture(GL_TEXTURE_2D, m_compositing_tex); + glEnable(GL_TEXTURE_2D); + glColor4f(1.,1.,1.,1.); + glBegin(GL_QUADS); + { + glTexCoord2f(0, 1.0); + glVertex2f(0, 0); + + glTexCoord2f(x_fraction, 1.0); + glVertex2f(width(), 0); + + glTexCoord2f(x_fraction, 1.0-y_fraction); + glVertex2f(width(), height()); + + glTexCoord2f(0, 1.0-y_fraction); + glVertex2f(0, height()); + } + glEnd(); + glDisable(GL_TEXTURE_2D); + } else +#endif + { + // using a QImage + if (m_buffer.size() != size()) { +#ifdef Q_WS_QWS + m_base_buffer = QPixmap(size()); + m_base_buffer.fill(Qt::transparent); +#else + m_buffer = QImage(size(), QImage::Format_ARGB32_Premultiplied); + m_base_buffer = QImage(size(), QImage::Format_ARGB32_Premultiplied); + + m_base_buffer.fill(0); +#endif + + QPainter p(&m_base_buffer); + + drawBase(p); + } + +#ifdef Q_WS_QWS + m_buffer = m_base_buffer; +#else + memcpy(m_buffer.bits(), m_base_buffer.bits(), m_buffer.numBytes()); +#endif + + { + QPainter p(&m_buffer); + drawSource(p); + } + +#ifdef Q_WS_QWS + painter->drawPixmap(0, 0, m_buffer); +#else + painter->drawImage(0, 0, m_buffer); +#endif + } + + if (m_animation_enabled && m_current_object == NoObject) { + updateCirclePos(); + } +} + +void CompositionRenderer::mousePressEvent(QMouseEvent *e) +{ + setDescriptionEnabled(false); + + QRectF circle = rectangle_around(m_circle_pos); + + if (circle.contains(e->pos())) { + m_current_object = Circle; + m_offset = circle.center() - e->pos(); + } else { + m_current_object = NoObject; + } +} + +void CompositionRenderer::mouseMoveEvent(QMouseEvent *e) +{ + if (m_current_object == Circle) setCirclePos(e->pos() + m_offset); +} + +void CompositionRenderer::mouseReleaseEvent(QMouseEvent *) +{ + m_current_object = NoObject; + + if (m_animation_enabled) + updateCirclePos(); +} + +void CompositionRenderer::setCirclePos(const QPointF &pos) +{ + const QRect oldRect = rectangle_around(m_circle_pos).toAlignedRect(); + m_circle_pos = pos; + const QRect newRect = rectangle_around(m_circle_pos).toAlignedRect(); +#if defined(QT_OPENGL_SUPPORT) && !defined(QT_OPENGL_ES) + if (usesOpenGL()) + update(); + else +#endif + update(oldRect | newRect); +} + diff --git a/demos/composition/composition.h b/demos/composition/composition.h new file mode 100644 index 0000000..1d504d0 --- /dev/null +++ b/demos/composition/composition.h @@ -0,0 +1,190 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 COMPOSITION_H +#define COMPOSITION_H + +#include "arthurwidgets.h" + +#include <QPainter> +#include <QEvent> + +QT_FORWARD_DECLARE_CLASS(QPushButton) +QT_FORWARD_DECLARE_CLASS(QRadioButton) + +#ifdef QT_OPENGL_SUPPORT +#include <QtOpenGL> +#endif + +class CompositionWidget : public QWidget +{ + Q_OBJECT + +public: + CompositionWidget(QWidget *parent); + +public slots: +void nextMode(); + +private: + bool m_cycle_enabled; + + QRadioButton *rbClear; + QRadioButton *rbSource; + QRadioButton *rbDest; + QRadioButton *rbSourceOver; + QRadioButton *rbDestOver; + QRadioButton *rbSourceIn; + QRadioButton *rbDestIn; + QRadioButton *rbSourceOut; + QRadioButton *rbDestOut; + QRadioButton *rbSourceAtop; + QRadioButton *rbDestAtop; + QRadioButton *rbXor; + + QRadioButton *rbPlus; + QRadioButton *rbMultiply; + QRadioButton *rbScreen; + QRadioButton *rbOverlay; + QRadioButton *rbDarken; + QRadioButton *rbLighten; + QRadioButton *rbColorDodge; + QRadioButton *rbColorBurn; + QRadioButton *rbHardLight; + QRadioButton *rbSoftLight; + QRadioButton *rbDifference; + QRadioButton *rbExclusion; +}; + +class CompositionRenderer : public ArthurFrame +{ + Q_OBJECT + + enum ObjectType { NoObject, Circle, Rectangle, Image }; + + Q_PROPERTY(int circleColor READ circleColor WRITE setCircleColor) + Q_PROPERTY(int circleAlpha READ circleAlpha WRITE setCircleAlpha) + Q_PROPERTY(bool animation READ animationEnabled WRITE setAnimationEnabled) + +public: + CompositionRenderer(QWidget *parent); + + void paint(QPainter *); + + void mousePressEvent(QMouseEvent *); + void mouseMoveEvent(QMouseEvent *); + void mouseReleaseEvent(QMouseEvent *); + + void setCirclePos(const QPointF &pos); + + QSize sizeHint() const { return QSize(500, 400); } + + bool animationEnabled() const { return m_animation_enabled; } + int circleColor() const { return m_circle_hue; } + int circleAlpha() const { return m_circle_alpha; } + +public slots: + void setClearMode() { m_composition_mode = QPainter::CompositionMode_Clear; update(); } + void setSourceMode() { m_composition_mode = QPainter::CompositionMode_Source; update(); } + void setDestMode() { m_composition_mode = QPainter::CompositionMode_Destination; update(); } + void setSourceOverMode() { m_composition_mode = QPainter::CompositionMode_SourceOver; update(); } + void setDestOverMode() { m_composition_mode = QPainter::CompositionMode_DestinationOver; update(); } + void setSourceInMode() { m_composition_mode = QPainter::CompositionMode_SourceIn; update(); } + void setDestInMode() { m_composition_mode = QPainter::CompositionMode_DestinationIn; update(); } + void setSourceOutMode() { m_composition_mode = QPainter::CompositionMode_SourceOut; update(); } + void setDestOutMode() { m_composition_mode = QPainter::CompositionMode_DestinationOut; update(); } + void setSourceAtopMode() { m_composition_mode = QPainter::CompositionMode_SourceAtop; update(); } + void setDestAtopMode() { m_composition_mode = QPainter::CompositionMode_DestinationAtop; update(); } + void setXorMode() { m_composition_mode = QPainter::CompositionMode_Xor; update(); } + + void setPlusMode() { m_composition_mode = QPainter::CompositionMode_Plus; update(); } + void setMultiplyMode() { m_composition_mode = QPainter::CompositionMode_Multiply; update(); } + void setScreenMode() { m_composition_mode = QPainter::CompositionMode_Screen; update(); } + void setOverlayMode() { m_composition_mode = QPainter::CompositionMode_Overlay; update(); } + void setDarkenMode() { m_composition_mode = QPainter::CompositionMode_Darken; update(); } + void setLightenMode() { m_composition_mode = QPainter::CompositionMode_Lighten; update(); } + void setColorDodgeMode() { m_composition_mode = QPainter::CompositionMode_ColorDodge; update(); } + void setColorBurnMode() { m_composition_mode = QPainter::CompositionMode_ColorBurn; update(); } + void setHardLightMode() { m_composition_mode = QPainter::CompositionMode_HardLight; update(); } + void setSoftLightMode() { m_composition_mode = QPainter::CompositionMode_SoftLight; update(); } + void setDifferenceMode() { m_composition_mode = QPainter::CompositionMode_Difference; update(); } + void setExclusionMode() { m_composition_mode = QPainter::CompositionMode_Exclusion; update(); } + + void setCircleAlpha(int alpha) { m_circle_alpha = alpha; update(); } + void setCircleColor(int hue) { m_circle_hue = hue; update(); } + void setAnimationEnabled(bool enabled) { m_animation_enabled = enabled; update(); } + +private: + void updateCirclePos(); + void drawBase(QPainter &p); + void drawSource(QPainter &p); + + QPainter::CompositionMode m_composition_mode; + +#ifdef Q_WS_QWS + QPixmap m_image; + QPixmap m_buffer; + QPixmap m_base_buffer; +#else + QImage m_image; + QImage m_buffer; + QImage m_base_buffer; +#endif + + int m_circle_alpha; + int m_circle_hue; + + QPointF m_circle_pos; + QPointF m_offset; + + ObjectType m_current_object; + bool m_animation_enabled; + +#ifdef QT_OPENGL_SUPPORT + QGLPixelBuffer *m_pbuffer; + GLuint m_base_tex; + GLuint m_compositing_tex; + int m_pbuffer_size; // width==height==size of pbuffer + QSize m_previous_size; +#endif +}; + +#endif // COMPOSITION_H diff --git a/demos/composition/composition.html b/demos/composition/composition.html new file mode 100644 index 0000000..1848ad8 --- /dev/null +++ b/demos/composition/composition.html @@ -0,0 +1,23 @@ +<html> + +<h1>Demo for composition modes</h1> + +<p> + This demo shows some of the more advanced composition modes supported by Qt. +</p> + +<p> + The two most common forms of composition are <b>Source</b> and <b>SourceOver</b>. + <b>Source</b> is used to draw opaque objects onto a paint device. In this mode, + each pixel in the source replaces the corresponding pixel in the destination. + In <b>SourceOver</b> composition mode, the source object is transparent and is + drawn on top of the destination. +</p> + +<p> + In addition to these standard modes, Qt defines the complete set of composition + modes as defined by Thomas Porter and Tom Duff. See the <tt>QPainter</tt> documentation + for details. +</p> + +</html> diff --git a/demos/composition/composition.pro b/demos/composition/composition.pro new file mode 100644 index 0000000..d5c4a60 --- /dev/null +++ b/demos/composition/composition.pro @@ -0,0 +1,27 @@ +SOURCES += main.cpp composition.cpp +HEADERS += composition.h + +SHARED_FOLDER = ../shared + +include($$SHARED_FOLDER/shared.pri) + +RESOURCES += composition.qrc +contains(QT_CONFIG, opengl) { + DEFINES += QT_OPENGL_SUPPORT + QT += opengl +} + +# install +target.path = $$[QT_INSTALL_DEMOS]/composition +sources.files = $$SOURCES $$HEADERS $$RESOURCES *.png *.jpg *.pro *.html +sources.path = $$[QT_INSTALL_DEMOS]/composition +INSTALLS += target sources + +win32-msvc* { + QMAKE_CXXFLAGS += /Zm500 + QMAKE_CFLAGS += /Zm500 +} + +wince* { + DEPLOYMENT_PLUGIN += qjpeg +} diff --git a/demos/composition/composition.qrc b/demos/composition/composition.qrc new file mode 100644 index 0000000..d02c397 --- /dev/null +++ b/demos/composition/composition.qrc @@ -0,0 +1,8 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/res/composition"> + <file>composition.cpp</file> + <file>composition.html</file> + <file>flower.jpg</file> + <file>flower_alpha.jpg</file> +</qresource> +</RCC> diff --git a/demos/composition/flower.jpg b/demos/composition/flower.jpg Binary files differnew file mode 100644 index 0000000..f8e022c --- /dev/null +++ b/demos/composition/flower.jpg diff --git a/demos/composition/flower_alpha.jpg b/demos/composition/flower_alpha.jpg Binary files differnew file mode 100644 index 0000000..6a3c2a0 --- /dev/null +++ b/demos/composition/flower_alpha.jpg diff --git a/demos/composition/main.cpp b/demos/composition/main.cpp new file mode 100644 index 0000000..74055b2 --- /dev/null +++ b/demos/composition/main.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the demonstration applications 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 "composition.h" + +#include <QApplication> + +int main(int argc, char **argv) +{ + // Q_INIT_RESOURCE(deform); + + QApplication app(argc, argv); + + CompositionWidget compWidget(0); + QStyle *arthurStyle = new ArthurStyle(); + compWidget.setStyle(arthurStyle); + + QList<QWidget *> widgets = qFindChildren<QWidget *>(&compWidget); + foreach (QWidget *w, widgets) + w->setStyle(arthurStyle); + compWidget.show(); + + return app.exec(); +} |