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
** No Commercial Usage
11
** This file contains pre-release code and may not be distributed.
12
** You may use this file in accordance with the terms and conditions
13
** contained in the Technology Preview License Agreement accompanying
14
** this package.
15
**
16
** GNU Lesser General Public License Usage
17
** Alternatively, this file may be used under the terms of the GNU Lesser
18
** General Public License version 2.1 as published by the Free Software
19
** Foundation and appearing in the file LICENSE.LGPL included in the
20
** packaging of this file.  Please review the following information to
21
** ensure the GNU Lesser General Public License version 2.1 requirements
22
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23
**
24
** In addition, as a special exception, Nokia gives you certain additional
25
** rights.  These rights are described in the Nokia Qt LGPL Exception
26
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27
**
28
** If you have questions regarding the use of this file, please contact
29
** Nokia at qt-info@nokia.com.
30
**
31
**
32
**
33
**
34
**
35
**
36
**
37
**
38
** $QT_END_LICENSE$
39
**
40
****************************************************************************/
41
42
#include <qdebug.h>
43
#include "qnativeimage_p.h"
44
#include "qcolormap.h"
45
46
#include "private/qpaintengine_raster_p.h"
47
48
#if defined(Q_WS_X11) && !defined(QT_NO_MITSHM)
49
#include <qx11info_x11.h>
50
#include <sys/ipc.h>
51
#include <sys/shm.h>
52
#include <qwidget.h>
53
#endif
54
55
#ifdef Q_WS_MAC
56
#include <private/qpaintengine_mac_p.h>
57
#endif
58
59
QT_BEGIN_NAMESPACE
60
61
#ifdef Q_WS_WIN
62
typedef struct {
63
    BITMAPINFOHEADER bmiHeader;
64
    DWORD redMask;
65
    DWORD greenMask;
66
    DWORD blueMask;
67
} BITMAPINFO_MASK;
68
69
70
QNativeImage::QNativeImage(int width, int height, QImage::Format format, bool isTextBuffer, QWidget *)
71
{
72
#ifndef Q_WS_WINCE
73
    Q_UNUSED(isTextBuffer);
74
#endif
75
    BITMAPINFO_MASK bmi;
76
    memset(&bmi, 0, sizeof(bmi));
77
    bmi.bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);
78
    bmi.bmiHeader.biWidth       = width;
79
    bmi.bmiHeader.biHeight      = -height;
80
    bmi.bmiHeader.biPlanes      = 1;
81
    bmi.bmiHeader.biSizeImage   = 0;
82
83
    if (format == QImage::Format_RGB16) {
84
        bmi.bmiHeader.biBitCount = 16;
85
#ifdef Q_WS_WINCE
86
        if (isTextBuffer) {
87
            bmi.bmiHeader.biCompression = BI_RGB;
88
            bmi.redMask = 0;
89
            bmi.greenMask = 0;
90
            bmi.blueMask = 0;
91
        } else
92
#endif
93
        {
94
            bmi.bmiHeader.biCompression = BI_BITFIELDS;
95
            bmi.redMask = 0xF800;
96
            bmi.greenMask = 0x07E0;
97
            bmi.blueMask = 0x001F;
98
        }
99
    } else {
100
        bmi.bmiHeader.biBitCount    = 32;
101
        bmi.bmiHeader.biCompression = BI_RGB;
102
        bmi.redMask = 0;
103
        bmi.greenMask = 0;
104
        bmi.blueMask = 0;
105
    }
106
107
    HDC display_dc = GetDC(0);
108
    hdc = CreateCompatibleDC(display_dc);
109
    ReleaseDC(0, display_dc);
110
    Q_ASSERT(hdc);
111
112
    uchar *bits = 0;
113
    bitmap = CreateDIBSection(hdc, reinterpret_cast<BITMAPINFO *>(&bmi), DIB_RGB_COLORS, (void**) &bits, 0, 0);
114
    Q_ASSERT(bitmap);
115
    Q_ASSERT(bits);
116
117
    null_bitmap = (HBITMAP)SelectObject(hdc, bitmap);
118
    image = QImage(bits, width, height, format);
119
120
    Q_ASSERT(image.paintEngine()->type() == QPaintEngine::Raster);
121
    static_cast<QRasterPaintEngine *>(image.paintEngine())->setDC(hdc);
122
123
#ifndef Q_WS_WINCE
124
    GdiFlush();
125
#endif
126
}
127
128
QNativeImage::~QNativeImage()
129
{
130
    if (bitmap || hdc) {
131
        Q_ASSERT(hdc);
132
        Q_ASSERT(bitmap);
133
        if (null_bitmap)
134
            SelectObject(hdc, null_bitmap);
135
        DeleteDC(hdc);
136
        DeleteObject(bitmap);
137
    }
138
}
139
140
QImage::Format QNativeImage::systemFormat()
141
{
142
    if (QColormap::instance().depth() == 16)
143
        return QImage::Format_RGB16;
144
    return QImage::Format_RGB32;
145
}
146
147
148
#elif defined(Q_WS_X11) && !defined(QT_NO_MITSHM)
149
150
QNativeImage::QNativeImage(int width, int height, QImage::Format format,bool /* isTextBuffer */, QWidget *widget)
151
    : xshmimg(0), xshmpm(0)
