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 QtGui 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 <qdebug.h> |
43 | #include "qnativeimage_p.h" |
44 | #include "qcolormap.h" |
45 | |
46 | #include "private/qpaintengine_raster_p.h" |
47 | |
48 | #include "private/qapplication_p.h" |
49 | #include "private/qgraphicssystem_p.h" |
50 | |
51 | #if defined(Q_WS_X11) && !defined(QT_NO_MITSHM) |
52 | #include <qx11info_x11.h> |
53 | #include <sys/ipc.h> |
54 | #include <sys/shm.h> |
55 | #include <qwidget.h> |
56 | #endif |
57 | |
58 | #ifdef Q_WS_MAC |
59 | #include <private/qpaintengine_mac_p.h> |
60 | #endif |
61 | |
62 | QT_BEGIN_NAMESPACE |
63 | |
64 | #ifdef Q_WS_WIN |
65 | typedef struct { |
66 | BITMAPINFOHEADER bmiHeader; |
67 | DWORD redMask; |
68 | DWORD greenMask; |
69 | DWORD blueMask; |
70 | } BITMAPINFO_MASK; |
71 | |
72 | |
73 | QNativeImage::QNativeImage(int width, int height, QImage::Format format, bool isTextBuffer, QWidget *) |
74 | { |
75 | #ifndef Q_WS_WINCE |
76 | Q_UNUSED(isTextBuffer); |
77 | #endif |
78 | BITMAPINFO_MASK bmi; |
79 | memset(&bmi, 0, sizeof(bmi)); |
80 | bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); |
81 | bmi.bmiHeader.biWidth = width; |
82 | bmi.bmiHeader.biHeight = -height; |
83 | bmi.bmiHeader.biPlanes = 1; |
84 | bmi.bmiHeader.biSizeImage = 0; |
85 | |
86 | if (format == QImage::Format_RGB16) { |
87 | bmi.bmiHeader.biBitCount = 16; |
88 | #ifdef Q_WS_WINCE |
89 | if (isTextBuffer) { |
90 | bmi.bmiHeader.biCompression = BI_RGB; |
91 | bmi.redMask = 0; |
92 | bmi.greenMask = 0; |
93 | bmi.blueMask = 0; |
94 | } else |
95 | #endif |
96 | { |
97 | bmi.bmiHeader.biCompression = BI_BITFIELDS; |
98 | bmi.redMask = 0xF800; |
99 | bmi.greenMask = 0x07E0; |
100 | bmi.blueMask = 0x001F; |
101 | } |
102 | } else { |
103 | bmi.bmiHeader.biBitCount = 32; |
104 | bmi.bmiHeader.biCompression = BI_RGB; |
105 | bmi.redMask = 0; |
106 | bmi.greenMask = 0; |
107 | bmi.blueMask = 0; |
108 | } |
109 | |
110 | HDC display_dc = GetDC(0); |
111 | hdc = CreateCompatibleDC(display_dc); |
112 | ReleaseDC(0, display_dc); |
113 | Q_ASSERT(hdc); |
114 | |
115 | uchar *bits = 0; |
116 | bitmap = CreateDIBSection(hdc, reinterpret_cast<BITMAPINFO *>(&bmi), DIB_RGB_COLORS, (void**) &bits, 0, 0); |
117 | Q_ASSERT(bitmap); |
118 | Q_ASSERT(bits); |
119 | |
120 | null_bitmap = (HBITMAP)SelectObject(hdc, bitmap); |
121 | image = QImage(bits, width, height, format); |
122 | |
123 | Q_ASSERT(image.paintEngine()->type() == QPaintEngine::Raster); |
124 | static_cast<QRasterPaintEngine *>(image.paintEngine())->setDC(hdc); |
125 | |
126 | #ifndef Q_WS_WINCE |
127 | GdiFlush(); |
128 | #endif |
129 | } |
130 | |
131 | QNativeImage::~QNativeImage() |
132 | { |
133 | if (bitmap || hdc) { |
134 | Q_ASSERT(hdc); |
135 | Q_ASSERT(bitmap); |
136 | if (null_bitmap) |
137 | SelectObject(hdc, null_bitmap); |
138 | DeleteDC(hdc); |
139 | DeleteObject(bitmap); |
140 | } |
141 | } |
142 | |
143 | QImage::Format QNativeImage::systemFormat() |
144 | { |
145 | if (QColormap::instance().depth() == 16) |
146 | return QImage::Format_RGB16; |
147 | return QImage::Format_RGB32; |
148 | } |
149 | |
150 | |
151 | #elif defined(Q_WS_X11) && !defined(QT_NO_MITSHM) |
152 | |
153 | QNativeImage::QNativeImage(int width, int height, QImage::Format format,bool /* isTextBuffer */, QWidget *widget) |
154 | : xshmimg(0), xshmpm(0) |
155 | { |
156 | QX11Info info = widget->x11Info(); |
157 | |
158 | int dd = info.depth(); |
159 | Visual *vis = (Visual*) info.visual(); |
160 | |
161 | if (!X11->use_mitshm || format != QImage::Format_RGB16 && X11->bppForDepth.value(dd) != 32) { |
162 | image = QImage(width, height, format); |
163 | // follow good coding practice and set xshminfo attributes, though values not used in this case |
164 | xshminfo.readOnly = true; |
165 | xshminfo.shmaddr = 0; |
166 | xshminfo.shmid = 0; |
167 | xshminfo.shmseg = 0; |
168 | return; |
169 | } |
170 | |
171 | xshmimg = XShmCreateImage(X11->display, vis, dd, ZPixmap, 0, &xshminfo, width, height); |
172 | if (!xshmimg) { |
173 | qWarning("QNativeImage: Unable to create shared XImage." ); |
174 | return; |
175 | } |
176 | |
177 | bool ok; |
178 | xshminfo.shmid = shmget(IPC_PRIVATE, xshmimg->bytes_per_line * xshmimg->height, |
179 | IPC_CREAT | 0700); |
180 | ok = xshminfo.shmid != -1; |
181 | if (ok) { |
182 | xshmimg->data = (char*)shmat(xshminfo.shmid, 0, 0); |
183 | xshminfo.shmaddr = xshmimg->data; |
184 | ok = (xshminfo.shmaddr != (char*)-1); |
185 | if (ok) |
186 | image = QImage((uchar *)xshmimg->data, width, height, format); |
187 | } |
188 | xshminfo.readOnly = false; |
189 | if (ok) { |
190 | ok = XShmAttach(X11->display, &xshminfo); |
191 | XSync(X11->display, False); |
192 | if (shmctl(xshminfo.shmid, IPC_RMID, 0) == -1) |
193 | qWarning() << "Error while marking the shared memory segment to be destroyed" ; |
194 | } |
195 | if (!ok) { |
196 | qWarning() << "QNativeImage: Unable to attach to shared memory segment." ; |
197 | if (xshmimg->data) { |
198 | free(xshmimg->data); |
199 | xshmimg->data = 0; |
200 | } |
201 | XDestroyImage(xshmimg); |
202 | xshmimg = 0; |
203 | if (xshminfo.shmaddr) |
204 | shmdt(xshminfo.shmaddr); |
205 | if (xshminfo.shmid != -1) |
206 | shmctl(xshminfo.shmid, IPC_RMID, 0); |
207 | return; |
208 | } |
209 | if (X11->use_mitshm_pixmaps) { |
210 | xshmpm = XShmCreatePixmap(X11->display, DefaultRootWindow(X11->display), xshmimg->data, |
211 | &xshminfo, width, height, dd); |
212 | if (!xshmpm) { |
213 | qWarning() << "QNativeImage: Unable to create shared Pixmap." ; |
214 | } |
215 | } |
216 | } |
217 | |
218 | |
219 | QNativeImage::~QNativeImage() |
220 | { |
221 | if (!xshmimg) |
222 | return; |
223 | |
224 | if (xshmpm) { |
225 | XFreePixmap(X11->display, xshmpm); |
226 | xshmpm = 0; |
227 | } |
228 | XShmDetach(X11->display, &xshminfo); |
229 | xshmimg->data = 0; |
230 | XDestroyImage(xshmimg); |
231 | xshmimg = 0; |
232 | shmdt(xshminfo.shmaddr); |
233 | shmctl(xshminfo.shmid, IPC_RMID, 0); |
234 | } |
235 | |
236 | QImage::Format QNativeImage::systemFormat() |
237 | { |
238 | if (QX11Info::appDepth() == 16) |
239 | return QImage::Format_RGB16; |
240 | return QImage::Format_RGB32; |
241 | } |
242 | |
243 | #elif defined(Q_WS_MAC) |
244 | |
245 | QNativeImage::QNativeImage(int width, int height, QImage::Format format, bool /* isTextBuffer */, QWidget *widget) |
246 | : image(width, height, format) |
247 | { |
248 | |
249 | uint cgflags = kCGImageAlphaNoneSkipFirst; |
250 | switch (format) { |
251 | case QImage::Format_ARGB32: |
252 | cgflags = kCGImageAlphaFirst; |
253 | break; |
254 | case QImage::Format_ARGB32_Premultiplied: |
255 | case QImage::Format_ARGB8565_Premultiplied: |
256 | case QImage::Format_ARGB6666_Premultiplied: |
257 | case QImage::Format_ARGB8555_Premultiplied: |
258 | case QImage::Format_ARGB4444_Premultiplied: |
259 | cgflags = kCGImageAlphaPremultipliedFirst; |
260 | break; |
261 | default: |
262 | break; |
263 | } |
264 | |
265 | #ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version |
266 | cgflags |= kCGBitmapByteOrder32Host; |
267 | #endif |
268 | |
269 | cg = CGBitmapContextCreate(image.bits(), width, height, 8, image.bytesPerLine(), |
270 | QCoreGraphicsPaintEngine::macDisplayColorSpace(widget), cgflags); |
271 | CGContextTranslateCTM(cg, 0, height); |
272 | CGContextScaleCTM(cg, 1, -1); |
273 | |
274 | Q_ASSERT(image.paintEngine()->type() == QPaintEngine::Raster); |
275 | static_cast<QRasterPaintEngine *>(image.paintEngine())->setCGContext(cg); |
276 | } |
277 | |
278 | |
279 | QNativeImage::~QNativeImage() |
280 | { |
281 | CGContextRelease(cg); |
282 | } |
283 | |
284 | QImage::Format QNativeImage::systemFormat() |
285 | { |
286 | return QImage::Format_RGB32; |
287 | } |
288 | |
289 | |
290 | #else // other platforms... |
291 | |
292 | QNativeImage::QNativeImage(int width, int height, QImage::Format format, bool /* isTextBuffer */, QWidget *) |
293 | : image(width, height, format) |
294 | { |
295 | |
296 | } |
297 | |
298 | |
299 | QNativeImage::~QNativeImage() |
300 | { |
301 | } |
302 | |
303 | QImage::Format QNativeImage::systemFormat() |
304 | { |
305 | #ifdef Q_WS_QPA |
306 | return QApplicationPrivate::platformIntegration()->screens().at(0)->format(); |
307 | #else |
308 | return QImage::Format_RGB32; |
309 | #endif |
310 | } |
311 | |
312 | #endif // platforms |
313 | |
314 | QT_END_NAMESPACE |
315 | |
316 | |