Replace 'i < len-1 && func(i+1)' by 'i+1 < len && func(i+1)'
[profile/ivi/qtbase.git] / src / gui / painting / qunifiedtoolbarsurface_mac.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 "qunifiedtoolbarsurface_mac_p.h"
43 #include <private/qt_cocoa_helpers_mac_p.h>
44 #include <private/qbackingstore_p.h>
45 #include <private/qmainwindowlayout_p.h>
46
47 #include <QDebug>
48
49 #ifdef QT_MAC_USE_COCOA
50
51 QT_BEGIN_NAMESPACE
52
53 QUnifiedToolbarSurface::QUnifiedToolbarSurface(QWidget *widget)
54     : QRasterWindowSurface(widget, false), d_ptr(new QUnifiedToolbarSurfacePrivate)
55 {
56     d_ptr->image = 0;
57     d_ptr->inSetGeometry = false;
58
59     setGeometry(QRect(QPoint(0, 0), QSize(widget->width(), 100))); // FIXME: Fix height.
60 }
61
62 QUnifiedToolbarSurface::~QUnifiedToolbarSurface()
63 {
64     if (d_ptr->image)
65         delete d_ptr->image;
66 }
67
68 QPaintDevice *QUnifiedToolbarSurface::paintDevice()
69 {
70     return &d_ptr->image->image;
71 }
72
73 void QUnifiedToolbarSurface::recursiveRedirect(QObject *object, QWidget *parent_toolbar, const QPoint &offset)
74 {
75     if (object != 0) {
76         if (object->isWidgetType()) {
77             QWidget *widget = qobject_cast<QWidget *>(object);
78
79             // We redirect the painting only if the widget is in the same window
80             // and is not a window in itself.
81             if (!(widget->windowType() & Qt::Window)) {
82                 widget->d_func()->unifiedSurface = this;
83                 widget->d_func()->isInUnifiedToolbar = true;
84                 widget->d_func()->toolbar_offset = offset;
85                 widget->d_func()->toolbar_ancestor = parent_toolbar;
86
87                 for (int i = 0; i < object->children().size(); ++i) {
88                     recursiveRedirect(object->children().at(i), parent_toolbar, offset);
89                 }
90             }
91         }
92     }
93 }
94
95 void QUnifiedToolbarSurface::insertToolbar(QWidget *toolbar, const QPoint &offset)
96 {
97     setGeometry(QRect(QPoint(0, 0), QSize(offset.x() + toolbar->width(), 100))); // FIXME
98     recursiveRedirect(toolbar, toolbar, offset);
99 }
100
101 // We basically undo what we set in recursiveRedirect().
102 void QUnifiedToolbarSurface::recursiveRemoval(QObject *object)
103 {
104     if (object != 0) {
105         if (object->isWidgetType()) {
106             QWidget *widget = qobject_cast<QWidget *>(object);
107
108             // If it's a pop-up or something similar, we don't redirect it.
109             if (widget->windowType() & Qt::Window)
110                 return;
111
112             widget->d_func()->unifiedSurface = 0;
113             widget->d_func()->isInUnifiedToolbar = false;
114             widget->d_func()->toolbar_offset = QPoint();
115             widget->d_func()->toolbar_ancestor = 0;
116         }
117
118         for (int i = 0; i < object->children().size(); ++i) {
119             recursiveRemoval(object->children().at(i));
120         }
121     }
122 }
123
124 void QUnifiedToolbarSurface::removeToolbar(QToolBar *toolbar)
125 {
126     recursiveRemoval(toolbar);
127 }
128
129 void QUnifiedToolbarSurface::setGeometry(const QRect &rect)
130 {
131     QWindowSurface::setGeometry(rect);
132     Q_D(QUnifiedToolbarSurface);
133     d->inSetGeometry = true;
134     if (d->image == 0 || d->image->width() < rect.width() || d->image->height() < rect.height())
135             prepareBuffer(QImage::Format_ARGB32_Premultiplied, window());
136     d->inSetGeometry = false;
137
138     // FIXME: set unified toolbar height.
139 }
140
141 void QUnifiedToolbarSurface::beginPaint(const QRegion &rgn)
142 {
143     QPainter p(&d_ptr->image->image);
144     p.setCompositionMode(QPainter::CompositionMode_Source);
145     const QVector<QRect> rects = rgn.rects();
146     const QColor blank = Qt::transparent;
147     for (QVector<QRect>::const_iterator it = rects.begin(); it != rects.end(); ++it) {
148         p.fillRect(*it, blank);
149     }
150 }
151
152 void QUnifiedToolbarSurface::updateToolbarOffset(QWidget *widget)
153 {
154     QMainWindowLayout *mlayout = qobject_cast<QMainWindowLayout*> (widget->window()->layout());
155     if (mlayout)
156         mlayout->updateUnifiedToolbarOffset();
157 }
158
159 void QUnifiedToolbarSurface::flush(QWidget *widget, const QRegion &region, const QPoint &offset)
160 {
161     Q_UNUSED(region);
162     Q_UNUSED(offset);
163
164     this->flush(widget);
165 }
166
167 void QUnifiedToolbarSurface::flush(QWidget *widget)
168 {
169     Q_D(QUnifiedToolbarSurface);
170
171     if (!d->image)
172         return;
173
174     if (widget->d_func()->flushRequested) {
175         // We call display: directly to avoid flickering in the toolbar.
176         qt_mac_display(widget);
177     }
178 }
179
180 void QUnifiedToolbarSurface::prepareBuffer(QImage::Format format, QWidget *widget)
181 {
182     Q_D(QUnifiedToolbarSurface);
183
184     int width = geometry().width();
185     int height = 100; // FIXME
186     if (d->image) {
187         width = qMax(d->image->width(), width);
188         height = qMax(d->image->height(), height);
189     }
190
191     if (width == 0 || height == 0) {
192         delete d->image;
193         d->image = 0;
194         return;
195     }
196
197     QNativeImage *oldImage = d->image;
198
199     d->image = new QNativeImage(width, height, format, false, widget);
200
201     if (oldImage && d->inSetGeometry && hasStaticContents()) {
202         // Make sure we use the const version of bits() (no detach).
203         const uchar *src = const_cast<const QImage &>(oldImage->image).bits();
204         uchar *dst = d->image->image.bits();
205
206         const int srcBytesPerLine = oldImage->image.bytesPerLine();
207         const int dstBytesPerLine = d->image->image.bytesPerLine();
208         const int bytesPerPixel = oldImage->image.depth() >> 3;
209
210         QRegion staticRegion(staticContents());
211         // Make sure we're inside the boundaries of the old image.
212         staticRegion &= QRect(0, 0, oldImage->image.width(), oldImage->image.height());
213         const QVector<QRect> &rects = staticRegion.rects();
214         const QRect *srcRect = rects.constData();
215
216         // Copy the static content of the old image into the new one.
217         int numRectsLeft = rects.size();
218         do {
219             const int bytesOffset = srcRect->x() * bytesPerPixel;
220             const int dy = srcRect->y();
221
222             // Adjust src and dst to point to the right offset.
223             const uchar *s = src + dy * srcBytesPerLine + bytesOffset;
224             uchar *d = dst + dy * dstBytesPerLine + bytesOffset;
225             const int numBytes = srcRect->width() * bytesPerPixel;
226
227             int numScanLinesLeft = srcRect->height();
228             do {
229                 ::memcpy(d, s, numBytes);
230                 d += dstBytesPerLine;
231                 s += srcBytesPerLine;
232             } while (--numScanLinesLeft);
233
234             ++srcRect;
235         } while (--numRectsLeft);
236     }
237
238     delete oldImage;
239 }
240
241 CGContextRef QUnifiedToolbarSurface::imageContext()
242 {
243     Q_D(QUnifiedToolbarSurface);
244     return d->image->cg;
245 }
246
247 void QUnifiedToolbarSurface::renderToolbar(QWidget *widget, bool forceFlush)
248 {
249     QWidget *toolbar = widget->d_func()->toolbar_ancestor;
250
251     updateToolbarOffset(toolbar);
252     QRect beginPaintRect(toolbar->d_func()->toolbar_offset.x(), toolbar->d_func()->toolbar_offset.y(), toolbar->geometry().width(), toolbar->geometry().height());
253     QRegion beginPaintRegion(beginPaintRect);
254
255     beginPaint(beginPaintRegion);
256     toolbar->render(paintDevice(), toolbar->d_func()->toolbar_offset, QRegion(toolbar->geometry()), QWidget::DrawChildren);
257     toolbar->d_func()->flushRequested = true;
258
259     if (forceFlush)
260         flush(toolbar);
261 }
262
263 QT_END_NAMESPACE
264
265 #endif // QT_MAC_USE_COCOA