summaryrefslogtreecommitdiffstats
path: root/src/declarative/canvas
diff options
context:
space:
mode:
authorMichael Brasser <michael.brasser@nokia.com>2009-04-22 04:47:24 (GMT)
committerMichael Brasser <michael.brasser@nokia.com>2009-04-22 04:47:24 (GMT)
commit2366667fc97eb6a56203b2dd7dac776ff4164abd (patch)
treeb2acb6cc6bfe475d7e619e4788973b61fff775e0 /src/declarative/canvas
parent2c762f3b8b284a7c6dc0c499b7052013bad5b707 (diff)
downloadQt-2366667fc97eb6a56203b2dd7dac776ff4164abd.zip
Qt-2366667fc97eb6a56203b2dd7dac776ff4164abd.tar.gz
Qt-2366667fc97eb6a56203b2dd7dac776ff4164abd.tar.bz2
Initial import of kinetic-dui branch from the old kinetic
Diffstat (limited to 'src/declarative/canvas')
-rw-r--r--src/declarative/canvas/canvas.pri19
-rw-r--r--src/declarative/canvas/qsimplecanvas.cpp981
-rw-r--r--src/declarative/canvas/qsimplecanvas.h187
-rw-r--r--src/declarative/canvas/qsimplecanvas_graphicsview.cpp180
-rw-r--r--src/declarative/canvas/qsimplecanvas_opengl.cpp456
-rw-r--r--src/declarative/canvas/qsimplecanvas_opengl1.cpp401
-rw-r--r--src/declarative/canvas/qsimplecanvas_p.h196
-rw-r--r--src/declarative/canvas/qsimplecanvas_software.cpp190
-rw-r--r--src/declarative/canvas/qsimplecanvasfilter.cpp323
-rw-r--r--src/declarative/canvas/qsimplecanvasfilter.h113
-rw-r--r--src/declarative/canvas/qsimplecanvasfilter_p.h70
-rw-r--r--src/declarative/canvas/qsimplecanvasitem.cpp1841
-rw-r--r--src/declarative/canvas/qsimplecanvasitem.h300
-rw-r--r--src/declarative/canvas/qsimplecanvasitem_p.h242
-rw-r--r--src/declarative/canvas/qsimplecanvasserver.cpp107
-rw-r--r--src/declarative/canvas/qsimplecanvasserver_p.h71
16 files changed, 5677 insertions, 0 deletions
diff --git a/src/declarative/canvas/canvas.pri b/src/declarative/canvas/canvas.pri
new file mode 100644
index 0000000..8abfd99
--- /dev/null
+++ b/src/declarative/canvas/canvas.pri
@@ -0,0 +1,19 @@
+SOURCES += \
+ canvas/qsimplecanvas.cpp \
+ canvas/qsimplecanvasitem.cpp \
+ canvas/qsimplecanvasfilter.cpp \
+ canvas/qsimplecanvasserver.cpp
+
+HEADERS += \
+ canvas/qsimplecanvas.h \
+ canvas/qsimplecanvasitem.h \
+ canvas/qsimplecanvasfilter.h \
+ canvas/qsimplecanvas_p.h \
+ canvas/qsimplecanvasitem_p.h \
+ canvas/qsimplecanvasfilter_p.h \
+ canvas/qsimplecanvasserver_p.h
+
+contains(QT_CONFIG, opengles2): SOURCES += canvas/qsimplecanvas_opengl.cpp
+else:contains(QT_CONFIG, opengles1): SOURCES += canvas/qsimplecanvas_opengl1.cpp
+else:SOURCES += canvas/qsimplecanvas_software.cpp
+SOURCES += canvas/qsimplecanvas_graphicsview.cpp
diff --git a/src/declarative/canvas/qsimplecanvas.cpp b/src/declarative/canvas/qsimplecanvas.cpp
new file mode 100644
index 0000000..5eb6c60
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvas.cpp
@@ -0,0 +1,981 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 "qwidget.h"
+#include "qmutex.h"
+#include "qdebug.h"
+#include "qcoreapplication.h"
+#include "qsimplecanvasitem.h"
+#include "qsimplecanvasitem_p.h"
+#include "qsimplecanvas_p.h"
+#include "qtimer.h"
+#include "qdatetime.h"
+#include "qgraphicssceneevent.h"
+#if defined(QFX_RENDER_OPENGL)
+#include <glheaders.h>
+#endif
+#include "qboxlayout.h"
+#include "qsimplecanvasserver_p.h"
+#include "qsimplecanvas.h"
+
+
+QT_BEGIN_NAMESPACE
+DEFINE_BOOL_CONFIG_OPTION(fullUpdate, GFX_CANVAS_FULL_UPDATE);
+DEFINE_BOOL_CONFIG_OPTION(continuousUpdate, GFX_CANVAS_CONTINUOUS_UPDATE);
+DEFINE_BOOL_CONFIG_OPTION(useGraphicsView, QFX_USE_GRAPHICSVIEW);
+
+template<class T, int s = 60>
+class CircularList
+{
+public:
+ CircularList()
+ : _first(0), _size(0) {}
+
+ void append(const T &t)
+ {
+ int entry = (_first + _size) % s;
+ _array[entry] = t;
+ if(_size == s)
+ _first = (_first + 1) % s;
+ else
+ _size++;
+ }
+
+ int size() const
+ {
+ return _size;
+ }
+
+ T &operator[](int idx)
+ {
+ Q_ASSERT(idx < _size);
+ int entry = (_first + idx) % s;
+ return _array[entry];
+ }
+
+ void clear()
+ {
+ _first = 0;
+ _size = 0;
+ }
+private:
+ int _first;
+ int _size;
+ T _array[s];
+};
+
+
+class QSimpleCanvasRootLayer : public QSimpleCanvasLayer
+{
+public:
+ QSimpleCanvasRootLayer(QSimpleCanvas *);
+ virtual void addDirty(QSimpleCanvasItem *);
+ virtual void remDirty(QSimpleCanvasItem *);
+
+private:
+ friend class QSimpleCanvasItem;
+ QSimpleCanvas *_canvas;
+};
+
+void QSimpleCanvasRootLayer::addDirty(QSimpleCanvasItem *i)
+{
+ _canvas->addDirty(i);
+}
+
+void QSimpleCanvasRootLayer::remDirty(QSimpleCanvasItem *i)
+{
+ _canvas->remDirty(i);
+}
+
+void QSimpleCanvasPrivate::clearFocusPanel(QSimpleCanvasItem *panel)
+{
+ if(q->activeFocusPanel() == panel) {
+ focusPanels.pop();
+
+ switchToFocusPanel(q->activeFocusPanel(), panel, Qt::OtherFocusReason);
+ panel->activePanelOutEvent();
+ } else {
+ for(int ii = 0; ii < focusPanels.count(); ++ii)
+ if(focusPanels.at(ii) == panel) {
+ focusPanels.remove(ii);
+ break;
+ }
+ }
+}
+
+void QSimpleCanvasPrivate::switchToFocusPanel(QSimpleCanvasItem *panel, QSimpleCanvasItem *wasPanel, Qt::FocusReason focusReason)
+{
+ if(panel)
+ panel->activePanelInEvent();
+
+ QSimpleCanvasItem *wasFocusRoot = focusPanelData.value(wasPanel);
+ if(wasFocusRoot)
+ clearActiveFocusItem(wasFocusRoot, focusReason);
+
+ QSimpleCanvasItem *newFocusRoot = focusPanelData.value(panel);
+ if(newFocusRoot)
+ setFocusItem(newFocusRoot, focusReason);
+}
+
+void QSimpleCanvasPrivate::setActiveFocusPanel(QSimpleCanvasItem *panel, Qt::FocusReason focusReason)
+{
+ if(q->activeFocusPanel() == panel)
+ return;
+
+ if(panel) {
+ for(int ii = 0; ii < focusPanels.count(); ++ii)
+ if(focusPanels.at(ii) == panel) {
+ focusPanels.remove(ii);
+ break;
+ }
+ }
+ QSimpleCanvasItem *old = q->activeFocusPanel();
+ if(panel)
+ focusPanels << panel;
+ switchToFocusPanel(panel, old, focusReason);
+ if(old)
+ old->activePanelOutEvent();
+}
+
+void QSimpleCanvasPrivate::clearActiveFocusItem(QSimpleCanvasItem *item,
+ Qt::FocusReason focusReason)
+{
+ if (!item || !item->d_func())
+ return;
+
+ if(!item->d_func()->hasActiveFocus)
+ return;
+
+ item->d_func()->hasActiveFocus = false;
+ if(item->options() & QSimpleCanvasItem::IsFocusRealm) {
+ QSimpleCanvasItem *newItem = focusPanelData.value(item);
+ if(newItem) {
+ clearActiveFocusItem(newItem, focusReason);
+ } else {
+ focusItem = 0;
+ QFocusEvent event(QEvent::FocusOut, focusReason);
+ item->focusOutEvent(&event);
+ }
+ } else {
+ focusItem = 0;
+ QFocusEvent event(QEvent::FocusOut, focusReason);
+ item->focusOutEvent(&event);
+ }
+
+ if(item->options() & QSimpleCanvasItem::AcceptsInputMethods){
+ if(q->testAttribute(Qt::WA_InputMethodEnabled))
+ q->setAttribute(Qt::WA_InputMethodEnabled,false);
+ }
+ item->activeFocusChanged(true);
+}
+
+void QSimpleCanvasPrivate::setActiveFocusItem(QSimpleCanvasItem *item,
+ Qt::FocusReason focusReason)
+{
+ while(true) {
+ item->d_func()->setActiveFocus(true);
+ item->activeFocusChanged(true);
+ if(item->options() & QSimpleCanvasItem::IsFocusRealm) {
+ QSimpleCanvasItem *newItem = focusPanelData.value(item);
+ if(newItem)
+ item = newItem;
+ else
+ break;
+ } else {
+ break;
+ }
+ }
+
+ if(item->options() & QSimpleCanvasItem::AcceptsInputMethods){
+ if(!q->testAttribute(Qt::WA_InputMethodEnabled))
+ q->setAttribute(Qt::WA_InputMethodEnabled,true);
+ }
+ focusItem = item;
+ QFocusEvent event(QEvent::FocusIn, focusReason);
+ focusItem->focusInEvent(&event);
+}
+
+void QSimpleCanvasPrivate::clearFocusItem(QSimpleCanvasItem *item)
+{
+ // XXX
+#if 0
+ while(item->focusProxy())
+ item = item->focusProxy();
+#endif
+
+ QSimpleCanvasItem *scope = 0;
+ QSimpleCanvasItem *citem = item;
+ while(citem && !scope) {
+ if(citem->options() & QSimpleCanvasItem::IsFocusPanel)
+ scope = citem;
+ else if(citem != item && citem->options() & QSimpleCanvasItem::IsFocusRealm)
+ scope = citem;
+ citem = citem->parent();
+ }
+ Q_ASSERT(scope); // At the very least we'll find the canvas root
+
+ bool isActive = false;
+
+ if(scope->options() & QSimpleCanvasItem::IsFocusPanel)
+ isActive = (scope == q->activeFocusPanel());
+ else if(scope->options() & QSimpleCanvasItem::IsFocusRealm)
+ isActive = scope->hasActiveFocus();
+
+ if(isActive) clearActiveFocusItem(item, Qt::OtherFocusReason);
+ item->d_func()->setFocus(false);
+ item->focusChanged(false);
+
+ focusPanelData.insert(scope, 0);
+
+ if(lastFocusItem == item)
+ lastFocusItem = 0;
+ if(focusItem == item)
+ focusItem = 0;
+
+ if(scope->options() & QSimpleCanvasItem::IsFocusRealm && scope->hasActiveFocus()) {
+ setActiveFocusItem(scope, Qt::OtherFocusReason);
+ } else {
+ QSimpleCanvasItem *item = QSimpleCanvasItem::findNextFocus(scope);
+ if (item)
+ item->setFocus(true);
+ }
+}
+
+void QSimpleCanvasPrivate::setFocusItem(QSimpleCanvasItem *item,
+ Qt::FocusReason focusReason,
+ bool overwrite)
+{
+ Q_ASSERT(item);
+
+ // XXX
+#if 0
+ while(item->focusProxy())
+ item = item->focusProxy();
+#endif
+
+ if(item == focusItem)
+ return;
+
+ QSimpleCanvasItem *scope = 0;
+ QSimpleCanvasItem *citem = item;
+ while(citem && !scope) {
+ if(citem->options() & QSimpleCanvasItem::IsFocusPanel)
+ scope = citem;
+ else if(citem != item && citem->options() & QSimpleCanvasItem::IsFocusRealm)
+ scope = citem;
+ citem = citem->parent();
+ }
+ Q_ASSERT(scope); // At the very least we'll find the canvas root
+
+ if(!overwrite && focusPanelData.contains(scope)) {
+ item->d_func()->setFocus(false);
+ item->focusChanged(false);
+ return;
+ }
+
+ QSimpleCanvasItem *oldFocus = focusPanelData.value(scope);
+ bool isActive = false;
+
+ if(scope->options() & QSimpleCanvasItem::IsFocusPanel)
+ isActive = (scope == q->activeFocusPanel());
+ else if(scope->options() & QSimpleCanvasItem::IsFocusRealm)
+ isActive = scope->hasActiveFocus();
+
+ if(oldFocus) {
+ if(isActive) clearActiveFocusItem(oldFocus, focusReason);
+ oldFocus->d_func()->setFocus(false);
+ oldFocus->focusChanged(false);
+ }
+
+ focusPanelData.insert(scope, item);
+
+ if(isActive)
+ lastFocusItem = item;
+
+ if (item) {
+ item->d_func()->setFocus(true);
+ item->focusChanged(true);
+ if(isActive)
+ setActiveFocusItem(item, focusReason);
+ }
+}
+
+
+bool QSimpleCanvas::eventFilter(QObject *obj, QEvent *event)
+{
+ Q_UNUSED(obj);
+ switch (event->type()) {
+ case QEvent::GraphicsSceneMouseMove: {
+ QGraphicsSceneMouseEvent *me = (QGraphicsSceneMouseEvent*)event;
+ if (!me->buttons())
+ break;
+ }
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseRelease: {
+ //same logic as filter() function
+ for(int ii = 0; ii < d->mouseFilters.count(); ++ii) {
+ if(d->mouseFilters.at(ii)->mouseFilter((QGraphicsSceneMouseEvent*)event))
+ return true;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return false;
+}
+
+void QSimpleCanvasPrivate::installMouseFilter(QSimpleCanvasItem *item)
+{
+ mouseFilters << item;
+}
+
+void QSimpleCanvasPrivate::removeMouseFilter(QSimpleCanvasItem *item)
+{
+ mouseFilters.removeAll(item);
+}
+
+bool QSimpleCanvasPrivate::filter(QMouseEvent *e)
+{
+ if(mouseFilters.isEmpty())
+ return false;
+
+ QGraphicsSceneMouseEvent *me = mouseEventToSceneMouseEvent(e, e->pos());
+ for(int ii = 0; ii < mouseFilters.count(); ++ii) {
+ if(mouseFilters.at(ii)->mouseFilter(me)) {
+ delete me;
+ return true;
+ }
+ }
+ delete me;
+ return false;
+}
+
+QGraphicsSceneMouseEvent *QSimpleCanvasPrivate::mouseEventToSceneMouseEvent(QMouseEvent *e, const QPoint &item)
+{
+ QEvent::Type t;
+ switch(e->type()) {
+ default:
+ case QEvent::MouseButtonPress:
+ t = QEvent::GraphicsSceneMousePress;
+ break;
+ case QEvent::MouseButtonRelease:
+ t = QEvent::GraphicsSceneMouseRelease;
+ break;
+ case QEvent::MouseMove:
+ t = QEvent::GraphicsSceneMouseMove;
+ break;
+ case QEvent::MouseButtonDblClick:
+ t = QGraphicsSceneEvent::GraphicsSceneMouseDoubleClick;
+ break;
+ }
+
+ QGraphicsSceneMouseEvent *me = new QGraphicsSceneMouseEvent(t);
+ me->setButton(e->button());
+ me->setButtons(e->buttons());
+ me->setPos(item);
+ me->setScreenPos(e->pos());
+ me->setScenePos(e->pos());
+ return me;
+}
+
+bool QSimpleCanvasPrivate::deliverMousePress(QSimpleCanvasItem *base, QMouseEvent *e)
+{
+ if(base->clipType()) {
+ QRectF br = base->boundingRect();
+ QPointF pos = base->mapFromScene(e->pos());
+ if(!br.contains(pos.toPoint()))
+ return false;
+ }
+
+ const QList<QSimpleCanvasItem *> &children = base->d_func()->children;
+ for(int ii = children.count() - 1; ii >= 0; --ii) {
+ if(children.at(ii)->visible() != 0.)
+ if(deliverMousePress(children.at(ii), e))
+ return true;
+ }
+
+ if(base->acceptedMouseButtons() & e->button()) {
+ QRectF br = base->boundingRect();
+ QPoint pos = base->mapFromScene(e->pos()).toPoint();
+
+ if(br.contains(pos)) {
+ QGraphicsSceneMouseEvent *me = mouseEventToSceneMouseEvent(e, pos);
+ if (me->type() == QEvent::GraphicsSceneMousePress)
+ base->mousePressEvent(me);
+ else
+ base->mouseDoubleClickEvent(me);
+ bool isAccepted = me->isAccepted();
+ delete me;
+ if(isAccepted) {
+ lastMouseItem = base;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+QSimpleCanvasRootLayer::QSimpleCanvasRootLayer(QSimpleCanvas *c)
+: _canvas(c)
+{
+ QSimpleCanvasItem::d_func()->canvas = c;
+ setOptions(IsFocusPanel);
+ update();
+}
+
+
+struct QSimpleCanvasTiming
+{
+ QSimpleCanvasTiming()
+ : time(-1), paintTime(-1), timeBetweenFrames(-1) {}
+ QSimpleCanvasTiming(const QRegion &_r, int _time, int _paintTime,
+ int _timeBetweenFrames)
+ : region(_r), time(_time), paintTime(_paintTime),
+ timeBetweenFrames(_timeBetweenFrames) {}
+ QSimpleCanvasTiming(const QSimpleCanvasTiming &other)
+ : region(other.region), time(other.time), paintTime(other.paintTime),
+ timeBetweenFrames(other.timeBetweenFrames) {}
+ QSimpleCanvasTiming &operator=(const QSimpleCanvasTiming &other) {
+ region = other.region; time = other.time; paintTime = other.paintTime;
+ timeBetweenFrames = other.timeBetweenFrames; return *this;
+ }
+ QRegion region;
+ int time;
+ int paintTime;
+ int timeBetweenFrames;
+};
+
+// XXX
+static CircularList<QSimpleCanvasTiming> gfxCanvasTiming;
+
+void QSimpleCanvasGraphicsView::paintEvent(QPaintEvent *pe)
+{
+ QRegion r = pe->region();
+ int tbf = canvas->frameTimer.restart();
+
+ canvas->lrpTimer.start();
+ QGraphicsView::paintEvent(pe);
+ canvas->lrpTime = canvas->lrpTimer.elapsed();
+
+ int frametimer = canvas->frameTimer.elapsed();
+ gfxCanvasTiming.append(QSimpleCanvasTiming(r, frametimer, canvas->lrpTime, tbf));
+ canvas->lrpTime = 0;
+ if(canvas->canvasServer)
+ canvas->canvasServer->addTiming(canvas->lrpTime, frametimer, tbf);
+}
+
+void QSimpleCanvasGraphicsView::focusInEvent(QFocusEvent *)
+{
+}
+
+/*!
+ \class QSimpleCanvas
+ \brief The QSimpleCanvas class implements the canvas used by Qt Declarative
+ */
+
+QSimpleCanvas::QSimpleCanvas(CanvasMode mode, QWidget *parent)
+: QWidget(parent), d(new QSimpleCanvasPrivate(this))
+{
+ d->init(mode);
+}
+
+QSimpleCanvas::QSimpleCanvas(QWidget *parent)
+: QWidget(parent), d(new QSimpleCanvasPrivate(this))
+{
+ d->init(useGraphicsView()?GraphicsView:SimpleCanvas);
+}
+
+void QSimpleCanvasPrivate::init(QSimpleCanvas::CanvasMode mode)
+{
+ this->mode = mode;
+
+ if(mode == QSimpleCanvas::SimpleCanvas)
+ qWarning("QSimpleCanvas: Using simple canvas");
+ else
+ qWarning("QSimpleCanvas: Using GraphicsView canvas");
+
+ if(fullUpdate())
+ qWarning("QSimpleCanvas: Full update enabled");
+ if(continuousUpdate())
+ qWarning("QSimpleCanvas: Continuous update enabled");
+
+ QByteArray env = qgetenv("GFX_CANVAS_SERVER_PORT");
+ if(!env.isEmpty()){
+ int port = env.toInt();
+ if(port >= 1024)
+ canvasServer = new QSimpleCanvasServer(port, q);
+ }
+
+ root = new QSimpleCanvasRootLayer(q);
+ root->setActiveFocusPanel(true);
+ q->setFocusPolicy(Qt::StrongFocus);
+
+ if(mode == QSimpleCanvas::GraphicsView) {
+ view = new QSimpleCanvasGraphicsView(this);
+ QHBoxLayout *layout = new QHBoxLayout(q);
+ layout->setSpacing(0);
+ layout->setContentsMargins(0, 0, 0, 0);
+ q->setLayout(layout);
+ layout->addWidget(view);
+ view->setOptimizationFlags(QGraphicsView::DontSavePainterState);
+ view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view->setFrameStyle(0);
+ static_cast<QSimpleCanvasItemPrivate*>(root->d_ptr)->convertToGraphicsItem();
+ view->scene()->addItem(static_cast<QSimpleCanvasItemPrivate*>(root->d_ptr)->graphicsItem);
+
+ // These seem to give the best performance
+ view->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
+ view->scene()->setItemIndexMethod(QGraphicsScene::NoIndex);
+ view->viewport()->setFocusPolicy(Qt::NoFocus);
+ }
+
+#if defined(QFX_RENDER_OPENGL) && defined(Q_WS_X11)
+ QTimer *t = new QTimer(q);
+ t->setInterval(200);
+ QObject::connect(t, SIGNAL(timeout()), &egl, SLOT(updateGL()));
+ t->start();
+#endif
+}
+
+QSimpleCanvas::~QSimpleCanvas()
+{
+ delete d->root;
+ delete d;
+}
+
+void QSimpleCanvasPrivate::paint(QPainter &p)
+{
+#if defined(QFX_RENDER_QPAINTER)
+ if(!isSetup)
+ root->d_func()->setupPainting(0, q->rect());
+
+ lrpTimer.start();
+
+ root->d_func()->paint(p);
+
+ lrpTime = lrpTimer.elapsed();
+#else
+ Q_UNUSED(p);
+#endif
+}
+
+QSimpleCanvas::CanvasMode QSimpleCanvas::canvasMode() const
+{
+ return d->mode;
+}
+
+QSimpleCanvasItem *QSimpleCanvas::root()
+{
+ return d->root;
+}
+
+void QSimpleCanvas::keyPressEvent(QKeyEvent *event)
+{
+ if (d->focusItem)
+ d->focusItem->keyPressEvent(event);
+ QWidget::keyPressEvent(event);
+}
+
+void QSimpleCanvas::keyReleaseEvent(QKeyEvent *event)
+{
+ if (d->focusItem)
+ d->focusItem->keyReleaseEvent(event);
+ QWidget::keyReleaseEvent(event);
+}
+
+void QSimpleCanvas::inputMethodEvent(QInputMethodEvent *event)
+{
+ if(d->focusItem)
+ d->focusItem->inputMethodEvent(event);
+ else
+ QWidget::inputMethodEvent(event);
+}
+
+QVariant QSimpleCanvas::inputMethodQuery(Qt::InputMethodQuery query) const
+{
+ if(d->focusItem)
+ return d->focusItem->inputMethodQuery(query);
+ return QWidget::inputMethodQuery(query);
+}
+
+void QSimpleCanvas::mousePressEvent(QMouseEvent *e)
+{
+ if(d->isSimpleCanvas() &&
+ (d->filter(e) || d->deliverMousePress(d->root, e))) {
+ e->accept();
+ } else {
+ QWidget::mousePressEvent(e);
+ }
+}
+
+void QSimpleCanvas::mouseDoubleClickEvent(QMouseEvent *e)
+{
+ if(d->isSimpleCanvas() &&
+ (d->filter(e) || d->deliverMousePress(d->root, e))) {
+ e->accept();
+ } else {
+ QWidget::mouseDoubleClickEvent(e);
+ }
+}
+
+void QSimpleCanvas::mouseMoveEvent(QMouseEvent *e)
+{
+ if(d->isSimpleCanvas() && d->filter(e)) {
+ e->accept();
+ } else if(d->isSimpleCanvas() && d->lastMouseItem) {
+ QPoint p = d->lastMouseItem->mapFromScene(e->pos()).toPoint();
+ QGraphicsSceneMouseEvent *me = d->mouseEventToSceneMouseEvent(e, p);
+ d->lastMouseItem->mouseMoveEvent(me);
+ e->setAccepted(me->isAccepted());
+ delete me;
+ } else {
+ QWidget::mouseMoveEvent(e);
+ }
+}
+
+void QSimpleCanvas::mouseReleaseEvent(QMouseEvent *e)
+{
+ if(d->isSimpleCanvas() && d->filter(e)) {
+ e->accept();
+ } else if(d->isSimpleCanvas() && d->lastMouseItem) {
+ QPoint p = d->lastMouseItem->mapFromScene(e->pos()).toPoint();
+ QGraphicsSceneMouseEvent *me = d->mouseEventToSceneMouseEvent(e, p);
+ d->lastMouseItem->mouseReleaseEvent(me);
+ d->lastMouseItem->mouseUngrabEvent();
+ e->setAccepted(me->isAccepted());
+ delete me;
+ d->lastMouseItem = 0;
+ } else {
+ QWidget::mouseReleaseEvent(e);
+ }
+}
+
+void QSimpleCanvas::focusInEvent(QFocusEvent *event)
+{
+ // XXX
+#if 0
+ if (d->lastFocusItem && event->reason() == Qt::ActiveWindowFocusReason) {
+ d->setFocusItem(d->lastFocusItem, event->reason());
+ } else {
+ QSimpleCanvasItem *panel = activeFocusPanel();
+ QSimpleCanvasItem *focusItem = 0;
+ if(panel->isFocusable())
+ focusItem = panel;
+ else
+ focusItem = QSimpleCanvasItem::findNextFocus(panel);
+
+ if (focusItem)
+ d->setFocusItem(focusItem, event->reason());
+ else
+ QWidget::focusNextPrevChild(true);
+ }
+#endif
+ QWidget::focusInEvent(event);
+}
+
+void QSimpleCanvas::focusOutEvent(QFocusEvent *event)
+{
+ // XXX
+#if 0
+ if (event->reason() == Qt::ActiveWindowFocusReason) {
+ d->lastFocusItem = activeFocusPanel();
+ d->setActiveFocusPanel(0, Qt::ActiveWindowFocusReason);
+ }
+#endif
+ QWidget::focusOutEvent(event);
+}
+
+bool QSimpleCanvas::focusNextPrevChild(bool)
+{
+ // XXX
+#if 0
+ if (d->focusItem) {
+ QSimpleCanvasItem *item = next ? QSimpleCanvasItem::findNextFocus(d->focusItem) : QSimpleCanvasItem::findPrevFocus(d->focusItem);
+ if (item) {
+ d->setFocusItem(item,
+ next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
+ return true;
+ }
+ }
+
+ QSimpleCanvasItem *panel = activeFocusPanel();
+ QSimpleCanvasItem *item = 0;
+ if(panel->isFocusable())
+ item = panel;
+ else
+ item = next ? QSimpleCanvasItem::findNextFocus(panel) : QSimpleCanvasItem::findPrevFocus(panel);
+ if (item && item != d->focusItem) {
+ d->setFocusItem(item,
+ next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
+ return true;
+ }
+
+ if (d->focusItem)
+ d->setActiveFocusPanel(0, next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
+
+#endif
+ return false;
+}
+
+
+void QSimpleCanvas::showEvent(QShowEvent *e)
+{
+#if defined(QFX_RENDER_OPENGL)
+ d->egl.resize(width(), height());
+#endif
+ if(d->isGraphicsView())
+ d->view->setSceneRect(rect());
+
+ QWidget::showEvent(e);
+}
+
+void QSimpleCanvas::resizeEvent(QResizeEvent *e)
+{
+#if defined(QFX_RENDER_OPENGL)
+ d->egl.resize(width(), height());
+#endif
+ if(d->isGraphicsView())
+ d->view->setSceneRect(rect());
+ QWidget::resizeEvent(e);
+}
+
+
+void QSimpleCanvas::remDirty(QSimpleCanvasItem *c)
+{
+ d->dirtyItems.removeAll(c);
+}
+
+void QSimpleCanvas::queueUpdate()
+{
+ if(!d->timer) {
+ QCoreApplication::postEvent(this, new QEvent(QEvent::User));
+ d->timer = 1;
+ }
+}
+
+void QSimpleCanvas::addDirty(QSimpleCanvasItem *c)
+{
+ queueUpdate();
+ if(d->isSimpleCanvas()) {
+ d->oldDirty |= c->d_func()->data()->lastPaintRect;
+#if defined(QFX_RENDER_OPENGL)
+ // Check for filters
+ QSimpleCanvasItem *fi = c->parent();
+ while(fi) {
+ if(fi->d_func()->data()->dirty) {
+ break;
+ } else if(fi->filter()) {
+ fi->update();
+ break;
+ }
+ fi = fi->parent();
+ }
+#endif
+ d->dirtyItems.append(c);
+ }
+}
+
+QRect QSimpleCanvasPrivate::dirtyItemClip() const
+{
+ QRect rv;
+ if(isSimpleCanvas()) {
+#if defined(QFX_RENDER_OPENGL)
+ QRectF r;
+ for(int ii = 0; ii < dirtyItems.count(); ++ii)
+ r |= dirtyItems.at(ii)->d_func()->data()->lastPaintRect;
+ rv = egl.map(r);
+#else
+ for(int ii = 0; ii < dirtyItems.count(); ++ii)
+ rv |= dirtyItems.at(ii)->d_func()->data()->lastPaintRect;
+#endif
+ }
+ return rv;
+}
+
+QRegion QSimpleCanvasPrivate::resetDirty()
+{
+ if(isSimpleCanvas()) {
+#if defined(QFX_RENDER_OPENGL)
+ QRect r = egl.map(oldDirty) | dirtyItemClip();
+#else
+ QRect r = oldDirty | dirtyItemClip();
+#endif
+ if (!r.isEmpty())
+ r.adjust(-1,-1,2,2); //make sure we get everything (since we rounded from floats to ints)
+ for(int ii = 0; ii < dirtyItems.count(); ++ii)
+ static_cast<QSimpleCanvasItemPrivate*>(dirtyItems.at(ii)->d_ptr)->data()->dirty = false;
+ dirtyItems.clear();
+ oldDirty = QRect();
+
+ if(fullUpdate())
+ return QRegion();
+ else
+ return QRegion(r);
+ } else {
+ return QRegion();
+ }
+}
+
+QSimpleCanvasItem *QSimpleCanvas::focusItem() const
+{
+ return d->focusItem;
+}
+
+QSimpleCanvasItem *QSimpleCanvas::activeFocusPanel() const
+{
+ if(d->focusPanels.isEmpty())
+ return 0;
+ else
+ return d->focusPanels.top();
+}
+
+bool QSimpleCanvas::event(QEvent *e)
+{
+ if(e->type() == QEvent::User && d->isSimpleCanvas()) {
+ d->timer = 0;
+ d->isSetup = true;
+#if defined(QFX_RENDER_OPENGL1)
+ unsigned int zero = 0;
+ d->root->d_func()->setupPainting(0, rect(), &zero);
+#else
+ d->root->d_func()->setupPainting(0, rect());
+#endif
+
+ QRegion r = d->resetDirty();
+
+ int tbf = d->frameTimer.restart();
+
+#if defined(QFX_RENDER_QPAINTER)
+ if(r.isEmpty() || fullUpdate())
+ repaint();
+ else
+ repaint(r);
+ emit framePainted();
+#else
+ QRect br = r.boundingRect();
+ QRect nr(br.x(), height() - br.y() - br.height(), br.width(), br.height());
+
+ if(r.isEmpty() || fullUpdate())
+ d->egl.updateGL();
+ else
+ d->egl.updateGL(nr);
+ emit framePainted();
+#endif
+ d->isSetup = false;
+
+ int frametimer = d->frameTimer.elapsed();
+ gfxCanvasTiming.append(QSimpleCanvasTiming(r, frametimer, d->lrpTime, tbf));
+ if(d->canvasServer)
+ d->canvasServer->addTiming(d->lrpTime, frametimer, tbf);
+ d->lrpTime = 0;
+ if(continuousUpdate())
+ queueUpdate();
+
+ return true;
+ } else {
+ return QWidget::event(e);
+ }
+}
+
+void QSimpleCanvas::paintEvent(QPaintEvent *)
+{
+#if defined(QFX_RENDER_QPAINTER)
+ if(d->mode == SimpleCanvas) {
+ QPainter p(this);
+ d->paint(p);
+ }
+#endif
+}
+
+void QSimpleCanvas::dumpTiming()
+{
+ for(int ii = 0; ii < gfxCanvasTiming.size(); ++ii) {
+ const QSimpleCanvasTiming &t = gfxCanvasTiming[ii];
+
+ qreal repaintFps = 1000. / qreal(t.time);
+ qreal paintFps = 1000. / qreal(t.paintTime);
+ qreal tbfFps = 1000. / qreal(t.timeBetweenFrames);
+
+ qWarning() << "repaint():" << t.time << "ms," << repaintFps << "fps. paint():" << t.paintTime << "ms," << paintFps << "fps. timeSinceLastFrame:" << t.timeBetweenFrames << "ms," << tbfFps << "fps.";
+ qWarning() << t.region;
+ }
+ gfxCanvasTiming.clear();
+}
+
+void QSimpleCanvas::dumpItems()
+{
+ int items = d->root->d_func()->dump(0);
+ qWarning() << "Total:" << items;
+}
+
+void QSimpleCanvas::checkState()
+{
+ if(d->isSimpleCanvas()) {
+ QSimpleCanvasItemPrivate::FocusStateCheckRDatas r;
+ if(d->root->d_func()->checkFocusState(0, &r))
+ qWarning() << "State OK";
+ }
+}
+
+/*!
+ Returns canvas as an image. Not a fast operation.
+*/
+QImage QSimpleCanvas::asImage() const
+{
+ if(d->isSimpleCanvas()) {
+#if defined(QFX_RENDER_QPAINTER)
+ QImage img(width(),height(),QImage::Format_RGB32);
+ QPainter p(&img);
+ const_cast<QSimpleCanvas*>(this)->d->paint(p);
+ return img;
+#elif defined(QFX_RENDER_OPENGL)
+ return d->egl.grabFrameBuffer();
+#endif
+ } else {
+ QImage img(width(),height(),QImage::Format_RGB32);
+ QPainter p(&img);
+ d->view->render(&p);
+ return img;
+ }
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvas.h b/src/declarative/canvas/qsimplecanvas.h
new file mode 100644
index 0000000..3da7251
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvas.h
@@ -0,0 +1,187 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 QSIMPLECANVAS_H
+#define QSIMPLECANVAS_H
+
+#include <qfxglobal.h>
+
+#ifdef QFX_RENDER_OPENGL
+#include <QtGui/qmatrix4x4.h>
+#endif
+
+#include <QTransform>
+#include <QPainter>
+#include <QDebug>
+#include <QWidget>
+#include <QImage>
+#include <QKeyEvent>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+namespace QSimpleCanvasConfig
+{
+ enum ImageType { Opaque, Translucent };
+
+#ifdef QFX_RENDER_OPENGL
+ typedef QMatrix4x4 Matrix;
+ typedef QImage Image;
+
+ inline Matrix transformToMatrix(const QTransform &)
+ {
+ return Matrix(); // XXX
+ }
+ inline QTransform matrixToTransform(const Matrix &)
+ {
+ return QTransform(); // XXX
+ }
+ inline bool needConvert(ImageType, const Image &)
+ { return false; }
+ inline Image convert(ImageType, const Image &i)
+ { return i; }
+ inline Image create(const QSize &s)
+ { return QImage(s, QImage::Format_ARGB32); }
+ inline const Image &toImage(const QImage &i)
+ { return i; }
+
+#elif defined(QFX_RENDER_QPAINTER)
+ typedef QTransform Matrix;
+ typedef QImage Image;
+
+ inline Matrix transformToMatrix(const QTransform &t)
+ { return t; }
+ inline QTransform matrixToTransform(const Matrix &t)
+ { return t; }
+ inline bool needConvert(ImageType type, const Image &img) {
+ QImage::Format f = img.format();
+ return !((type == Opaque && f == QImage::Format_RGB16) ||
+ (type == Translucent && f == QImage::Format_ARGB32_Premultiplied));
+ }
+ inline Image convert(ImageType type, const Image &img) {
+ if(type == Opaque)
+ return img.convertToFormat(QImage::Format_RGB16);
+ else
+ return img.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ }
+ inline Image create(const QSize &s)
+ { return QImage(s, QImage::Format_ARGB32_Premultiplied); }
+ inline const Image &toImage(const QImage &i)
+ { return i; }
+#endif
+}
+
+class QSimpleCanvas;
+class QSimpleCanvasLayer;
+
+class QGraphicsSceneMouseEvent;
+class GLBasicShaders;
+class QSimpleCanvasItem;
+class QSimpleCanvasPrivate;
+class Q_DECLARATIVE_EXPORT QSimpleCanvas : public QWidget
+{
+Q_OBJECT
+public:
+ typedef QSimpleCanvasConfig::Matrix Matrix;
+
+ enum CanvasMode { GraphicsView, SimpleCanvas };
+
+ QSimpleCanvas(QWidget *parent = 0);
+ QSimpleCanvas(CanvasMode, QWidget *parent = 0);
+ virtual ~QSimpleCanvas();
+
+ CanvasMode canvasMode() const;
+
+ QSimpleCanvasItem *root();
+
+ // Debugging
+ void dumpTiming();
+ void dumpItems();
+ void checkState();
+
+ QSimpleCanvasItem *focusItem() const;
+ QSimpleCanvasItem *activeFocusPanel() const;
+ QImage asImage() const;
+
+Q_SIGNALS:
+ void framePainted();
+
+protected:
+ virtual bool event(QEvent *);
+ virtual void paintEvent(QPaintEvent *);
+ virtual void keyPressEvent(QKeyEvent *);
+ virtual void keyReleaseEvent(QKeyEvent *);
+ virtual void mousePressEvent(QMouseEvent *);
+ virtual void mouseDoubleClickEvent(QMouseEvent *);
+ virtual void mouseMoveEvent(QMouseEvent *);
+ virtual void mouseReleaseEvent(QMouseEvent *);
+ virtual void focusInEvent(QFocusEvent *event);
+ virtual void focusOutEvent(QFocusEvent *event);
+ virtual bool focusNextPrevChild(bool next);
+ virtual bool eventFilter(QObject *obj, QEvent *event);
+ virtual void inputMethodEvent(QInputMethodEvent *event);
+ virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
+
+ virtual void showEvent(QShowEvent *);
+ virtual void resizeEvent(QResizeEvent *);
+private:
+
+ friend class QSimpleCanvasRootLayer;
+ friend class QSimpleCanvasPrivate;
+ friend class QSimpleCanvasItem;
+ friend class QSimpleCanvasItemPrivate;
+ friend class QSimpleCanvasFilter;
+ friend class QSimpleGraphicsItem;
+
+ void queueUpdate();
+ QSimpleCanvasPrivate *d;
+ void addDirty(QSimpleCanvasItem *);
+ void remDirty(QSimpleCanvasItem *);
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/canvas/qsimplecanvas_graphicsview.cpp b/src/declarative/canvas/qsimplecanvas_graphicsview.cpp
new file mode 100644
index 0000000..0f80128
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvas_graphicsview.cpp
@@ -0,0 +1,180 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 "qsimplecanvas.h"
+#include "qsimplecanvas_p.h"
+#include "qsimplecanvasitem.h"
+#include "qsimplecanvasitem_p.h"
+#include <QGraphicsItem>
+#include <QGraphicsSceneMouseEvent>
+
+
+QT_BEGIN_NAMESPACE
+static QHash<QGraphicsScene*,QSimpleCanvas*> sceneMap;
+
+QSimpleCanvasGraphicsView::QSimpleCanvasGraphicsView(QSimpleCanvasPrivate *parent)
+: QGraphicsView(parent->q), canvas(parent)
+{
+ setScene(&_scene);
+ sceneMap[&_scene] = parent->q;
+ setFrameShape(QFrame::NoFrame);
+ viewport()->setAttribute(Qt::WA_OpaquePaintEvent);
+}
+
+QSimpleCanvasGraphicsView::~QSimpleCanvasGraphicsView()
+{
+ sceneMap.remove(&_scene);
+}
+
+QSimpleGraphicsItem::QSimpleGraphicsItem(QSimpleCanvasItem *canvasItem)
+: /*scene(0),*/ owner(canvasItem)
+{
+ setAcceptedMouseButtons(Qt::NoButton);
+}
+
+QSimpleGraphicsItem::~QSimpleGraphicsItem()
+{
+ owner->d_func()->graphicsItem = 0;
+}
+
+void QSimpleGraphicsItem::paint(QPainter *painter,
+ const QStyleOptionGraphicsItem *, QWidget *)
+{
+ owner->paintContents(*painter);
+}
+
+QRectF QSimpleGraphicsItem::boundingRect() const
+{
+ return owner->boundingRect();
+}
+
+void QSimpleGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ owner->mousePressEvent(event);
+}
+
+void QSimpleGraphicsItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ owner->mouseReleaseEvent(event);
+}
+
+void QSimpleGraphicsItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
+{
+ owner->mouseDoubleClickEvent(event);
+}
+
+void QSimpleGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ owner->mouseMoveEvent(event);
+}
+
+bool QSimpleGraphicsItem::sceneEvent(QEvent *event)
+{
+ bool rv = QGraphicsItem::sceneEvent(event);
+ if(event->type() == QEvent::UngrabMouse)
+ owner->mouseUngrabEvent();
+ return rv;
+}
+
+QVariant QSimpleGraphicsItem::itemChange(GraphicsItemChange change, const QVariant &value)
+{
+ if(change == ItemSceneHasChanged) {
+ QSimpleCanvasItemPrivate *owner_d = static_cast<QSimpleCanvasItemPrivate*>(owner->d_ptr);
+ QSimpleCanvas *oldCanvas = owner_d->canvas;
+ owner_d->canvas = sceneMap[scene()];
+ if (owner_d->canvas){
+ if (owner->hasFocus())
+ owner->canvas()->d->setFocusItem(owner, Qt::OtherFocusReason);
+ if (owner->options() & QSimpleCanvasItem::IsFocusPanel) {
+ if (owner_d->wantsActiveFocusPanelPendingCanvas) {
+ owner_d->hasBeenActiveFocusPanel = true;
+ owner->canvas()->d->setActiveFocusPanel(owner);
+ owner_d->wantsActiveFocusPanelPendingCanvas = false;
+ }
+ }
+ }
+ if(owner->options() & QSimpleCanvasItem::MouseFilter)
+ owner_d->gvRemoveMouseFilter();
+
+ if (oldCanvas != owner_d->canvas)
+ owner->canvasChanged();
+
+ if(owner->options() & QSimpleCanvasItem::MouseFilter)
+ owner_d->gvAddMouseFilter();
+ }
+
+ return QGraphicsItem::itemChange(change, value);
+}
+
+void QSimpleGraphicsItem::keyPressEvent(QKeyEvent *event)
+{
+ owner->keyPressEvent(event);
+ QGraphicsItem::keyPressEvent(event);
+}
+
+void QSimpleGraphicsItem::keyReleaseEvent(QKeyEvent *event)
+{
+ owner->keyReleaseEvent(event);
+ QGraphicsItem::keyReleaseEvent(event);
+}
+
+void QSimpleGraphicsItem::focusInEvent(QFocusEvent *)
+{
+ if (!owner->hasFocus())
+ owner->setFocus(true);
+}
+
+void QSimpleCanvasItemPrivate::gvRemoveMouseFilter()
+{
+ QGraphicsScene *scene = graphicsItem->scene();
+ if(!scene) return;
+
+ scene->removeEventFilter(q_ptr);
+}
+
+void QSimpleCanvasItemPrivate::gvAddMouseFilter()
+{
+ QGraphicsScene *scene = graphicsItem->scene();
+ if(!scene) return;
+
+ scene->installEventFilter(q_ptr);
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvas_opengl.cpp b/src/declarative/canvas/qsimplecanvas_opengl.cpp
new file mode 100644
index 0000000..f508aea
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvas_opengl.cpp
@@ -0,0 +1,456 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 "qsimplecanvas.h"
+#include "qsimplecanvas_p.h"
+#include "qsimplecanvasitem_p.h"
+#include "qsimplecanvasfilter_p.h"
+#include <glsave.h>
+#include <QtOpenGL/qglframebufferobject.h>
+#include <gltexture.h>
+#include <math.h>
+
+
+QT_BEGIN_NAMESPACE
+void CanvasEGLWidget::paintGL()
+{
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+ _canvas->paintGL();
+}
+
+void CanvasEGLWidget::updateGL()
+{
+ _clip = QRect();
+ QGLWidget::updateGL();
+}
+
+void CanvasEGLWidget::updateGL(const QRect &r)
+{
+ if(r.isEmpty())
+ return;
+
+ _clip = r;
+ QGLWidget::updateGL();
+}
+
+void CanvasEGLWidget::resizeGL(int w, int h)
+{
+ glViewport(0, 0, w, h);
+}
+
+QRect CanvasEGLWidget::map(const QRectF &f) const
+{
+ return invDefaultTransform.mapRect(f).toAlignedRect();
+}
+
+void CanvasEGLWidget::resizeEvent(QResizeEvent *e)
+{
+ defaultTransform.setIdentity();
+ defaultTransform.flipCoordinates();
+ defaultTransform.translate(-1, -1, 0);
+ defaultTransform.scale(2. / width(), 2. / height(), 1. / (1024. * 1024.));
+ invDefaultTransform = defaultTransform.inverted();
+ _canvas->root->d_func()->data()->transformActive = defaultTransform;
+ _canvas->root->d_func()->data()->transformValid = true;
+
+ QGLWidget::resizeEvent(e);
+}
+
+void CanvasEGLWidget::initializeGL()
+{
+ glEnable(GL_BLEND);
+ glEnable(GL_STENCIL_TEST);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
+ GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ glStencilFunc(GL_EQUAL, 0, 0xFFFFFFFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+}
+
+void QSimpleCanvasPrivate::paintGL()
+{
+ lrpTimer.start();
+
+ QSimpleCanvasItemPrivate::GLPaintParameters p;
+ p.sceneRect = QRect(0, 0, q->width(), q->height());
+ p.clipRect = p.sceneRect;
+ p.stencilValue = 0;
+ p.opacity = 1;
+ p.forceParamRefresh = false;
+ if(!isSetup)
+ root->d_func()->setupPainting(0, QRect());
+ root->d_func()->paint(p);
+
+ lrpTime = lrpTimer.elapsed();
+}
+
+QGLFramebufferObject *QSimpleCanvasPrivate::acquire(int w, int h)
+{
+ if(w <= 0 || h <= 0)
+ return 0;
+
+ int size = qMax(w, h);
+ for(int ii = 0; ii < frameBuffers.count(); ++ii) {
+ if(frameBuffers.at(ii)->width() >= size) {
+ QGLFramebufferObject *rv = frameBuffers.at(ii);
+ frameBuffers.removeAt(ii);
+ return rv;
+ }
+ }
+
+ // Find power of two
+ size--;
+ size |= size >> 1;
+ size |= size >> 2;
+ size |= size >> 4;
+ size |= size >> 8;
+ size |= size >> 16;
+ size++;
+
+ QGLFramebufferObject *fbo = new QGLFramebufferObject(size, size);
+ return fbo;
+}
+
+void QSimpleCanvasPrivate::release(QGLFramebufferObject *buf)
+{
+ int size = qMax(buf->width(), buf->height());
+ for(int ii = 0; ii < frameBuffers.count(); ++ii) {
+ if(frameBuffers.at(ii)->width() >= size) {
+ frameBuffers.insert(ii, buf);
+ return;
+ }
+ }
+ frameBuffers.append(buf);
+}
+
+GLBasicShaders *QSimpleCanvasItemPrivate::basicShaders() const
+{
+ return canvas->d->basicShaders();
+}
+
+QSimpleCanvas::Matrix QSimpleCanvasItemPrivate::localTransform() const
+{
+ Q_Q(const QSimpleCanvasItem);
+
+ QSimpleCanvas::Matrix trans;
+ trans.translate(q->x(), q->y());
+ QPointF to = transformOrigin();
+ trans.translate(to.x(), to.y());
+ trans.scale(q->scale(), q->scale());
+ trans.translate(-to.x(), -to.y());
+ if(data()->transformUser)
+ trans *= *data()->transformUser;
+ return trans;
+}
+
+void QSimpleCanvasItemPrivate::simplePaintChild(const GLPaintParameters &params, QSimpleCanvasItem *child)
+{
+ Q_Q(QSimpleCanvasItem);
+
+ GLPaintParameters childParams = params;
+ if(clip)
+ ++childParams.stencilValue;
+
+ if(child->d_func()->data()->activeOpacity != 0) {
+ childParams.boundingRect = child->boundingRect();
+
+ if(child->filter() && child->filter()->enabled()) {
+ QSimpleCanvasItem::GLPainter painter(q);
+ painter.activeTransform = child->d_func()->data()->transformActive;
+ painter.activeOpacity = child->d_func()->data()->activeOpacity;
+ painter.sceneClipRect = params.clipRect;
+ child->filter()->d->doFilterGL(painter, childParams);
+ } else {
+ child->d_func()->paint(childParams);
+ }
+ }
+}
+
+void QSimpleCanvasItemPrivate::paintChild(const GLPaintParameters &params,
+ QSimpleCanvasItem *child)
+{
+ if(params.forceParamRefresh) {
+ QSimpleCanvas::Matrix t = child->d_func()->data()->transformActive;
+ qreal o = child->d_func()->data()->activeOpacity;
+ setupChildState(child);
+ simplePaintChild(params, child);
+ child->d_func()->data()->transformActive = t;
+ child->d_func()->data()->transformValid = true;
+ child->d_func()->data()->activeOpacity = o;
+ } else {
+ simplePaintChild(params, child);
+ }
+}
+
+void QSimpleCanvasItemPrivate::setupChildState(QSimpleCanvasItem *child)
+{
+ qreal visible = child->visible();
+ child->d_func()->data()->activeOpacity = data()->activeOpacity;
+ if(visible != 1)
+ child->d_func()->data()->activeOpacity *= visible;
+
+ if(child->d_func()->data()->activeOpacity != 0) {
+ // Calculate child's transform
+ qreal x = child->x();
+ qreal y = child->y();
+ qreal scale = child->scale();
+ QSimpleCanvasItem::Flip flip = child->flip();
+
+ QSimpleCanvas::Matrix &am = child->d_func()->data()->transformActive;
+ am = data()->transformActive;
+ if(x != 0 || y != 0)
+ am.translate(x, y);
+ if(scale != 1) {
+ QPointF to = child->d_func()->transformOrigin();
+ if(to.x() != 0. || to.y() != 0.)
+ am.translate(to.x(), to.y());
+ am.scale(scale, scale);
+ if(to.x() != 0. || to.y() != 0.)
+ am.translate(-to.x(), -to.y());
+ }
+ if(child->d_func()->data()->transformUser)
+ am *= *child->d_func()->data()->transformUser;
+ if(flip) {
+ QRectF br = child->boundingRect();
+ am.translate(br.width() / 2., br.height() / 2);
+ am.rotate(180, (flip & QSimpleCanvasItem::VerticalFlip)?1:0, (flip & QSimpleCanvasItem::HorizontalFlip)?1:0, 0);
+ am.translate(-br.width() / 2., -br.height() / 2);
+ }
+ child->d_func()->data()->transformValid = true;
+ }
+}
+
+QRectF QSimpleCanvasItemPrivate::setupPainting(int version, const QRect &bounding)
+{
+ Q_Q(QSimpleCanvasItem);
+
+ QRectF filteredBoundRect = q->boundingRect();
+ if(filter)
+ filteredBoundRect = filter->itemBoundingRect(filteredBoundRect);
+ QRectF rv = data()->transformActive.mapRect(filteredBoundRect);
+
+ for(int ii = 0; ii < children.count(); ++ii) {
+ QSimpleCanvasItem *child = children.at(ii);
+ setupChildState(child);
+
+ if(child->d_func()->data()->activeOpacity != 0)
+ rv |= child->d_func()->setupPainting(version, bounding);
+ }
+
+ data()->lastPaintRect = rv;
+ return rv;
+}
+
+void QSimpleCanvasItemPrivate::paint(GLPaintParameters &oldParams, QSimpleCanvasFilter::Layer layer)
+{
+ if(!layer)
+ return;
+
+ Q_Q(QSimpleCanvasItem);
+
+ GLPaintParameters params = oldParams;
+
+ qreal width = params.boundingRect.width();
+ qreal height = params.boundingRect.height();
+
+ GLfloat vertices[] = { 0, height,
+ width, height,
+ 0, 0,
+ width, 0 };
+
+ // XXX Handle separate cliping modes
+ if(clip) {
+ if(params.stencilValue == 255)
+ qWarning()
+ << "OpenGL: Clip recursion greater than 255 not permitted.";
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+
+ glStencilFunc(GL_EQUAL, params.stencilValue, 0xFFFFFFFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
+
+ ConstantColorShader *shader = basicShaders()->constantColor();
+ shader->enable();
+ shader->setTransform(data()->transformActive);
+
+ shader->setAttributeArray(ConstantColorShader::Vertices, vertices, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ shader->disableAttributeArray(ConstantColorShader::Vertices);
+
+ glStencilFunc(GL_EQUAL, params.stencilValue + 1, 0xFFFFFFFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+
+ // XXX Copied from qsimplecanvas_opengl1 scissor based clipping
+ QRectF r = data()->transformActive.mapRect(params.boundingRect);
+ r.translate(1, 1);
+ float xscale = 0.5 * float(params.sceneRect.width());
+ float yscale = 0.5 * float(params.sceneRect.height());
+ r.moveTo(r.x() * xscale, r.y() * yscale);
+ r.setSize(QSizeF(r.width() * xscale, r.height() * yscale));
+ int sr_x = int(::floorf(r.x()));
+ int sr_y = int(::floorf(r.y()));
+ int sr_width = int(::ceilf(r.right())) - sr_x;
+ int sr_height = int(::ceilf(r.bottom())) - sr_y;
+ QRect sr(sr_x, sr_y, sr_width, sr_height);
+ sr.moveTo(sr.x(), params.sceneRect.height() - sr.y() - sr.height());
+ sr &= params.clipRect;
+ params.clipRect = sr;
+ }
+
+ zOrderChildren();
+
+ int upto = 0;
+ for(upto = 0; upto < children.count(); ++upto) {
+ QSimpleCanvasItem *c = children.at(upto);
+ if(c->z() < 0) {
+ if(layer & QSimpleCanvasFilter::ChildrenUnderItem)
+ paintChild(params, c);
+ } else {
+ break;
+ }
+ }
+
+ if(layer & QSimpleCanvasFilter::Item &&
+ q->options() & QSimpleCanvasItem::HasContents) {
+ QSimpleCanvasItem::GLPainter painter(q);
+ painter.activeTransform = data()->transformActive;
+ painter.activeOpacity = data()->activeOpacity;
+ painter.sceneClipRect = params.clipRect;
+
+ q->paintGLContents(painter);
+ }
+
+ if(layer & QSimpleCanvasFilter::ChildrenAboveItem) {
+ for(; upto < children.count(); ++upto) {
+ QSimpleCanvasItem *c = children.at(upto);
+ paintChild(params, c);
+ }
+ }
+
+ if(clip) {
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ glStencilFunc(GL_EQUAL, params.stencilValue + 1, 0xFFFFFFFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
+
+ ConstantColorShader *shader = basicShaders()->constantColor();
+ shader->enable();
+ shader->setTransform(data()->transformActive);
+
+ shader->setAttributeArray(ConstantColorShader::Vertices, vertices, 2);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ shader->disableAttributeArray(ConstantColorShader::Vertices);
+
+ glStencilFunc(GL_EQUAL, params.stencilValue, 0xFFFFFFFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ }
+}
+
+QGLShaderProgram *QSimpleCanvasItem::GLPainter::useTextureShader()
+{
+ if(activeOpacity == 1.) {
+ item->basicShaders()->singleTexture()->enable();
+ item->basicShaders()->singleTexture()->setTransform(activeTransform);
+ return item->basicShaders()->singleTexture();
+ } else {
+ item->basicShaders()->singleTextureOpacity()->enable();
+ item->basicShaders()->singleTextureOpacity()->setTransform(activeTransform);
+ item->basicShaders()->singleTextureOpacity()->setOpacity(activeOpacity);
+ return item->basicShaders()->singleTextureOpacity();
+ }
+
+}
+
+QGLShaderProgram *QSimpleCanvasItem::GLPainter::useColorShader(const QColor &color)
+{
+ QColor c = color;
+ item->basicShaders()->constantColor()->enable();
+ if(activeOpacity != 1.) {
+ c.setAlpha(int(c.alpha() * activeOpacity));
+ }
+
+ item->basicShaders()->constantColor()->setColor(c);
+ item->basicShaders()->constantColor()->setTransform(activeTransform);
+
+ return item->basicShaders()->constantColor();
+}
+
+void QSimpleCanvasItem::GLPainter::drawImage(const QPointF &point,
+ const GLTexture &texture)
+{
+ drawImage(QRectF(point, QSizeF(texture.width(), texture.height())), texture);
+}
+
+void QSimpleCanvasItem::GLPainter::drawImage(const QRectF &rect,
+ const GLTexture &img)
+{
+ QGLShaderProgram *shader = useTextureShader();
+
+ GLfloat vertices[8];
+ GLfloat texVertices[8];
+
+ float widthV = img.width();
+ float heightV = img.height();
+
+ vertices[0] = rect.x(); vertices[1] = rect.y()+heightV;
+ vertices[2] = rect.x()+widthV; vertices[3] = rect.y()+heightV;
+ vertices[4] = rect.x(); vertices[5] = rect.y();
+ vertices[6] = rect.x()+widthV; vertices[7] = rect.y();
+
+ texVertices[0] = 0; texVertices[1] = 0;
+ texVertices[2] = 1; texVertices[3] = 0;
+ texVertices[4] = 0; texVertices[5] = 1;
+ texVertices[6] = 1; texVertices[7] = 1;
+
+ shader->setAttributeArray(SingleTextureShader::Vertices, vertices, 2);
+ shader->setAttributeArray(SingleTextureShader::TextureCoords, texVertices, 2);
+
+ glBindTexture(GL_TEXTURE_2D, img.texture());
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ shader->disableAttributeArray(SingleTextureShader::Vertices);
+ shader->disableAttributeArray(SingleTextureShader::TextureCoords);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvas_opengl1.cpp b/src/declarative/canvas/qsimplecanvas_opengl1.cpp
new file mode 100644
index 0000000..ad21c77
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvas_opengl1.cpp
@@ -0,0 +1,401 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 "qsimplecanvas.h"
+#include "qsimplecanvas_p.h"
+#include "qsimplecanvasitem_p.h"
+#include "qsimplecanvasfilter_p.h"
+#include <gltexture.h>
+#include <glsave.h>
+#include <math.h>
+
+
+QT_BEGIN_NAMESPACE
+void CanvasEGLWidget::updateGL()
+{
+ _clip = QRect();
+ QGLWidget::updateGL();
+}
+
+void CanvasEGLWidget::updateGL(const QRect &r)
+{
+ if(r.isEmpty())
+ return;
+
+ _clip = r;
+ QGLWidget::updateGL();
+}
+
+void CanvasEGLWidget::paintGL()
+{
+ if(!_clip.isEmpty()) {
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(_clip.x(), _clip.y(), _clip.width(), _clip.height());
+ } else {
+ glDisable(GL_SCISSOR_TEST);
+ }
+
+ glDepthMask(GL_TRUE);
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glDepthMask(GL_FALSE);
+
+ _canvas->paintGL();
+}
+
+QRect CanvasEGLWidget::map(const QRectF &f)
+{
+ return invDefaultTransform.mapRect(f).toAlignedRect();
+}
+
+void CanvasEGLWidget::resizeGL(int w, int h)
+{
+ glViewport(0, 0, w, h);
+}
+
+void CanvasEGLWidget::resizeEvent(QResizeEvent *e)
+{
+ defaultTransform.identity();
+ defaultTransform.flipCoordinates();
+ defaultTransform.translate(-1, -1, 0);
+ defaultTransform.scale(2. / width(), 2. / height(), -2. / 65536.);
+ invDefaultTransform = defaultTransform.inverted();
+ _canvas->root->d_func()->transformActive = defaultTransform;
+ QGLWidget::resizeEvent(e);
+}
+
+void CanvasEGLWidget::initializeGL()
+{
+ glEnable(GL_BLEND);
+ glEnable(GL_DEPTH_TEST);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glDepthFunc(GL_GREATER);
+#ifdef QT_OPENGL_ES
+ glClearDepthf(0);
+#else
+ glClearDepth(0);
+#endif
+}
+
+void QSimpleCanvasPrivate::paintGL()
+{
+ lrpTimer.start();
+
+ QSimpleCanvasItemPrivate::GLPaintParameters p;
+ p.sceneRect = QRect(0, 0, q->width(), q->height());
+ p.clipRect = p.sceneRect;
+ p.opacity = 1;
+ p.forceParamRefresh = false;
+ if(!isSetup) {
+ unsigned int zero = 0;
+ root->d_func()->setupPainting(0, QRect(), &zero);
+ }
+ root->d_func()->paint(p);
+
+ lrpTime = lrpTimer.elapsed();
+}
+
+QSimpleCanvas::Matrix QSimpleCanvasItemPrivate::localTransform() const
+{
+ Q_Q(const QSimpleCanvasItem);
+
+ QSimpleCanvas::Matrix trans;
+ trans.translate(q->x(), q->y());
+ QPointF to = transformOrigin();
+ trans.translate(to.x(), to.y());
+ trans.scale(q->scale().value(), q->scale().value());
+ trans.translate(-to.x(), -to.y());
+ trans *= transformUser;
+ return trans;
+}
+
+void QSimpleCanvasItemPrivate::simplePaintChild(const GLPaintParameters &params, QSimpleCanvasItem *child)
+{
+ GLPaintParameters childParams = params;
+
+ if(child->d_func()->activeOpacity != 0) {
+ childParams.boundingRect = child->boundingRect();
+ child->d_func()->paint(childParams);
+ }
+}
+
+void QSimpleCanvasItemPrivate::paintChild(const GLPaintParameters &params,
+ QSimpleCanvasItem *child)
+{
+ if(params.forceParamRefresh) {
+ QSimpleCanvas::Matrix t = child->d_func()->transformActive;
+ qreal o = child->d_func()->activeOpacity;
+ setupChildState(child);
+ simplePaintChild(params, child);
+ child->d_func()->transformActive = t;
+ child->d_func()->activeOpacity = o;
+ } else {
+ simplePaintChild(params, child);
+ }
+}
+
+
+void QSimpleCanvasItemPrivate::setupChildState(QSimpleCanvasItem *child)
+{
+ qreal visible = child->visible().value();
+ child->d_func()->activeOpacity = activeOpacity;
+ if(visible != 1)
+ child->d_func()->activeOpacity *= visible;
+
+ if(child->d_func()->activeOpacity != 0) {
+ // Calculate child's transform
+ qreal x = child->x();
+ qreal y = child->y();
+ qreal scale = child->scale().value();
+ QSimpleCanvasItem::Flip flip = child->flip();
+
+ QSimpleCanvas::Matrix &am = child->d_func()->transformActive;
+ am = transformActive;
+ if(x != 0 || y != 0)
+ am.translate(x, y);
+ if(scale != 1) {
+ QPointF to = child->d_func()->transformOrigin();
+ if(to.x() != 0. || to.y() != 0.)
+ am.translate(to.x(), to.y());
+ am.scale(scale, scale);
+ if(to.x() != 0. || to.y() != 0.)
+ am.translate(-to.x(), -to.y());
+ }
+ if(child->d_func()->transformUserSet)
+ am *= child->d_func()->transformUser;
+ if(flip) {
+ QRectF br = child->boundingRect();
+ am.translate(br.width() / 2., br.height() / 2);
+ am.rotate(180, (flip & QSimpleCanvasItem::VerticalFlip)?1:0, (flip & QSimpleCanvasItem::HorizontalFlip)?1:0, 0);
+ am.translate(-br.width() / 2., -br.height() / 2);
+ }
+ }
+}
+
+QRectF QSimpleCanvasItemPrivate::setupPainting(int version, const QRect &bounding, unsigned int *zero)
+{
+ Q_Q(QSimpleCanvasItem);
+
+ QRectF rv = transformActive.mapRect(q->boundingRect());
+
+ unsigned int oldZero = *zero;
+
+ for(int ii = 0; ii < children.count(); ++ii) {
+ QSimpleCanvasItem *child = children.at(ii);
+ setupChildState(child);
+
+ if(child->d_func()->activeOpacity != 0)
+ rv |= child->d_func()->setupPainting(version, bounding, zero);
+ }
+
+ if(clip || oldZero != *zero)
+ (*zero)++;
+ transformActive.translate(0, 0, *zero);
+
+ lastPaintRect = rv;
+ return rv;
+}
+
+void QSimpleCanvasItemPrivate::paintNoClip(GLPaintParameters &params, QSimpleCanvasFilter::Layer layer)
+{
+ Q_Q(QSimpleCanvasItem);
+
+ zOrderChildren();
+
+ int upto = 0;
+ for(upto = 0; upto < children.count(); ++upto) {
+ QSimpleCanvasItem *c = children.at(upto);
+ if(c->zValue().value() < 0) {
+ if(layer & QSimpleCanvasFilter::ChildrenUnderItem)
+ paintChild(params, c);
+ } else {
+ break;
+ }
+ }
+
+ if(layer & QSimpleCanvasFilter::Item &&
+ q->options() & QSimpleCanvasItem::HasContents) {
+ QSimpleCanvasItem::GLPainter painter(q);
+ painter.activeTransform = transformActive;
+ painter.activeOpacity = activeOpacity;
+ painter.sceneClipRect = params.clipRect;
+
+ q->paintGLContents(painter);
+ }
+
+ if(layer & QSimpleCanvasFilter::ChildrenAboveItem) {
+ for(; upto < children.count(); ++upto) {
+ QSimpleCanvasItem *c = children.at(upto);
+ paintChild(params, c);
+ }
+ }
+}
+
+void QSimpleCanvasItemPrivate::paint(GLPaintParameters &params, QSimpleCanvasFilter::Layer layer)
+{
+ if(!layer)
+ return;
+
+ // XXX Handle separate cliping modes
+ if(clip) {
+
+ GLSaveScissor ss;
+ qreal width = params.boundingRect.width();
+ qreal height = params.boundingRect.height();
+ float margin = width + height;
+
+ GLfloat clipvertices[] =
+ {
+ -margin, -margin,
+ margin, -margin,
+ margin, 0,
+
+ -margin, -margin,
+ -margin, 0,
+ margin, 0,
+
+ -margin, 0,
+ -margin, margin,
+ 0, 0,
+
+ 0, 0,
+ 0, margin,
+ -margin, margin,
+
+ 0, height,
+ 0, margin,
+ margin, margin,
+
+ margin, margin,
+ 0, height,
+ margin, height,
+
+ width, 0,
+ margin, 0,
+ margin, height,
+
+ margin, height,
+ width, height,
+ width, 0
+ };
+
+ QRectF r = transformActive.mapRect(params.boundingRect);
+ r.translate(1, 1);
+ float xscale = 0.5 * float(params.sceneRect.width());
+ float yscale = 0.5 * float(params.sceneRect.height());
+ r.moveTo(r.x() * xscale, r.y() * yscale);
+ r.setSize(QSizeF(r.width() * xscale, r.height() * yscale));
+
+ glEnable(GL_SCISSOR_TEST);
+ int sr_x = ::floorf(r.x());
+ int sr_y = ::floorf(r.y());
+ int sr_width = ::ceilf(r.right()) - sr_x;
+ int sr_height = ::ceilf(r.bottom()) - sr_y;
+
+ QRect sr(sr_x, sr_y, sr_width, sr_height);
+ if(ss.wasEnabled())
+ sr &= ss.rect();
+
+ glScissor(sr.x(), sr.y(), sr.width(), sr.height());
+
+ {
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(transformActive.data());
+ glDepthMask(GL_TRUE);
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(2, GL_FLOAT, 0, clipvertices);
+ glDrawArrays(GL_TRIANGLES, 0, 24);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glDepthMask(GL_FALSE);
+ }
+
+ GLPaintParameters newParams = params;
+ newParams.clipRect = sr;
+ newParams.clipRect.moveTo(sr.x(), params.sceneRect.height() - sr.y() - sr.height());
+ paintNoClip(newParams, layer);
+ } else {
+ paintNoClip(params, layer);
+ }
+}
+
+QGLShaderProgram *QSimpleCanvasItem::GLPainter::useTextureShader()
+{
+ qFatal("Cannot call QSimpleCanvasItem::GLPainter::useTextureShader() when using OpenGL ES 1.1");
+ return 0;
+}
+
+QGLShaderProgram *QSimpleCanvasItem::GLPainter::useColorShader(const QColor &color)
+{
+ Q_UNUSED(color);
+ qFatal("Cannot call QSimpleCanvasItem::GLPainter::useColorShader() when using OpenGL ES 1.1");
+ return 0;
+}
+
+GLBasicShaders *QSimpleCanvasItemPrivate::basicShaders() const
+{
+ qFatal("Cannot call QSimpleCanvasItem::basicShaders() when using OpenGL ES 1.1");
+ return 0;
+}
+
+QGLFramebufferObject *QSimpleCanvasPrivate::acquire(int, int)
+{
+ return 0;
+}
+
+void QSimpleCanvasPrivate::release(QGLFramebufferObject *)
+{
+}
+
+void QSimpleCanvasItem::GLPainter::drawImage(const QPointF &point,
+ const GLTexture &texture)
+{
+ drawImage(QRectF(point, QSizeF(texture.width(), texture.height())), texture);
+}
+
+void QSimpleCanvasItem::GLPainter::drawImage(const QRectF &rect,
+ const GLTexture &img)
+{
+ qFatal("Cannot call QSimpleCanvasItem::GLPainter::drawImage() when using OpenGL ES 1.1");
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvas_p.h b/src/declarative/canvas/qsimplecanvas_p.h
new file mode 100644
index 0000000..4c8b41e
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvas_p.h
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 QSIMPLECANVAS_P_H
+#define QSIMPLECANVAS_P_H
+
+#include "qsimplecanvas.h"
+#include <qstack.h>
+#include <qdatetime.h>
+
+#if defined(QFX_RENDER_OPENGL)
+
+#if defined(QFX_RENDER_OPENGL2)
+#include "glbasicshaders.h"
+#endif
+
+#include <QGLWidget>
+QT_BEGIN_NAMESPACE
+
+class CanvasEGLWidget : public QGLWidget
+{
+public:
+ CanvasEGLWidget(QSimpleCanvas *parent, QSimpleCanvasPrivate *canvas)
+ :
+ QGLWidget(parent),
+ _canvas(canvas)
+ {
+ }
+
+ virtual void paintGL();
+ virtual void resizeGL(int,int);
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void initializeGL();
+
+ void updateGL();
+ void updateGL(const QRect &);
+
+ QRect map(const QRectF &) const;
+private:
+ QRect _clip;
+ QSimpleCanvasPrivate *_canvas;
+ QSimpleCanvas::Matrix defaultTransform;
+ QSimpleCanvas::Matrix invDefaultTransform;
+};
+#endif
+
+#include <QGraphicsView>
+#include <QGraphicsScene>
+
+struct QSimpleCanvasGraphicsView : public QGraphicsView
+{
+public:
+ QSimpleCanvasGraphicsView(QSimpleCanvasPrivate *parent);
+ ~QSimpleCanvasGraphicsView();
+
+protected:
+ virtual void paintEvent(QPaintEvent *);
+ virtual void focusInEvent(QFocusEvent *);
+
+private:
+ QSimpleCanvasPrivate *canvas;
+ QGraphicsScene _scene;
+};
+
+class QGLFramebufferObject;
+class QSimpleCanvasServer;
+class QSimpleCanvasPrivate
+{
+public:
+ QSimpleCanvasPrivate(QSimpleCanvas *canvas)
+ : q(canvas), timer(0), root(0), lrpTime(0), canvasServer(0), focusItem(0),
+ lastFocusItem(0), lastMouseItem(0), isSetup(false),
+ view(0)
+#if defined(QFX_RENDER_OPENGL)
+ ,egl(q, this), basicShadersInstance(0)
+#endif
+ {
+ }
+
+ QSimpleCanvas *q;
+ QSimpleCanvas::CanvasMode mode;
+ bool isSimpleCanvas() const { return mode == QSimpleCanvas::SimpleCanvas; }
+ bool isGraphicsView() const { return mode == QSimpleCanvas::GraphicsView; }
+
+#if defined(QFX_RENDER_OPENGL)
+ QRectF oldDirty;
+#else
+ QRect oldDirty;
+#endif
+ QRegion resetDirty();
+ void paint(QPainter &p);
+
+
+ int timer;
+
+ QSimpleCanvasLayer *root;
+ QList<QSimpleCanvasItem *> dirtyItems;
+ int lrpTime;
+
+ QTime frameTimer;
+ QTime lrpTimer;
+
+ QSimpleCanvasServer *canvasServer;
+
+ QStack<QSimpleCanvasItem *> focusPanels;
+ QHash<QSimpleCanvasItem *, QSimpleCanvasItem *> focusPanelData;
+ QSimpleCanvasItem *focusItem;
+ QSimpleCanvasItem *lastFocusItem;
+
+ QRect dirtyItemClip() const;
+ void clearFocusPanel(QSimpleCanvasItem *);
+ void setActiveFocusPanel(QSimpleCanvasItem *, Qt::FocusReason focusReason = Qt::OtherFocusReason);
+ void switchToFocusPanel(QSimpleCanvasItem *, QSimpleCanvasItem *, Qt::FocusReason focusReason);
+
+ void setFocusItem(QSimpleCanvasItem *item, Qt::FocusReason focusReason,
+ bool overwrite = true);
+ void clearFocusItem(QSimpleCanvasItem *item);
+
+ void clearActiveFocusItem(QSimpleCanvasItem *, Qt::FocusReason focusReason);
+ void setActiveFocusItem(QSimpleCanvasItem *, Qt::FocusReason focusReason);
+ void installMouseFilter(QSimpleCanvasItem *);
+ void removeMouseFilter(QSimpleCanvasItem *);
+ QList<QSimpleCanvasItem *> mouseFilters;
+ bool filter(QMouseEvent *e);
+ bool deliverMousePress(QSimpleCanvasItem *, QMouseEvent *);
+ QGraphicsSceneMouseEvent *mouseEventToSceneMouseEvent(QMouseEvent *, const QPoint &);
+ QSimpleCanvasItem *lastMouseItem;
+
+ bool isSetup;
+
+ void init(QSimpleCanvas::CanvasMode mode);
+
+ QSimpleCanvasGraphicsView *view;
+
+#if defined(QFX_RENDER_OPENGL)
+ CanvasEGLWidget egl;
+ GLBasicShaders *basicShaders() const
+ {
+#if defined(QFX_RENDER_OPENGL2)
+ if(!basicShadersInstance)
+ basicShadersInstance = new GLBasicShaders;
+ return basicShadersInstance;
+#else
+ return 0;
+#endif
+ }
+ mutable GLBasicShaders *basicShadersInstance;
+
+ QList<QGLFramebufferObject *> frameBuffers;
+ QGLFramebufferObject *acquire(int, int);
+ void release(QGLFramebufferObject *);
+ void paintGL();
+#endif
+};
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvas_software.cpp b/src/declarative/canvas/qsimplecanvas_software.cpp
new file mode 100644
index 0000000..06e221e
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvas_software.cpp
@@ -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 QtDeclarative 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 "qsimplecanvas.h"
+#include "qsimplecanvasitem_p.h"
+
+
+QT_BEGIN_NAMESPACE
+QRect QSimpleCanvasItemPrivate::setupPainting(int version, const QRect &bounding)
+{
+ Q_Q(QSimpleCanvasItem);
+
+ QRectF boundingRectActive = q->boundingRect();
+ QRect rv =
+ data()->transformActive.mapRect(boundingRectActive).toAlignedRect() & bounding;
+ QRect myBounding = bounding;
+ if(q->clip())
+ myBounding &= rv;
+
+ for(int ii = 0; ii < children.count(); ++ii) {
+ QSimpleCanvasItem *child = children.at(ii);
+
+ qreal visible = child->visible();
+ child->d_func()->data()->activeOpacity = data()->activeOpacity;
+ if(visible != 1)
+ child->d_func()->data()->activeOpacity *= visible;
+
+ if(child->d_func()->data()->activeOpacity != 0) {
+ // Calculate child's transform
+ qreal x = child->x();
+ qreal y = child->y();
+ qreal scale = child->scale();
+ QSimpleCanvasItem::Flip flip = child->flip();
+
+ QSimpleCanvas::Matrix &am = child->d_func()->data()->transformActive;
+ am = data()->transformActive;
+ if(x != 0 || y != 0)
+ am.translate(x, y);
+ if(scale != 1) {
+ QPointF to = child->d_func()->transformOrigin();
+ if(to.x() != 0. || to.y() != 0.)
+ am.translate(to.x(), to.y());
+ am.scale(scale, scale);
+ if(to.x() != 0. || to.y() != 0.)
+ am.translate(-to.x(), -to.y());
+ }
+
+ if(child->d_func()->data()->transformUser)
+ am = *child->d_func()->data()->transformUser * am;
+
+ if(flip) {
+ QRectF br = child->boundingRect();
+ am.translate(br.width() / 2., br.height() / 2);
+ am.scale((flip & QSimpleCanvasItem::HorizontalFlip)?-1:1,
+ (flip & QSimpleCanvasItem::VerticalFlip)?-1:1);
+ am.translate(-br.width() / 2., -br.height() / 2);
+ }
+ child->d_func()->data()->transformValid = true;
+ rv |= child->d_func()->setupPainting(version, myBounding);
+ }
+ }
+
+ data()->lastPaintRect = rv;
+ return rv;
+}
+
+void QSimpleCanvasItemPrivate::paint(QPainter &p)
+{
+ Q_Q(QSimpleCanvasItem);
+
+ QRect oldUcr;
+ if(clip) {
+
+ p.save();
+ QRectF boundingRectActive = q->boundingRect();
+
+ QRect cr;
+ switch(clip) {
+ case QSimpleCanvasItem::ClipToHeight:
+ {
+ qWarning("QSimpleCanvasItem: ClipToHeight not implemented");
+ QRect r = p.clipRegion().boundingRect();
+ cr = QRect(r.x(), 0, r.width(),
+ boundingRectActive.height());
+ }
+ break;
+ case QSimpleCanvasItem::ClipToWidth:
+ {
+ qWarning("QSimpleCanvasItem: ClipToWidth not implemented");
+ QRect r = p.clipRegion().boundingRect();
+ cr = QRect(0, r.y(), boundingRectActive.width(),
+ r.height());
+ }
+ break;
+ case QSimpleCanvasItem::ClipToRect:
+ cr = boundingRectActive.toAlignedRect();
+ break;
+ default:
+ break;
+ }
+
+ p.setWorldTransform(data()->transformActive);
+ if(p.clipRegion().isEmpty()) {
+ p.setClipRect(cr);
+ } else {
+ p.setClipRect(cr, Qt::IntersectClip);
+ }
+
+ if(p.clipRegion().isEmpty()) {
+ p.restore();
+ return;
+ }
+ }
+
+ zOrderChildren();
+
+ int upto = 0;
+ for(upto = 0; upto < children.count(); ++upto) {
+ QSimpleCanvasItem *c = children.at(upto);
+ if(c->z() < 0) {
+ paintChild(p, c);
+ } else {
+ break;
+ }
+ }
+
+ p.setWorldTransform(data()->transformActive);
+ q->paintContents(p);
+
+ for(; upto < children.count(); ++upto) {
+ QSimpleCanvasItem *c = children.at(upto);
+ paintChild(p, c);
+ }
+
+ if(clip)
+ p.restore();
+}
+
+void QSimpleCanvasItemPrivate::paintChild(QPainter &p, QSimpleCanvasItem *c)
+{
+ if(c->d_func()->data()->activeOpacity != 0) {
+
+ qreal op = p.opacity();
+ p.setOpacity(c->d_func()->data()->activeOpacity);
+
+ c->d_func()->paint(p);
+
+ p.setOpacity(op);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvasfilter.cpp b/src/declarative/canvas/qsimplecanvasfilter.cpp
new file mode 100644
index 0000000..00c88c5
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvasfilter.cpp
@@ -0,0 +1,323 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 "qsimplecanvasfilter.h"
+#include "qsimplecanvasfilter_p.h"
+#include "qsimplecanvasitem_p.h"
+#include "qsimplecanvas.h"
+#include "qsimplecanvas_p.h"
+
+#if defined(QFX_RENDER_OPENGL2)
+#include <glsave.h>
+#include <QtOpenGL/qglframebufferobject.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlclass Filter
+ \brief A Filter is a graphical filter that can be applied to items.
+*/
+
+QSimpleCanvasFilter::QSimpleCanvasFilter(QObject *parent)
+: QObject(parent), d(new QSimpleCanvasFilterPrivate(this))
+{
+}
+
+QSimpleCanvasFilter::~QSimpleCanvasFilter()
+{
+ if(d->item) d->item->setFilter(0);
+ delete d; d = 0;
+}
+
+bool QSimpleCanvasFilter::enabled() const
+{
+ return d->enabled;
+}
+
+/*!
+ \qmlproperty bool Filter::enabled
+ \brief Controls whether the filter is applied.
+*/
+
+void QSimpleCanvasFilter::setEnabled(bool e)
+{
+ if(e == d->enabled)
+ return;
+ d->enabled = e;
+ emit enabledChanged();
+ update();
+}
+
+QGLFramebufferObject *QSimpleCanvasFilter::renderToFBO(float scale, const QRectF &src, const QPoint &offset, Layer)
+{
+ // XXX - respect src
+#if defined(QFX_RENDER_OPENGL2)
+ Q_UNUSED(src);
+ Q_UNUSED(offset);
+
+ QSimpleCanvasItem *item = d->item;
+ QRect br = item->itemBoundingRect();
+ if(br.isEmpty())
+ return 0;
+ QGLFramebufferObject *fbo =
+ item->canvas()->d->acquire(int(br.width() * scale), int(br.height() * scale));
+
+ GLSaveViewport sv; GLSaveScissor ss;
+ qreal oldOpacity = item->d_func()->data()->activeOpacity;
+ item->d_func()->data()->activeOpacity = 1;
+
+ fbo->bind();
+
+ glClearColor(0,0,0,0);
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(0, 0, int(br.width() * scale), int(br.height() * scale));
+ glClear(GL_COLOR_BUFFER_BIT);
+ glViewport(0, 0, int(br.width() * scale), int(br.height() * scale));
+
+ QMatrix4x4 mat;
+ mat.flipCoordinates();
+ mat.translate(-1, -1, 0);
+ mat.scale(2. / (br.width()), 2. / (br.height()), 1. / (1024. * 1024.));
+
+ renderToScreen(mat);
+
+ fbo->release();
+
+ item->d_func()->data()->activeOpacity = oldOpacity;
+ return fbo;
+#else
+ Q_UNUSED(src);
+ Q_UNUSED(offset);
+ Q_UNUSED(scale);
+ return 0;
+#endif
+}
+
+QGLFramebufferObject *QSimpleCanvasFilter::renderToFBO(const QRectF &src, const QPoint &offset, Layer)
+{
+ // XXX - respect src
+#if defined(QFX_RENDER_OPENGL2)
+ Q_UNUSED(src);
+ Q_UNUSED(offset);
+
+ QSimpleCanvasItem *item = d->item;
+ QRect br = item->itemBoundingRect();
+ if(br.isEmpty())
+ return 0;
+ QGLFramebufferObject *fbo =
+ item->canvas()->d->acquire(br.width(), br.height());
+
+ GLSaveViewport sv; GLSaveScissor ss;
+ qreal oldOpacity = item->d_func()->data()->activeOpacity;
+ item->d_func()->data()->activeOpacity = 1;
+
+ fbo->bind();
+
+ glClearColor(0,0,0,0);
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(0, 0, br.width(), br.height());
+ glClear(GL_COLOR_BUFFER_BIT);
+ glViewport(0, 0, br.width(), br.height());
+
+ QMatrix4x4 mat;
+ mat.flipCoordinates();
+ mat.translate(-1, -1, 0);
+ mat.scale(2. / br.width(), 2. / br.height(), 1. / (1024. * 1024.));
+
+ renderToScreen(mat);
+
+ fbo->release();
+
+ item->d_func()->data()->activeOpacity = oldOpacity;
+ return fbo;
+#else
+ Q_UNUSED(src);
+ Q_UNUSED(offset);
+ return 0;
+#endif
+}
+
+QGLFramebufferObject *QSimpleCanvasFilter::acquireFBO(const QSize &s)
+{
+#if defined(QFX_RENDER_OPENGL2)
+ QSize size;
+ QSimpleCanvasItem *item = d->item;
+ if(size.isNull()) {
+ QRect br = item->itemBoundingRect();
+ size = br.size();
+ } else {
+ size = s;
+ }
+
+ QGLFramebufferObject *fbo =
+ item->canvas()->d->acquire(s.width(), s.height());
+
+ return fbo;
+#else
+ Q_UNUSED(s);
+ return 0;
+#endif
+}
+
+void QSimpleCanvasFilter::releaseFBO(QGLFramebufferObject *fbo)
+{
+#if defined(QFX_RENDER_OPENGL2)
+ d->item->d_func()->canvas->d->release(fbo);
+#else
+ Q_UNUSED(fbo);
+#endif
+}
+
+void QSimpleCanvasFilter::renderToScreen(const QRectF &src, Layer layer)
+{
+ // XXX - respect src
+#if defined(QFX_RENDER_OPENGL2)
+ Q_UNUSED(src);
+ Q_UNUSED(layer);
+ d->item->d_func()->paint(d->params, layer);
+#else
+ Q_UNUSED(src);
+ Q_UNUSED(layer);
+#endif
+}
+
+void QSimpleCanvasFilter::renderToScreen(const QSimpleCanvas::Matrix &trans, const QRectF &src, Layer layer)
+{
+ // XXX - respect src
+#if defined(QFX_RENDER_OPENGL2)
+ Q_UNUSED(src);
+ QSimpleCanvas::Matrix old = d->item->d_func()->data()->transformActive;
+ d->item->d_func()->data()->transformActive = trans;
+ QSimpleCanvasItemPrivate::GLPaintParameters params = d->params;
+ params.forceParamRefresh = true;
+ d->item->d_func()->paint(params, layer);
+ d->item->d_func()->data()->transformActive = old;
+#else
+ Q_UNUSED(trans);
+ Q_UNUSED(src);
+ Q_UNUSED(layer);
+#endif
+}
+
+QSimpleCanvasItem *QSimpleCanvasFilter::item() const
+{
+ return d->item;
+}
+
+void QSimpleCanvasFilter::setItem(QSimpleCanvasItem *i)
+{
+ if(d->item == i)
+ return;
+ if(d->item) {
+ d->item->setFilter(0);
+ d->item = 0;
+ }
+
+ if(i->filter() != this) {
+ i->setFilter(this);
+ } else {
+ d->item = i;
+ }
+}
+
+#if defined(QFX_RENDER_OPENGL2)
+void QSimpleCanvasFilterPrivate::doFilterGL(QSimpleCanvasItem::GLPainter &p, const QSimpleCanvasItemPrivate::GLPaintParameters &prms)
+{
+ params = prms;
+ q->filterGL(p);
+}
+#endif
+
+QRectF QSimpleCanvasFilter::itemBoundingRect(const QRectF &r) const
+{
+ return r;
+}
+
+void QSimpleCanvasFilter::filterGL(QSimpleCanvasItem::GLPainter &p)
+{
+ Q_UNUSED(p);
+}
+
+void QSimpleCanvasFilter::filter(QPainter &)
+{
+}
+
+void QSimpleCanvasFilter::update()
+{
+ if(d->item)
+ d->item->update();
+}
+
+#if defined(QFX_RENDER_OPENGL2)
+bool QSimpleCanvasFilterPrivate::isSimpleItem(QSimpleCanvasItem *item, QSimpleCanvasItem **out, QSimpleCanvas::Matrix *mout)
+{
+ if(item->options() & QSimpleCanvasItem::SimpleItem && !item->hasChildren()) {
+ *out = item;
+ return true;
+ } else if(!(item->options() & QSimpleCanvasItem::HasContents) &&
+ item->children().count() == 1) {
+ QSimpleCanvasItem *child = item->children().first();
+ if(child->filter() && child->filter()->enabled())
+ return false;
+ bool rv = isSimpleItem(child, out, mout);
+ if(rv)
+ *mout *= child->d_func()->localTransform();
+ return rv;
+ } else {
+ return false;
+ }
+}
+#endif
+
+bool QSimpleCanvasFilter::isSimpleItem(QSimpleCanvasItem **out, QSimpleCanvas::Matrix *mout)
+{
+#if defined(QFX_RENDER_OPENGL2)
+ return d->isSimpleItem(item(), out, mout);
+#else
+ Q_UNUSED(out);
+ Q_UNUSED(mout);
+#endif
+
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvasfilter.h b/src/declarative/canvas/qsimplecanvasfilter.h
new file mode 100644
index 0000000..cb75ddf
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvasfilter.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 QSIMPLECANVASFILTER_H
+#define QSIMPLECANVASFILTER_H
+
+#include <QtCore/qobject.h>
+#include <qfxglobal.h>
+#include <qsimplecanvasitem.h>
+#include <qsimplecanvas.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QSimpleCanvasFilterPrivate;
+class QRectF;
+class QPoint;
+class QGLFramebufferObject;
+class GLShaderProgram;
+class Q_DECLARATIVE_EXPORT QSimpleCanvasFilter : public QObject
+{
+Q_OBJECT
+public:
+ QSimpleCanvasFilter(QObject *parent);
+ virtual ~QSimpleCanvasFilter();
+
+ enum Layer { ChildrenUnderItem = 0x01,
+ Item = 0x02,
+ ChildrenAboveItem = 0x04,
+ All = 0x07 };
+
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged);
+ bool enabled() const;
+ void setEnabled(bool);
+
+ QSimpleCanvasItem *item() const;
+ void setItem(QSimpleCanvasItem *);
+Q_SIGNALS:
+ void enabledChanged();
+
+protected:
+
+ virtual QRectF itemBoundingRect(const QRectF &) const;
+ virtual void filterGL(QSimpleCanvasItem::GLPainter &p);
+ virtual void filter(QPainter &p);
+
+ QGLFramebufferObject *renderToFBO(const QRectF &src = QRect(), const QPoint &offset = QPoint(), Layer = All);
+ QGLFramebufferObject *renderToFBO(float scale, const QRectF &src = QRect(), const QPoint &offset = QPoint(), Layer = All);
+ QGLFramebufferObject *acquireFBO(const QSize & = QSize());
+ void releaseFBO(QGLFramebufferObject *);
+
+ void renderToScreen(const QRectF &src = QRect(), Layer = All);
+ void renderToScreen(const QSimpleCanvas::Matrix &trans, const QRectF &src = QRect(), Layer = All);
+
+ void update();
+
+ bool isSimpleItem(QSimpleCanvasItem **, QSimpleCanvas::Matrix *);
+
+private:
+ friend class QSimpleCanvasFilterPrivate;
+ friend class QSimpleCanvasItemPrivate;
+ friend class QSimpleCanvasItem;
+
+ QSimpleCanvasFilterPrivate *d;
+};
+
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/canvas/qsimplecanvasfilter_p.h b/src/declarative/canvas/qsimplecanvasfilter_p.h
new file mode 100644
index 0000000..1c72993
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvasfilter_p.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 QSIMPLECANVASFILTER_P_H
+#define QSIMPLECANVASFILTER_P_H
+
+#include "qsimplecanvasitem.h"
+#include "qsimplecanvasitem_p.h"
+
+
+QT_BEGIN_NAMESPACE
+class QSimpleCanvasFilterPrivate
+{
+public:
+ QSimpleCanvasFilterPrivate(QSimpleCanvasFilter *_q)
+ : q(_q), item(0), enabled(true) {}
+
+ QSimpleCanvasFilter *q;
+
+ QSimpleCanvasItem *item;
+ bool enabled;
+#if defined(QFX_RENDER_OPENGL)
+ QSimpleCanvasItemPrivate::GLPaintParameters params;
+
+ void doFilterGL(QSimpleCanvasItem::GLPainter &, const QSimpleCanvasItemPrivate::GLPaintParameters &);
+
+ bool isSimpleItem(QSimpleCanvasItem *item, QSimpleCanvasItem **out, QSimpleCanvas::Matrix *mout);
+#endif
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/declarative/canvas/qsimplecanvasitem.cpp b/src/declarative/canvas/qsimplecanvasitem.cpp
new file mode 100644
index 0000000..3d3bf84
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvasitem.cpp
@@ -0,0 +1,1841 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 "qsimplecanvasitem.h"
+#include "qsimplecanvas.h"
+#include "qsimplecanvasitem_p.h"
+#include "qsimplecanvas_p.h"
+#include <qfxitem.h>
+#include <QGraphicsSceneEvent>
+
+
+QT_BEGIN_NAMESPACE
+QSimpleCanvasItemData::QSimpleCanvasItemData()
+: buttons(Qt::NoButton), flip(QSimpleCanvasItem::NoFlip),
+ dirty(false), transformValid(true), x(0), y(0), z(0), visible(1),
+ transformUser(0), activeOpacity(1)
+{
+}
+
+QSimpleCanvasItemData::~QSimpleCanvasItemData()
+{
+ if(transformUser)
+ delete transformUser;
+}
+
+/*!
+ \class QSimpleCanvasItem
+ \brief The QSimpleCanvasItem class is the base class of canvas items.
+ */
+QSimpleCanvasLayer::QSimpleCanvasLayer()
+{
+}
+
+QSimpleCanvasLayer::QSimpleCanvasLayer(QSimpleCanvasItem *parent)
+: QSimpleCanvasItem(parent)
+{
+}
+
+void QSimpleCanvasLayer::addChild(QSimpleCanvasItem *c)
+{
+ QSimpleCanvasItem::addChild(c);
+}
+
+void QSimpleCanvasLayer::addDirty(QSimpleCanvasItem *)
+{
+}
+
+void QSimpleCanvasLayer::remDirty(QSimpleCanvasItem *)
+{
+}
+
+QSimpleCanvasLayer *QSimpleCanvasLayer::layer()
+{
+ return this;
+}
+
+QSimpleCanvasItem::Options QSimpleCanvasItem::options() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return (QSimpleCanvasItem::Options)d->options;
+}
+
+bool QSimpleCanvasItem::mouseFilter(QGraphicsSceneMouseEvent *)
+{
+ return false;
+}
+
+void QSimpleCanvasItem::mousePressEvent(QGraphicsSceneMouseEvent *)
+{
+}
+
+void QSimpleCanvasItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *)
+{
+}
+
+void QSimpleCanvasItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *)
+{
+}
+
+void QSimpleCanvasItem::mouseMoveEvent(QGraphicsSceneMouseEvent *)
+{
+}
+
+void QSimpleCanvasItem::hoverEnterEvent(QGraphicsSceneHoverEvent *)
+{
+}
+
+void QSimpleCanvasItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *)
+{
+}
+
+void QSimpleCanvasItem::mouseUngrabEvent()
+{
+}
+
+void QSimpleCanvasItem::keyPressEvent(QKeyEvent *)
+{
+}
+
+void QSimpleCanvasItem::keyReleaseEvent(QKeyEvent *)
+{
+}
+
+void QSimpleCanvasItem::focusOutEvent(QFocusEvent *)
+{
+}
+
+void QSimpleCanvasItem::focusInEvent(QFocusEvent *)
+{
+}
+
+void QSimpleCanvasItem::activePanelInEvent()
+{
+}
+
+void QSimpleCanvasItem::activePanelOutEvent()
+{
+}
+
+void QSimpleCanvasItem::inputMethodEvent(QInputMethodEvent *)
+{
+}
+
+QVariant QSimpleCanvasItem::inputMethodQuery(Qt::InputMethodQuery) const
+{
+ return QVariant();
+}
+
+void QSimpleCanvasItem::childrenChanged()
+{
+}
+
+QRectF QSimpleCanvasItem::boundingRect() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return QRectF(0., 0., d->width, d->height);
+}
+
+void QSimpleCanvasItem::paintContents(QPainter &)
+{
+}
+
+void QSimpleCanvasItem::paintGLContents(GLPainter &)
+{
+}
+
+uint QSimpleCanvasItem::glSimpleItemData(float *vertices, float *texVertices,
+ GLTexture **texture, uint count)
+{
+ Q_UNUSED(vertices);
+ Q_UNUSED(texVertices);
+ Q_UNUSED(texture);
+ Q_UNUSED(count);
+ return 0;
+}
+
+void QSimpleCanvasItem::canvasChanged()
+{
+}
+
+void QSimpleCanvasItem::focusChanged(bool)
+{
+}
+
+void QSimpleCanvasItem::activeFocusChanged(bool)
+{
+}
+
+void QSimpleCanvasItem::parentChanged(QSimpleCanvasItem *, QSimpleCanvasItem *)
+{
+}
+
+GLBasicShaders *QSimpleCanvasItem::basicShaders() const
+{
+#if defined(QFX_RENDER_OPENGL2)
+ return canvas()->d->basicShaders();
+#else
+ return 0;
+#endif
+}
+
+/*!
+ Returns the item's (0, 0) point relative to its parent.
+ */
+QPointF QSimpleCanvasItem::pos() const
+{
+ return QPointF(x(),y());
+}
+
+/*!
+ Returns the item's (0, 0) point mapped to scene coordinates.
+ */
+QPointF QSimpleCanvasItem::scenePos() const
+{
+ return mapToScene(QPointF(0, 0));
+}
+
+/*!
+ \enum QSimpleCanvasItem::TransformOrigin
+
+ Controls the point about which simple transforms like scale apply.
+
+ \o TopLeft The top-left corner of the item.
+ \o TopCenter The center point of the top of the item.
+ \o TopRight The top-right corner of the item.
+ \o MiddleLeft The left most point of the vertical middle.
+ \o Center The center of the item.
+ \o MiddleRight The right most point of the vertical middle.
+ \o BottomLeft The bottom-left corner of the item.
+ \o BottomCenter The center point of the bottom of the item.
+ \o BottomRight The bottom-right corner of the item.
+*/
+
+/*!
+ Returns the current transform origin.
+*/
+QSimpleCanvasItem::TransformOrigin QSimpleCanvasItem::transformOrigin() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->origin;
+}
+
+/*!
+ Set the transform \a origin.
+*/
+void QSimpleCanvasItem::setTransformOrigin(TransformOrigin origin)
+{
+ Q_D(QSimpleCanvasItem);
+ if(origin != d->origin) {
+ d->origin = origin;
+ update();
+ }
+}
+
+QPointF QSimpleCanvasItem::transformOriginPoint() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->transformOrigin();
+}
+
+/*!
+ Returns the canvas the item is on, or 0 if the item is not on a canvas.
+ */
+QSimpleCanvas *QSimpleCanvasItem::canvas() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->canvas;
+}
+
+/*!
+ Returns the parent if the item, or 0 if the item has no parent.
+ */
+QSimpleCanvasItem *QSimpleCanvasItem::parent() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->parent;
+}
+
+void QSimpleCanvasItemPrivate::zOrderChildren()
+{
+ if(!needsZOrder || children.count() <= 1)
+ return;
+
+ needsZOrder = false;
+ // This is a bubble sort for a reason - it is the fastest sort for a mostly
+ // ordered list. We only expect z ordering to change infrequently.
+ bool swap = true;
+ int c = 0;
+ while(swap) {
+ ++c;
+ swap = false;
+ QSimpleCanvasItem *item = children.first();
+ qreal z = item->z();
+ for(int ii = 1; ii < children.count(); ++ii) {
+ QSimpleCanvasItem *i2 = children.at(ii);
+ qreal z2 = i2->z();
+ if(z2 < z) {
+ swap = true;
+ children[ii] = item;
+ children[ii - 1] = i2;
+ } else {
+ item = i2;
+ z = z2;
+ }
+ }
+ }
+}
+
+void QSimpleCanvasItemPrivate::canvasChanged(QSimpleCanvas *newCanvas, QSimpleCanvas *oldCanvas)
+{
+ Q_Q(QSimpleCanvasItem);
+ canvas = newCanvas;
+ if(options & QSimpleCanvasItem::MouseFilter) {
+ if(oldCanvas) oldCanvas->d->removeMouseFilter(q);
+ if(newCanvas) newCanvas->d->installMouseFilter(q);
+ }
+ if(newCanvas) {
+ if(!oldCanvas && hasFocus)
+ newCanvas->d->setFocusItem(q, Qt::OtherFocusReason, false);
+ if(wantsActiveFocusPanelPendingCanvas) {
+ hasBeenActiveFocusPanel = true;
+ newCanvas->d->setActiveFocusPanel(q);
+ wantsActiveFocusPanelPendingCanvas = false;
+ }
+ }
+
+ for(int ii = 0; ii < children.count(); ++ii)
+ children.at(ii)->d_func()->canvasChanged(newCanvas, oldCanvas);
+ q->canvasChanged();
+}
+
+void QSimpleCanvasItem::setFocus(bool focus)
+{
+ Q_D(QSimpleCanvasItem);
+ if(d->hasFocus == focus)
+ return;
+ QSimpleCanvas *c = canvas();
+
+ if(c) {
+ if(focus)
+ c->d->setFocusItem(this, Qt::OtherFocusReason);
+ else
+ c->d->clearFocusItem(this);
+ } else {
+ d->setFocus(focus);
+ focusChanged(d->hasFocus);
+ }
+}
+
+qreal QSimpleCanvasItem::x() const
+{
+ Q_D(const QSimpleCanvasItem);
+ if(d->graphicsItem)
+ return d->graphicsItem->x();
+ else if(d->data_ptr)
+ return d->data()->x;
+ else
+ return 0;
+}
+
+qreal QSimpleCanvasItem::y() const
+{
+ Q_D(const QSimpleCanvasItem);
+ if(d->graphicsItem)
+ return d->graphicsItem->y();
+ else if(d->data_ptr)
+ return d->data()->y;
+ else
+ return 0;
+}
+
+qreal QSimpleCanvasItem::z() const
+{
+ Q_D(const QSimpleCanvasItem);
+ if(d->graphicsItem)
+ return d->graphicsItem->zValue();
+ else if(d->data_ptr)
+ return d->data()->z;
+ else
+ return 0;
+}
+
+void QSimpleCanvasItem::setX(qreal x)
+{
+ Q_D(QSimpleCanvasItem);
+ if(x == this->x())
+ return;
+
+ qreal oldX = this->x();
+
+ if(d->graphicsItem) {
+ d->graphicsItem->setPos(x, y());
+ } else {
+ d->data()->x = x;
+ update();
+ }
+
+ geometryChanged(QRectF(this->x(), y(), width(), height()),
+ QRectF(oldX, y(), width(), height()));
+}
+
+void QSimpleCanvasItem::setY(qreal y)
+{
+ Q_D(QSimpleCanvasItem);
+ if(y == this->y())
+ return;
+
+ qreal oldY = this->y();
+
+ if(d->graphicsItem) {
+ d->graphicsItem->setPos(x(), y);
+ } else {
+ d->data()->y = y;
+ update();
+ }
+
+ geometryChanged(QRectF(x(), this->y(), width(), height()),
+ QRectF(x(), oldY, width(), height()));
+}
+
+void QSimpleCanvasItem::setZ(qreal z)
+{
+ Q_D(QSimpleCanvasItem);
+ if(z == this->z())
+ return;
+
+ if(d->graphicsItem) {
+ d->graphicsItem->setZValue(z);
+ } else {
+ if(d->data()->z == z)
+ return;
+
+ d->data()->z = z;
+ if(parent())
+ static_cast<QSimpleCanvasItemPrivate*>(parent()->d_ptr)->needsZOrder = true;
+ update();
+ }
+}
+
+qreal QSimpleCanvasItem::width() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->width;
+}
+
+void QSimpleCanvasItem::setWidth(qreal w)
+{
+ Q_D(QSimpleCanvasItem);
+ d->widthValid = true;
+ if(d->width == w)
+ return;
+
+ qreal oldWidth = d->width;
+
+ d->width = w;
+ update();
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), y(), oldWidth, height()));
+}
+
+void QSimpleCanvasItem::setImplicitWidth(qreal w)
+{
+ Q_D(QSimpleCanvasItem);
+ if(d->width == w || widthValid())
+ return;
+
+ qreal oldWidth = d->width;
+
+ d->width = w;
+ update();
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), y(), oldWidth, height()));
+}
+
+bool QSimpleCanvasItem::widthValid() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->widthValid;
+}
+
+qreal QSimpleCanvasItem::height() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->height;
+}
+
+void QSimpleCanvasItem::setHeight(qreal h)
+{
+ Q_D(QSimpleCanvasItem);
+ d->heightValid = true;
+ if(d->height == h)
+ return;
+
+ qreal oldHeight = d->height;
+
+ d->height = h;
+ update();
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), y(), width(), oldHeight));
+}
+
+void QSimpleCanvasItem::setImplicitHeight(qreal h)
+{
+ Q_D(QSimpleCanvasItem);
+ if(d->height == h || heightValid())
+ return;
+
+ qreal oldHeight = d->height;
+
+ d->height = h;
+ update();
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), y(), width(), oldHeight));
+}
+
+bool QSimpleCanvasItem::heightValid() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->heightValid;
+}
+
+void QSimpleCanvasItem::setPos(const QPointF &point)
+{
+ Q_D(QSimpleCanvasItem);
+ qreal oldX = x();
+ qreal oldY = y();
+
+ if(d->graphicsItem) {
+ d->graphicsItem->setPos(point);
+ } else {
+ d->data()->x = point.x();
+ d->data()->y = point.y();
+ update();
+ }
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(oldX, oldY, width(), height()));
+}
+
+qreal QSimpleCanvasItem::scale() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->scale;
+}
+
+void QSimpleCanvasItem::setScale(qreal s)
+{
+ Q_D(QSimpleCanvasItem);
+ d->scale = s;
+ if(d->graphicsItem) {
+ QTransform t;
+ QPointF to = transformOriginPoint();
+ if(to.x() != 0. || to.y() != 0.)
+ t.translate(to.x(), to.y());
+ t.scale(s, s);
+ if(to.x() != 0. || to.y() != 0.)
+ t.translate(-to.x(), -to.y());
+ d->graphicsItem->setTransform(t * d->graphicsItem->transform);
+ } else {
+ update();
+ }
+}
+
+bool QSimpleCanvasItem::isVisible() const
+{
+ if(visible() <= 0)
+ return false;
+ else if(!parent())
+ return true;
+ else
+ return parent()->isVisible();
+}
+
+qreal QSimpleCanvasItem::visible() const
+{
+ Q_D(const QSimpleCanvasItem);
+ if(d->graphicsItem)
+ return d->graphicsItem->opacity();
+ else if(d->data_ptr)
+ return d->data()->visible;
+ else
+ return 1;
+}
+
+void QSimpleCanvasItem::setVisible(qreal v)
+{
+ Q_D(QSimpleCanvasItem);
+ if(d->graphicsItem) {
+ d->graphicsItem->setOpacity(v);
+ } else {
+ if(v == visible())
+ return;
+ if(v == 0)
+ update();
+
+ d->data()->visible = v;
+
+ if(v != 0)
+ update();
+ }
+}
+
+void QSimpleCanvasItem::addChild(QSimpleCanvasItem *c)
+{
+ Q_D(QSimpleCanvasItem);
+ d->children.append(c);
+ if(d->graphicsItem) {
+ // XXX - GraphicsView does not preserve the stacking order of items
+ c->setZ(d->children.count());
+ } else {
+ d->needsZOrder = true;
+ }
+ childrenChanged();
+}
+
+void QSimpleCanvasItem::remChild(QSimpleCanvasItem *c)
+{
+ Q_D(QSimpleCanvasItem);
+ d->children.removeAll(c);
+ childrenChanged();
+}
+
+QSimpleCanvasFilter *QSimpleCanvasItem::filter() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->filter;
+}
+
+/*!
+QSimpleCanvasItem takes ownership of filter.
+*/
+void QSimpleCanvasItem::setFilter(QSimpleCanvasFilter *f)
+{
+ Q_D(QSimpleCanvasItem);
+ if(!d || f == d->filter)
+ return;
+
+ d->filter = f;
+ if(d->filter)
+ d->filter->setItem(this);
+ update();
+}
+
+const QList<QSimpleCanvasItem *> &QSimpleCanvasItem::children() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->children;
+}
+
+bool QSimpleCanvasItem::hasChildren() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return !d->children.isEmpty();
+}
+
+QSimpleCanvasLayer *QSimpleCanvasItem::layer()
+{
+ if(parent())
+ return parent()->layer();
+ else
+ return 0;
+}
+
+void QSimpleCanvasItem::update()
+{
+ Q_D(QSimpleCanvasItem);
+ if(d->graphicsItem) {
+ d->graphicsItem->update();
+ } else {
+ if(!parent())
+ return;
+
+ if(d->data()->dirty || 0. == d->data()->visible) return;
+
+ QSimpleCanvasLayer *l = layer();
+ if(l == this && parent())
+ l = parent()->layer();
+ if(l) {
+ l->addDirty(this);
+ d->data()->dirty = true;
+ d->data()->transformValid = false;
+ }
+ }
+}
+
+bool QSimpleCanvasItem::clip() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->clip;
+}
+
+void QSimpleCanvasItem::setClip(bool c)
+{
+ Q_D(const QSimpleCanvasItem);
+ if(bool(d->clip) == c)
+ return;
+
+ if(c)
+ setClipType(ClipToRect);
+ else
+ setClipType(NoClip);
+
+ update();
+}
+
+QSimpleCanvasItem::ClipType QSimpleCanvasItem::clipType() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->clip;
+}
+
+void QSimpleCanvasItem::setClipType(ClipType c)
+{
+ Q_D(QSimpleCanvasItem);
+ d->clip = c;
+ if(d->graphicsItem)
+ d->graphicsItem->setFlag(QGraphicsItem::ItemClipsChildrenToShape, bool(c));
+ else
+ update();
+}
+
+Qt::MouseButtons QSimpleCanvasItem::acceptedMouseButtons() const
+{
+ Q_D(const QSimpleCanvasItem);
+ if(d->graphicsItem)
+ return d->graphicsItem->acceptedMouseButtons();
+ else if(d->data_ptr)
+ return (Qt::MouseButtons)d->data()->buttons;
+ else
+ return Qt::NoButton;
+}
+
+void QSimpleCanvasItem::setAcceptedMouseButtons(Qt::MouseButtons buttons)
+{
+ Q_D(QSimpleCanvasItem);
+ if(d->graphicsItem)
+ d->graphicsItem->setAcceptedMouseButtons(buttons);
+ else
+ d->data()->buttons = buttons;
+}
+
+
+QRect QSimpleCanvasItem::itemBoundingRect()
+{
+ return boundingRect().toAlignedRect();
+}
+
+QPointF QSimpleCanvasItemPrivate::adjustFrom(const QPointF &p) const
+{
+#if defined(QFX_RENDER_OPENGL)
+ if(!canvas)
+ return p;
+
+ QPointF rv(-1. + 2. * p.x() / qreal(canvas->width()),
+ 1 - 2. * p.y() / qreal(canvas->height()));
+
+ return rv;
+#else
+ return p;
+#endif
+}
+
+QRectF QSimpleCanvasItemPrivate::adjustFrom(const QRectF &r) const
+{
+#if defined(QFX_RENDER_OPENGL)
+ if(!canvas)
+ return r;
+
+ qreal width = r.width() * 2. / qreal(canvas->width());
+ qreal height = r.height() * 2. / qreal(canvas->height());
+ qreal x = -1. + 2. * r.x() / qreal(canvas->width());
+ qreal y = 1. - 2. * r.y() / qreal(canvas->height()) - height;
+
+ return QRectF(x, y, width, height);
+#else
+ return r;
+#endif
+}
+
+QPointF QSimpleCanvasItemPrivate::adjustTo(const QPointF &p) const
+{
+#if defined(QFX_RENDER_OPENGL)
+ if(!canvas)
+ return p;
+
+ QPointF rv(0.5 * (p.x() + 1.) * qreal(canvas->width()),
+ 0.5 * (1. - p.y()) * qreal(canvas->height()));
+
+ return rv;
+#else
+ return p;
+#endif
+}
+
+QRectF QSimpleCanvasItemPrivate::adjustTo(const QRectF &r) const
+{
+#if defined(QFX_RENDER_OPENGL)
+ if(!canvas)
+ return r;
+
+ qreal width = 0.5 * r.width() * qreal(canvas->width());
+ qreal height = 0.5 * r.height() * qreal(canvas->height());
+ qreal x = 0.5 * (r.x() + 1.) * qreal(canvas->width());
+ qreal y = 0.5 * (1. - r.y()) * qreal(canvas->height()) - height;
+
+ return QRectF(x, y, width, height);
+#else
+ return r;
+#endif
+}
+
+QPointF QSimpleCanvasItem::mapFromScene(const QPointF &p) const
+{
+ Q_D(const QSimpleCanvasItem);
+ if(d->graphicsItem) {
+ return d->graphicsItem->mapFromScene(p);
+ } else {
+ QPointF mp = d->adjustFrom(p);
+ d->freshenTransforms();
+#if defined(QFX_RENDER_OPENGL)
+ // m20X + m21Y + m22Z + m23 = 1
+ // Z = (1 - m23 - m20X - m21Y) / m22
+
+ QMatrix4x4 inv = d->data()->transformActive.inverted();
+ qreal z_s = (1 - inv(2,3) - inv(2,0) * mp.x() - inv(2, 1) * mp.y()) / inv(2, 2);
+
+ QVector3D vec(mp.x(), mp.y(), z_s);
+ QVector3D r = inv.map(vec);
+
+ return r.toPointF();
+#else
+ return d->data()->transformActive.inverted().map(mp);
+#endif
+ }
+}
+
+QRectF QSimpleCanvasItem::mapFromScene(const QRectF &r) const
+{
+ Q_D(const QSimpleCanvasItem);
+ if(d->graphicsItem) {
+ return d->graphicsItem->mapFromScene(r).boundingRect();
+ } else {
+ QRectF mr = d->adjustFrom(r);
+ d->freshenTransforms();
+#if defined(QFX_RENDER_OPENGL)
+ // m20X + m21Y + m22Z + m23 = 1
+ // Z = (1 - m23 - m20X - m21Y) / m22
+
+ QMatrix4x4 inv = d->data()->transformActive.inverted();
+ qreal tl_z_s = (1 - inv(2,3) - inv(2,0) * mr.topLeft().x() - inv(2, 1) * mr.topLeft().y()) / inv(2, 2);
+ qreal tr_z_s = (1 - inv(2,3) - inv(2,0) * mr.topRight().x() - inv(2, 1) * mr.topRight().y()) / inv(2, 2);
+ qreal bl_z_s = (1 - inv(2,3) - inv(2,0) * mr.bottomLeft().x() - inv(2, 1) * mr.bottomLeft().y()) / inv(2, 2);
+ qreal br_z_s = (1 - inv(2,3) - inv(2,0) * mr.bottomRight().x() - inv(2, 1) * mr.bottomRight().y()) / inv(2, 2);
+
+ QVector3D tl(mr.topLeft().x(), mr.topLeft().y(), tl_z_s);
+ QVector3D tr(mr.topRight().x(), mr.topRight().y(), tr_z_s);
+ QVector3D bl(mr.bottomLeft().x(), mr.bottomLeft().y(), bl_z_s);
+ QVector3D br(mr.bottomRight().x(), mr.bottomRight().y(), br_z_s);
+
+ tl = inv.map(tl); tr = inv.map(tr); bl = inv.map(bl); br = inv.map(br);
+
+ qreal xmin = qMin(qMin(tl.x(), tr.x()), qMin(bl.x(), br.x()));
+ qreal xmax = qMax(qMax(tl.x(), tr.x()), qMax(bl.x(), br.x()));
+ qreal ymin = qMin(qMin(tl.y(), tr.y()), qMin(bl.y(), br.y()));
+ qreal ymax = qMax(qMax(tl.y(), tr.y()), qMax(bl.y(), br.y()));
+
+ return QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax));
+#else
+ return d->data()->transformActive.inverted().mapRect(mr);
+#endif
+ }
+}
+
+QPointF QSimpleCanvasItem::mapToScene(const QPointF &p) const
+{
+ Q_D(const QSimpleCanvasItem);
+ if(d->graphicsItem) {
+ return d->graphicsItem->mapToScene(p);
+ } else {
+ d->freshenTransforms();
+ QPointF rp = d->data()->transformActive.map(p);
+ return d->adjustTo(rp);
+ }
+}
+
+QRectF QSimpleCanvasItem::mapToScene(const QRectF &r) const
+{
+ Q_D(const QSimpleCanvasItem);
+ if(d->graphicsItem) {
+ return d->graphicsItem->mapToScene(r).boundingRect();
+ } else {
+ d->freshenTransforms();
+ QRectF rr = d->data()->transformActive.mapRect(r);
+ return d->adjustTo(rr);
+ }
+}
+
+int QSimpleCanvasItemPrivate::nextTransformVersion = 1;
+
+void QSimpleCanvasItemPrivate::freshenTransforms() const
+{
+ if(freshenNeeded())
+ doFreshenTransforms();
+}
+
+bool QSimpleCanvasItemPrivate::freshenNeeded() const
+{
+#if 0
+ return parent &&
+ (data()->transformVersion == -1 ||
+ data()->parentTransformVersion == -1 ||
+ parent->d_func()->data()->transformVersion != data()->parentTransformVersion);
+#else
+ const QSimpleCanvasItemPrivate *me = this;
+ while(me) {
+ if(me->data_ptr && !me->data_ptr->transformValid)
+ return true;
+ if(me->parent)
+ me = me->parent->d_func();
+ else
+ me = 0;
+ }
+ return false;
+#endif
+}
+
+void QSimpleCanvasItemPrivate::doFreshenTransforms() const
+{
+ Q_Q(const QSimpleCanvasItem);
+ if(parent)
+ parent->d_func()->doFreshenTransforms();
+
+ if(freshenNeeded()) {
+ if(parent)
+ data()->transformActive = parent->d_func()->data()->transformActive;
+ else
+ data()->transformActive = QSimpleCanvas::Matrix();
+ data()->transformActive.translate(q->x(), q->y());
+ if(scale != 1.) {
+ QPointF to = transformOrigin();
+ if(to.x() != 0. || to.y() != 0.)
+ data()->transformActive.translate(to.x(), to.y());
+ data()->transformActive.scale(scale, scale);
+ if(to.x() != 0. || to.y() != 0.)
+ data()->transformActive.translate(-to.x(), -to.y());
+ }
+
+ Q_Q(const QSimpleCanvasItem);
+#if defined(QFX_RENDER_OPENGL)
+ if(q->d_func()->data()->transformUser)
+ data()->transformActive *= *q->d_func()->data()->transformUser;
+#endif
+
+ if(data()->flip) {
+ QRectF br = q->boundingRect();
+ data()->transformActive.translate(br.width() / 2., br.height() / 2);
+#if defined(QFX_RENDER_OPENGL)
+ data()->transformActive.rotate(180, (data()->flip & QSimpleCanvasItem::VerticalFlip)?1:0, (data()->flip & QSimpleCanvasItem::HorizontalFlip)?1:0, 0);
+#else
+ data()->transformActive.scale((data()->flip & QSimpleCanvasItem::HorizontalFlip)?-1:1,
+ (data()->flip & QSimpleCanvasItem::VerticalFlip)?-1:1);
+#endif
+ data()->transformActive.translate(-br.width() / 2., -br.height() / 2);
+ }
+ }
+}
+
+QSimpleCanvas::Matrix QSimpleCanvasItem::transform() const
+{
+ Q_D(const QSimpleCanvasItem);
+ if(d->graphicsItem)
+ return QSimpleCanvasConfig::transformToMatrix(d->graphicsItem->transform);
+ else if(d->data()->transformUser)
+ return *d->data()->transformUser;
+ else
+ return QSimpleCanvas::Matrix();
+}
+
+void QSimpleCanvasItem::setTransform(const QSimpleCanvas::Matrix &m)
+{
+ Q_D(QSimpleCanvasItem);
+ if(d->graphicsItem) {
+ d->graphicsItem->transform = QSimpleCanvasConfig::matrixToTransform(m);
+ d->graphicsItem->setTransform(QTransform::fromScale(d->scale, d->scale) * d->graphicsItem->transform);
+ } else {
+ if(!d->data()->transformUser)
+ d->data()->transformUser = new QSimpleCanvas::Matrix;
+ *d->data()->transformUser = m;
+ update();
+ }
+}
+
+QSimpleCanvasItem *QSimpleCanvasItem::mouseGrabberItem() const
+{
+ Q_D(const QSimpleCanvasItem);
+ if(d->graphicsItem) {
+ QGraphicsScene *s = d->graphicsItem->scene();
+ if(s) {
+ QGraphicsItem *item = s->mouseGrabberItem();
+ QSimpleGraphicsItem *dgi = static_cast<QSimpleGraphicsItem *>(item);
+ return dgi?static_cast<QSimpleCanvasItem*>(dgi->owner):0;
+ }
+ } else {
+ QSimpleCanvas *c = canvas();
+ if(c)
+ return c->d->lastMouseItem;
+ }
+ return 0;
+}
+
+void QSimpleCanvasItem::ungrabMouse()
+{
+ Q_D(QSimpleCanvasItem);
+ if(d->graphicsItem) {
+ d->graphicsItem->ungrabMouse();
+ } else {
+ QSimpleCanvas *c = canvas();
+ if(c && c->d->lastMouseItem == this) {
+ c->d->lastMouseItem->mouseUngrabEvent();
+ c->d->lastMouseItem = 0;
+ }
+ }
+}
+
+void QSimpleCanvasItem::grabMouse()
+{
+ Q_D(QSimpleCanvasItem);
+ if(d->graphicsItem) {
+ d->graphicsItem->grabMouse();
+ } else {
+ QSimpleCanvas *c = canvas();
+ if(c) {
+ if(c->d->lastMouseItem != this) {
+ if(c->d->lastMouseItem)
+ c->d->lastMouseItem->mouseUngrabEvent();
+ c->d->lastMouseItem = this;
+ }
+ }
+ }
+}
+
+bool QSimpleCanvasItem::isFocusable() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->focusable;
+}
+
+void QSimpleCanvasItem::setFocusable(bool f)
+{
+ Q_D(QSimpleCanvasItem);
+ d->focusable = f;
+}
+
+bool QSimpleCanvasItem::hasFocus() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->hasFocus;
+}
+
+void QSimpleCanvasItemPrivate::setFocus(bool f)
+{
+ hasFocus = f;
+}
+
+void QSimpleCanvasItemPrivate::setActiveFocus(bool f)
+{
+ hasActiveFocus = f;
+
+ if(graphicsItem) {
+ if (f) {
+ if (!(graphicsItem->flags() & QGraphicsItem::ItemIsFocusable))
+ graphicsItem->setFlag(QGraphicsItem::ItemIsFocusable);
+ graphicsItem->setFocus();
+ } else {
+ graphicsItem->clearFocus();
+ if ((graphicsItem->flags() & QGraphicsItem::ItemIsFocusable) && !focusable)
+ graphicsItem->setFlag(QGraphicsItem::ItemIsFocusable, false);
+ }
+
+ }
+}
+
+QSimpleCanvasItem::Flip QSimpleCanvasItem::flip() const
+{
+ Q_D(const QSimpleCanvasItem);
+ if(d->graphicsItem)
+ return NoFlip;
+ else if(d->data_ptr)
+ return d->data()->flip;
+ else
+ return NoFlip;
+}
+
+void QSimpleCanvasItem::setFlip(Flip f)
+{
+ Q_D(QSimpleCanvasItem);
+ if(d->graphicsItem)
+ return;
+
+ if(d->data()->flip == f)
+ return;
+
+ d->data()->flip = f;
+ update();
+}
+
+/*!
+ Places the item under \a item in the parent item's stack.
+
+ The item itself and \a item must be siblings, or this method has no effect.
+
+ \sa stackOver(), stackAt()
+ */
+void QSimpleCanvasItem::stackUnder(QSimpleCanvasItem *item)
+{
+ Q_D(QSimpleCanvasItem);
+ if(d->graphicsItem)
+ return; // XXX
+
+ QSimpleCanvasItem *p = parent();
+ if(!p || !item || item == this) return;
+
+ QSimpleCanvasItemPrivate *parent_d_ptr = static_cast<QSimpleCanvasItemPrivate*>(p->d_ptr);
+ int idx = parent_d_ptr->children.indexOf(item);
+ if(idx == -1) return;
+
+ parent_d_ptr->children.removeAll(this);
+ idx = parent_d_ptr->children.indexOf(item);
+ parent_d_ptr->children.insert(idx + 1, this);
+ parent_d_ptr->needsZOrder = true;
+
+ p->childrenChanged();
+}
+
+/*!
+ Places the item over \a item in the parent item's stack.
+
+ The item itself and \a item must be siblings, or this method has no effect.
+
+ \sa stackUnder(), stackAt()
+ */
+void QSimpleCanvasItem::stackOver(QSimpleCanvasItem *item)
+{
+ Q_D(QSimpleCanvasItem);
+ if(d->graphicsItem)
+ return; // XXX
+
+ QSimpleCanvasItem *p = parent();
+ if(!p || !item || item == this) return;
+
+ QSimpleCanvasItemPrivate *parent_d_ptr = static_cast<QSimpleCanvasItemPrivate*>(p->d_ptr);
+ int idx = parent_d_ptr->children.indexOf(item);
+ if(idx == -1) return;
+
+ parent_d_ptr->children.removeAll(this);
+ idx = parent_d_ptr->children.indexOf(item);
+ parent_d_ptr->children.insert(idx, this);
+ parent_d_ptr->needsZOrder = true;
+
+ p->childrenChanged();
+}
+
+/*!
+ Places the item at position \a index in the parent item's stack.
+
+ If index is zero or less, the item is placed at the beginning of the
+ stack. If the index is greater than the number of items in the stack, the
+ item is placed at the end.
+
+ \sa stackOver(), stackUnder()
+ */
+void QSimpleCanvasItem::stackAt(int index)
+{
+ Q_D(QSimpleCanvasItem);
+ if(d->graphicsItem)
+ return; // XXX
+
+ QSimpleCanvasItem *p = parent();
+ if(!p) return;
+
+ QSimpleCanvasItemPrivate *parent_d_ptr = static_cast<QSimpleCanvasItemPrivate*>(p->d_ptr);
+ parent_d_ptr->children.removeAll(this);
+
+ if(index < 0) index = 0;
+ if(index > parent_d_ptr->children.size()) index = parent_d_ptr->children.size();
+
+ parent_d_ptr->children.insert(index, this);
+ parent_d_ptr->needsZOrder = true;
+ p->childrenChanged();
+}
+
+/*!
+ Returns the current stacking index for the child \a item.
+
+ If \a item is not a child, -1 is returned.
+
+ \sa stackAt()
+ */
+int QSimpleCanvasItem::indexForChild(QSimpleCanvasItem *item)
+{
+ Q_D(QSimpleCanvasItem);
+ return d->children.indexOf(item);
+}
+
+bool QSimpleCanvasItem::eventFilter(QObject *o, QEvent *e)
+{
+ Q_D(QSimpleCanvasItem);
+ if(d->graphicsItem) {
+ switch(e->type()) {
+ case QEvent::GraphicsSceneMouseDoubleClick:
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseRelease:
+ if(mouseFilter(static_cast<QGraphicsSceneMouseEvent *>(e)))
+ return true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return QObject::eventFilter(o, e);
+}
+
+void QSimpleCanvasItem::setOptions(Options options, bool set)
+{
+ Q_D(QSimpleCanvasItem);
+ Options old = (Options)d->options;
+
+ if(options & IsFocusPanel) {
+ if(!set) {
+ qWarning("QSimpleCanvasItem::setOptions: Cannot unset IsFocusPanel");
+ return;
+ } else if(hasChildren()) {
+ qWarning("QSimpleCanvasItem::setOptions: Cannot set IsFocusPanel once item has children");
+ return;
+ }
+ }
+
+ if(options & IsFocusRealm) {
+ if(!set) {
+ qWarning("QSimpleCanvasItem::setOptions: Cannot unset IsFocusRealm");
+ return;
+ }
+ }
+
+ if(set)
+ d->options |= options;
+ else
+ d->options &= ~options;
+
+ if((d->options & IsFocusPanel) && (d->options & IsFocusRealm)) {
+ qWarning("QSimpleCanvasItem::setOptions: Cannot set both IsFocusPanel and IsFocusRealm. IsFocusRealm will be unset.");
+ d->options &= ~IsFocusRealm;
+ }
+
+ if((old & MouseFilter) != (d->options & MouseFilter)) {
+ if(d->graphicsItem) {
+ if(d->options & MouseFilter)
+ d->gvAddMouseFilter();
+ else
+ d->gvRemoveMouseFilter();
+ } else {
+ QSimpleCanvas *c = canvas();
+ if(c) {
+ if(d->options & MouseFilter)
+ c->d->installMouseFilter(this);
+ else
+ c->d->removeMouseFilter(this);
+ }
+ }
+ }
+}
+
+QSimpleCanvasItem::QSimpleCanvasItem(QSimpleCanvasItemPrivate &dd, QSimpleCanvasItem *parent)
+: QObject(dd, parent)
+{
+}
+
+QSimpleCanvasItem::QSimpleCanvasItem(QSimpleCanvasItem *p)
+: QObject(*(new QSimpleCanvasItemPrivate), p)
+{
+}
+
+QSimpleCanvasItem::~QSimpleCanvasItem()
+{
+ Q_D(QSimpleCanvasItem);
+ if(d->graphicsItem) {
+ if ((d->options & (IsFocusPanel|IsFocusRealm)) && d->canvas)
+ d->canvas->d->focusPanelData.remove(this);
+ if (d->hasFocus && d->canvas) {
+ QSimpleCanvasItem *prnt = parent();
+ while (prnt && !(prnt->options() & (IsFocusPanel|IsFocusRealm)))
+ prnt = prnt->parent();
+ if (prnt && d->canvas->d->focusPanelData.value(prnt) == this)
+ d->canvas->d->focusPanelData.remove(prnt);
+ }
+ if(d->filter)
+ delete d->filter;
+
+ qDeleteAll(children());
+ if(parent())
+ parent()->remChild(this);
+ delete d->graphicsItem;
+ } else {
+ setOptions(MouseFilter, false);
+
+ if(d->canvas){
+ if(d->canvas->focusItem() == this)
+ d->canvas->d->focusItem = 0;
+ if(d->canvas->d->lastFocusItem == this)
+ d->canvas->d->lastFocusItem = 0;
+ if(d->hasBeenActiveFocusPanel)
+ d->canvas->d->clearFocusPanel(this);
+ if(d->hasFocus)
+ d->canvas->d->clearFocusItem(this);
+ }
+
+ while(!d->children.isEmpty()) {
+ QSimpleCanvasItem *child = d->children.takeFirst();
+ delete child;
+ }
+
+ delete d->filter;
+
+ if (parent() && d->data_ptr && d->data()->dirty) {
+ QSimpleCanvasLayer *l = parent()->layer();
+ if(l) {
+ l->remDirty(this);
+ }
+ }
+ if (d->parent)
+ d->parent->remChild(this);
+
+
+ if(d->data_ptr)
+ delete d->data_ptr;
+ }
+}
+
+QSimpleCanvasItem::operator QGraphicsItem *()
+{
+ Q_D(QSimpleCanvasItem);
+ if(!d->graphicsItem) {
+ if(parent()) {
+ qWarning("QSimpleCanvasItem: Only the root item can be converted into a QGraphicsItem");
+ return 0;
+ }
+ d->convertToGraphicsItem();
+ }
+ return d->graphicsItem;
+}
+
+QPointF QSimpleCanvasItemPrivate::transformOrigin() const
+{
+ Q_Q(const QSimpleCanvasItem);
+
+ QRectF br = q->boundingRect();
+
+ switch(origin) {
+ default:
+ case QSimpleCanvasItem::TopLeft:
+ return QPointF(0, 0);
+ case QSimpleCanvasItem::TopCenter:
+ return QPointF(br.width() / 2., 0);
+ case QSimpleCanvasItem::TopRight:
+ return QPointF(br.width(), 0);
+ case QSimpleCanvasItem::MiddleLeft:
+ return QPointF(0, br.height() / 2.);
+ case QSimpleCanvasItem::Center:
+ return QPointF(br.width() / 2., br.height() / 2.);
+ case QSimpleCanvasItem::MiddleRight:
+ return QPointF(br.width(), br.height() / 2.);
+ case QSimpleCanvasItem::BottomLeft:
+ return QPointF(0, br.height());
+ case QSimpleCanvasItem::BottomCenter:
+ return QPointF(br.width() / 2., br.height());
+ case QSimpleCanvasItem::BottomRight:
+ return QPointF(br.width(), br.height());
+ }
+}
+
+void QSimpleCanvasItemPrivate::setParentInternal(QSimpleCanvasItem *p)
+{
+ Q_Q(QSimpleCanvasItem);
+ QSimpleCanvasItem *oldParent = parent;
+ if(graphicsItem) {
+ if(oldParent)
+ oldParent->remChild(q);
+
+ parent = p;
+ graphicsItem->setParentItem(p->d_func()->graphicsItem);
+
+ if(parent)
+ p->addChild(q);
+
+ } else {
+ bool canvasChange = false;
+ if(p)
+ canvasChange = (p->d_func()->canvas != canvas);
+ QSimpleCanvas *old = canvas;
+
+ QSimpleCanvasLayer *o = q->layer();
+ if(q->parent()) {
+ q->update();
+ q->parent()->remChild(q);
+ }
+ parent = p;
+ QSimpleCanvasLayer *n = 0;
+ if(q->parent()) {
+ q->parent()->addChild(q);
+ n = q->layer();
+ }
+
+ if(o != n) {
+ data()->dirty = false;
+ data()->transformValid = false;
+ if(o) o->remDirty(q);
+ if(n) n->addDirty(q);
+ }
+
+ if(canvasChange)
+ canvasChanged(p->d_func()->canvas, old);
+
+ q->update();
+ }
+}
+
+void QSimpleCanvasItemPrivate::convertToGraphicsItem(QGraphicsItem *parent)
+{
+ Q_Q(QSimpleCanvasItem);
+ Q_ASSERT(!graphicsItem);
+ graphicsItem = new QSimpleGraphicsItem(q);
+ if(parent)
+ graphicsItem->setParentItem(parent);
+
+ QSimpleCanvasItemData *old = data_ptr;
+ data_ptr = 0;
+
+ if(old) {
+ q->QSimpleCanvasItem::setX(old->x);
+ q->QSimpleCanvasItem::setY(old->y);
+ q->QSimpleCanvasItem::setZ(old->z);
+ q->QSimpleCanvasItem::setVisible(old->visible);
+ if(old->transformUser)
+ q->QSimpleCanvasItem::setTransform(*old->transformUser);
+ q->QSimpleCanvasItem::setFlip(old->flip);
+ q->QSimpleCanvasItem::setAcceptedMouseButtons((Qt::MouseButtons)old->buttons);
+ delete old;
+ }
+
+ if(scale != 1) {
+ qreal s = scale;
+ scale = 1;
+ q->QSimpleCanvasItem::setScale(s);
+ }
+
+ q->setClipType(clip);
+
+ for(int ii = 0; ii < children.count(); ++ii) {
+ static_cast<QSimpleCanvasItemPrivate*>(children.at(ii)->d_ptr)->convertToGraphicsItem(graphicsItem);
+ if(children.at(ii)->z() == 0)
+ children.at(ii)->setZ(ii);
+ }
+}
+
+/*!
+ \fn void QSimpleCanvasItem::setParent(QSimpleCanvasItem *parent)
+
+ Sets the parent of the item to \a parent.
+ */
+void QSimpleCanvasItem::setParent(QSimpleCanvasItem *p)
+{
+ Q_D(QSimpleCanvasItem);
+ if(p == parent() || !p) return;
+
+ QObject::setParent(p);
+
+ if(d->graphicsItem && !static_cast<QSimpleCanvasItemPrivate*>(p->d_ptr)->graphicsItem)
+ qWarning("QSimpleCanvasItem: Cannot reparent a QGraphicsView item to a QSimpleCanvas item");
+
+ if(static_cast<QSimpleCanvasItemPrivate*>(p->d_ptr)->graphicsItem && !d->graphicsItem) {
+ d->setParentInternal(0);
+ d->convertToGraphicsItem();
+ }
+
+ QSimpleCanvasItem *oldParent = d->parent;
+ d->setParentInternal(p);
+ parentChanged(p, oldParent);
+}
+
+int QSimpleCanvasItemPrivate::dump(int indent)
+{
+ Q_Q(QSimpleCanvasItem);
+ QByteArray ba(indent * 2, ' ');
+
+ QByteArray state;
+ if(options & QSimpleCanvasItem::MouseFilter)
+ state.append("i");
+ else
+ state.append("-");
+ if(options & QSimpleCanvasItem::HoverEvents)
+ state.append("h");
+ else
+ state.append("-");
+ if(options & QSimpleCanvasItem::MouseEvents)
+ state.append("m");
+ else
+ state.append("-");
+ if(options & QSimpleCanvasItem::HasContents)
+ state.append("c");
+ else
+ state.append("-");
+ if(options & QSimpleCanvasItem::SimpleItem)
+ state.append("s");
+ else
+ state.append("-");
+ if(options & QSimpleCanvasItem::IsFocusPanel) {
+ if(q->activeFocusPanel())
+ state.append("P");
+ else
+ state.append("p");
+ } else {
+ state.append("-");
+ }
+ if(options & QSimpleCanvasItem::IsFocusRealm)
+ state.append("r");
+ else
+ state.append("-");
+ if(q->hasFocus()) {
+ if(q->hasActiveFocus())
+ state.append("F");
+ else
+ state.append("f");
+ } else {
+ if(q->hasActiveFocus())
+ state.append("X");
+ else
+ state.append("-");
+ }
+
+ QByteArray name;
+ QFxItem *i = qobject_cast<QFxItem *>(q);
+ if(i)
+ name = i->id().toLatin1();
+ qWarning().nospace() << ba.constData() << state.constData() << " " << children.count() << " " << q << " " << name.constData();
+
+ int rv = 0;
+
+ for(int ii = 0; ii < children.count(); ++ii)
+ rv += children.at(ii)->d_func()->dump(indent + 1);
+
+ return rv + 1;
+}
+
+bool QSimpleCanvasItemPrivate::checkFocusState(FocusStateCheckDatas d,
+ FocusStateCheckRDatas *r)
+{
+ Q_Q(QSimpleCanvasItem);
+
+ bool rv = true;
+ bool isRealm = (options & QSimpleCanvasItem::IsFocusPanel ||
+ options & QSimpleCanvasItem::IsFocusRealm);
+
+ if(options & QSimpleCanvasItem::IsFocusPanel) {
+
+ if(q->activeFocusPanel()) {
+ if(d & InActivePanel) {
+ qWarning() << "State ERROR: Nested active focus panels";
+ rv = false;
+ }
+
+ d |= InActivePanel;
+ } else {
+ d &= ~InActivePanel;
+ }
+
+ }
+
+ if(q->hasActiveFocus()) {
+ if(!(d & InActivePanel)) {
+ qWarning() << "State ERROR: Active focus in non-active panel";
+ rv = false;
+ }
+
+ if(d & InRealm && !(d & InActiveFocusedRealm)) {
+ qWarning() << "State ERROR: Active focus in non-active-focused realm";
+ rv = false;
+ }
+
+ if(!q->hasFocus()) {
+ qWarning() << "State ERROR: Active focus on element that does not have focus";
+ rv = false;
+ }
+
+ if(*r & SeenActiveFocus) {
+ qWarning() << "State ERROR: Two active focused elements in same realm";
+ rv = false;
+ }
+
+ *r |= SeenActiveFocus;
+ }
+
+ if(q->hasFocus()) {
+ if(*r & SeenFocus) {
+ qWarning() << "State ERROR: Two focused elements in same realm";
+ rv = false;
+ }
+
+ *r |= SeenFocus;
+ }
+
+ if(options & QSimpleCanvasItem::IsFocusRealm) {
+ d |= InRealm;
+
+ if(q->hasActiveFocus())
+ d |= InActiveFocusedRealm;
+ else
+ d &= ~InActiveFocusedRealm;
+ }
+
+ FocusStateCheckRDatas newR = NoCheckRData;
+ if(isRealm)
+ r = &newR;
+
+ for(int ii = 0; ii < children.count(); ++ii)
+ rv &= children.at(ii)->d_func()->checkFocusState(d, r);
+
+ return rv;
+}
+
+bool QSimpleCanvasItem::activeFocusPanel() const
+{
+ QSimpleCanvas *c = canvas();
+ if(!c) {
+ Q_D(const QSimpleCanvasItem);
+ return d->wantsActiveFocusPanelPendingCanvas;
+ } else {
+ return c->activeFocusPanel() == this;
+ }
+}
+
+void QSimpleCanvasItem::setActiveFocusPanel(bool b)
+{
+ if(!(options() & IsFocusPanel)) {
+ qWarning("QSimpleCanvasItem::setActiveFocusPanel: Item is not a focus panel");
+ return;
+ }
+
+ QSimpleCanvas *c = canvas();
+ Q_D(QSimpleCanvasItem);
+ if(c) {
+ if(b) {
+ d->hasBeenActiveFocusPanel = true;
+ c->d->setActiveFocusPanel(this);
+ } else if(d->hasBeenActiveFocusPanel) {
+ d->hasBeenActiveFocusPanel = false;
+ c->d->clearFocusPanel(this);
+ }
+ } else {
+ d->wantsActiveFocusPanelPendingCanvas = b;
+ }
+}
+
+bool QSimpleCanvasItem::hasActiveFocus() const
+{
+ Q_D(const QSimpleCanvasItem);
+ return d->hasActiveFocus;
+}
+
+QSimpleCanvasItem *QSimpleCanvasItem::findFirstFocusChild() const
+{
+ Q_D(const QSimpleCanvasItem);
+
+ const QList<QSimpleCanvasItem *> &children = d->children;
+
+ for (int i = 0; i < children.count(); ++i) {
+ QSimpleCanvasItem *child = children.at(i);
+ if(child->options() & IsFocusPanel)
+ continue;
+
+ if (child->isFocusable())
+ return child;
+
+ QSimpleCanvasItem *testFocus = child->findFirstFocusChild();
+ if (testFocus)
+ return testFocus;
+ }
+
+ return 0;
+}
+
+QSimpleCanvasItem *QSimpleCanvasItem::findLastFocusChild() const
+{
+ Q_D(const QSimpleCanvasItem);
+
+ const QList<QSimpleCanvasItem *> &children = d->children;
+
+ for (int i = children.count()-1; i >= 0; --i) {
+ QSimpleCanvasItem *child = children.at(i);
+ if(child->options() & IsFocusPanel)
+ continue;
+
+ if (child->isFocusable())
+ return child;
+ QSimpleCanvasItem *testFocus = child->findLastFocusChild();
+ if (testFocus)
+ return testFocus;
+ }
+
+ return 0;
+}
+
+QSimpleCanvasItem *QSimpleCanvasItem::findPrevFocus(QSimpleCanvasItem *item)
+{
+ QSimpleCanvasItem *focusChild = item->findLastFocusChild();
+ if (focusChild)
+ return focusChild;
+
+ if(item->options() & IsFocusPanel) {
+ if(item->isFocusable())
+ return item;
+ else
+ return 0;
+ }
+
+ QSimpleCanvasItem *parent = item->parent();
+ while (parent) {
+ const QList<QSimpleCanvasItem *> &children = parent->d_func()->children;
+
+ int idx = children.indexOf(item);
+ QSimpleCanvasItem *testFocus = 0;
+ if (idx > 0) {
+ while (--idx >= 0) {
+ testFocus = children.at(idx);
+ if(testFocus->options() & IsFocusPanel)
+ continue;
+ if (testFocus->isFocusable())
+ return testFocus;
+ testFocus = testFocus->findLastFocusChild();
+ if (testFocus)
+ return testFocus;
+ }
+ }
+ if(parent->options() & IsFocusPanel) {
+ if(parent->isFocusable())
+ return parent;
+ else
+ return 0;
+ }
+ item = parent;
+ parent = parent->parent();
+ }
+
+ return 0;
+}
+
+QSimpleCanvasItem *QSimpleCanvasItem::findNextFocus(QSimpleCanvasItem *item)
+{
+ QSimpleCanvasItem *focusChild = item->findFirstFocusChild();
+ if (focusChild)
+ return focusChild;
+
+ if(item->options() & IsFocusPanel) {
+ if(item->isFocusable())
+ return item;
+ else
+ return 0;
+ }
+
+ QSimpleCanvasItem *parent = item->parent();
+ while (parent) {
+ const QList<QSimpleCanvasItem *> &children = parent->d_func()->children;
+
+ int idx = children.indexOf(item);
+ QSimpleCanvasItem *testFocus = 0;
+ if (idx >= 0) {
+ while (++idx < children.count()) {
+ testFocus = children.at(idx);
+ if(testFocus->options() & IsFocusPanel)
+ continue;
+ if (testFocus->isFocusable())
+ return testFocus;
+ testFocus = testFocus->findFirstFocusChild();
+ if (testFocus)
+ return testFocus;
+ }
+ }
+ if(parent->options() & IsFocusPanel) {
+ if(parent->isFocusable())
+ return parent;
+ else
+ return 0;
+ }
+ item = parent;
+ parent = parent->parent();
+ }
+
+ return 0;
+}
+
+QImage QSimpleCanvasItem::string(const QString &str, const QColor &c, const QFont &f)
+{
+ QFontMetrics fm(f);
+ QSize size(fm.width(str), fm.height()*(str.count(QLatin1Char('\n'))+1)); //fm.boundingRect(str).size();
+ QImage img(size, QImage::Format_ARGB32_Premultiplied);
+ img.fill(0);
+ QPainter p(&img);
+ p.setPen(c);
+ p.setFont(f);
+ p.drawText(img.rect(), Qt::AlignVCenter, str);
+ return img;
+}
+
+void QSimpleCanvasItem::geometryChanged(const QRectF &, const QRectF &)
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvasitem.h b/src/declarative/canvas/qsimplecanvasitem.h
new file mode 100644
index 0000000..d51f2c8
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvasitem.h
@@ -0,0 +1,300 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 QSIMPLECANVASITEM_H
+#define QSIMPLECANVASITEM_H
+
+#include <gfxtimeline.h>
+#include <qfxglobal.h>
+#include <qsimplecanvas.h>
+#include <QObject>
+#include <QGraphicsItem>
+class QPainter;
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QRect;
+class QSimpleCanvas;
+class QMouseEvent;
+class QKeyEvent;
+class QSimpleCanvasItemPrivate;
+class QSimpleCanvasLayer;
+class QPointF;
+class QRectF;
+class QGraphicsSceneHoverEvent;
+class QSimpleCanvasFilter;
+class GLTexture;
+class QGLShaderProgram;
+
+class Q_DECLARATIVE_EXPORT QSimpleCanvasItem : public QObject
+{
+ Q_OBJECT
+ Q_CAST_INTERFACES(QGraphicsItem)
+ Q_DECLARE_PRIVATE(QSimpleCanvasItem)
+ Q_ENUMS(TransformOrigin)
+ Q_PROPERTY(TransformOrigin transformOrigin READ transformOrigin WRITE setTransformOrigin);
+
+public:
+ enum ClipType { NoClip = 0x00,
+ ClipToHeight = 0x01,
+ ClipToWidth = 0x02,
+ ClipToRect = 0x03 };
+ enum Option { NoOption = 0x00000000,
+ MouseFilter = 0x00000001,
+ HoverEvents = 0x00000002,
+ MouseEvents = 0x00000004,
+ HasContents = 0x00000008,
+ SimpleItem = 0x00000010,
+ IsFocusPanel = 0x00000020,
+ IsFocusRealm = 0x00000040,
+ AcceptsInputMethods = 0x00000080};
+ Q_DECLARE_FLAGS(Options, Option);
+
+ QSimpleCanvasItem(QSimpleCanvasItem *parent=0);
+ virtual ~QSimpleCanvasItem();
+ operator QGraphicsItem *();
+
+ bool clip() const;
+ void setClip(bool);
+ ClipType clipType() const;
+ void setClipType(ClipType);
+
+ Options options() const;
+ void setOptions(Options, bool set = true);
+
+ Qt::MouseButtons acceptedMouseButtons() const;
+ void setAcceptedMouseButtons(Qt::MouseButtons buttons);
+
+ qreal x() const;
+ qreal y() const;
+ qreal z() const;
+ QPointF pos() const;
+ void setX(qreal);
+ void setY(qreal);
+ virtual void setZ(qreal);
+ void setPos(const QPointF &);
+
+ qreal width() const;
+ void setWidth(qreal);
+ void setImplicitWidth(qreal);
+ bool widthValid() const;
+ qreal height() const;
+ void setHeight(qreal);
+ void setImplicitHeight(qreal);
+ bool heightValid() const;
+
+ QPointF scenePos() const;
+
+ enum TransformOrigin {
+ TopLeft, TopCenter, TopRight,
+ MiddleLeft, Center, MiddleRight,
+ BottomLeft, BottomCenter, BottomRight
+ };
+ TransformOrigin transformOrigin() const;
+ void setTransformOrigin(TransformOrigin);
+ QPointF transformOriginPoint() const;
+
+
+ qreal scale() const;
+ virtual void setScale(qreal);
+
+ enum Flip { NoFlip = 0,
+ VerticalFlip = 0x01,
+ HorizontalFlip = 0x02,
+ VerticalAndHorizontalFlip = 0x03 };
+ Flip flip() const;
+ void setFlip(Flip);
+
+ qreal visible() const;
+ virtual void setVisible(qreal);
+ bool isVisible() const;
+
+ QSimpleCanvas *canvas() const;
+
+ QSimpleCanvasItem *parent() const;
+ void setParent(QSimpleCanvasItem *);
+ void stackUnder(QSimpleCanvasItem *);
+ void stackOver(QSimpleCanvasItem *);
+ void stackAt(int idx);
+ int indexForChild(QSimpleCanvasItem *);
+
+ QRect itemBoundingRect();
+
+ class GLPainter
+ {
+ public:
+ GLPainter(QSimpleCanvasItem *i) : item(i), activeOpacity(1) {}
+ QSimpleCanvasItem *item;
+ QSimpleCanvas::Matrix activeTransform;
+ qreal activeOpacity;
+ QRect sceneClipRect;
+
+ QGLShaderProgram *useTextureShader();
+ QGLShaderProgram *useColorShader(const QColor &);
+ void drawImage(const QPointF &, const GLTexture &);
+ void drawImage(const QRectF &, const GLTexture &);
+ private:
+ GLPainter(const GLPainter &);
+ GLPainter &operator=(const GLPainter &);
+ };
+
+
+ QRectF boundingRect() const;
+ virtual void paintContents(QPainter &);
+ virtual void paintGLContents(GLPainter &);
+ virtual uint glSimpleItemData(float *vertices, float *texVertices,
+ GLTexture **texture, uint count);
+
+ void update();
+
+ virtual QSimpleCanvasLayer *layer();
+
+ bool hasChildren() const;
+ const QList<QSimpleCanvasItem *> &children() const;
+
+ QPointF mapFromScene(const QPointF &) const;
+ QRectF mapFromScene(const QRectF &) const;
+ QPointF mapToScene(const QPointF &) const;
+ QRectF mapToScene(const QRectF &) const;
+
+ QSimpleCanvas::Matrix transform() const;
+ void setTransform(const QSimpleCanvas::Matrix &);
+
+ QSimpleCanvasFilter *filter() const;
+ void setFilter(QSimpleCanvasFilter *);
+
+ QSimpleCanvasItem *mouseGrabberItem() const;
+ void ungrabMouse();
+ void grabMouse();
+
+ virtual bool isFocusable() const;
+ void setFocusable(bool);
+ virtual bool hasFocus() const;
+ void setFocus(bool);
+ bool activeFocusPanel() const;
+ void setActiveFocusPanel(bool);
+
+ bool hasActiveFocus() const;
+
+ QSimpleCanvasItem *findFirstFocusChild() const;
+ QSimpleCanvasItem *findLastFocusChild() const;
+ static QSimpleCanvasItem *findPrevFocus(QSimpleCanvasItem *item);
+ static QSimpleCanvasItem *findNextFocus(QSimpleCanvasItem *item);
+
+ GLBasicShaders *basicShaders() const;
+
+ static QImage string(const QString &, const QColor & = Qt::black, const QFont & = QFont());
+
+protected:
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+ virtual void addChild(QSimpleCanvasItem *);
+ virtual void remChild(QSimpleCanvasItem *);
+ virtual void canvasChanged();
+ virtual void childrenChanged();
+ virtual void parentChanged(QSimpleCanvasItem *, QSimpleCanvasItem *);
+ virtual void focusChanged(bool);
+ virtual void activeFocusChanged(bool);
+ virtual bool eventFilter(QObject *, QEvent *);
+
+public:
+ // Events
+ virtual bool mouseFilter(QGraphicsSceneMouseEvent *);
+ virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
+ virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *);
+ virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *);
+ virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseUngrabEvent();
+ virtual void keyPressEvent(QKeyEvent *event);
+ virtual void keyReleaseEvent(QKeyEvent *event);
+ virtual void focusOutEvent(QFocusEvent *e);
+ virtual void focusInEvent(QFocusEvent *e);
+ virtual void activePanelInEvent();
+ virtual void activePanelOutEvent();
+ virtual void inputMethodEvent(QInputMethodEvent* event);
+ virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
+
+private:
+ friend class QSimpleCanvas;
+ friend class QSimpleCanvasPrivate;
+ friend class QSimpleCanvasRootLayer;
+ friend class QSimpleCanvasItem::GLPainter;
+ friend class QSimpleCanvasFilter;
+ friend class QGraphicsQSimpleCanvasItem;
+ friend class QSimpleGraphicsItem;
+ friend class CanvasEGLWidget;
+ friend class QSimpleCanvasFilterPrivate;
+
+public:
+ QSimpleCanvasItem(QSimpleCanvasItemPrivate &dd, QSimpleCanvasItem *parent);
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QSimpleCanvasItem::Options);
+
+class QSimpleCanvasLayer : public QSimpleCanvasItem
+{
+public:
+ QSimpleCanvasLayer(QSimpleCanvasItem *parent);
+
+ virtual void addChild(QSimpleCanvasItem *);
+ virtual void addDirty(QSimpleCanvasItem *);
+ virtual void remDirty(QSimpleCanvasItem *);
+ virtual QSimpleCanvasLayer *layer();
+
+private:
+ friend class QSimpleCanvas;
+ friend class QSimpleCanvasRootLayer;
+ QSimpleCanvasLayer();
+};
+
+
+
+#endif // _GFXCANVASITEM_H_
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/canvas/qsimplecanvasitem_p.h b/src/declarative/canvas/qsimplecanvasitem_p.h
new file mode 100644
index 0000000..7f66be5
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvasitem_p.h
@@ -0,0 +1,242 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 QSIMPLECANVASITEM_P_H
+#define QSIMPLECANVASITEM_P_H
+
+#include "private/qobject_p.h"
+#include "qsimplecanvas.h"
+#include "qsimplecanvasitem.h"
+#include "qsimplecanvasfilter.h"
+
+#if defined(QFX_RENDER_OPENGL2)
+#include <glbasicshaders.h>
+#endif
+
+#include "qgraphicsitem.h"
+
+
+QT_BEGIN_NAMESPACE
+class QSimpleGraphicsItem : public QGraphicsItem
+{
+public:
+ QSimpleGraphicsItem(QSimpleCanvasItem *);
+ virtual ~QSimpleGraphicsItem();
+
+ virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
+ virtual QRectF boundingRect() const;
+
+ QTransform transform;
+protected:
+ virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ virtual bool sceneEvent(QEvent *);
+ virtual QVariant itemChange(GraphicsItemChange, const QVariant &);
+ virtual void keyPressEvent(QKeyEvent *event);
+ virtual void keyReleaseEvent(QKeyEvent *event);
+ virtual void focusInEvent(QFocusEvent *event);
+
+private:
+ friend class QSimpleCanvasItem;
+ QSimpleCanvasItem *owner;
+};
+
+class QSimpleCanvasItemData
+{
+public:
+ QSimpleCanvasItemData();
+ ~QSimpleCanvasItemData();
+
+ // 5 bits is all that's needed to store Qt::MouseButtons
+ int buttons:5;
+ QSimpleCanvasItem::Flip flip:2;
+ bool dirty:1;
+ bool transformValid:1;
+
+ qreal x;
+ qreal y;
+ qreal z;
+ float visible;
+
+ QSimpleCanvas::Matrix *transformUser;
+ QSimpleCanvas::Matrix transformActive;
+
+ float activeOpacity;
+
+#if defined(QFX_RENDER_OPENGL)
+ QRectF lastPaintRect;
+#else
+ QRect lastPaintRect;
+#endif
+};
+
+class QSimpleCanvasFilter;
+class QGraphicsQSimpleCanvasItem;
+class QSimpleCanvasItemPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QSimpleCanvasItem);
+public:
+ QSimpleCanvasItemPrivate()
+ : parent(0), canvas(0), filter(0), clip(QSimpleCanvasItem::NoClip),
+ origin(QSimpleCanvasItem::TopLeft), options(QSimpleCanvasItem::NoOption),
+ focusable(false), wantsActiveFocusPanelPendingCanvas(false),
+ hasBeenActiveFocusPanel(false),
+ hasFocus(false), hasActiveFocus(false), needsZOrder(false),
+ widthValid(false), heightValid(false), width(0), height(0), scale(1),
+ graphicsItem(0), data_ptr(0)
+ {
+ }
+
+ virtual ~QSimpleCanvasItemPrivate() {}
+
+ QSimpleCanvasItem *parent;
+ QSimpleCanvas *canvas;
+ QList<QSimpleCanvasItem *> children;
+
+ QSimpleCanvasFilter *filter;
+
+ QSimpleCanvasItem::ClipType clip:3;
+ QSimpleCanvasItem::TransformOrigin origin:4;
+ int options:8;
+ bool focusable:1;
+ bool wantsActiveFocusPanelPendingCanvas:1;
+ bool hasBeenActiveFocusPanel:1;
+ bool hasFocus:1;
+ bool hasActiveFocus:1;
+ bool needsZOrder:1;
+ bool widthValid:1;
+ bool heightValid:1;
+
+ void setFocus(bool f);
+ void setActiveFocus(bool f);
+
+ qreal width;
+ qreal height;
+ qreal scale;
+
+ QSimpleGraphicsItem *graphicsItem;
+ inline QSimpleCanvasItemData *data() const {
+ if(!data_ptr) data_ptr = new QSimpleCanvasItemData;
+ return data_ptr;
+ }
+ mutable QSimpleCanvasItemData *data_ptr;
+
+ void gvRemoveMouseFilter();
+ void gvAddMouseFilter();
+
+ void canvasChanged(QSimpleCanvas *newCanvas, QSimpleCanvas *oldCanvas);
+
+ void freshenTransforms() const;
+
+ QPointF adjustFrom(const QPointF &) const;
+ QRectF adjustFrom(const QRectF &) const;
+ QPointF adjustTo(const QPointF &) const;
+ QRectF adjustTo(const QRectF &) const;
+
+ QPointF transformOrigin() const;
+
+ void setParentInternal(QSimpleCanvasItem *);
+ void convertToGraphicsItem(QGraphicsItem * = 0);
+
+#if defined(QFX_RENDER_QPAINTER)
+ void paint(QPainter &);
+ void paintChild(QPainter &, QSimpleCanvasItem *);
+ QRect setupPainting(int version, const QRect &bounding);
+#else
+ struct GLPaintParameters
+ {
+ QRect sceneRect;
+ QRectF boundingRect;
+ QRect clipRect;
+#if defined(QFX_RENDER_OPENGL2)
+ uchar stencilValue;
+#endif
+ float opacity;
+ bool forceParamRefresh;
+ };
+#if defined(QFX_RENDER_OPENGL2)
+ QRectF setupPainting(int version, const QRect &bounding);
+#elif defined(QFX_RENDER_OPENGL1)
+ QRectF setupPainting(int version, const QRect &bounding, unsigned int *zero);
+#endif
+ void setupChildState(QSimpleCanvasItem *);
+
+ void paint(GLPaintParameters &, QSimpleCanvasFilter::Layer = QSimpleCanvasFilter::All);
+#if defined(QFX_RENDER_OPENGL1)
+ void paintNoClip(GLPaintParameters &, QSimpleCanvasFilter::Layer = QSimpleCanvasFilter::All);
+#endif
+ void paintChild(const GLPaintParameters &, QSimpleCanvasItem *);
+ void simplePaintChild(const GLPaintParameters &, QSimpleCanvasItem *);
+
+ inline GLBasicShaders *basicShaders() const;
+
+ QSimpleCanvas::Matrix localTransform() const;
+
+#endif
+
+ void zOrderChildren();
+ static int nextTransformVersion;
+ bool freshenNeeded() const;
+ void doFreshenTransforms() const;
+
+ // Debugging
+ int dump(int);
+ enum FocusStateCheckData { NoCheckData = 0x00,
+ InActivePanel = 0x01,
+ InRealm = 0x02,
+ InActiveFocusedRealm = 0x04
+ };
+ Q_DECLARE_FLAGS(FocusStateCheckDatas, FocusStateCheckData);
+ enum FocusStateCheckRData { NoCheckRData = 0x00,
+ SeenFocus = 0x01,
+ SeenActiveFocus = 0x02 };
+ Q_DECLARE_FLAGS(FocusStateCheckRDatas, FocusStateCheckRData);
+ bool checkFocusState(FocusStateCheckDatas, FocusStateCheckRDatas *);
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QSimpleCanvasItemPrivate::FocusStateCheckDatas);
+Q_DECLARE_OPERATORS_FOR_FLAGS(QSimpleCanvasItemPrivate::FocusStateCheckRDatas);
+
+#endif // QSIMPLECANVASITEM_P_H
+
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvasserver.cpp b/src/declarative/canvas/qsimplecanvasserver.cpp
new file mode 100644
index 0000000..7eebe65
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvasserver.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 "qsimplecanvasserver_p.h"
+#include "qdebug.h"
+#ifndef Q_OS_WIN32
+#include <arpa/inet.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+QSimpleCanvasServer::QSimpleCanvasServer(int port, QObject *parent)
+: QObject(parent), _tcpServer(new QTcpServer(this))
+{
+ QObject::connect(_tcpServer, SIGNAL(newConnection()),
+ this, SLOT(newConnection()));
+
+ _time.start();
+
+ if(!_tcpServer->listen(QHostAddress::Any, port)) {
+ qWarning() << "QSimpleCanvasServer: Cannot listen on port" << port;
+ return;
+ }
+}
+
+void QSimpleCanvasServer::newConnection()
+{
+ QTcpSocket *socket = _tcpServer->nextPendingConnection();
+ QObject::connect(socket, SIGNAL(disconnected()),
+ this, SLOT(disconnected()));
+ _tcpClients << socket;
+}
+
+void QSimpleCanvasServer::addTiming(quint32 paint,
+ quint32 repaint,
+ quint32 timeBetweenFrames)
+{
+ /*
+ quint32 data[3];
+ data[0] = ::htonl(paint);
+ data[1] = ::htonl(repaint);
+ data[2] = ::htonl(timeBetweenFrames);
+ */
+
+ int e = _time.elapsed();
+ QString d = QString::number(paint) + QLatin1String(" ") + QString::number(repaint) + QLatin1String(" ") + QString::number(timeBetweenFrames) + QLatin1String(" ") + QString::number(e) + QLatin1String("\n");
+ QByteArray ba = d.toLatin1();
+
+ // XXX
+ for(int ii = 0; ii < _tcpClients.count(); ++ii)
+// _tcpClients.at(ii)->write((const char *)data, 12);
+ _tcpClients.at(ii)->write(ba.constData(), ba.length());
+}
+
+void QSimpleCanvasServer::disconnected()
+{
+ QTcpSocket *socket = static_cast<QTcpSocket *>(sender());
+
+ for(int ii = 0; ii < _tcpClients.count(); ++ii) {
+ if(_tcpClients.at(ii) == socket) {
+ socket->disconnect();
+ socket->deleteLater();
+ _tcpClients.removeAt(ii);
+ return;
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/canvas/qsimplecanvasserver_p.h b/src/declarative/canvas/qsimplecanvasserver_p.h
new file mode 100644
index 0000000..7d53357
--- /dev/null
+++ b/src/declarative/canvas/qsimplecanvasserver_p.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 QtDeclarative 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 QSIMPLECANVASSERVER_P_H
+#define QSIMPLECANVASSERVER_P_H
+
+#include "qobject.h"
+#include "qtcpserver.h"
+#include "qtcpsocket.h"
+#include "qdatetime.h"
+
+
+QT_BEGIN_NAMESPACE
+class QSimpleCanvasServer : public QObject
+{
+Q_OBJECT
+public:
+ QSimpleCanvasServer(int port, QObject *parent);
+
+ void addTiming(quint32, quint32, quint32);
+
+private Q_SLOTS:
+ void newConnection();
+ void disconnected();
+
+private:
+ QTcpServer *_tcpServer;
+ QList<QTcpSocket *> _tcpClients;
+ QTime _time;
+};
+
+QT_END_NAMESPACE
+#endif // GFXCANVASSERVER_P_H