Qt 4.8
qdeclarativepainteditem.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "private/qdeclarativepainteditem_p.h"
43 #include "private/qdeclarativepainteditem_p_p.h"
44 
45 #include <QDebug>
46 #include <QPen>
47 #include <QEvent>
48 #include <QApplication>
49 #include <QGraphicsSceneMouseEvent>
50 #include <QPainter>
51 #include <QPaintEngine>
52 #include <qmath.h>
53 
55 
94 // XXX bug in WebKit - can call repaintRequested and other cache-changing functions from within render!
95 static int inpaint=0;
96 static int inpaint_clearcache=0;
97 
99 
107 {
109  QRect srect(qCeil(rect.x()*d->contentsScale),
110  qCeil(rect.y()*d->contentsScale),
111  qCeil(rect.width()*d->contentsScale),
112  qCeil(rect.height()*d->contentsScale));
113  for (int i=0; i < d->imagecache.count(); ) {
115  QRect isect = (c->area & srect) | c->dirty;
116  if (isect == c->area && !inpaint) {
117  delete d->imagecache.takeAt(i);
118  } else {
119  c->dirty = isect;
120  ++i;
121  }
122  }
123 }
124 
131 {
132  if (inpaint) {
134  return;
135  }
137  qDeleteAll(d->imagecache);
138  d->imagecache.clear();
139 }
140 
147 {
149  return d->contentsSize;
150 }
151 
158 {
160  if (d->contentsSize == size) return;
162  d->contentsSize = size;
163  clearCache();
164  update();
166 }
167 
169 {
171  return d->contentsScale;
172 }
173 
175 {
177  if (d->contentsScale == scale) return;
178  d->contentsScale = scale;
179  clearCache();
180  update();
182 }
183 
184 
190 {
191 }
192 
202  : QDeclarativeItem(dd, parent)
203 {
204 }
205 
210 {
211  clearCache();
212 }
213 
215  const QRectF &oldGeometry)
216 {
217  if (newGeometry.width() != oldGeometry.width() ||
218  newGeometry.height() != oldGeometry.height())
219  clearCache();
220 
221  QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
222 }
223 
225  const QVariant &value)
226 {
227  if (change == ItemVisibleHasChanged)
228  clearCache();
229 
230  return QDeclarativeItem::itemChange(change, value);
231 }
232 
234 {
236  if (d->cachefrozen == frozen)
237  return;
238  d->cachefrozen = frozen;
239  // XXX clear cache?
240 }
241 
243 {
245  qreal w = d->mWidth;
246  QSizeF sz = d->contentsSize * d->contentsScale;
247  if (w < sz.width())
248  w = sz.width();
249  qreal h = d->mHeight;
250  if (h < sz.height())
251  h = sz.height();
252  return QRectF(0.0,0.0,w,h);
253 }
254 
259 {
261  const QRect content = boundingRect().toRect();
262  if (content.width() <= 0 || content.height() <= 0)
263  return;
264 
265  ++inpaint;
266 
267  const QTransform &x = p->deviceTransform();
268  QTransform xinv = x.inverted();
269  QRegion effectiveClip;
270  QRegion sysClip = p->paintEngine()->systemClip();
271  if (xinv.type() <= QTransform::TxScale && sysClip.numRects() < 5) {
272  // simple transform, region gets no more complicated...
273  effectiveClip = xinv.map(sysClip);
274  } else {
275  // do not make complicated regions...
276  effectiveClip = xinv.mapRect(sysClip.boundingRect());
277  }
278 
279  QRegion topaint = p->clipRegion();
280  if (topaint.isEmpty()) {
281  if (effectiveClip.isEmpty())
282  topaint = QRect(0,0,p->device()->width(),p->device()->height());
283  else
284  topaint = effectiveClip;
285  } else if (!effectiveClip.isEmpty()) {
286  topaint &= effectiveClip;
287  }
288 
289  topaint &= content;
290  QRegion uncached(content);
292 
293  int cachesize=0;
294  for (int i=0; i<d->imagecache.count(); ++i) {
295  QRect area = d->imagecache[i]->area;
296  if (topaint.contains(area)) {
297  QRectF target(area.x(), area.y(), area.width(), area.height());
298  if (!d->cachefrozen) {
299  if (!d->imagecache[i]->dirty.isNull() && topaint.contains(d->imagecache[i]->dirty)) {
300 #ifdef Q_WS_MAC
301  bool oldSmooth = qt_applefontsmoothing_enabled;
303 #endif
304  QPainter qp(&d->imagecache[i]->image);
305 #ifdef Q_WS_MAC
306  qt_applefontsmoothing_enabled = oldSmooth;
307 #endif
309  qp.translate(-area.x(), -area.y());
310  qp.scale(d->contentsScale,d->contentsScale);
311  QRect clip = d->imagecache[i]->dirty;
312  QRect sclip(qFloor(clip.x()/d->contentsScale),
313  qFloor(clip.y()/d->contentsScale),
314  qCeil(clip.width()/d->contentsScale+clip.x()/d->contentsScale-qFloor(clip.x()/d->contentsScale)),
315  qCeil(clip.height()/d->contentsScale+clip.y()/d->contentsScale-qFloor(clip.y()/d->contentsScale)));
316  qp.setClipRect(sclip);
317  if (d->fillColor.isValid()){
318  if(d->fillColor.alpha() < 255){
319  // ### Might not work outside of raster paintengine
322  qp.fillRect(sclip,d->fillColor);
323  qp.setCompositionMode(prev);
324  }else{
325  qp.fillRect(sclip,d->fillColor);
326  }
327  }
328  drawContents(&qp, sclip);
329  d->imagecache[i]->dirty = QRect();
330  }
331  }
332  p->drawPixmap(target.toRect(), d->imagecache[i]->image);
333  topaint -= area;
334  d->imagecache[i]->age=0;
335  } else {
336  d->imagecache[i]->age++;
337  }
338  cachesize += area.width()*area.height();
339  uncached -= area;
340  }
341 
342  if (!topaint.isEmpty()) {
343  if (!d->cachefrozen) {
344  // Find a sensible larger area, otherwise will paint lots of tiny images.
345  QRect biggerrect = topaint.boundingRect().adjusted(-64,-64,128,128);
346  cachesize += biggerrect.width() * biggerrect.height();
347  while (d->imagecache.count() && cachesize > d->max_imagecache_size) {
348  int oldest=-1;
349  int age=-1;
350  for (int i=0; i<d->imagecache.count(); ++i) {
351  int a = d->imagecache[i]->age;
352  if (a > age) {
353  oldest = i;
354  age = a;
355  }
356  }
357  cachesize -= d->imagecache[oldest]->area.width()*d->imagecache[oldest]->area.height();
358  uncached += d->imagecache[oldest]->area;
359  delete d->imagecache.takeAt(oldest);
360  }
361  const QRegion bigger = QRegion(biggerrect) & uncached;
362  const QVector<QRect> rects = bigger.rects();
363  for (int i = 0; i < rects.count(); ++i) {
364  const QRect &r = rects.at(i);
365  QPixmap img(r.size());
366  if (d->fillColor.isValid())
367  img.fill(d->fillColor);
368  {
369 #ifdef Q_WS_MAC
370  bool oldSmooth = qt_applefontsmoothing_enabled;
372 #endif
373  QPainter qp(&img);
374 #ifdef Q_WS_MAC
375  qt_applefontsmoothing_enabled = oldSmooth;
376 #endif
378 
379  qp.translate(-r.x(),-r.y());
380  qp.scale(d->contentsScale,d->contentsScale);
381  QRect sclip(qFloor(r.x()/d->contentsScale),
382  qFloor(r.y()/d->contentsScale),
383  qCeil(r.width()/d->contentsScale+r.x()/d->contentsScale-qFloor(r.x()/d->contentsScale)),
384  qCeil(r.height()/d->contentsScale+r.y()/d->contentsScale-qFloor(r.y()/d->contentsScale)));
385  drawContents(&qp, sclip);
386  }
388  newitem->area = r;
389  newitem->image = img;
390  d->imagecache.append(newitem);
391  p->drawPixmap(r, newitem->image);
392  }
393  } else {
394  const QVector<QRect> rects = uncached.rects();
395  for (int i = 0; i < rects.count(); ++i)
396  p->fillRect(rects.at(i), Qt::lightGray);
397  }
398  }
399 
400  if (inpaint_clearcache) {
401  clearCache();
402  inpaint_clearcache = 0;
403  }
404 
405  --inpaint;
406 }
407 
429 {
431  return d->max_imagecache_size;
432 }
433 
435 {
437  if (pixels < d->max_imagecache_size) {
438  int cachesize=0;
439  for (int i=0; i<d->imagecache.count(); ++i) {
440  QRect area = d->imagecache[i]->area;
441  cachesize += area.width()*area.height();
442  }
443  while (d->imagecache.count() && cachesize > pixels) {
444  int oldest=-1;
445  int age=-1;
446  for (int i=0; i<d->imagecache.count(); ++i) {
447  int a = d->imagecache[i]->age;
448  if (a > age) {
449  oldest = i;
450  age = a;
451  }
452  }
453  cachesize -= d->imagecache[oldest]->area.width()*d->imagecache[oldest]->area.height();
454  delete d->imagecache.takeAt(oldest);
455  }
456  }
457  d->max_imagecache_size = pixels;
458 }
459 
460 
461 
475 {
477  if (d->fillColor == c)
478  return;
479  d->fillColor = c;
481  update();
482 }
483 
485 {
487  return d->fillColor;
488 }
489 
503 {
505  return d->smoothCache;
506 }
507 
509 {
511  if (d->smoothCache != on) {
512  d->smoothCache = on;
513  clearCache();
514  }
515 }
516 
517 
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
The QPainter class performs low-level painting on widgets and other paint devices.
Definition: qpainter.h:86
QPaintDevice * device() const
Returns the paint device on which this painter is currently painting, or 0 if the painter is not acti...
Definition: qpainter.cpp:1530
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition: qcolor.h:67
static int inpaint_clearcache
QT_DEPRECATED int numRects() const
Returns the number of rectangles that will be returned in rects().
Definition: qregion.cpp:4456
QRect adjusted(int x1, int y1, int x2, int y2) const
Returns a new rectangle with dx1, dy1, dx2 and dy2 added respectively to the existing coordinates of ...
Definition: qrect.h:431
static int inpaint
double qreal
Definition: qglobal.h:1193
unsigned char c[8]
Definition: qnumeric_p.h:62
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
QDeclarativePaintedItem(QDeclarativeItem *parent=0)
Constructs a new QDeclarativePaintedItem with the given parent.
QDeclarativeParserStatus ** d
CompositionMode
Defines the modes supported for digital image compositing.
Definition: qpainter.h:138
int qCeil(qreal v)
Definition: qmath.h:63
int count(const T &t) const
Returns the number of occurrences of value in the vector.
Definition: qvector.h:742
int qFloor(qreal v)
Definition: qmath.h:73
qreal contentsScale() const
qreal width() const
Returns the width.
Definition: qsize.h:284
#define Q_GUI_EXPORT
Definition: qglobal.h:1450
int height() const
Definition: qpaintdevice.h:92
void setClipRect(const QRectF &, Qt::ClipOperation op=Qt::ReplaceClip)
Enables clipping, and sets the clip region to the given rectangle using the given clip operation...
Definition: qpainter.cpp:2801
void setContentsSize(const QSize &)
Sets the size of the contents to the given size.
qreal height() const
Returns the height.
Definition: qsize.h:287
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
virtual void drawContents(QPainter *p, const QRect &)=0
This function is called when the cache needs to be refreshed.
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
long ASN1_INTEGER_get ASN1_INTEGER * a
GraphicsItemChange
This enum describes the state changes that are notified by QGraphicsItem::itemChange().
QRect boundingRect() const
Returns the bounding rectangle of this region.
Definition: qregion.cpp:4363
Q_GUI_EXPORT bool qt_applefontsmoothing_enabled
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
void update(const QRectF &rect=QRectF())
Schedules a redraw of the area covered by rect in this item.
~QDeclarativePaintedItem()
Destroys the image item.
TransformationType type() const
Returns the transformation type of this matrix.
#define Q_D(Class)
Definition: qglobal.h:2482
The QSizeF class defines the size of a two-dimensional object using floating point precision...
Definition: qsize.h:202
QTransform inverted(bool *invertible=0) const
Returns an inverted copy of this matrix.
Definition: qtransform.cpp:364
qreal scale() const
Returns the scale factor of the item.
The QDeclarativePaintedItem class is an abstract base class for QDeclarativeView items that want cach...
QRegion clipRegion() const
Returns the currently set clip region.
Definition: qpainter.cpp:2562
QRect mapRect(const QRect &) const
Creates and returns a QRect object that is a copy of the given rectangle, mapped into the coordinate ...
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
int width() const
Definition: qpaintdevice.h:91
The QRectF class defines a rectangle in the plane using floating point precision. ...
Definition: qrect.h:511
The QDeclarativeItem class provides the most basic of all visual items in QML.
bool isEmpty() const
Returns true if the region is empty; otherwise returns false.
Definition: qregion.cpp:4098
qreal height() const
Returns the height of the rectangle.
Definition: qrect.h:710
QSize size() const
Returns the size of the rectangle.
Definition: qrect.h:309
#define emit
Definition: qobjectdefs.h:76
CompositionMode compositionMode() const
Returns the current composition mode.
Definition: qpainter.cpp:2466
QColor fillColor() const
QPoint map(const QPoint &p) const
Creates and returns a QPoint object that is a copy of the given point, mapped into the coordinate sys...
bool clip() const
bool contains(const QPoint &p) const
Returns true if the region contains the point p; otherwise returns false.
Definition: qregion.cpp:4104
const QTransform & deviceTransform() const
Returns the matrix that transforms from logical coordinates to device coordinates of the platform dep...
Definition: qpainter.cpp:9579
qreal width() const
Returns the width of the rectangle.
Definition: qrect.h:707
QPaintEngine * paintEngine() const
Returns the paint engine that the painter is currently operating on if the painter is active; otherwi...
Definition: qpainter.cpp:1991
The QRegion class specifies a clip region for a painter.
Definition: qregion.h:68
void dirtyCache(const QRect &)
Marks areas of the cache that intersect with the given rect as dirty and in need of being refreshed...
QSize contentsSize() const
virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
This function is called to handle this item&#39;s changes in geometry from oldGeometry to newGeometry...
QRect toRect() const
Returns a QRect based on the values of this rectangle.
Definition: qrect.h:845
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
void fill(const QColor &fillColor=Qt::white)
Fills the pixmap with the given color.
Definition: qpixmap.cpp:1080
void setRenderHints(RenderHints hints, bool on=true)
Sets the given render hints on the painter if on is true; otherwise clears the render hints...
Definition: qpainter.cpp:7649
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *)
void setCompositionMode(CompositionMode mode)
Sets the composition mode to the given mode.
Definition: qpainter.cpp:2422
virtual QVariant itemChange(GraphicsItemChange, const QVariant &)
Note that unlike QGraphicsItems, QDeclarativeItem::itemChange() is not called during initial widget p...
void prepareGeometryChange()
Prepares the item for a geometry change.
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
QObject * parent() const
Returns a pointer to the parent object.
Definition: qobject.h:273
qreal x() const
This convenience function is equivalent to calling pos().
QVector< QRect > rects() const
Returns an array of non-overlapping rectangles that make up the region.
Definition: qregion.cpp:4412
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value)
Note that unlike QGraphicsItems, QDeclarativeItem::itemChange() is not called during initial widget p...
if(void) toggleToolbarShown
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
The QPixmap class is an off-screen image representation that can be used as a paint device...
Definition: qpixmap.h:71
void clearCache()
Marks the entirety of the contents cache as dirty.
void scale(qreal sx, qreal sy)
Scales the coordinate system by ({sx}, {sy}).
Definition: qpainter.cpp:3234
void drawPixmap(const QRectF &targetRect, const QPixmap &pixmap, const QRectF &sourceRect)
Draws the rectangular portion source of the given pixmap into the given target in the paint device...
Definition: qpainter.cpp:5619
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
The QStyleOptionGraphicsItem class is used to describe the parameters needed to draw a QGraphicsItem...
Definition: qstyleoption.h:867
QRegion systemClip() const
Returns the system clip.
Q_OUTOFLINE_TEMPLATE void qDeleteAll(ForwardIterator begin, ForwardIterator end)
Definition: qalgorithms.h:319
virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
This function is called to handle this item&#39;s changes in geometry from oldGeometry to newGeometry...
int pixelCacheSize() const
bool smoothCache() const
void fillRect(const QRectF &, const QBrush &)
Fills the given rectangle with the brush specified.
Definition: qpainter.cpp:7420
The QTransform class specifies 2D transformations of a coordinate system.
Definition: qtransform.h:65
static int area(const QSize &s)
Definition: qicon.cpp:155
void translate(const QPointF &offset)
Translates the coordinate system by the given offset; i.e.
Definition: qpainter.cpp:3311