152
{
153
    if (!X11->use_mitshm) {
154
        image = QImage(width, height, format);
155
        // follow good coding practice and set xshminfo attributes, though values not used in this case
156
        xshminfo.readOnly = true;
157
        xshminfo.shmaddr = 0;
158
        xshminfo.shmid = 0;
159
        xshminfo.shmseg = 0;
160
        return;
161
    }
162
163
    QX11Info info = widget->x11Info();
164
165
    int dd = info.depth();
166
    Visual *vis = (Visual*) info.visual();
167
168
    xshmimg = XShmCreateImage(X11->display, vis, dd, ZPixmap, 0, &xshminfo, width, height);
169
    if (!xshmimg) {
170
        qWarning("QNativeImage: Unable to create shared XImage.");
171
        return;
172
    }
173
174
    bool ok;
175
    xshminfo.shmid = shmget(IPC_PRIVATE, xshmimg->bytes_per_line * xshmimg->height,
176
                            IPC_CREAT | 0777);
177
    ok = xshminfo.shmid != -1;
178
    if (ok) {
179
        xshmimg->data = (char*)shmat(xshminfo.shmid, 0, 0);
180
        xshminfo.shmaddr = xshmimg->data;
181
        if (shmctl(xshminfo.shmid, IPC_RMID, 0) == -1)
182
            qWarning() << "Error while marking the shared memory segment to be destroyed";
183
        ok = (xshminfo.shmaddr != (char*)-1);
184
        if (ok)
185
            image = QImage((uchar *)xshmimg->data, width, height, format);
186
    }
187
    xshminfo.readOnly = false;
188
    if (ok)
189
        ok = XShmAttach(X11->display, &xshminfo);
190
    if (!ok) {
191
        qWarning() << "QNativeImage: Unable to attach to shared memory segment.";
192
        if (xshmimg->data) {
193
            free(xshmimg->data);
194
            xshmimg->data = 0;
195
        }
196
        XDestroyImage(xshmimg);
197
        xshmimg = 0;
198
        if (xshminfo.shmaddr)
199
            shmdt(xshminfo.shmaddr);
200
        if (xshminfo.shmid != -1)
201
            shmctl(xshminfo.shmid, IPC_RMID, 0);
202
        return;
203
    }
204
    if (X11->use_mitshm_pixmaps) {
205
        xshmpm = XShmCreatePixmap(X11->display, DefaultRootWindow(X11->display), xshmimg->data,
206
                                  &xshminfo, width, height, dd);
207
        if (!xshmpm) {
208
            qWarning() << "QNativeImage: Unable to create shared Pixmap.";
209
        }
210
    }
211
}
212
213
214
QNativeImage::~QNativeImage()
215
{
216
    if (!xshmimg)
217
        return;
218
219
    if (xshmpm) {
220
        XFreePixmap(X11->display, xshmpm);
221
        xshmpm = 0;
222
    }
223
    XShmDetach(X11->display, &xshminfo);
224
    xshmimg->data = 0;
225
    XDestroyImage(xshmimg);
226
    xshmimg = 0;
227
    shmdt(xshminfo.shmaddr);
228
    shmctl(xshminfo.shmid, IPC_RMID, 0);
229
}
230
231
QImage::Format QNativeImage::systemFormat()
232
{
233
    if (QX11Info::appDepth() == 16)
234
        return QImage::Format_RGB16;
235
    return QImage::Format_RGB32;
236
}
237
238
#elif defined(Q_WS_MAC)
239
240
QNativeImage::QNativeImage(int width, int height, QImage::Format format, bool /* isTextBuffer */, QWidget *widget)
241
    : image(width, height, format)
242
{
243
244
245
    uint cgflags = kCGImageAlphaNoneSkipFirst;
246
247
#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version
248
    cgflags |= kCGBitmapByteOrder32Host;
249
#endif
250
251
    cg = CGBitmapContextCreate(image.bits(), width, height, 8, image.bytesPerLine(),
252
                               QCoreGraphicsPaintEngine::macDisplayColorSpace(widget), cgflags);
253
    CGContextTranslateCTM(cg, 0, height);
254
    CGContextScaleCTM(cg, 1, -1);
255
256
    Q_ASSERT(image.paintEngine()->type() == QPaintEngine::Raster);
257
    static_cast<QRasterPaintEngine *>(image.paintEngine())->setCGContext(cg);
258
}
259
260
261
QNativeImage::~QNativeImage()
262
{
263
    CGContextRelease(cg);
264
}
265
266
QImage::Format QNativeImage::systemFormat()
267
{
268
    return QImage::Format_RGB32;
269
}
270
271
272
#else // other platforms...
273
274
QNativeImage::QNativeImage(int width, int height, QImage::Format format,  bool /* isTextBuffer */, QWidget *)
275
    : image(width, height, format)
276
{
277
278
}
279
280
281
QNativeImage::~QNativeImage()
282
{
283
}
284
285
QImage::Format QNativeImage::systemFormat()
286
{
287
    return QImage::Format_RGB32;
288
}
289
290
#endif // platforms
291
292
QT_END_NAMESPACE