740417a0afda5e6892f89e9a621e089a8d2e4636
[profile/ivi/qtdeclarative.git] / src / quick / items / qquickpainteditem.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
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.
17 **
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.
21 **
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.
29 **
30 ** Other Usage
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.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qquickpainteditem.h"
43 #include <private/qquickpainteditem_p.h>
44
45 #include <QtQuick/private/qsgpainternode_p.h>
46 #include <QtQuick/private/qsgcontext_p.h>
47 #include <private/qsgadaptationlayer_p.h>
48
49 #include <qmath.h>
50
51 QT_BEGIN_NAMESPACE
52
53 /*!
54     \class QQuickPaintedItem
55     \brief The QQuickPaintedItem class provides a way to use the QPainter API in the
56     QML Scene Graph.
57
58     \inmodule QtQuick
59
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.
67
68     To enable QPainter to do anti-aliased rendering, use setAntialiasing().
69
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.
72
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().
77 */
78
79 /*!
80     \enum QQuickPaintedItem::RenderTarget
81
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.
84
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.
89
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.
94
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
99     painter transform.
100
101     \sa setRenderTarget()
102 */
103
104 /*!
105     \enum QQuickPaintedItem::PerformanceHint
106
107     This enum describes flags that you can enable to improve rendering
108     performance in QQuickPaintedItem. By default, none of these flags are set.
109
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.
115 */
116
117 /*!
118     \internal
119 */
120 QQuickPaintedItemPrivate::QQuickPaintedItemPrivate()
121     : QQuickItemPrivate()
122     , contentsScale(1.0)
123     , fillColor(Qt::transparent)
124     , renderTarget(QQuickPaintedItem::Image)
125     , performanceHints(0)
126     , opaquePainting(false)
127     , antialiasing(false)
128     , mipmap(false)
129 {
130 }
131
132 /*!
133     Constructs a QQuickPaintedItem with the given \a parent item.
134  */
135 QQuickPaintedItem::QQuickPaintedItem(QQuickItem *parent)
136     : QQuickItem(*(new QQuickPaintedItemPrivate), parent)
137 {
138     setFlag(ItemHasContents);
139 }
140
141 /*!
142     \internal
143 */
144 QQuickPaintedItem::QQuickPaintedItem(QQuickPaintedItemPrivate &dd, QQuickItem *parent)
145     : QQuickItem(dd, parent)
146 {
147     setFlag(ItemHasContents);
148 }
149
150 /*!
151     Destroys the QQuickPaintedItem.
152 */
153 QQuickPaintedItem::~QQuickPaintedItem()
154 {
155 }
156
157 /*!
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.
160
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.
164
165     Note that calling this function will trigger a repaint of the whole scene.
166
167     \sa paint()
168 */
169 void QQuickPaintedItem::update(const QRect &rect)
170 {
171     Q_D(QQuickPaintedItem);
172
173     if (rect.isNull() && !d->dirtyRect.isNull())
174         d->dirtyRect = contentsBoundingRect().toAlignedRect();
175     else
176         d->dirtyRect |= (contentsBoundingRect() & rect).toAlignedRect();
177     QQuickItem::update();
178 }
179
180 /*!
181     Returns true if this item is opaque; otherwise, false is returned.
182
183     By default, painted items are not opaque.
184
185     \sa setOpaquePainting()
186 */
187 bool QQuickPaintedItem::opaquePainting() const
188 {
189     Q_D(const QQuickPaintedItem);
190     return d->opaquePainting;
191 }
192
193 /*!
194     If \a opaque is true, the item is opaque; otherwise, it is considered as translucent.
195
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.
198
199     By default, painted items are not opaque.
200
201     \sa opaquePainting()
202 */
203 void QQuickPaintedItem::setOpaquePainting(bool opaque)
204 {
205     Q_D(QQuickPaintedItem);
206
207     if (d->opaquePainting == opaque)
208         return;
209
210     d->opaquePainting = opaque;
211     QQuickItem::update();
212 }
213
214 /*!
215     Returns true if antialiased painting is enabled; otherwise, false is returned.
216
217     By default, antialiasing is not enabled.
218
219     \sa setAntialiasing()
220 */
221 bool QQuickPaintedItem::antialiasing() const
222 {
223     Q_D(const QQuickPaintedItem);
224     return d->antialiasing;
225 }
226
227 /*!
228     If \a enable is true, antialiased painting is enabled.
229
230     By default, antialiasing is not enabled.
231
232     \sa antialiasing()
233 */
234 void QQuickPaintedItem::setAntialiasing(bool enable)
235 {
236     Q_D(QQuickPaintedItem);
237
238     if (d->antialiasing == enable)
239         return;
240
241     d->antialiasing = enable;
242     update();
243 }
244
245 /*!
246     Returns true if mipmaps are enabled; otherwise, false is returned.
247
248     By default, mipmapping is not enabled.
249
250     \sa setMipmap()
251 */
252 bool QQuickPaintedItem::mipmap() const
253 {
254     Q_D(const QQuickPaintedItem);
255     return d->mipmap;
256 }
257
258 /*!
259     If \a enable is true, mipmapping is enabled on the associated texture.
260
261     Mipmapping increases rendering speed and reduces aliasing artifacts when the item is
262     scaled down.
263
264     By default, mipmapping is not enabled.
265
266     \sa mipmap()
267 */
268 void QQuickPaintedItem::setMipmap(bool enable)
269 {
270     Q_D(QQuickPaintedItem);
271
272     if (d->mipmap == enable)
273         return;
274
275     d->mipmap = enable;
276     update();
277 }
278
279 /*!
280     Returns the performance hints.
281
282     By default, no performance hint is enabled/
283
284     \sa setPerformanceHint(), setPerformanceHints()
285 */
286 QQuickPaintedItem::PerformanceHints QQuickPaintedItem::performanceHints() const
287 {
288     Q_D(const QQuickPaintedItem);
289     return d->performanceHints;
290 }
291
292 /*!
293     Sets the given performance \a hint on the item if \a enabled is true;
294     otherwise clears the performance hint.
295
296     By default, no performance hint is enabled/
297
298     \sa setPerformanceHints(), performanceHints()
299 */
300 void QQuickPaintedItem::setPerformanceHint(QQuickPaintedItem::PerformanceHint hint, bool enabled)
301 {
302     Q_D(QQuickPaintedItem);
303     PerformanceHints oldHints = d->performanceHints;
304     if (enabled)
305         d->performanceHints |= hint;
306     else
307         d->performanceHints &= ~hint;
308     if (oldHints != d->performanceHints)
309        update();
310 }
311
312 /*!
313     Sets the performance hints to \a hints
314
315     By default, no performance hint is enabled/
316
317     \sa setPerformanceHint(), performanceHints()
318 */
319 void QQuickPaintedItem::setPerformanceHints(QQuickPaintedItem::PerformanceHints hints)
320 {
321     Q_D(QQuickPaintedItem);
322     if (d->performanceHints == hints)
323         return;
324     d->performanceHints = hints;
325     update();
326 }
327
328 /*!
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.
331
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.
334
335     Use this function to know the area painted by the item.
336
337     \sa QQuickItem::width(), QQuickItem::height(), contentsSize(), contentsScale()
338 */
339 QRectF QQuickPaintedItem::contentsBoundingRect() const
340 {
341     Q_D(const QQuickPaintedItem);
342
343     qreal w = d->width;
344     QSizeF sz = d->contentsSize * d->contentsScale;
345     if (w < sz.width())
346         w = sz.width();
347     qreal h = d->height;
348     if (h < sz.height())
349         h = sz.height();
350
351     return QRectF(0, 0, w, h);
352 }
353
354 /*!
355     \property QQuickPaintedItem::contentsSize
356     \brief The size of the contents
357
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().
361 */
362 QSize QQuickPaintedItem::contentsSize() const
363 {
364     Q_D(const QQuickPaintedItem);
365     return d->contentsSize;
366 }
367
368 void QQuickPaintedItem::setContentsSize(const QSize &size)
369 {
370     Q_D(QQuickPaintedItem);
371
372     if (d->contentsSize == size)
373         return;
374
375     d->contentsSize = size;
376     update();
377 }
378
379 /*!
380     This convenience function is equivalent to calling setContentsSize(QSize()).
381 */
382 void QQuickPaintedItem::resetContentsSize()
383 {
384     setContentsSize(QSize());
385 }
386
387 /*!
388     \property QQuickPaintedItem::contentsScale
389     \brief The scale of the contents
390
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().
393
394     The default value is 1.
395 */
396 qreal QQuickPaintedItem::contentsScale() const
397 {
398     Q_D(const QQuickPaintedItem);
399     return d->contentsScale;
400 }
401
402 void QQuickPaintedItem::setContentsScale(qreal scale)
403 {
404     Q_D(QQuickPaintedItem);
405
406     if (d->contentsScale == scale)
407         return;
408
409     d->contentsScale = scale;
410     update();
411 }
412
413 /*!
414     \property QQuickPaintedItem::fillColor
415     \brief The item's background fill color.
416
417     By default, the fill color is set to Qt::transparent.
418 */
419 QColor QQuickPaintedItem::fillColor() const
420 {
421     Q_D(const QQuickPaintedItem);
422     return d->fillColor;
423 }
424
425 void QQuickPaintedItem::setFillColor(const QColor &c)
426 {
427     Q_D(QQuickPaintedItem);
428
429     if (d->fillColor == c)
430         return;
431
432     d->fillColor = c;
433     update();
434
435     emit fillColorChanged();
436 }
437
438 /*!
439     \property QQuickPaintedItem::renderTarget
440     \brief The item's render target.
441
442     This property defines which render target the QPainter renders into, it can be either
443     QSGPaintedItem::Image, QSGPaintedItem::FramebufferObject or QSGPaintedItem::InvertedYFramebufferObject.
444
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.
448
449     \warning Resizing a framebuffer object is a costly operation, avoid using
450     the QQuickPaintedItem::FramebufferObject render target if the item gets resized often.
451
452     By default, the render target is QQuickPaintedItem::Image.
453 */
454 QQuickPaintedItem::RenderTarget QQuickPaintedItem::renderTarget() const
455 {
456     Q_D(const QQuickPaintedItem);
457     return d->renderTarget;
458 }
459
460 void QQuickPaintedItem::setRenderTarget(RenderTarget target)
461 {
462     Q_D(QQuickPaintedItem);
463
464     if (d->renderTarget == target)
465         return;
466
467     d->renderTarget = target;
468     update();
469
470     emit renderTargetChanged();
471 }
472
473 /*!
474     \fn virtual void QQuickPaintedItem::paint(QPainter *painter) = 0
475
476     This function, which is usually called by the QML Scene Graph, paints the
477     contents of an item in local coordinates.
478
479     The function is called after the item has been filled with the fillColor.
480
481     Reimplement this function in a QQuickPaintedItem subclass to provide the
482     item's painting implementation, using \a painter.
483
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.
489 */
490
491 /*!
492     This function is called when the Scene Graph node associated to the item needs to
493     be updated.
494 */
495 QSGNode *QQuickPaintedItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
496 {
497     Q_UNUSED(data);
498     Q_D(QQuickPaintedItem);
499
500     if (width() <= 0 || height() <= 0) {
501         delete oldNode;
502         return 0;
503     }
504
505     QSGPainterNode *node = static_cast<QSGPainterNode *>(oldNode);
506     if (!node)
507         node = new QSGPainterNode(this);
508
509     QRectF br = contentsBoundingRect();
510
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);
521     node->update();
522
523     d->dirtyRect = QRect();
524
525     return node;
526 }
527
528 QT_END_NAMESPACE