1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include "qsgpainteditem.h"
43 #include <private/qsgpainteditem_p.h>
44 #include <private/qsgpainternode_p.h>
46 #include <private/qsgcontext_p.h>
47 #include <private/qsgadaptationlayer_p.h>
54 \brief The QSGPaintedItem class provides a way to use the QPainter API in the
57 The QSGPaintedItem makes it possible to use the QPainter API with the QML Scene Graph.
58 It sets up a textured rectangle in the Scene Graph and uses a QPainter to paint
59 onto the texture. The render target can be either a QImage or a QGLFramebufferObject.
60 When the render target is a QImage, QPainter first renders into the image then
61 the content is uploaded to the texture.
62 When a QGLFramebufferObject is used, QPainter paints directly onto the texture.
63 Call update() to trigger a repaint.
65 To enable QPainter to do anti-aliased rendering, use setAntialiasing().
67 QSGPaintedItem is meant to make it easier to port old code that is using the
68 QPainter API to the QML Scene Graph API and it should be used only for that purpose.
70 To write your own painted item, you first create a subclass of QSGPaintedItem, and then
71 start by implementing its only pure virtual public function: paint(), which implements
72 the actual painting. To get the size of the area painted by the item, use
73 contentsBoundingRect().
77 \enum QSGPaintedItem::RenderTarget
79 This enum describes QSGPaintedItem's render targets. The render target is the
80 surface QPainter paints onto before the item is rendered on screen.
82 \value Image The default; QPainter paints into a QImage using the raster paint engine.
83 The image's content needs to be uploaded to graphics memory afterward, this operation
84 can potentially be slow if the item is large. This render target allows high quality
85 anti-aliasing and fast item resizing.
87 \value FramebufferObject QPainter paints into a QGLFramebufferObject using the GL
88 paint engine. Painting can be faster as no texture upload is required, but anti-aliasing
89 quality is not as good as if using an image. This render target allows faster rendering
90 in some cases, but you should avoid using it if the item is resized often.
98 QSGPaintedItemPrivate::QSGPaintedItemPrivate()
101 , fillColor(Qt::transparent)
102 , renderTarget(QSGPaintedItem::Image)
103 , geometryDirty(false)
104 , contentsDirty(false)
105 , opaquePainting(false)
110 Constructs a QSGPaintedItem with the given \a parent item.
112 QSGPaintedItem::QSGPaintedItem(QSGItem *parent)
113 : QSGItem(*(new QSGPaintedItemPrivate), parent)
115 setFlag(ItemHasContents);
121 QSGPaintedItem::QSGPaintedItem(QSGPaintedItemPrivate &dd, QSGItem *parent)
122 : QSGItem(dd, parent)
124 setFlag(ItemHasContents);
128 Destroys the QSGPaintedItem.
130 QSGPaintedItem::~QSGPaintedItem()
135 Schedules a redraw of the area covered by \a rect in this item. You can call this function
136 whenever your item needs to be redrawn, such as if it changes appearance or size.
138 This function does not cause an immediate paint; instead it schedules a paint request that
139 is processed by the QML Scene Graph when the next frame is rendered. The item will only be
140 redrawn if it is visible.
142 Note that calling this function will trigger a repaint of the whole scene.
146 void QSGPaintedItem::update(const QRect &rect)
149 d->contentsDirty = true;
151 QRect srect(qCeil(rect.x()*d->contentsScale),
152 qCeil(rect.y()*d->contentsScale),
153 qCeil(rect.width()*d->contentsScale),
154 qCeil(rect.height()*d->contentsScale));
156 if (srect.isNull() && !d->dirtyRect.isNull())
157 d->dirtyRect = contentsBoundingRect().toAlignedRect();
159 d->dirtyRect |= (contentsBoundingRect() & srect).toAlignedRect();
164 Returns true if this item is opaque; otherwise, false is returned.
166 By default, painted items are not opaque.
168 \sa setOpaquePainting()
170 bool QSGPaintedItem::opaquePainting() const
172 Q_D(const QSGPaintedItem);
173 return d->opaquePainting;
177 If \a opaque is true, the item is opaque; otherwise, it is considered as translucent.
179 Opaque items are not blended with the rest of the scene, you should set this to true
180 if the content of the item is opaque to speed up rendering.
182 By default, painted items are not opaque.
186 void QSGPaintedItem::setOpaquePainting(bool opaque)
190 if (d->opaquePainting == opaque)
193 d->opaquePainting = opaque;
198 Returns true if antialiased painting is enabled; otherwise, false is returned.
200 By default, antialiasing is not enabled.
202 \sa setAntialiasing()
204 bool QSGPaintedItem::antialiasing() const
206 Q_D(const QSGPaintedItem);
207 return d->antialiasing;
211 If \a enable is true, antialiased painting is enabled.
213 By default, antialiasing is not enabled.
217 void QSGPaintedItem::setAntialiasing(bool enable)
221 if (d->antialiasing == enable)
224 d->antialiasing = enable;
229 This function returns the outer bounds of the item as a rectangle; all painting must be
230 restricted to inside an item's bounding rect.
232 If the contents size has not been set it reflects the size of the item; otherwise
233 it reflects the contents size scaled by the contents scale.
235 Use this function to know the area painted by the item.
237 \sa QSGItem::width(), QSGItem::height(), contentsSize(), contentsScale()
239 QRectF QSGPaintedItem::contentsBoundingRect() const
241 Q_D(const QSGPaintedItem);
244 QSizeF sz = d->contentsSize * d->contentsScale;
251 return QRectF(0, 0, w, h);
255 \property QSGPaintedItem::contentsSize
256 \brief The size of the contents
258 The contents size is the size of the item in regards to how it is painted
259 using the paint() function. This is distinct from the size of the
260 item in regards to height() and width().
262 QSize QSGPaintedItem::contentsSize() const
264 Q_D(const QSGPaintedItem);
265 return d->contentsSize;
268 void QSGPaintedItem::setContentsSize(const QSize &size)
272 if (d->contentsSize == size)
275 d->contentsSize = size;
280 This convenience function is equivalent to calling setContentsSize(QSize()).
282 void QSGPaintedItem::resetContentsSize()
284 setContentsSize(QSize());
288 \property QSGPaintedItem::contentsScale
289 \brief The scale of the contents
291 All painting happening in paint() is scaled by the contents scale. This is distinct
292 from the scale of the item in regards to scale().
294 The default value is 1.
296 qreal QSGPaintedItem::contentsScale() const
298 Q_D(const QSGPaintedItem);
299 return d->contentsScale;
302 void QSGPaintedItem::setContentsScale(qreal scale)
306 if (d->contentsScale == scale)
309 d->contentsScale = scale;
314 \property QSGPaintedItem::fillColor
315 \brief The item's background fill color.
317 By default, the fill color is set to Qt::transparent.
319 QColor QSGPaintedItem::fillColor() const
321 Q_D(const QSGPaintedItem);
325 void QSGPaintedItem::setFillColor(const QColor &c)
329 if (d->fillColor == c)
335 emit fillColorChanged();
339 \property QSGPaintedItem::renderTarget
340 \brief The item's render target.
342 This property defines which render target the QPainter renders into, it can be either
343 QSGPaintedItem::Image or QSGPaintedItem::FramebufferObject. Both have certains benefits,
344 typically performance versus quality. Using a framebuffer object avoids a costly upload
345 of the image contents to the texture in graphics memory, while using an image enables
346 high quality anti-aliasing.
348 \warning Resizing a framebuffer object is a costly operation, avoid using
349 the QSGPaintedItem::FramebufferObject render target if the item gets resized often.
351 By default, the render target is QSGPaintedItem::Image.
353 QSGPaintedItem::RenderTarget QSGPaintedItem::renderTarget() const
355 Q_D(const QSGPaintedItem);
356 return d->renderTarget;
359 void QSGPaintedItem::setRenderTarget(RenderTarget target)
363 if (d->renderTarget == target)
366 d->renderTarget = target;
369 emit renderTargetChanged();
373 \fn virtual void QSGPaintedItem::paint(QPainter *painter) = 0
375 This function, which is usually called by the QML Scene Graph, paints the
376 contents of an item in local coordinates.
378 The function is called after the item has been filled with the fillColor.
380 Reimplement this function in a QSGPaintedItem subclass to provide the
381 item's painting implementation, using \a painter.
385 This function is called after the item's geometry has changed.
387 void QSGPaintedItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
390 d->geometryDirty = true;
391 QSGItem::geometryChanged(newGeometry, oldGeometry);
396 This function is called when the Scene Graph node associated to the item needs to
399 QSGNode *QSGPaintedItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
404 if (width() <= 0 || height() <= 0) {
409 QSGPainterNode *node = static_cast<QSGPainterNode *>(oldNode);
411 node = new QSGPainterNode(this);
413 QRectF br = contentsBoundingRect();
415 node->setPreferredRenderTarget(d->renderTarget);
416 node->setSize(QSize(qRound(br.width()), qRound(br.height())));
417 node->setSmoothPainting(d->antialiasing);
418 node->setLinearFiltering(d->smooth);
419 node->setMipmapping(d->smooth);
420 node->setOpaquePainting(d->opaquePainting);
421 node->setFillColor(d->fillColor);
422 node->setContentsScale(d->contentsScale);
423 node->setDirty(d->contentsDirty || d->geometryDirty, d->dirtyRect);
426 d->contentsDirty = false;
427 d->geometryDirty = false;
428 d->dirtyRect = QRect();