1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qquickpainteditem.h"
43 #include <private/qquickpainteditem_p.h>
45 #include <QtQuick/private/qsgpainternode_p.h>
46 #include <QtQuick/private/qsgcontext_p.h>
47 #include <private/qsgadaptationlayer_p.h>
54 \class QQuickPaintedItem
55 \brief The QQuickPaintedItem class provides a way to use the QPainter API in the
60 The QQuickPaintedItem makes it possible to use the QPainter API with the QML Scene Graph.
61 It sets up a textured rectangle in the Scene Graph and uses a QPainter to paint
62 onto the texture. The render target can be either a QImage or a QOpenGLFramebufferObject.
63 When the render target is a QImage, QPainter first renders into the image then
64 the content is uploaded to the texture.
65 When a QOpenGLFramebufferObject is used, QPainter paints directly onto the texture.
66 Call update() to trigger a repaint.
68 To enable QPainter to do anti-aliased rendering, use setAntialiasing().
70 QQuickPaintedItem is meant to make it easier to port old code that is using the
71 QPainter API to the QML Scene Graph API and it should be used only for that purpose.
73 To write your own painted item, you first create a subclass of QQuickPaintedItem, and then
74 start by implementing its only pure virtual public function: paint(), which implements
75 the actual painting. To get the size of the area painted by the item, use
76 contentsBoundingRect().
80 \enum QQuickPaintedItem::RenderTarget
82 This enum describes QQuickPaintedItem's render targets. The render target is the
83 surface QPainter paints onto before the item is rendered on screen.
85 \value Image The default; QPainter paints into a QImage using the raster paint engine.
86 The image's content needs to be uploaded to graphics memory afterward, this operation
87 can potentially be slow if the item is large. This render target allows high quality
88 anti-aliasing and fast item resizing.
90 \value FramebufferObject QPainter paints into a QOpenGLFramebufferObject using the GL
91 paint engine. Painting can be faster as no texture upload is required, but anti-aliasing
92 quality is not as good as if using an image. This render target allows faster rendering
93 in some cases, but you should avoid using it if the item is resized often.
95 \value InvertedYFramebufferObject Exactly as for FramebufferObject above, except once
96 the painting is done, prior to rendering the painted image is flipped about the
97 x-axis so that the top-most pixels are now at the bottom. Since this is done with the
98 OpenGL texture coordinates it is a much faster way to achieve this effect than using a
101 \sa setRenderTarget()
105 \enum QQuickPaintedItem::PerformanceHint
107 This enum describes flags that you can enable to improve rendering
108 performance in QQuickPaintedItem. By default, none of these flags are set.
110 \value FastFBOResizing If your item gets resized often and you are using the
111 QQuickPaintedItem::FramebufferObject render target, set this flag to true to reduce the
112 item resizing time at the cost of using more graphics memory. Resizing a Framebuffer object
113 is a costly operation, by enabling this property the Framebuffer Object will use a texture
114 larger than the actual size of the item to avoid as much as possible resizing it.
120 QQuickPaintedItemPrivate::QQuickPaintedItemPrivate()
121 : QQuickItemPrivate()
123 , fillColor(Qt::transparent)
124 , renderTarget(QQuickPaintedItem::Image)
125 , performanceHints(0)
126 , opaquePainting(false)
127 , antialiasing(false)
133 Constructs a QQuickPaintedItem with the given \a parent item.
135 QQuickPaintedItem::QQuickPaintedItem(QQuickItem *parent)
136 : QQuickItem(*(new QQuickPaintedItemPrivate), parent)
138 setFlag(ItemHasContents);
144 QQuickPaintedItem::QQuickPaintedItem(QQuickPaintedItemPrivate &dd, QQuickItem *parent)
145 : QQuickItem(dd, parent)
147 setFlag(ItemHasContents);
151 Destroys the QQuickPaintedItem.
153 QQuickPaintedItem::~QQuickPaintedItem()
158 Schedules a redraw of the area covered by \a rect in this item. You can call this function
159 whenever your item needs to be redrawn, such as if it changes appearance or size.
161 This function does not cause an immediate paint; instead it schedules a paint request that
162 is processed by the QML Scene Graph when the next frame is rendered. The item will only be
163 redrawn if it is visible.
165 Note that calling this function will trigger a repaint of the whole scene.
169 void QQuickPaintedItem::update(const QRect &rect)
171 Q_D(QQuickPaintedItem);
173 if (rect.isNull() && !d->dirtyRect.isNull())
174 d->dirtyRect = contentsBoundingRect().toAlignedRect();
176 d->dirtyRect |= (contentsBoundingRect() & rect).toAlignedRect();
177 QQuickItem::update();
181 Returns true if this item is opaque; otherwise, false is returned.
183 By default, painted items are not opaque.
185 \sa setOpaquePainting()
187 bool QQuickPaintedItem::opaquePainting() const
189 Q_D(const QQuickPaintedItem);
190 return d->opaquePainting;
194 If \a opaque is true, the item is opaque; otherwise, it is considered as translucent.
196 Opaque items are not blended with the rest of the scene, you should set this to true
197 if the content of the item is opaque to speed up rendering.
199 By default, painted items are not opaque.
203 void QQuickPaintedItem::setOpaquePainting(bool opaque)
205 Q_D(QQuickPaintedItem);
207 if (d->opaquePainting == opaque)
210 d->opaquePainting = opaque;
211 QQuickItem::update();
215 Returns true if antialiased painting is enabled; otherwise, false is returned.
217 By default, antialiasing is not enabled.
219 \sa setAntialiasing()
221 bool QQuickPaintedItem::antialiasing() const
223 Q_D(const QQuickPaintedItem);
224 return d->antialiasing;
228 If \a enable is true, antialiased painting is enabled.
230 By default, antialiasing is not enabled.
234 void QQuickPaintedItem::setAntialiasing(bool enable)
236 Q_D(QQuickPaintedItem);
238 if (d->antialiasing == enable)
241 d->antialiasing = enable;
246 Returns true if mipmaps are enabled; otherwise, false is returned.
248 By default, mipmapping is not enabled.
252 bool QQuickPaintedItem::mipmap() const
254 Q_D(const QQuickPaintedItem);
259 If \a enable is true, mipmapping is enabled on the associated texture.
261 Mipmapping increases rendering speed and reduces aliasing artifacts when the item is
264 By default, mipmapping is not enabled.
268 void QQuickPaintedItem::setMipmap(bool enable)
270 Q_D(QQuickPaintedItem);
272 if (d->mipmap == enable)
280 Returns the performance hints.
282 By default, no performance hint is enabled/
284 \sa setPerformanceHint(), setPerformanceHints()
286 QQuickPaintedItem::PerformanceHints QQuickPaintedItem::performanceHints() const
288 Q_D(const QQuickPaintedItem);
289 return d->performanceHints;
293 Sets the given performance \a hint on the item if \a enabled is true;
294 otherwise clears the performance hint.
296 By default, no performance hint is enabled/
298 \sa setPerformanceHints(), performanceHints()
300 void QQuickPaintedItem::setPerformanceHint(QQuickPaintedItem::PerformanceHint hint, bool enabled)
302 Q_D(QQuickPaintedItem);
303 PerformanceHints oldHints = d->performanceHints;
305 d->performanceHints |= hint;
307 d->performanceHints &= ~hint;
308 if (oldHints != d->performanceHints)
313 Sets the performance hints to \a hints
315 By default, no performance hint is enabled/
317 \sa setPerformanceHint(), performanceHints()
319 void QQuickPaintedItem::setPerformanceHints(QQuickPaintedItem::PerformanceHints hints)
321 Q_D(QQuickPaintedItem);
322 if (d->performanceHints == hints)
324 d->performanceHints = hints;
329 This function returns the outer bounds of the item as a rectangle; all painting must be
330 restricted to inside an item's bounding rect.
332 If the contents size has not been set it reflects the size of the item; otherwise
333 it reflects the contents size scaled by the contents scale.
335 Use this function to know the area painted by the item.
337 \sa QQuickItem::width(), QQuickItem::height(), contentsSize(), contentsScale()
339 QRectF QQuickPaintedItem::contentsBoundingRect() const
341 Q_D(const QQuickPaintedItem);
344 QSizeF sz = d->contentsSize * d->contentsScale;
351 return QRectF(0, 0, w, h);
355 \property QQuickPaintedItem::contentsSize
356 \brief The size of the contents
358 The contents size is the size of the item in regards to how it is painted
359 using the paint() function. This is distinct from the size of the
360 item in regards to height() and width().
362 QSize QQuickPaintedItem::contentsSize() const
364 Q_D(const QQuickPaintedItem);
365 return d->contentsSize;
368 void QQuickPaintedItem::setContentsSize(const QSize &size)
370 Q_D(QQuickPaintedItem);
372 if (d->contentsSize == size)
375 d->contentsSize = size;
380 This convenience function is equivalent to calling setContentsSize(QSize()).
382 void QQuickPaintedItem::resetContentsSize()
384 setContentsSize(QSize());
388 \property QQuickPaintedItem::contentsScale
389 \brief The scale of the contents
391 All painting happening in paint() is scaled by the contents scale. This is distinct
392 from the scale of the item in regards to scale().
394 The default value is 1.
396 qreal QQuickPaintedItem::contentsScale() const
398 Q_D(const QQuickPaintedItem);
399 return d->contentsScale;
402 void QQuickPaintedItem::setContentsScale(qreal scale)
404 Q_D(QQuickPaintedItem);
406 if (d->contentsScale == scale)
409 d->contentsScale = scale;
414 \property QQuickPaintedItem::fillColor
415 \brief The item's background fill color.
417 By default, the fill color is set to Qt::transparent.
419 QColor QQuickPaintedItem::fillColor() const
421 Q_D(const QQuickPaintedItem);
425 void QQuickPaintedItem::setFillColor(const QColor &c)
427 Q_D(QQuickPaintedItem);
429 if (d->fillColor == c)
435 emit fillColorChanged();
439 \property QQuickPaintedItem::renderTarget
440 \brief The item's render target.
442 This property defines which render target the QPainter renders into, it can be either
443 QSGPaintedItem::Image, QSGPaintedItem::FramebufferObject or QSGPaintedItem::InvertedYFramebufferObject.
445 Each has certain benefits, typically performance versus quality. Using a framebuffer
446 object avoids a costly upload of the image contents to the texture in graphics memory,
447 while using an image enables high quality anti-aliasing.
449 \warning Resizing a framebuffer object is a costly operation, avoid using
450 the QQuickPaintedItem::FramebufferObject render target if the item gets resized often.
452 By default, the render target is QQuickPaintedItem::Image.
454 QQuickPaintedItem::RenderTarget QQuickPaintedItem::renderTarget() const
456 Q_D(const QQuickPaintedItem);
457 return d->renderTarget;
460 void QQuickPaintedItem::setRenderTarget(RenderTarget target)
462 Q_D(QQuickPaintedItem);
464 if (d->renderTarget == target)
467 d->renderTarget = target;
470 emit renderTargetChanged();
474 \fn virtual void QQuickPaintedItem::paint(QPainter *painter) = 0
476 This function, which is usually called by the QML Scene Graph, paints the
477 contents of an item in local coordinates.
479 The function is called after the item has been filled with the fillColor.
481 Reimplement this function in a QQuickPaintedItem subclass to provide the
482 item's painting implementation, using \a painter.
484 \note The QML Scene Graph uses two separate threads, the main thread does things such as
485 processing events or updating animations while a second thread does the actual OpenGL rendering.
486 As a consequence, paint() is not called from the main GUI thread but from the GL enabled
487 renderer thread. At the moment paint() is called, the GUI thread is blocked and this is
488 therefore thread-safe.
492 This function is called when the Scene Graph node associated to the item needs to
495 QSGNode *QQuickPaintedItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
498 Q_D(QQuickPaintedItem);
500 if (width() <= 0 || height() <= 0) {
505 QSGPainterNode *node = static_cast<QSGPainterNode *>(oldNode);
507 node = new QSGPainterNode(this);
509 QRectF br = contentsBoundingRect();
511 node->setPreferredRenderTarget(d->renderTarget);
512 node->setFastFBOResizing(d->performanceHints & FastFBOResizing);
513 node->setSize(QSize(qRound(br.width()), qRound(br.height())));
514 node->setSmoothPainting(d->antialiasing);
515 node->setLinearFiltering(d->smooth);
516 node->setMipmapping(d->mipmap);
517 node->setOpaquePainting(d->opaquePainting);
518 node->setFillColor(d->fillColor);
519 node->setContentsScale(d->contentsScale);
520 node->setDirty(d->dirtyRect);
523 d->dirtyRect = QRect();