Replace 'i < len-1 && func(i+1)' by 'i+1 < len && func(i+1)'
[profile/ivi/qtbase.git] / src / gui / painting / qwindowsurface.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 QtGui 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 <private/qwindowsurface_p.h>
43 #include <qwidget.h>
44 #include <private/qwidget_p.h>
45 #include <private/qbackingstore_p.h>
46 #include <private/qapplication_p.h>
47
48 QT_BEGIN_NAMESPACE
49
50 class QWindowSurfacePrivate
51 {
52 public:
53     QWindowSurfacePrivate(QWidget *w)
54         : window(w)
55     {
56     }
57
58     QWidget *window;
59 #if !defined(Q_WS_QPA)
60     QRect geometry;
61 #else
62     QSize size;
63 #endif //Q_WS_QPA
64     QRegion staticContents;
65     QList<QImage*> bufferImages;
66 };
67
68 /*!
69     \class QWindowSurface
70     \since 4.3
71     \internal
72     \preliminary
73     \ingroup qws qpa
74
75     \brief The QWindowSurface class provides the drawing area for top-level
76     windows.
77 */
78
79
80 /*!
81     \fn void QWindowSurface::beginPaint(const QRegion &region)
82
83     This function is called before painting onto the surface begins,
84     with the \a region in which the painting will occur.
85
86     \sa endPaint(), paintDevice()
87 */
88
89 /*!
90     \fn void QWindowSurface::endPaint(const QRegion &region)
91
92     This function is called after painting onto the surface has ended,
93     with the \a region in which the painting was performed.
94
95     \sa beginPaint(), paintDevice()
96 */
97
98 /*!
99     \fn void QWindowSurface::flush(QWidget *widget, const QRegion &region,
100                                   const QPoint &offset)
101
102     Flushes the given \a region from the specified \a widget onto the
103     screen.
104
105     Note that the \a offset parameter is currently unused.
106 */
107
108 /*!
109     \fn QPaintDevice* QWindowSurface::paintDevice()
110
111     Implement this function to return the appropriate paint device.
112 */
113
114 /*!
115     Constructs an empty surface for the given top-level \a window.
116 */
117 QWindowSurface::QWindowSurface(QWidget *window, bool setDefaultSurface)
118     : d_ptr(new QWindowSurfacePrivate(window))
119 {
120     if (!QApplicationPrivate::runtime_graphics_system) {
121         if(setDefaultSurface && window)
122             window->setWindowSurface(this);
123     }
124 }
125
126 /*!
127     Destroys this surface.
128 */
129 QWindowSurface::~QWindowSurface()
130 {
131     if (d_ptr->window)
132         d_ptr->window->d_func()->extra->topextra->windowSurface = 0;
133     delete d_ptr;
134 }
135
136 /*!
137     Returns a pointer to the top-level window associated with this
138     surface.
139 */
140 QWidget* QWindowSurface::window() const
141 {
142     return d_ptr->window;
143 }
144
145 void QWindowSurface::beginPaint(const QRegion &)
146 {
147 }
148
149 void QWindowSurface::endPaint(const QRegion &)
150 {
151 //     QApplication::syncX();
152     qDeleteAll(d_ptr->bufferImages);
153     d_ptr->bufferImages.clear();
154 }
155
156 #if !defined(Q_WS_QPA)
157 /*!
158     Sets the currently allocated area to be the given \a rect.
159
160     This function is called whenever area covered by the top-level
161     window changes.
162
163     \sa geometry()
164 */
165 void QWindowSurface::setGeometry(const QRect &rect)
166 {
167     d_ptr->geometry = rect;
168 }
169
170 /*!
171     Returns the currently allocated area on the screen.
172 */
173 QRect QWindowSurface::geometry() const
174 {
175     return d_ptr->geometry;
176 }
177 #else
178
179 /*!
180       Sets the size of the windowsurface to be \a size.
181
182       \sa size()
183 */
184 void QWindowSurface::resize(const QSize &size)
185 {
186     d_ptr->size = size;
187 }
188
189 /*!
190     Returns the current size of the windowsurface.
191 */
192 QSize QWindowSurface::size() const
193 {
194     return d_ptr->size;
195 }
196 #endif //Q_WS_QPA
197
198 /*!
199     Scrolls the given \a area \a dx pixels to the right and \a dy
200     downward; both \a dx and \a dy may be negative.
201
202     Returns true if the area was scrolled successfully; false otherwise.
203 */
204 bool QWindowSurface::scroll(const QRegion &area, int dx, int dy)
205 {
206     Q_UNUSED(area);
207     Q_UNUSED(dx);
208     Q_UNUSED(dy);
209
210     return false;
211 }
212
213 /*!
214     Returns a QImage pointer which represents the actual buffer the \a widget
215     is drawn into or 0 if this is unavailable.
216
217     You must call beginPaint() before you call this function and the returned
218     pointer is only valid until endPaint() is called.
219 */
220 QImage* QWindowSurface::buffer(const QWidget *widget)
221 {
222     if (widget->window() != window())
223         return 0;
224
225     QPaintDevice *pdev = paintDevice();
226     if (!pdev || pdev->devType() != QInternal::Image)
227         return 0;
228
229     const QPoint off = offset(widget);
230     QImage *img = static_cast<QImage*>(pdev);
231
232     QRect rect(off, widget->size());
233     rect &= QRect(QPoint(), img->size());
234
235     if (rect.isEmpty())
236         return 0;
237
238     img = new QImage(img->scanLine(rect.y()) + rect.x() * img->depth() / 8,
239                      rect.width(), rect.height(),
240                      img->bytesPerLine(), img->format());
241     d_ptr->bufferImages.append(img);
242
243     return img;
244 }
245
246 /*!
247   Returns a QPixmap generated from the part of the backing store
248   corresponding to \a widget. Returns a null QPixmap if an error
249   occurs. The contents of the pixmap are only defined for the regions
250   of \a widget that have received paint events since the last resize
251   of the backing store.
252
253   If \a rectangle is a null rectangle (the default), the entire widget
254   is grabbed. Otherwise, the grabbed area is limited to \a rectangle.
255
256   The default implementation uses QWindowSurface::buffer().
257
258   \sa QPixmap::grabWidget()
259 */
260 QPixmap QWindowSurface::grabWidget(const QWidget *widget, const QRect &rectangle) const
261 {
262     QPixmap result;
263
264     if (widget->window() != window())
265         return result;
266
267     const QImage *img = const_cast<QWindowSurface *>(this)->buffer(widget->window());
268
269     if (!img || img->isNull())
270         return result;
271
272     QRect rect = rectangle.isEmpty() ? widget->rect() : (widget->rect() & rectangle);
273
274     rect.translate(offset(widget) - offset(widget->window()));
275     rect &= QRect(QPoint(), img->size());
276
277     if (rect.isEmpty())
278         return result;
279
280     QImage subimg(img->scanLine(rect.y()) + rect.x() * img->depth() / 8,
281                   rect.width(), rect.height(),
282                   img->bytesPerLine(), img->format());
283     subimg.detach(); //### expensive -- maybe we should have a real SubImage that shares reference count
284
285     result = QPixmap::fromImage(subimg);
286     return result;
287 }
288
289 /*!
290   Returns the offset of \a widget in the coordinates of this
291   window surface.
292  */
293 QPoint QWindowSurface::offset(const QWidget *widget) const
294 {
295     QWidget *window = d_ptr->window;
296     QPoint offset = widget->mapTo(window, QPoint());
297 #ifdef Q_WS_QWS
298     offset += window->geometry().topLeft() - window->frameGeometry().topLeft();
299 #endif
300     return offset;
301 }
302
303 /*!
304   \fn QRect QWindowSurface::rect(const QWidget *widget) const
305
306   Returns the rectangle for \a widget in the coordinates of this
307   window surface.
308 */
309
310 void QWindowSurface::setStaticContents(const QRegion &region)
311 {
312     d_ptr->staticContents = region;
313 }
314
315 QRegion QWindowSurface::staticContents() const
316 {
317     return d_ptr->staticContents;
318 }
319
320 bool QWindowSurface::hasStaticContents() const
321 {
322     return hasFeature(QWindowSurface::StaticContents) && !d_ptr->staticContents.isEmpty();
323 }
324
325 QWindowSurface::WindowSurfaceFeatures QWindowSurface::features() const
326 {
327     return PartialUpdates | PreservedContents;
328 }
329
330 #ifdef Q_WS_QPA
331 #define Q_EXPORT_SCROLLRECT Q_GUI_EXPORT
332 #else
333 #define Q_EXPORT_SCROLLRECT
334 #endif
335
336 void Q_EXPORT_SCROLLRECT qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset)
337 {
338     // make sure we don't detach
339     uchar *mem = const_cast<uchar*>(const_cast<const QImage &>(img).bits());
340
341     int lineskip = img.bytesPerLine();
342     int depth = img.depth() >> 3;
343
344     const QRect imageRect(0, 0, img.width(), img.height());
345     const QRect r = rect & imageRect & imageRect.translated(-offset);
346     const QPoint p = rect.topLeft() + offset;
347
348     if (r.isEmpty())
349         return;
350
351     const uchar *src;
352     uchar *dest;
353
354     if (r.top() < p.y()) {
355         src = mem + r.bottom() * lineskip + r.left() * depth;
356         dest = mem + (p.y() + r.height() - 1) * lineskip + p.x() * depth;
357         lineskip = -lineskip;
358     } else {
359         src = mem + r.top() * lineskip + r.left() * depth;
360         dest = mem + p.y() * lineskip + p.x() * depth;
361     }
362
363     const int w = r.width();
364     int h = r.height();
365     const int bytes = w * depth;
366
367     // overlapping segments?
368     if (offset.y() == 0 && qAbs(offset.x()) < w) {
369         do {
370             ::memmove(dest, src, bytes);
371             dest += lineskip;
372             src += lineskip;
373         } while (--h);
374     } else {
375         do {
376             ::memcpy(dest, src, bytes);
377             dest += lineskip;
378             src += lineskip;
379         } while (--h);
380     }
381 }
382
383 QT_END_NAMESPACE