aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/items/qquickpainteditem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/items/qquickpainteditem.cpp')
-rw-r--r--src/declarative/items/qquickpainteditem.cpp537
1 files changed, 537 insertions, 0 deletions
diff --git a/src/declarative/items/qquickpainteditem.cpp b/src/declarative/items/qquickpainteditem.cpp
new file mode 100644
index 0000000000..5e5eb79f36
--- /dev/null
+++ b/src/declarative/items/qquickpainteditem.cpp
@@ -0,0 +1,537 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.1, 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickpainteditem.h"
+#include <private/qquickpainteditem_p.h>
+
+#include <private/qsgpainternode_p.h>
+#include <private/qsgcontext_p.h>
+#include <private/qsgadaptationlayer_p.h>
+
+#include <qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QQuickPaintedItem
+ \brief The QQuickPaintedItem class provides a way to use the QPainter API in the
+ QML Scene Graph.
+
+ \inmodule QtDeclarative
+
+ The QQuickPaintedItem makes it possible to use the QPainter API with the QML Scene Graph.
+ It sets up a textured rectangle in the Scene Graph and uses a QPainter to paint
+ onto the texture. The render target can be either a QImage or a QOpenGLFramebufferObject.
+ When the render target is a QImage, QPainter first renders into the image then
+ the content is uploaded to the texture.
+ When a QOpenGLFramebufferObject is used, QPainter paints directly onto the texture.
+ Call update() to trigger a repaint.
+
+ To enable QPainter to do anti-aliased rendering, use setAntialiasing().
+
+ QQuickPaintedItem is meant to make it easier to port old code that is using the
+ QPainter API to the QML Scene Graph API and it should be used only for that purpose.
+
+ To write your own painted item, you first create a subclass of QQuickPaintedItem, and then
+ start by implementing its only pure virtual public function: paint(), which implements
+ the actual painting. To get the size of the area painted by the item, use
+ contentsBoundingRect().
+*/
+
+/*!
+ \enum QQuickPaintedItem::RenderTarget
+
+ This enum describes QQuickPaintedItem's render targets. The render target is the
+ surface QPainter paints onto before the item is rendered on screen.
+
+ \value Image The default; QPainter paints into a QImage using the raster paint engine.
+ The image's content needs to be uploaded to graphics memory afterward, this operation
+ can potentially be slow if the item is large. This render target allows high quality
+ anti-aliasing and fast item resizing.
+
+ \value FramebufferObject QPainter paints into a QOpenGLFramebufferObject using the GL
+ paint engine. Painting can be faster as no texture upload is required, but anti-aliasing
+ quality is not as good as if using an image. This render target allows faster rendering
+ in some cases, but you should avoid using it if the item is resized often.
+
+ \sa setRenderTarget()
+*/
+
+/*!
+ \enum QQuickPaintedItem::PerformanceHint
+
+ This enum describes flags that you can enable to improve rendering
+ performance in QQuickPaintedItem. By default, none of these flags are set.
+
+ \value FastFBOResizing If your item gets resized often and you are using the
+ QQuickPaintedItem::FramebufferObject render target, set this flag to true to reduce the
+ item resizing time at the cost of using more graphics memory. Resizing a Framebuffer object
+ is a costly operation, by enabling this property the Framebuffer Object will use a texture
+ larger than the actual size of the item to avoid as much as possible resizing it.
+*/
+
+/*!
+ \internal
+*/
+QQuickPaintedItemPrivate::QQuickPaintedItemPrivate()
+ : QQuickItemPrivate()
+ , contentsScale(1.0)
+ , fillColor(Qt::transparent)
+ , renderTarget(QQuickPaintedItem::Image)
+ , performanceHints(0)
+ , geometryDirty(false)
+ , contentsDirty(false)
+ , opaquePainting(false)
+ , antialiasing(false)
+ , mipmap(false)
+{
+}
+
+/*!
+ Constructs a QQuickPaintedItem with the given \a parent item.
+ */
+QQuickPaintedItem::QQuickPaintedItem(QQuickItem *parent)
+ : QQuickItem(*(new QQuickPaintedItemPrivate), parent)
+{
+ setFlag(ItemHasContents);
+}
+
+/*!
+ \internal
+*/
+QQuickPaintedItem::QQuickPaintedItem(QQuickPaintedItemPrivate &dd, QQuickItem *parent)
+ : QQuickItem(dd, parent)
+{
+ setFlag(ItemHasContents);
+}
+
+/*!
+ Destroys the QQuickPaintedItem.
+*/
+QQuickPaintedItem::~QQuickPaintedItem()
+{
+}
+
+/*!
+ Schedules a redraw of the area covered by \a rect in this item. You can call this function
+ whenever your item needs to be redrawn, such as if it changes appearance or size.
+
+ This function does not cause an immediate paint; instead it schedules a paint request that
+ is processed by the QML Scene Graph when the next frame is rendered. The item will only be
+ redrawn if it is visible.
+
+ Note that calling this function will trigger a repaint of the whole scene.
+
+ \sa paint()
+*/
+void QQuickPaintedItem::update(const QRect &rect)
+{
+ Q_D(QQuickPaintedItem);
+ d->contentsDirty = true;
+
+ if (rect.isNull() && !d->dirtyRect.isNull())
+ d->dirtyRect = contentsBoundingRect().toAlignedRect();
+ else
+ d->dirtyRect |= (contentsBoundingRect() & rect).toAlignedRect();
+ QQuickItem::update();
+}
+
+/*!
+ Returns true if this item is opaque; otherwise, false is returned.
+
+ By default, painted items are not opaque.
+
+ \sa setOpaquePainting()
+*/
+bool QQuickPaintedItem::opaquePainting() const
+{
+ Q_D(const QQuickPaintedItem);
+ return d->opaquePainting;
+}
+
+/*!
+ If \a opaque is true, the item is opaque; otherwise, it is considered as translucent.
+
+ Opaque items are not blended with the rest of the scene, you should set this to true
+ if the content of the item is opaque to speed up rendering.
+
+ By default, painted items are not opaque.
+
+ \sa opaquePainting()
+*/
+void QQuickPaintedItem::setOpaquePainting(bool opaque)
+{
+ Q_D(QQuickPaintedItem);
+
+ if (d->opaquePainting == opaque)
+ return;
+
+ d->opaquePainting = opaque;
+ QQuickItem::update();
+}
+
+/*!
+ Returns true if antialiased painting is enabled; otherwise, false is returned.
+
+ By default, antialiasing is not enabled.
+
+ \sa setAntialiasing()
+*/
+bool QQuickPaintedItem::antialiasing() const
+{
+ Q_D(const QQuickPaintedItem);
+ return d->antialiasing;
+}
+
+/*!
+ If \a enable is true, antialiased painting is enabled.
+
+ By default, antialiasing is not enabled.
+
+ \sa antialiasing()
+*/
+void QQuickPaintedItem::setAntialiasing(bool enable)
+{
+ Q_D(QQuickPaintedItem);
+
+ if (d->antialiasing == enable)
+ return;
+
+ d->antialiasing = enable;
+ update();
+}
+
+/*!
+ Returns true if mipmaps are enabled; otherwise, false is returned.
+
+ By default, mipmapping is not enabled.
+
+ \sa setMipmap()
+*/
+bool QQuickPaintedItem::mipmap() const
+{
+ Q_D(const QQuickPaintedItem);
+ return d->mipmap;
+}
+
+/*!
+ If \a enable is true, mipmapping is enabled on the associated texture.
+
+ Mipmapping increases rendering speed and reduces aliasing artifacts when the item is
+ scaled down.
+
+ By default, mipmapping is not enabled.
+
+ \sa mipmap()
+*/
+void QQuickPaintedItem::setMipmap(bool enable)
+{
+ Q_D(QQuickPaintedItem);
+
+ if (d->mipmap == enable)
+ return;
+
+ d->mipmap = enable;
+ update();
+}
+
+/*!
+ Returns the performance hints.
+
+ By default, no performance hint is enabled/
+
+ \sa setPerformanceHint(), setPerformanceHints()
+*/
+QQuickPaintedItem::PerformanceHints QQuickPaintedItem::performanceHints() const
+{
+ Q_D(const QQuickPaintedItem);
+ return d->performanceHints;
+}
+
+/*!
+ Sets the given performance \a hint on the item if \a enabled is true;
+ otherwise clears the performance hint.
+
+ By default, no performance hint is enabled/
+
+ \sa setPerformanceHints(), performanceHints()
+*/
+void QQuickPaintedItem::setPerformanceHint(QQuickPaintedItem::PerformanceHint hint, bool enabled)
+{
+ Q_D(QQuickPaintedItem);
+ PerformanceHints oldHints = d->performanceHints;
+ if (enabled)
+ d->performanceHints |= hint;
+ else
+ d->performanceHints &= ~hint;
+ if (oldHints != d->performanceHints)
+ update();
+}
+
+/*!
+ Sets the performance hints to \a hints
+
+ By default, no performance hint is enabled/
+
+ \sa setPerformanceHint(), performanceHints()
+*/
+void QQuickPaintedItem::setPerformanceHints(QQuickPaintedItem::PerformanceHints hints)
+{
+ Q_D(QQuickPaintedItem);
+ if (d->performanceHints == hints)
+ return;
+ d->performanceHints = hints;
+ update();
+}
+
+/*!
+ This function returns the outer bounds of the item as a rectangle; all painting must be
+ restricted to inside an item's bounding rect.
+
+ If the contents size has not been set it reflects the size of the item; otherwise
+ it reflects the contents size scaled by the contents scale.
+
+ Use this function to know the area painted by the item.
+
+ \sa QQuickItem::width(), QQuickItem::height(), contentsSize(), contentsScale()
+*/
+QRectF QQuickPaintedItem::contentsBoundingRect() const
+{
+ Q_D(const QQuickPaintedItem);
+
+ qreal w = d->width;
+ QSizeF sz = d->contentsSize * d->contentsScale;
+ if (w < sz.width())
+ w = sz.width();
+ qreal h = d->height;
+ if (h < sz.height())
+ h = sz.height();
+
+ return QRectF(0, 0, w, h);
+}
+
+/*!
+ \property QQuickPaintedItem::contentsSize
+ \brief The size of the contents
+
+ The contents size is the size of the item in regards to how it is painted
+ using the paint() function. This is distinct from the size of the
+ item in regards to height() and width().
+*/
+QSize QQuickPaintedItem::contentsSize() const
+{
+ Q_D(const QQuickPaintedItem);
+ return d->contentsSize;
+}
+
+void QQuickPaintedItem::setContentsSize(const QSize &size)
+{
+ Q_D(QQuickPaintedItem);
+
+ if (d->contentsSize == size)
+ return;
+
+ d->contentsSize = size;
+ update();
+}
+
+/*!
+ This convenience function is equivalent to calling setContentsSize(QSize()).
+*/
+void QQuickPaintedItem::resetContentsSize()
+{
+ setContentsSize(QSize());
+}
+
+/*!
+ \property QQuickPaintedItem::contentsScale
+ \brief The scale of the contents
+
+ All painting happening in paint() is scaled by the contents scale. This is distinct
+ from the scale of the item in regards to scale().
+
+ The default value is 1.
+*/
+qreal QQuickPaintedItem::contentsScale() const
+{
+ Q_D(const QQuickPaintedItem);
+ return d->contentsScale;
+}
+
+void QQuickPaintedItem::setContentsScale(qreal scale)
+{
+ Q_D(QQuickPaintedItem);
+
+ if (d->contentsScale == scale)
+ return;
+
+ d->contentsScale = scale;
+ update();
+}
+
+/*!
+ \property QQuickPaintedItem::fillColor
+ \brief The item's background fill color.
+
+ By default, the fill color is set to Qt::transparent.
+*/
+QColor QQuickPaintedItem::fillColor() const
+{
+ Q_D(const QQuickPaintedItem);
+ return d->fillColor;
+}
+
+void QQuickPaintedItem::setFillColor(const QColor &c)
+{
+ Q_D(QQuickPaintedItem);
+
+ if (d->fillColor == c)
+ return;
+
+ d->fillColor = c;
+ update();
+
+ emit fillColorChanged();
+}
+
+/*!
+ \property QQuickPaintedItem::renderTarget
+ \brief The item's render target.
+
+ This property defines which render target the QPainter renders into, it can be either
+ QQuickPaintedItem::Image or QQuickPaintedItem::FramebufferObject. Both have certains benefits,
+ typically performance versus quality. Using a framebuffer object avoids a costly upload
+ of the image contents to the texture in graphics memory, while using an image enables
+ high quality anti-aliasing.
+
+ \warning Resizing a framebuffer object is a costly operation, avoid using
+ the QQuickPaintedItem::FramebufferObject render target if the item gets resized often.
+
+ By default, the render target is QQuickPaintedItem::Image.
+*/
+QQuickPaintedItem::RenderTarget QQuickPaintedItem::renderTarget() const
+{
+ Q_D(const QQuickPaintedItem);
+ return d->renderTarget;
+}
+
+void QQuickPaintedItem::setRenderTarget(RenderTarget target)
+{
+ Q_D(QQuickPaintedItem);
+
+ if (d->renderTarget == target)
+ return;
+
+ d->renderTarget = target;
+ update();
+
+ emit renderTargetChanged();
+}
+
+/*!
+ \fn virtual void QQuickPaintedItem::paint(QPainter *painter) = 0
+
+ This function, which is usually called by the QML Scene Graph, paints the
+ contents of an item in local coordinates.
+
+ The function is called after the item has been filled with the fillColor.
+
+ Reimplement this function in a QQuickPaintedItem subclass to provide the
+ item's painting implementation, using \a painter.
+
+ \note The QML Scene Graph uses two separate threads, the main thread does things such as
+ processing events or updating animations while a second thread does the actual OpenGL rendering.
+ As a consequence, paint() is not called from the main GUI thread but from the GL enabled
+ renderer thread. At the moment paint() is called, the GUI thread is blocked and this is
+ therefore thread-safe.
+*/
+
+/*!
+ This function is called after the item's geometry has changed.
+*/
+void QQuickPaintedItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_D(QQuickPaintedItem);
+ d->geometryDirty = true;
+ QQuickItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+
+/*!
+ This function is called when the Scene Graph node associated to the item needs to
+ be updated.
+*/
+QSGNode *QQuickPaintedItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
+{
+ Q_UNUSED(data);
+ Q_D(QQuickPaintedItem);
+
+ if (width() <= 0 || height() <= 0) {
+ delete oldNode;
+ return 0;
+ }
+
+ QSGPainterNode *node = static_cast<QSGPainterNode *>(oldNode);
+ if (!node)
+ node = new QSGPainterNode(this);
+
+ QRectF br = contentsBoundingRect();
+
+ node->setPreferredRenderTarget(d->renderTarget);
+ node->setFastFBOResizing(d->performanceHints & FastFBOResizing);
+ node->setSize(QSize(qRound(br.width()), qRound(br.height())));
+ node->setSmoothPainting(d->antialiasing);
+ node->setLinearFiltering(d->smooth);
+ node->setMipmapping(d->mipmap);
+ node->setOpaquePainting(d->opaquePainting);
+ node->setFillColor(d->fillColor);
+ node->setContentsScale(d->contentsScale);
+ node->setDirty(d->contentsDirty || d->geometryDirty, d->dirtyRect);
+ node->update();
+
+ d->contentsDirty = false;
+ d->geometryDirty = false;
+ d->dirtyRect = QRect();
+
+ return node;
+}
+
+QT_END_NAMESPACE