Fix test fails related to QTBUG-22237
[profile/ivi/qtdeclarative.git] / src / declarative / items / qsgpainteditem.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
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 "qsgpainteditem.h"
43 #include <private/qsgpainteditem_p.h>
44 #include <private/qsgpainternode_p.h>
45
46 #include <private/qsgcontext_p.h>
47 #include <private/qsgadaptationlayer_p.h>
48 #include <qmath.h>
49
50 QT_BEGIN_NAMESPACE
51
52 /*!
53     \class QSGPaintedItem
54     \brief The QSGPaintedItem class provides a way to use the QPainter API in the
55     QML Scene Graph.
56
57     \inmodule QtDeclarative
58
59     The QSGPaintedItem makes it possible to use the QPainter API with the QML Scene Graph.
60     It sets up a textured rectangle in the Scene Graph and uses a QPainter to paint
61     onto the texture. The render target can be either a QImage or a QOpenGLFramebufferObject.
62     When the render target is a QImage, QPainter first renders into the image then
63     the content is uploaded to the texture.
64     When a QOpenGLFramebufferObject is used, QPainter paints directly onto the texture.
65     Call update() to trigger a repaint.
66
67     To enable QPainter to do anti-aliased rendering, use setAntialiasing().
68
69     QSGPaintedItem is meant to make it easier to port old code that is using the
70     QPainter API to the QML Scene Graph API and it should be used only for that purpose.
71
72     To write your own painted item, you first create a subclass of QSGPaintedItem, and then
73     start by implementing its only pure virtual public function: paint(), which implements
74     the actual painting. To get the size of the area painted by the item, use
75     contentsBoundingRect().
76 */
77
78 /*!
79     \enum QSGPaintedItem::RenderTarget
80
81     This enum describes QSGPaintedItem's render targets. The render target is the
82     surface QPainter paints onto before the item is rendered on screen.
83
84     \value Image The default; QPainter paints into a QImage using the raster paint engine.
85     The image's content needs to be uploaded to graphics memory afterward, this operation
86     can potentially be slow if the item is large. This render target allows high quality
87     anti-aliasing and fast item resizing.
88
89     \value FramebufferObject QPainter paints into a QOpenGLFramebufferObject using the GL
90     paint engine. Painting can be faster as no texture upload is required, but anti-aliasing
91     quality is not as good as if using an image. This render target allows faster rendering
92     in some cases, but you should avoid using it if the item is resized often.
93
94     \sa setRenderTarget()
95 */
96
97 /*!
98     \enum QSGPaintedItem::PerformanceHint
99
100     This enum describes flags that you can enable to improve rendering
101     performance in QSGPaintedItem. By default, none of these flags are set.
102
103     \value FastFBOResizing If your item gets resized often and you are using the
104     QSGPaintedItem::FramebufferObject render target, set this flag to true to reduce the
105     item resizing time at the cost of using more graphics memory. Resizing a Framebuffer object
106     is a costly operation, by enabling this property the Framebuffer Object will use a texture
107     larger than the actual size of the item to avoid as much as possible resizing it.
108 */
109
110 /*!
111     \internal
112 */
113 QSGPaintedItemPrivate::QSGPaintedItemPrivate()
114     : QSGItemPrivate()
115     , contentsScale(1.0)
116     , fillColor(Qt::transparent)
117     , renderTarget(QSGPaintedItem::Image)
118     , performanceHints(0)
119     , geometryDirty(false)
120     , contentsDirty(false)
121     , opaquePainting(false)
122     , antialiasing(false)
123     , mipmap(false)
124 {
125 }
126
127 /*!
128     Constructs a QSGPaintedItem with the given \a parent item.
129  */
130 QSGPaintedItem::QSGPaintedItem(QSGItem *parent)
131     : QSGItem(*(new QSGPaintedItemPrivate), parent)
132 {
133     setFlag(ItemHasContents);
134 }
135
136 /*!
137     \internal
138 */
139 QSGPaintedItem::QSGPaintedItem(QSGPaintedItemPrivate &dd, QSGItem *parent)
140     : QSGItem(dd, parent)
141 {
142     setFlag(ItemHasContents);
143 }
144
145 /*!
146     Destroys the QSGPaintedItem.
147 */
148 QSGPaintedItem::~QSGPaintedItem()
149 {
150 }
151
152 /*!
153     Schedules a redraw of the area covered by \a rect in this item. You can call this function
154     whenever your item needs to be redrawn, such as if it changes appearance or size.
155
156     This function does not cause an immediate paint; instead it schedules a paint request that
157     is processed by the QML Scene Graph when the next frame is rendered. The item will only be
158     redrawn if it is visible.
159
160     Note that calling this function will trigger a repaint of the whole scene.
161
162     \sa paint()
163 */
164 void QSGPaintedItem::update(const QRect &rect)
165 {
166     Q_D(QSGPaintedItem);
167     d->contentsDirty = true;
168
169     if (rect.isNull() && !d->dirtyRect.isNull())
170         d->dirtyRect = contentsBoundingRect().toAlignedRect();
171     else
172         d->dirtyRect |= (contentsBoundingRect() & rect).toAlignedRect();
173     QSGItem::update();
174 }
175
176 /*!
177     Returns true if this item is opaque; otherwise, false is returned.
178
179     By default, painted items are not opaque.
180
181     \sa setOpaquePainting()
182 */
183 bool QSGPaintedItem::opaquePainting() const
184 {
185     Q_D(const QSGPaintedItem);
186     return d->opaquePainting;
187 }
188
189 /*!
190     If \a opaque is true, the item is opaque; otherwise, it is considered as translucent.
191
192     Opaque items are not blended with the rest of the scene, you should set this to true
193     if the content of the item is opaque to speed up rendering.
194
195     By default, painted items are not opaque.
196
197     \sa opaquePainting()
198 */
199 void QSGPaintedItem::setOpaquePainting(bool opaque)
200 {
201     Q_D(QSGPaintedItem);
202
203     if (d->opaquePainting == opaque)
204         return;
205
206     d->opaquePainting = opaque;
207     QSGItem::update();
208 }
209
210 /*!
211     Returns true if antialiased painting is enabled; otherwise, false is returned.
212
213     By default, antialiasing is not enabled.
214
215     \sa setAntialiasing()
216 */
217 bool QSGPaintedItem::antialiasing() const
218 {
219     Q_D(const QSGPaintedItem);
220     return d->antialiasing;
221 }
222
223 /*!
224     If \a enable is true, antialiased painting is enabled.
225
226     By default, antialiasing is not enabled.
227
228     \sa antialiasing()
229 */
230 void QSGPaintedItem::setAntialiasing(bool enable)
231 {
232     Q_D(QSGPaintedItem);
233
234     if (d->antialiasing == enable)
235         return;
236
237     d->antialiasing = enable;
238     update();
239 }
240
241 /*!
242     Returns true if mipmaps are enabled; otherwise, false is returned.
243
244     By default, mipmapping is not enabled.
245
246     \sa setMipmap()
247 */
248 bool QSGPaintedItem::mipmap() const
249 {
250     Q_D(const QSGPaintedItem);
251     return d->mipmap;
252 }
253
254 /*!
255     If \a enable is true, mipmapping is enabled on the associated texture.
256
257     Mipmapping increases rendering speed and reduces aliasing artifacts when the item is
258     scaled down.
259
260     By default, mipmapping is not enabled.
261
262     \sa mipmap()
263 */
264 void QSGPaintedItem::setMipmap(bool enable)
265 {
266     Q_D(QSGPaintedItem);
267
268     if (d->mipmap == enable)
269         return;
270
271     d->mipmap = enable;
272     update();
273 }
274
275 /*!
276     Returns the performance hints.
277
278     By default, no performance hint is enabled/
279
280     \sa setPerformanceHint(), setPerformanceHints()
281 */
282 QSGPaintedItem::PerformanceHints QSGPaintedItem::performanceHints() const
283 {
284     Q_D(const QSGPaintedItem);
285     return d->performanceHints;
286 }
287
288 /*!
289     Sets the given performance \a hint on the item if \a enabled is true;
290     otherwise clears the performance hint.
291
292     By default, no performance hint is enabled/
293
294     \sa setPerformanceHints(), performanceHints()
295 */
296 void QSGPaintedItem::setPerformanceHint(QSGPaintedItem::PerformanceHint hint, bool enabled)
297 {
298     Q_D(QSGPaintedItem);
299     PerformanceHints oldHints = d->performanceHints;
300     if (enabled)
301         d->performanceHints |= hint;
302     else
303         d->performanceHints &= ~hint;
304     if (oldHints != d->performanceHints)
305        update();
306 }
307
308 /*!
309     Sets the performance hints to \a hints
310
311     By default, no performance hint is enabled/
312
313     \sa setPerformanceHint(), performanceHints()
314 */
315 void QSGPaintedItem::setPerformanceHints(QSGPaintedItem::PerformanceHints hints)
316 {
317     Q_D(QSGPaintedItem);
318     if (d->performanceHints == hints)
319         return;
320     d->performanceHints = hints;
321     update();
322 }
323
324 /*!
325     This function returns the outer bounds of the item as a rectangle; all painting must be
326     restricted to inside an item's bounding rect.
327
328     If the contents size has not been set it reflects the size of the item; otherwise
329     it reflects the contents size scaled by the contents scale.
330
331     Use this function to know the area painted by the item.
332
333     \sa QSGItem::width(), QSGItem::height(), contentsSize(), contentsScale()
334 */
335 QRectF QSGPaintedItem::contentsBoundingRect() const
336 {
337     Q_D(const QSGPaintedItem);
338
339     qreal w = d->width;
340     QSizeF sz = d->contentsSize * d->contentsScale;
341     if (w < sz.width())
342         w = sz.width();
343     qreal h = d->height;
344     if (h < sz.height())
345         h = sz.height();
346
347     return QRectF(0, 0, w, h);
348 }
349
350 /*!
351     \property QSGPaintedItem::contentsSize
352     \brief The size of the contents
353
354     The contents size is the size of the item in regards to how it is painted
355     using the paint() function.  This is distinct from the size of the
356     item in regards to height() and width().
357 */
358 QSize QSGPaintedItem::contentsSize() const
359 {
360     Q_D(const QSGPaintedItem);
361     return d->contentsSize;
362 }
363
364 void QSGPaintedItem::setContentsSize(const QSize &size)
365 {
366     Q_D(QSGPaintedItem);
367
368     if (d->contentsSize == size)
369         return;
370
371     d->contentsSize = size;
372     update();
373 }
374
375 /*!
376     This convenience function is equivalent to calling setContentsSize(QSize()).
377 */
378 void QSGPaintedItem::resetContentsSize()
379 {
380     setContentsSize(QSize());
381 }
382
383 /*!
384     \property QSGPaintedItem::contentsScale
385     \brief The scale of the contents
386
387     All painting happening in paint() is scaled by the contents scale. This is distinct
388     from the scale of the item in regards to scale().
389
390     The default value is 1.
391 */
392 qreal QSGPaintedItem::contentsScale() const
393 {
394     Q_D(const QSGPaintedItem);
395     return d->contentsScale;
396 }
397
398 void QSGPaintedItem::setContentsScale(qreal scale)
399 {
400     Q_D(QSGPaintedItem);
401
402     if (d->contentsScale == scale)
403         return;
404
405     d->contentsScale = scale;
406     update();
407 }
408
409 /*!
410     \property QSGPaintedItem::fillColor
411     \brief The item's background fill color.
412
413     By default, the fill color is set to Qt::transparent.
414 */
415 QColor QSGPaintedItem::fillColor() const
416 {
417     Q_D(const QSGPaintedItem);
418     return d->fillColor;
419 }
420
421 void QSGPaintedItem::setFillColor(const QColor &c)
422 {
423     Q_D(QSGPaintedItem);
424
425     if (d->fillColor == c)
426         return;
427
428     d->fillColor = c;
429     update();
430
431     emit fillColorChanged();
432 }
433
434 /*!
435     \property QSGPaintedItem::renderTarget
436     \brief The item's render target.
437
438     This property defines which render target the QPainter renders into, it can be either
439     QSGPaintedItem::Image or QSGPaintedItem::FramebufferObject. Both have certains benefits,
440     typically performance versus quality. Using a framebuffer object avoids a costly upload
441     of the image contents to the texture in graphics memory, while using an image enables
442     high quality anti-aliasing.
443
444     \warning Resizing a framebuffer object is a costly operation, avoid using
445     the QSGPaintedItem::FramebufferObject render target if the item gets resized often.
446
447     By default, the render target is QSGPaintedItem::Image.
448 */
449 QSGPaintedItem::RenderTarget QSGPaintedItem::renderTarget() const
450 {
451     Q_D(const QSGPaintedItem);
452     return d->renderTarget;
453 }
454
455 void QSGPaintedItem::setRenderTarget(RenderTarget target)
456 {
457     Q_D(QSGPaintedItem);
458
459     if (d->renderTarget == target)
460         return;
461
462     d->renderTarget = target;
463     update();
464
465     emit renderTargetChanged();
466 }
467
468 /*!
469     \fn virtual void QSGPaintedItem::paint(QPainter *painter) = 0
470
471     This function, which is usually called by the QML Scene Graph, paints the
472     contents of an item in local coordinates.
473
474     The function is called after the item has been filled with the fillColor.
475
476     Reimplement this function in a QSGPaintedItem subclass to provide the
477     item's painting implementation, using \a painter.
478
479     \note The QML Scene Graph uses two separate threads, the main thread does things such as
480     processing events or updating animations while a second thread does the actual OpenGL rendering.
481     As a consequence, paint() is not called from the main GUI thread but from the GL enabled
482     renderer thread. At the moment paint() is called, the GUI thread is blocked and this is
483     therefore thread-safe.
484 */
485
486 /*!
487     This function is called after the item's geometry has changed.
488 */
489 void QSGPaintedItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
490 {
491     Q_D(QSGPaintedItem);
492     d->geometryDirty = true;
493     QSGItem::geometryChanged(newGeometry, oldGeometry);
494 }
495
496
497 /*!
498     This function is called when the Scene Graph node associated to the item needs to
499     be updated.
500 */
501 QSGNode *QSGPaintedItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
502 {
503     Q_UNUSED(data);
504     Q_D(QSGPaintedItem);
505
506     if (width() <= 0 || height() <= 0) {
507         delete oldNode;
508         return 0;
509     }
510
511     QSGPainterNode *node = static_cast<QSGPainterNode *>(oldNode);
512     if (!node)
513         node = new QSGPainterNode(this);
514
515     QRectF br = contentsBoundingRect();
516
517     node->setPreferredRenderTarget(d->renderTarget);
518     node->setFastFBOResizing(d->performanceHints & FastFBOResizing);
519     node->setSize(QSize(qRound(br.width()), qRound(br.height())));
520     node->setSmoothPainting(d->antialiasing);
521     node->setLinearFiltering(d->smooth);
522     node->setMipmapping(d->mipmap);
523     node->setOpaquePainting(d->opaquePainting);
524     node->setFillColor(d->fillColor);
525     node->setContentsScale(d->contentsScale);
526     node->setDirty(d->contentsDirty || d->geometryDirty, d->dirtyRect);
527     node->update();
528
529     d->contentsDirty = false;
530     d->geometryDirty = false;
531     d->dirtyRect = QRect();
532
533     return node;
534 }
535
536 QT_END_NAMESPACE