source: trunk/src/gui/image/qpixmap_x11.cpp@ 284

Last change on this file since 284 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 78.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42// Uncomment the next line to enable the MIT Shared Memory extension
43//
44// WARNING: This has some problems:
45//
46// 1. Consumes a 800x600 pixmap
47// 2. Qt does not handle the ShmCompletion message, so you will
48// get strange effects if you xForm() repeatedly.
49//
50// #define QT_MITSHM
51
52#if defined(Q_OS_WIN32) && defined(QT_MITSHM)
53#undef QT_MITSHM
54#endif
55
56#include "qplatformdefs.h"
57
58#include "qdebug.h"
59#include "qiodevice.h"
60#include "qpixmap_x11_p.h"
61#include "qbitmap.h"
62#include "qcolormap.h"
63#include "qimage.h"
64#include "qmatrix.h"
65#include "qapplication.h"
66#include <private/qpaintengine_x11_p.h>
67#include <private/qt_x11_p.h>
68#include "qx11info_x11.h"
69#include <private/qdrawhelper_p.h>
70
71#include <stdlib.h>
72
73#if defined(Q_CC_MIPS)
74# define for if(0){}else for
75#endif
76
77QT_BEGIN_NAMESPACE
78
79QPixmap qt_toX11Pixmap(const QImage &image)
80{
81 QPixmapData *data =
82 new QX11PixmapData(image.depth() == 1
83 ? QPixmapData::BitmapType
84 : QPixmapData::PixmapType);
85
86 data->fromImage(image, Qt::AutoColor);
87
88 return QPixmap(data);
89}
90
91QPixmap qt_toX11Pixmap(const QPixmap &pixmap)
92{
93 if (pixmap.isNull())
94 return QPixmap();
95
96 if (QPixmap(pixmap).data_ptr()->classId() == QPixmapData::X11Class)
97 return pixmap;
98
99 return qt_toX11Pixmap(pixmap.toImage());
100}
101
102// For thread-safety:
103// image->data does not belong to X11, so we must free it ourselves.
104
105inline static void qSafeXDestroyImage(XImage *x)
106{
107 if (x->data) {
108 free(x->data);
109 x->data = 0;
110 }
111 XDestroyImage(x);
112}
113
114QBitmap QX11PixmapData::mask_to_bitmap(int screen) const
115{
116 if (!x11_mask)
117 return QBitmap();
118 QPixmap::x11SetDefaultScreen(screen);
119 QBitmap bm(w, h);
120 GC gc = XCreateGC(X11->display, bm.handle(), 0, 0);
121 XCopyArea(X11->display, x11_mask, bm.handle(), gc, 0, 0,
122 bm.data->width(), bm.data->height(), 0, 0);
123 XFreeGC(X11->display, gc);
124 return bm;
125}
126
127Qt::HANDLE QX11PixmapData::bitmap_to_mask(const QBitmap &bitmap, int screen)
128{
129 if (bitmap.isNull())
130 return 0;
131 QBitmap bm = bitmap;
132 bm.x11SetScreen(screen);
133
134 Pixmap mask = XCreatePixmap(X11->display, RootWindow(X11->display, screen),
135 bm.data->width(), bm.data->height(), 1);
136 GC gc = XCreateGC(X11->display, mask, 0, 0);
137 XCopyArea(X11->display, bm.handle(), mask, gc, 0, 0,
138 bm.data->width(), bm.data->height(), 0, 0);
139 XFreeGC(X11->display, gc);
140 return mask;
141}
142
143
144/*****************************************************************************
145 MIT Shared Memory Extension support: makes xForm noticeably (~20%) faster.
146 *****************************************************************************/
147
148#if defined(QT_MITSHM)
149
150static bool xshminit = false;
151static XShmSegmentInfo xshminfo;
152static XImage *xshmimg = 0;
153static Pixmap xshmpm = 0;
154
155static void qt_cleanup_mitshm()
156{
157 if (xshmimg == 0)
158 return;
159 Display *dpy = QX11Info::appDisplay();
160 if (xshmpm) {
161 XFreePixmap(dpy, xshmpm);
162 xshmpm = 0;
163 }
164 XShmDetach(dpy, &xshminfo); xshmimg->data = 0;
165 qSafeXDestroyImage(xshmimg); xshmimg = 0;
166 shmdt(xshminfo.shmaddr);
167 shmctl(xshminfo.shmid, IPC_RMID, 0);
168}
169
170static bool qt_create_mitshm_buffer(const QPaintDevice* dev, int w, int h)
171{
172 static int major, minor;
173 static Bool pixmaps_ok;
174 Display *dpy = dev->data->xinfo->display();
175 int dd = dev->x11Depth();
176 Visual *vis = (Visual*)dev->x11Visual();
177
178 if (xshminit) {
179 qt_cleanup_mitshm();
180 } else {
181 if (!XShmQueryVersion(dpy, &major, &minor, &pixmaps_ok))
182 return false; // MIT Shm not supported
183 qAddPostRoutine(qt_cleanup_mitshm);
184 xshminit = true;
185 }
186
187 xshmimg = XShmCreateImage(dpy, vis, dd, ZPixmap, 0, &xshminfo, w, h);
188 if (!xshmimg)
189 return false;
190
191 bool ok;
192 xshminfo.shmid = shmget(IPC_PRIVATE,
193 xshmimg->bytes_per_line * xshmimg->height,
194 IPC_CREAT | 0777);
195 ok = xshminfo.shmid != -1;
196 if (ok) {
197 xshmimg->data = (char*)shmat(xshminfo.shmid, 0, 0);
198 xshminfo.shmaddr = xshmimg->data;
199 ok = (xshminfo.shmaddr != (char*)-1);
200 }
201 xshminfo.readOnly = false;
202 if (ok)
203 ok = XShmAttach(dpy, &xshminfo);
204 if (!ok) {
205 qSafeXDestroyImage(xshmimg);
206 xshmimg = 0;
207 if (xshminfo.shmaddr)
208 shmdt(xshminfo.shmaddr);
209 if (xshminfo.shmid != -1)
210 shmctl(xshminfo.shmid, IPC_RMID, 0);
211 return false;
212 }
213 if (pixmaps_ok)
214 xshmpm = XShmCreatePixmap(dpy, DefaultRootWindow(dpy), xshmimg->data,
215 &xshminfo, w, h, dd);
216
217 return true;
218}
219
220#else
221
222// If extern, need a dummy.
223//
224// static bool qt_create_mitshm_buffer(QPaintDevice*, int, int)
225// {
226// return false;
227// }
228
229#endif // QT_MITSHM
230
231
232/*****************************************************************************
233 Internal functions
234 *****************************************************************************/
235
236extern const uchar *qt_get_bitflip_array(); // defined in qimage.cpp
237
238// Returns position of highest bit set or -1 if none
239static int highest_bit(uint v)
240{
241 int i;
242 uint b = (uint)1 << 31;
243 for (i=31; ((b & v) == 0) && i>=0; i--)
244 b >>= 1;
245 return i;
246}
247
248// Returns position of lowest set bit in 'v' as an integer (0-31), or -1
249static int lowest_bit(uint v)
250{
251 int i;
252 ulong lb;
253 lb = 1;
254 for (i=0; ((v & lb) == 0) && i<32; i++, lb<<=1) {}
255 return i==32 ? -1 : i;
256}
257
258// Counts the number of bits set in 'v'
259static uint n_bits(uint v)
260{
261 int i = 0;
262 while (v) {
263 v = v & (v - 1);
264 i++;
265 }
266 return i;
267}
268
269static uint *red_scale_table = 0;
270static uint *green_scale_table = 0;
271static uint *blue_scale_table = 0;
272
273static void cleanup_scale_tables()
274{
275 delete[] red_scale_table;
276 delete[] green_scale_table;
277 delete[] blue_scale_table;
278}
279
280/*
281 Could do smart bitshifting, but the "obvious" algorithm only works for
282 nBits >= 4. This is more robust.
283*/
284static void build_scale_table(uint **table, uint nBits)
285{
286 if (nBits > 7) {
287 qWarning("build_scale_table: internal error, nBits = %i", nBits);
288 return;
289 }
290 if (!*table) {
291 static bool firstTable = true;
292 if (firstTable) {
293 qAddPostRoutine(cleanup_scale_tables);
294 firstTable = false;
295 }
296 *table = new uint[256];
297 }
298 int maxVal = (1 << nBits) - 1;
299 int valShift = 8 - nBits;
300 int i;
301 for(i = 0 ; i < maxVal + 1 ; i++)
302 (*table)[i << valShift] = i*255/maxVal;
303}
304
305static int defaultScreen = -1;
306
307/*****************************************************************************
308 QPixmap member functions
309 *****************************************************************************/
310
311static int qt_pixmap_serial = 0;
312int Q_GUI_EXPORT qt_x11_preferred_pixmap_depth = 0;
313
314QX11PixmapData::QX11PixmapData(PixelType type)
315 : QPixmapData(type, X11Class), hd(0), w(0), h(0), d(0),
316 uninit(true), read_only(false), x11_mask(0), picture(0), mask_picture(0), hd2(0),
317 share_mode(QPixmap::ImplicitlyShared), pengine(0)
318{
319}
320
321void QX11PixmapData::resize(int width, int height)
322{
323 setSerialNumber(++qt_pixmap_serial);
324
325 w = width;
326 h = height;
327
328 if (defaultScreen >= 0 && defaultScreen != xinfo.screen()) {
329 QX11InfoData* xd = xinfo.getX11Data(true);
330 xd->screen = defaultScreen;
331 xd->depth = QX11Info::appDepth(xd->screen);
332 xd->cells = QX11Info::appCells(xd->screen);
333 xd->colormap = QX11Info::appColormap(xd->screen);
334 xd->defaultColormap = QX11Info::appDefaultColormap(xd->screen);
335 xd->visual = (Visual *)QX11Info::appVisual(xd->screen);
336 xd->defaultVisual = QX11Info::appDefaultVisual(xd->screen);
337 xinfo.setX11Data(xd);
338 }
339
340 int dd = xinfo.depth();
341
342 if (qt_x11_preferred_pixmap_depth)
343 dd = qt_x11_preferred_pixmap_depth;
344
345 bool make_null = w <= 0 || h <= 0; // create null pixmap
346 d = (pixelType() == BitmapType ? 1 : dd);
347 if (make_null || d == 0) {
348 w = 0;
349 h = 0;
350 hd = 0;
351 picture = 0;
352 d = 0;
353 if (!make_null)
354 qWarning("QPixmap: Invalid pixmap parameters");
355 return;
356 }
357 hd = (Qt::HANDLE)XCreatePixmap(X11->display,
358 RootWindow(X11->display, xinfo.screen()),
359 w, h, d);
360#ifndef QT_NO_XRENDER
361 if (X11->use_xrender) {
362 XRenderPictFormat *format = d == 1
363 ? XRenderFindStandardFormat(X11->display, PictStandardA1)
364 : XRenderFindVisualFormat(X11->display, (Visual *)xinfo.visual());
365 picture = XRenderCreatePicture(X11->display, hd, format, 0, 0);
366 }
367#endif // QT_NO_XRENDER
368}
369
370void QX11PixmapData::fromImage(const QImage &img,
371 Qt::ImageConversionFlags flags)
372{
373 setSerialNumber(++qt_pixmap_serial);
374
375 w = img.width();
376 h = img.height();
377 d = img.depth();
378
379 if (defaultScreen >= 0 && defaultScreen != xinfo.screen()) {
380 QX11InfoData* xd = xinfo.getX11Data(true);
381 xd->screen = defaultScreen;
382 xd->depth = QX11Info::appDepth(xd->screen);
383 xd->cells = QX11Info::appCells(xd->screen);
384 xd->colormap = QX11Info::appColormap(xd->screen);
385 xd->defaultColormap = QX11Info::appDefaultColormap(xd->screen);
386 xd->visual = (Visual *)QX11Info::appVisual(xd->screen);
387 xd->defaultVisual = QX11Info::appDefaultVisual(xd->screen);
388 xinfo.setX11Data(xd);
389 }
390
391 if (pixelType() == BitmapType) {
392 bitmapFromImage(img);
393 return;
394 }
395
396 if (uint(w) >= 32768 || uint(h) >= 32768) {
397 w = h = 0;
398 return;
399 }
400
401 int dd = X11->use_xrender && img.hasAlphaChannel() ? 32 : xinfo.depth();
402 if (qt_x11_preferred_pixmap_depth)
403 dd = qt_x11_preferred_pixmap_depth;
404
405 QImage image = img;
406
407 // must be monochrome
408 if (dd == 1 || (flags & Qt::ColorMode_Mask) == Qt::MonoOnly) {
409 if (d != 1) {
410 // dither
411 image = image.convertToFormat(QImage::Format_MonoLSB, flags);
412 d = 1;
413 }
414 } else { // can be both
415 bool conv8 = false;
416 if (d > 8 && dd <= 8) { // convert to 8 bit
417 if ((flags & Qt::DitherMode_Mask) == Qt::AutoDither)
418 flags = (flags & ~Qt::DitherMode_Mask)
419 | Qt::PreferDither;
420 conv8 = true;
421 } else if ((flags & Qt::ColorMode_Mask) == Qt::ColorOnly) {
422 conv8 = (d == 1); // native depth wanted
423 } else if (d == 1) {
424 if (image.numColors() == 2) {
425 QRgb c0 = image.color(0); // Auto: convert to best
426 QRgb c1 = image.color(1);
427 conv8 = qMin(c0,c1) != qRgb(0,0,0) || qMax(c0,c1) != qRgb(255,255,255);
428 } else {
429 // eg. 1-color monochrome images (they do exist).
430 conv8 = true;
431 }
432 }
433 if (conv8) {
434 image = image.convertToFormat(QImage::Format_Indexed8, flags);
435 d = 8;
436 }
437 }
438
439 if (d == 1 || d == 16 || d == 24) {
440 image = image.convertToFormat(QImage::Format_RGB32, flags);
441 fromImage(image, Qt::AutoColor);
442 return;
443 }
444
445 Display *dpy = X11->display;
446 Visual *visual = (Visual *)xinfo.visual();
447 XImage *xi = 0;
448 bool trucol = (visual->c_class >= TrueColor);
449 int nbytes = image.numBytes();
450 uchar *newbits= 0;
451
452#ifndef QT_NO_XRENDER
453 if (X11->use_xrender && image.hasAlphaChannel()) {
454 const QImage &cimage = image;
455
456 d = 32;
457
458 if (QX11Info::appDepth() != d) {
459 if (xinfo.x11data) {
460 xinfo.x11data->depth = d;
461 } else {
462 QX11InfoData *xd = xinfo.getX11Data(true);
463 xd->screen = QX11Info::appScreen();
464 xd->depth = d;
465 xd->cells = QX11Info::appCells();
466 xd->colormap = QX11Info::appColormap();
467 xd->defaultColormap = QX11Info::appDefaultColormap();
468 xd->visual = (Visual *)QX11Info::appVisual();
469 xd->defaultVisual = QX11Info::appDefaultVisual();
470 xinfo.setX11Data(xd);
471 }
472 }
473
474 hd = (Qt::HANDLE)XCreatePixmap(dpy, RootWindow(dpy, xinfo.screen()),
475 w, h, d);
476 picture = XRenderCreatePicture(X11->display, hd,
477 XRenderFindStandardFormat(X11->display, PictStandardARGB32), 0, 0);
478
479 xi = XCreateImage(dpy, visual, d, ZPixmap, 0, 0, w, h, 32, 0);
480 Q_CHECK_PTR(xi);
481 newbits = (uchar *)malloc(xi->bytes_per_line*h);
482 Q_CHECK_PTR(newbits);
483 xi->data = (char *)newbits;
484
485 switch(cimage.format()) {
486 case QImage::Format_Indexed8: {
487 QVector<QRgb> colorTable = cimage.colorTable();
488 uint *xidata = (uint *)xi->data;
489 for (int y = 0; y < h; ++y) {
490 const uchar *p = cimage.scanLine(y);
491 for (int x = 0; x < w; ++x) {
492 const QRgb rgb = colorTable[p[x]];
493 const int a = qAlpha(rgb);
494 if (a == 0xff)
495 *xidata = rgb;
496 else
497 // RENDER expects premultiplied alpha
498 *xidata = qRgba(qt_div_255(qRed(rgb) * a),
499 qt_div_255(qGreen(rgb) * a),
500 qt_div_255(qBlue(rgb) * a),
501 a);
502 ++xidata;
503 }
504 }
505 }
506 break;
507 case QImage::Format_RGB32: {
508 uint *xidata = (uint *)xi->data;
509 for (int y = 0; y < h; ++y) {
510 const QRgb *p = (const QRgb *) cimage.scanLine(y);
511 for (int x = 0; x < w; ++x)
512 *xidata++ = p[x] | 0xff000000;
513 }
514 }
515 break;
516 case QImage::Format_ARGB32: {
517 uint *xidata = (uint *)xi->data;
518 for (int y = 0; y < h; ++y) {
519 const QRgb *p = (const QRgb *) cimage.scanLine(y);
520 for (int x = 0; x < w; ++x) {
521 const QRgb rgb = p[x];
522 const int a = qAlpha(rgb);
523 if (a == 0xff)
524 *xidata = rgb;
525 else
526 // RENDER expects premultiplied alpha
527 *xidata = qRgba(qt_div_255(qRed(rgb) * a),
528 qt_div_255(qGreen(rgb) * a),
529 qt_div_255(qBlue(rgb) * a),
530 a);
531 ++xidata;
532 }
533 }
534
535 }
536 break;
537 case QImage::Format_ARGB32_Premultiplied: {
538 uint *xidata = (uint *)xi->data;
539 for (int y = 0; y < h; ++y) {
540 const QRgb *p = (const QRgb *) cimage.scanLine(y);
541 memcpy(xidata, p, w*sizeof(QRgb));
542 xidata += w;
543 }
544 }
545 break;
546 default:
547 Q_ASSERT(false);
548 }
549
550 if ((xi->byte_order == MSBFirst) != (QSysInfo::ByteOrder == QSysInfo::BigEndian)) {
551 uint *xidata = (uint *)xi->data;
552 uint *xiend = xidata + w*h;
553 while (xidata < xiend) {
554 *xidata = (*xidata >> 24)
555 | ((*xidata >> 8) & 0xff00)
556 | ((*xidata << 8) & 0xff0000)
557 | (*xidata << 24);
558 ++xidata;
559 }
560 }
561
562 GC gc = XCreateGC(dpy, hd, 0, 0);
563 XPutImage(dpy, hd, gc, xi, 0, 0, 0, 0, w, h);
564 XFreeGC(dpy, gc);
565
566 qSafeXDestroyImage(xi);
567
568 return;
569 }
570#endif // QT_NO_XRENDER
571
572 if (trucol) { // truecolor display
573 if (image.format() == QImage::Format_ARGB32_Premultiplied)
574 image = image.convertToFormat(QImage::Format_ARGB32);
575
576 const QImage &cimage = image;
577 QRgb pix[256]; // pixel translation table
578 const bool d8 = (d == 8);
579 const uint red_mask = (uint)visual->red_mask;
580 const uint green_mask = (uint)visual->green_mask;
581 const uint blue_mask = (uint)visual->blue_mask;
582 const int red_shift = highest_bit(red_mask) - 7;
583 const int green_shift = highest_bit(green_mask) - 7;
584 const int blue_shift = highest_bit(blue_mask) - 7;
585 const uint rbits = highest_bit(red_mask) - lowest_bit(red_mask) + 1;
586 const uint gbits = highest_bit(green_mask) - lowest_bit(green_mask) + 1;
587 const uint bbits = highest_bit(blue_mask) - lowest_bit(blue_mask) + 1;
588
589 if (d8) { // setup pixel translation
590 QVector<QRgb> ctable = cimage.colorTable();
591 for (int i=0; i < cimage.numColors(); i++) {
592 int r = qRed (ctable[i]);
593 int g = qGreen(ctable[i]);
594 int b = qBlue (ctable[i]);
595 r = red_shift > 0 ? r << red_shift : r >> -red_shift;
596 g = green_shift > 0 ? g << green_shift : g >> -green_shift;
597 b = blue_shift > 0 ? b << blue_shift : b >> -blue_shift;
598 pix[i] = (b & blue_mask) | (g & green_mask) | (r & red_mask)
599 | ~(blue_mask | green_mask | red_mask);
600 }
601 }
602
603 xi = XCreateImage(dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0);
604 Q_CHECK_PTR(xi);
605 newbits = (uchar *)malloc(xi->bytes_per_line*h);
606 Q_CHECK_PTR(newbits);
607 if (!newbits) // no memory
608 return;
609 int bppc = xi->bits_per_pixel;
610
611 bool contig_bits = n_bits(red_mask) == rbits &&
612 n_bits(green_mask) == gbits &&
613 n_bits(blue_mask) == bbits;
614 bool dither_tc =
615 // Want it?
616 (flags & Qt::Dither_Mask) != Qt::ThresholdDither &&
617 (flags & Qt::DitherMode_Mask) != Qt::AvoidDither &&
618 // Need it?
619 bppc < 24 && !d8 &&
620 // Can do it? (Contiguous bits?)
621 contig_bits;
622
623 static bool init=false;
624 static int D[16][16];
625 if (dither_tc && !init) {
626 // I also contributed this code to XV - WWA.
627 /*
628 The dither matrix, D, is obtained with this formula:
629
630 D2 = [0 2]
631 [3 1]
632
633
634 D2*n = [4*Dn 4*Dn+2*Un]
635 [4*Dn+3*Un 4*Dn+1*Un]
636 */
637 int n,i,j;
638 init=1;
639
640 /* Set D2 */
641 D[0][0]=0;
642 D[1][0]=2;
643 D[0][1]=3;
644 D[1][1]=1;
645
646 /* Expand using recursive definition given above */
647 for (n=2; n<16; n*=2) {
648 for (i=0; i<n; i++) {
649 for (j=0; j<n; j++) {
650 D[i][j]*=4;
651 D[i+n][j]=D[i][j]+2;
652 D[i][j+n]=D[i][j]+3;
653 D[i+n][j+n]=D[i][j]+1;
654 }
655 }
656 }
657 init=true;
658 }
659
660 enum { BPP8,
661 BPP16_565, BPP16_555,
662 BPP16_MSB, BPP16_LSB,
663 BPP24_888,
664 BPP24_MSB, BPP24_LSB,
665 BPP32_8888,
666 BPP32_MSB, BPP32_LSB
667 } mode = BPP8;
668
669 bool same_msb_lsb = (xi->byte_order == MSBFirst) == (QSysInfo::ByteOrder == QSysInfo::BigEndian);
670
671 if(bppc == 8) // 8 bit
672 mode = BPP8;
673 else if(bppc == 16) { // 16 bit MSB/LSB
674 if(red_shift == 8 && green_shift == 3 && blue_shift == -3 && !d8 && same_msb_lsb)
675 mode = BPP16_565;
676 else if(red_shift == 7 && green_shift == 2 && blue_shift == -3 && !d8 && same_msb_lsb)
677 mode = BPP16_555;
678 else
679 mode = (xi->byte_order == LSBFirst) ? BPP16_LSB : BPP16_MSB;
680 } else if(bppc == 24) { // 24 bit MSB/LSB
681 if (red_shift == 16 && green_shift == 8 && blue_shift == 0 && !d8 && same_msb_lsb)
682 mode = BPP24_888;
683 else
684 mode = (xi->byte_order == LSBFirst) ? BPP24_LSB : BPP24_MSB;
685 } else if(bppc == 32) { // 32 bit MSB/LSB
686 if(red_shift == 16 && green_shift == 8 && blue_shift == 0 && !d8 && same_msb_lsb)
687 mode = BPP32_8888;
688 else
689 mode = (xi->byte_order == LSBFirst) ? BPP32_LSB : BPP32_MSB;
690 } else
691 qFatal("Logic error 3");
692
693#define GET_PIXEL \
694 uint pixel; \
695 if (d8) pixel = pix[*src++]; \
696 else { \
697 int r = qRed (*p); \
698 int g = qGreen(*p); \
699 int b = qBlue (*p++); \
700 r = red_shift > 0 \
701 ? r << red_shift : r >> -red_shift; \
702 g = green_shift > 0 \
703 ? g << green_shift : g >> -green_shift; \
704 b = blue_shift > 0 \
705 ? b << blue_shift : b >> -blue_shift; \
706 pixel = (r & red_mask)|(g & green_mask) | (b & blue_mask) \
707 | ~(blue_mask | green_mask | red_mask); \
708 }
709
710#define GET_PIXEL_DITHER_TC \
711 int r = qRed (*p); \
712 int g = qGreen(*p); \
713 int b = qBlue (*p++); \
714 const int thres = D[x%16][y%16]; \
715 if (r <= (255-(1<<(8-rbits))) && ((r<<rbits) & 255) \
716 > thres) \
717 r += (1<<(8-rbits)); \
718 if (g <= (255-(1<<(8-gbits))) && ((g<<gbits) & 255) \
719 > thres) \
720 g += (1<<(8-gbits)); \
721 if (b <= (255-(1<<(8-bbits))) && ((b<<bbits) & 255) \
722 > thres) \
723 b += (1<<(8-bbits)); \
724 r = red_shift > 0 \
725 ? r << red_shift : r >> -red_shift; \
726 g = green_shift > 0 \
727 ? g << green_shift : g >> -green_shift; \
728 b = blue_shift > 0 \
729 ? b << blue_shift : b >> -blue_shift; \
730 uint pixel = (r & red_mask)|(g & green_mask) | (b & blue_mask);
731
732// again, optimized case
733// can't be optimized that much :(
734#define GET_PIXEL_DITHER_TC_OPT(red_shift,green_shift,blue_shift,red_mask,green_mask,blue_mask, \
735 rbits,gbits,bbits) \
736 const int thres = D[x%16][y%16]; \
737 int r = qRed (*p); \
738 if (r <= (255-(1<<(8-rbits))) && ((r<<rbits) & 255) \
739 > thres) \
740 r += (1<<(8-rbits)); \
741 int g = qGreen(*p); \
742 if (g <= (255-(1<<(8-gbits))) && ((g<<gbits) & 255) \
743 > thres) \
744 g += (1<<(8-gbits)); \
745 int b = qBlue (*p++); \
746 if (b <= (255-(1<<(8-bbits))) && ((b<<bbits) & 255) \
747 > thres) \
748 b += (1<<(8-bbits)); \
749 uint pixel = ((r red_shift) & red_mask) \
750 | ((g green_shift) & green_mask) \
751 | ((b blue_shift) & blue_mask);
752
753#define CYCLE(body) \
754 for (int y=0; y<h; y++) { \
755 const uchar* src = cimage.scanLine(y); \
756 uchar* dst = newbits + xi->bytes_per_line*y; \
757 const QRgb* p = (const QRgb *)src; \
758 body \
759 }
760
761 if (dither_tc) {
762 switch (mode) {
763 case BPP16_565:
764 CYCLE(
765 quint16* dst16 = (quint16*)dst;
766 for (int x=0; x<w; x++) {
767 GET_PIXEL_DITHER_TC_OPT(<<8,<<3,>>3,0xf800,0x7e0,0x1f,5,6,5)
768 *dst16++ = pixel;
769 }
770 )
771 break;
772 case BPP16_555:
773 CYCLE(
774 quint16* dst16 = (quint16*)dst;
775 for (int x=0; x<w; x++) {
776 GET_PIXEL_DITHER_TC_OPT(<<7,<<2,>>3,0x7c00,0x3e0,0x1f,5,5,5)
777 *dst16++ = pixel;
778 }
779 )
780 break;
781 case BPP16_MSB: // 16 bit MSB
782 CYCLE(
783 for (int x=0; x<w; x++) {
784 GET_PIXEL_DITHER_TC
785 *dst++ = (pixel >> 8);
786 *dst++ = pixel;
787 }
788 )
789 break;
790 case BPP16_LSB: // 16 bit LSB
791 CYCLE(
792 for (int x=0; x<w; x++) {
793 GET_PIXEL_DITHER_TC
794 *dst++ = pixel;
795 *dst++ = pixel >> 8;
796 }
797 )
798 break;
799 default:
800 qFatal("Logic error");
801 }
802 } else {
803 switch (mode) {
804 case BPP8: // 8 bit
805 CYCLE(
806 Q_UNUSED(p);
807 for (int x=0; x<w; x++)
808 *dst++ = pix[*src++];
809 )
810 break;
811 case BPP16_565:
812 CYCLE(
813 quint16* dst16 = (quint16*)dst;
814 for (int x = 0; x < w; x++) {
815 *dst16++ = ((*p >> 8) & 0xf800)
816 | ((*p >> 5) & 0x7e0)
817 | ((*p >> 3) & 0x1f);
818 ++p;
819 }
820 )
821 break;
822 case BPP16_555:
823 CYCLE(
824 quint16* dst16 = (quint16*)dst;
825 for (int x=0; x<w; x++) {
826 *dst16++ = ((*p >> 9) & 0x7c00)
827 | ((*p >> 6) & 0x3e0)
828 | ((*p >> 3) & 0x1f);
829 ++p;
830 }
831 )
832 break;
833 case BPP16_MSB: // 16 bit MSB
834 CYCLE(
835 for (int x=0; x<w; x++) {
836 GET_PIXEL
837 *dst++ = (pixel >> 8);
838 *dst++ = pixel;
839 }
840 )
841 break;
842 case BPP16_LSB: // 16 bit LSB
843 CYCLE(
844 for (int x=0; x<w; x++) {
845 GET_PIXEL
846 *dst++ = pixel;
847 *dst++ = pixel >> 8;
848 }
849 )
850 break;
851 case BPP24_888: // 24 bit MSB
852 CYCLE(
853 for (int x=0; x<w; x++) {
854 *dst++ = qRed (*p);
855 *dst++ = qGreen(*p);
856 *dst++ = qBlue (*p++);
857 }
858 )
859 break;
860 case BPP24_MSB: // 24 bit MSB
861 CYCLE(
862 for (int x=0; x<w; x++) {
863 GET_PIXEL
864 *dst++ = pixel >> 16;
865 *dst++ = pixel >> 8;
866 *dst++ = pixel;
867 }
868 )
869 break;
870 case BPP24_LSB: // 24 bit LSB
871 CYCLE(
872 for (int x=0; x<w; x++) {
873 GET_PIXEL
874 *dst++ = pixel;
875 *dst++ = pixel >> 8;
876 *dst++ = pixel >> 16;
877 }
878 )
879 break;
880 case BPP32_8888:
881 CYCLE(
882 memcpy(dst, p, w * 4);
883 )
884 break;
885 case BPP32_MSB: // 32 bit MSB
886 CYCLE(
887 for (int x=0; x<w; x++) {
888 GET_PIXEL
889 *dst++ = pixel >> 24;
890 *dst++ = pixel >> 16;
891 *dst++ = pixel >> 8;
892 *dst++ = pixel;
893 }
894 )
895 break;
896 case BPP32_LSB: // 32 bit LSB
897 CYCLE(
898 for (int x=0; x<w; x++) {
899 GET_PIXEL
900 *dst++ = pixel;
901 *dst++ = pixel >> 8;
902 *dst++ = pixel >> 16;
903 *dst++ = pixel >> 24;
904 }
905 )
906 break;
907 default:
908 qFatal("Logic error 2");
909 }
910 }
911 xi->data = (char *)newbits;
912 }
913
914 if (d == 8 && !trucol) { // 8 bit pixmap
915 int pop[256]; // pixel popularity
916
917 if (image.numColors() == 0)
918 image.setNumColors(1);
919
920 const QImage &cimage = image;
921 memset(pop, 0, sizeof(int)*256); // reset popularity array
922 for (int i = 0; i < h; i++) { // for each scanline...
923 const uchar* p = cimage.scanLine(i);
924 const uchar *end = p + w;
925 while (p < end) // compute popularity
926 pop[*p++]++;
927 }
928
929 newbits = (uchar *)malloc(nbytes); // copy image into newbits
930 Q_CHECK_PTR(newbits);
931 if (!newbits) // no memory
932 return;
933 uchar* p = newbits;
934 memcpy(p, cimage.bits(), nbytes); // copy image data into newbits
935
936 /*
937 * The code below picks the most important colors. It is based on the
938 * diversity algorithm, implemented in XV 3.10. XV is (C) by John Bradley.
939 */
940
941 struct PIX { // pixel sort element
942 uchar r,g,b,n; // color + pad
943 int use; // popularity
944 int index; // index in colormap
945 int mindist;
946 };
947 int ncols = 0;
948 for (int i=0; i< cimage.numColors(); i++) { // compute number of colors
949 if (pop[i] > 0)
950 ncols++;
951 }
952 for (int i = cimage.numColors(); i < 256; i++) // ignore out-of-range pixels
953 pop[i] = 0;
954
955 // works since we make sure above to have at least
956 // one color in the image
957 if (ncols == 0)
958 ncols = 1;
959
960 PIX pixarr[256]; // pixel array
961 PIX pixarr_sorted[256]; // pixel array (sorted)
962 memset(pixarr, 0, ncols*sizeof(PIX));
963 PIX *px = &pixarr[0];
964 int maxpop = 0;
965 int maxpix = 0;
966 uint j = 0;
967 QVector<QRgb> ctable = cimage.colorTable();
968 for (int i = 0; i < 256; i++) { // init pixel array
969 if (pop[i] > 0) {
970 px->r = qRed (ctable[i]);
971 px->g = qGreen(ctable[i]);
972 px->b = qBlue (ctable[i]);
973 px->n = 0;
974 px->use = pop[i];
975 if (pop[i] > maxpop) { // select most popular entry
976 maxpop = pop[i];
977 maxpix = j;
978 }
979 px->index = i;
980 px->mindist = 1000000;
981 px++;
982 j++;
983 }
984 }
985 pixarr_sorted[0] = pixarr[maxpix];
986 pixarr[maxpix].use = 0;
987
988 for (int i = 1; i < ncols; i++) { // sort pixels
989 int minpix = -1, mindist = -1;
990 px = &pixarr_sorted[i-1];
991 int r = px->r;
992 int g = px->g;
993 int b = px->b;
994 int dist;
995 if ((i & 1) || i<10) { // sort on max distance
996 for (int j=0; j<ncols; j++) {
997 px = &pixarr[j];
998 if (px->use) {
999 dist = (px->r - r)*(px->r - r) +
1000 (px->g - g)*(px->g - g) +
1001 (px->b - b)*(px->b - b);
1002 if (px->mindist > dist)
1003 px->mindist = dist;
1004 if (px->mindist > mindist) {
1005 mindist = px->mindist;
1006 minpix = j;
1007 }
1008 }
1009 }
1010 } else { // sort on max popularity
1011 for (int j=0; j<ncols; j++) {
1012 px = &pixarr[j];
1013 if (px->use) {
1014 dist = (px->r - r)*(px->r - r) +
1015 (px->g - g)*(px->g - g) +
1016 (px->b - b)*(px->b - b);
1017 if (px->mindist > dist)
1018 px->mindist = dist;
1019 if (px->use > mindist) {
1020 mindist = px->use;
1021 minpix = j;
1022 }
1023 }
1024 }
1025 }
1026 pixarr_sorted[i] = pixarr[minpix];
1027 pixarr[minpix].use = 0;
1028 }
1029
1030 QColormap cmap = QColormap::instance(xinfo.screen());
1031 uint pix[256]; // pixel translation table
1032 px = &pixarr_sorted[0];
1033 for (int i = 0; i < ncols; i++) { // allocate colors
1034 QColor c(px->r, px->g, px->b);
1035 pix[px->index] = cmap.pixel(c);
1036 px++;
1037 }
1038
1039 p = newbits;
1040 for (int i = 0; i < nbytes; i++) { // translate pixels
1041 *p = pix[*p];
1042 p++;
1043 }
1044 }
1045
1046 if (!xi) { // X image not created
1047 xi = XCreateImage(dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0);
1048 if (xi->bits_per_pixel == 16) { // convert 8 bpp ==> 16 bpp
1049 ushort *p2;
1050 int p2inc = xi->bytes_per_line/sizeof(ushort);
1051 ushort *newerbits = (ushort *)malloc(xi->bytes_per_line * h);
1052 Q_CHECK_PTR(newerbits);
1053 if (!newerbits) // no memory
1054 return;
1055 uchar* p = newbits;
1056 for (int y = 0; y < h; y++) { // OOPS: Do right byte order!!
1057 p2 = newerbits + p2inc*y;
1058 for (int x = 0; x < w; x++)
1059 *p2++ = *p++;
1060 }
1061 free(newbits);
1062 newbits = (uchar *)newerbits;
1063 } else if (xi->bits_per_pixel != 8) {
1064 qWarning("QPixmap::fromImage: Display not supported "
1065 "(bpp=%d)", xi->bits_per_pixel);
1066 }
1067 xi->data = (char *)newbits;
1068 }
1069
1070 hd = (Qt::HANDLE)XCreatePixmap(X11->display,
1071 RootWindow(X11->display, xinfo.screen()),
1072 w, h, dd);
1073
1074 GC gc = XCreateGC(dpy, hd, 0, 0);
1075 XPutImage(dpy, hd, gc, xi, 0, 0, 0, 0, w, h);
1076 XFreeGC(dpy, gc);
1077
1078 qSafeXDestroyImage(xi);
1079 d = dd;
1080
1081#ifndef QT_NO_XRENDER
1082 if (X11->use_xrender) {
1083 XRenderPictFormat *format = d == 1
1084 ? XRenderFindStandardFormat(X11->display, PictStandardA1)
1085 : XRenderFindVisualFormat(X11->display, (Visual *)xinfo.visual());
1086 picture = XRenderCreatePicture(X11->display, hd, format, 0, 0);
1087 }
1088#endif
1089
1090 if (image.hasAlphaChannel()) {
1091 QBitmap m = QBitmap::fromImage(image.createAlphaMask(flags));
1092 setMask(m);
1093 }
1094}
1095
1096void QX11PixmapData::bitmapFromImage(const QImage &image)
1097{
1098 QImage img = image.convertToFormat(QImage::Format_MonoLSB);
1099 const QRgb c0 = QColor(Qt::black).rgb();
1100 const QRgb c1 = QColor(Qt::white).rgb();
1101 if (img.color(0) == c0 && img.color(1) == c1) {
1102 img.invertPixels();
1103 img.setColor(0, c1);
1104 img.setColor(1, c0);
1105 }
1106
1107 char *bits;
1108 uchar *tmp_bits;
1109 w = img.width();
1110 h = img.height();
1111 d = 1;
1112 int bpl = (w + 7) / 8;
1113 int ibpl = img.bytesPerLine();
1114 if (bpl != ibpl) {
1115 tmp_bits = new uchar[bpl*h];
1116 bits = (char *)tmp_bits;
1117 uchar *p, *b;
1118 int y;
1119 b = tmp_bits;
1120 p = img.scanLine(0);
1121 for (y = 0; y < h; y++) {
1122 memcpy(b, p, bpl);
1123 b += bpl;
1124 p += ibpl;
1125 }
1126 } else {
1127 bits = (char *)img.bits();
1128 tmp_bits = 0;
1129 }
1130 hd = (Qt::HANDLE)XCreateBitmapFromData(xinfo.display(),
1131 RootWindow(xinfo.display(), xinfo.screen()),
1132 bits, w, h);
1133
1134#ifndef QT_NO_XRENDER
1135 if (X11->use_xrender)
1136 picture = XRenderCreatePicture(X11->display, hd,
1137 XRenderFindStandardFormat(X11->display, PictStandardA1), 0, 0);
1138#endif // QT_NO_XRENDER
1139
1140 if (tmp_bits) // Avoid purify complaint
1141 delete [] tmp_bits;
1142}
1143
1144void QX11PixmapData::fill(const QColor &fillColor)
1145{
1146 if (fillColor.alpha() != 255) {
1147#ifndef QT_NO_XRENDER
1148 if (X11->use_xrender) {
1149 if (!picture || d != 32)
1150 convertToARGB32(/*preserveContents = */false);
1151
1152 ::Picture src = X11->getSolidFill(xinfo.screen(), fillColor);
1153 XRenderComposite(X11->display, PictOpSrc, src, 0, picture,
1154 0, 0, width(), height(),
1155 0, 0, width(), height());
1156 } else
1157#endif
1158 {
1159 QImage im(width(), height(), QImage::Format_ARGB32_Premultiplied);
1160 im.fill(PREMUL(fillColor.rgba()));
1161 release();
1162 fromImage(im, Qt::AutoColor | Qt::OrderedAlphaDither);
1163 }
1164 return;
1165 }
1166
1167 GC gc = XCreateGC(X11->display, hd, 0, 0);
1168 if (depth() == 1) {
1169 XSetForeground(X11->display, gc, qGray(fillColor.rgb()) > 127 ? 0 : 1);
1170 } else if (X11->use_xrender && d >= 24) {
1171 XSetForeground(X11->display, gc, fillColor.rgba());
1172 } else {
1173 XSetForeground(X11->display, gc,
1174 QColormap::instance(xinfo.screen()).pixel(fillColor));
1175 }
1176 XFillRectangle(X11->display, hd, gc, 0, 0, width(), height());
1177 XFreeGC(X11->display, gc);
1178}
1179
1180QX11PixmapData::~QX11PixmapData()
1181{
1182 release();
1183}
1184
1185void QX11PixmapData::release()
1186{
1187 delete pengine;
1188 pengine = 0;
1189
1190 if (!X11)
1191 return;
1192
1193 if (x11_mask) {
1194#ifndef QT_NO_XRENDER
1195 if (mask_picture)
1196 XRenderFreePicture(X11->display, mask_picture);
1197 mask_picture = 0;
1198#endif
1199 XFreePixmap(X11->display, x11_mask);
1200 x11_mask = 0;
1201 }
1202
1203 if (hd) {
1204#ifndef QT_NO_XRENDER
1205 if (picture) {
1206 XRenderFreePicture(X11->display, picture);
1207 picture = 0;
1208 }
1209#endif // QT_NO_XRENDER
1210
1211 if (hd2) {
1212 XFreePixmap(xinfo.display(), hd2);
1213 hd2 = 0;
1214 }
1215 if (!read_only)
1216 XFreePixmap(xinfo.display(), hd);
1217 hd = 0;
1218 }
1219}
1220
1221QPixmap QX11PixmapData::alphaChannel() const
1222{
1223 if (!hasAlphaChannel())
1224 return QPixmap();
1225 QImage im(toImage());
1226 return QPixmap::fromImage(im.alphaChannel(), Qt::OrderedDither);
1227}
1228
1229void QX11PixmapData::setAlphaChannel(const QPixmap &alpha)
1230{
1231 QImage image(toImage());
1232 image.setAlphaChannel(alpha.toImage());
1233 release();
1234 fromImage(image, Qt::OrderedDither | Qt::OrderedAlphaDither);
1235}
1236
1237
1238QBitmap QX11PixmapData::mask() const
1239{
1240 QBitmap mask;
1241#ifndef QT_NO_XRENDER
1242 if (picture && d == 32) {
1243 // #### slow - there must be a better way..
1244 mask = QBitmap::fromImage(toImage().createAlphaMask());
1245 } else
1246#endif
1247 if (d == 1) {
1248 QX11PixmapData *that = const_cast<QX11PixmapData*>(this);
1249 mask = QPixmap(that);
1250 } else {
1251 mask = mask_to_bitmap(xinfo.screen());
1252 }
1253 return mask;
1254}
1255
1256
1257/*!
1258 Sets a mask bitmap.
1259
1260 The \a newmask bitmap defines the clip mask for this pixmap. Every
1261 pixel in \a newmask corresponds to a pixel in this pixmap. Pixel
1262 value 1 means opaque and pixel value 0 means transparent. The mask
1263 must have the same size as this pixmap.
1264
1265 \warning Setting the mask on a pixmap will cause any alpha channel
1266 data to be cleared. For example:
1267 \snippet doc/src/snippets/image/image.cpp 2
1268 Now, alpha and alphacopy are visually different.
1269
1270 Setting a null mask resets the mask.
1271
1272 The effect of this function is undefined when the pixmap is being
1273 painted on.
1274
1275 \sa mask(), {QPixmap#Pixmap Transformations}{Pixmap
1276 Transformations}, QBitmap
1277*/
1278void QX11PixmapData::setMask(const QBitmap &newmask)
1279{
1280 if (newmask.isNull()) { // clear mask
1281#ifndef QT_NO_XRENDER
1282 if (picture && d == 32) {
1283 QX11PixmapData newData(pixelType());
1284 newData.resize(w, h);
1285 newData.fill(Qt::black);
1286 XRenderComposite(X11->display, PictOpOver,
1287 picture, 0, newData.picture,
1288 0, 0, 0, 0, 0, 0, w, h);
1289 release();
1290 *this = newData;
1291 // the new QX11PixmapData object isn't referenced yet, so
1292 // ref it
1293 ref.ref();
1294
1295 // the below is to make sure the QX11PixmapData destructor
1296 // doesn't delete our newly created render picture
1297 newData.hd = 0;
1298 newData.x11_mask = 0;
1299 newData.picture = 0;
1300 newData.mask_picture = 0;
1301 newData.hd2 = 0;
1302 } else
1303#endif
1304 if (x11_mask) {
1305#ifndef QT_NO_XRENDER
1306 if (picture) {
1307 XRenderPictureAttributes attrs;
1308 attrs.alpha_map = 0;
1309 XRenderChangePicture(X11->display, picture, CPAlphaMap,
1310 &attrs);
1311 }
1312 if (mask_picture)
1313 XRenderFreePicture(X11->display, mask_picture);
1314 mask_picture = 0;
1315#endif
1316 XFreePixmap(X11->display, x11_mask);
1317 x11_mask = 0;
1318 }
1319 return;
1320 }
1321
1322#ifndef QT_NO_XRENDER
1323 if (picture && d == 32) {
1324 XRenderComposite(X11->display, PictOpSrc,
1325 picture, newmask.x11PictureHandle(),
1326 picture, 0, 0, 0, 0, 0, 0, w, h);
1327 } else
1328#endif
1329 if (depth() == 1) {
1330 XGCValues vals;
1331 vals.function = GXand;
1332 GC gc = XCreateGC(X11->display, hd, GCFunction, &vals);
1333 XCopyArea(X11->display, newmask.handle(), hd, gc, 0, 0,
1334 width(), height(), 0, 0);
1335 XFreeGC(X11->display, gc);
1336 } else {
1337 // ##### should or the masks together
1338 if (x11_mask) {
1339 XFreePixmap(X11->display, x11_mask);
1340#ifndef QT_NO_XRENDER
1341 if (mask_picture)
1342 XRenderFreePicture(X11->display, mask_picture);
1343#endif
1344 }
1345 x11_mask = QX11PixmapData::bitmap_to_mask(newmask, xinfo.screen());
1346#ifndef QT_NO_XRENDER
1347 if (picture) {
1348 mask_picture = XRenderCreatePicture(X11->display, x11_mask,
1349 XRenderFindStandardFormat(X11->display, PictStandardA1), 0, 0);
1350 XRenderPictureAttributes attrs;
1351 attrs.alpha_map = mask_picture;
1352 XRenderChangePicture(X11->display, picture, CPAlphaMap, &attrs);
1353 }
1354#endif
1355 }
1356}
1357
1358int QX11PixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const
1359{
1360 switch (metric) {
1361 case QPaintDevice::PdmWidth:
1362 return w;
1363 case QPaintDevice::PdmHeight:
1364 return h;
1365 case QPaintDevice::PdmNumColors:
1366 return 1 << d;
1367 case QPaintDevice::PdmDepth:
1368 return d;
1369 case QPaintDevice::PdmWidthMM: {
1370 const int screen = xinfo.screen();
1371 const int mm = DisplayWidthMM(X11->display, screen) * w
1372 / DisplayWidth(X11->display, screen);
1373 return mm;
1374 }
1375 case QPaintDevice::PdmHeightMM: {
1376 const int screen = xinfo.screen();
1377 const int mm = (DisplayHeightMM(X11->display, screen) * h)
1378 / DisplayHeight(X11->display, screen);
1379 return mm;
1380 }
1381 case QPaintDevice::PdmDpiX:
1382 case QPaintDevice::PdmPhysicalDpiX:
1383 return QX11Info::appDpiX(xinfo.screen());
1384 case QPaintDevice::PdmDpiY:
1385 case QPaintDevice::PdmPhysicalDpiY:
1386 return QX11Info::appDpiY(xinfo.screen());
1387 default:
1388 qWarning("QX11PixmapData::metric(): Invalid metric");
1389 return 0;
1390 }
1391}
1392
1393/*!
1394 Converts the pixmap to a QImage. Returns a null image if the
1395 conversion fails.
1396
1397 If the pixmap has 1-bit depth, the returned image will also be 1
1398 bit deep. If the pixmap has 2- to 8-bit depth, the returned image
1399 has 8-bit depth. If the pixmap has greater than 8-bit depth, the
1400 returned image has 32-bit depth.
1401
1402 Note that for the moment, alpha masks on monochrome images are
1403 ignored.
1404
1405 \sa fromImage(), {QImage#Image Formats}{Image Formats}
1406*/
1407
1408QImage QX11PixmapData::toImage() const
1409{
1410 int d = depth();
1411 Visual *visual = (Visual *)xinfo.visual();
1412 bool trucol = (visual->c_class >= TrueColor) && d > 1;
1413
1414 QImage::Format format = QImage::Format_Mono;
1415 if (d > 1 && d <= 8) {
1416 d = 8;
1417 format = QImage::Format_Indexed8;
1418 }
1419 // we could run into the situation where d == 8 AND trucol is true, which can
1420 // cause problems when converting to and from images. in this case, always treat
1421 // the depth as 32...
1422 if (d > 8 || trucol) {
1423 d = 32;
1424 format = QImage::Format_RGB32;
1425 }
1426
1427 XImage *xi = XGetImage(X11->display, hd, 0, 0, w, h, AllPlanes,
1428 (d == 1) ? XYPixmap : ZPixmap);
1429
1430 Q_CHECK_PTR(xi);
1431 if (!xi)
1432 return QImage();
1433
1434 if (picture && depth() == 32) {
1435 QImage image(w, h, QImage::Format_ARGB32_Premultiplied);
1436 memcpy(image.bits(), xi->data, xi->bytes_per_line * xi->height);
1437
1438 // we may have to swap the byte order
1439 if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && xi->byte_order == MSBFirst)
1440 || (QSysInfo::ByteOrder == QSysInfo::BigEndian))
1441 {
1442 for (int i=0; i < image.height(); i++) {
1443 uint *p = (uint*)image.scanLine(i);
1444 uint *end = p + image.width();
1445 if ((xi->byte_order == LSBFirst && QSysInfo::ByteOrder == QSysInfo::BigEndian)
1446 || (xi->byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::LittleEndian)) {
1447 while (p < end) {
1448 *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000)
1449 | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff);
1450 p++;
1451 }
1452 } else if (xi->byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::BigEndian) {
1453 while (p < end) {
1454 *p = ((*p << 16) & 0x00ff0000) | ((*p >> 16) & 0x000000ff)
1455 | ((*p ) & 0xff00ff00);
1456 p++;
1457 }
1458 }
1459 }
1460 }
1461
1462 // throw away image data
1463 qSafeXDestroyImage(xi);
1464
1465 return image;
1466 }
1467
1468 if (d == 1 && xi->bitmap_bit_order == LSBFirst)
1469 format = QImage::Format_MonoLSB;
1470 if (x11_mask && format == QImage::Format_RGB32)
1471 format = QImage::Format_ARGB32;
1472
1473 QImage image(w, h, format);
1474 if (image.isNull()) // could not create image
1475 return image;
1476
1477 QImage alpha;
1478 if (x11_mask) {
1479 alpha = mask().toImage();
1480 }
1481 bool ale = alpha.format() == QImage::Format_MonoLSB;
1482
1483 if (trucol) { // truecolor
1484 const uint red_mask = (uint)visual->red_mask;
1485 const uint green_mask = (uint)visual->green_mask;
1486 const uint blue_mask = (uint)visual->blue_mask;
1487 const int red_shift = highest_bit(red_mask) - 7;
1488 const int green_shift = highest_bit(green_mask) - 7;
1489 const int blue_shift = highest_bit(blue_mask) - 7;
1490
1491 const uint red_bits = n_bits(red_mask);
1492 const uint green_bits = n_bits(green_mask);
1493 const uint blue_bits = n_bits(blue_mask);
1494
1495 static uint red_table_bits = 0;
1496 static uint green_table_bits = 0;
1497 static uint blue_table_bits = 0;
1498
1499 if (red_bits < 8 && red_table_bits != red_bits) {
1500 build_scale_table(&red_scale_table, red_bits);
1501 red_table_bits = red_bits;
1502 }
1503 if (blue_bits < 8 && blue_table_bits != blue_bits) {
1504 build_scale_table(&blue_scale_table, blue_bits);
1505 blue_table_bits = blue_bits;
1506 }
1507 if (green_bits < 8 && green_table_bits != green_bits) {
1508 build_scale_table(&green_scale_table, green_bits);
1509 green_table_bits = green_bits;
1510 }
1511
1512 int r, g, b;
1513
1514 QRgb *dst;
1515 uchar *src;
1516 uint pixel;
1517 int bppc = xi->bits_per_pixel;
1518
1519 if (bppc > 8 && xi->byte_order == LSBFirst)
1520 bppc++;
1521
1522 for (int y = 0; y < h; ++y) {
1523 uchar* asrc = x11_mask ? alpha.scanLine(y) : 0;
1524 dst = (QRgb *)image.scanLine(y);
1525 src = (uchar *)xi->data + xi->bytes_per_line*y;
1526 for (int x = 0; x < w; x++) {
1527 switch (bppc) {
1528 case 8:
1529 pixel = *src++;
1530 break;
1531 case 16: // 16 bit MSB
1532 pixel = src[1] | (uint)src[0] << 8;
1533 src += 2;
1534 break;
1535 case 17: // 16 bit LSB
1536 pixel = src[0] | (uint)src[1] << 8;
1537 src += 2;
1538 break;
1539 case 24: // 24 bit MSB
1540 pixel = src[2] | (uint)src[1] << 8 | (uint)src[0] << 16;
1541 src += 3;
1542 break;
1543 case 25: // 24 bit LSB
1544 pixel = src[0] | (uint)src[1] << 8 | (uint)src[2] << 16;
1545 src += 3;
1546 break;
1547 case 32: // 32 bit MSB
1548 pixel = src[3] | (uint)src[2] << 8 | (uint)src[1] << 16 | (uint)src[0] << 24;
1549 src += 4;
1550 break;
1551 case 33: // 32 bit LSB
1552 pixel = src[0] | (uint)src[1] << 8 | (uint)src[2] << 16 | (uint)src[3] << 24;
1553 src += 4;
1554 break;
1555 default: // should not really happen
1556 x = w; // leave loop
1557 y = h;
1558 pixel = 0; // eliminate compiler warning
1559 qWarning("QPixmap::convertToImage: Invalid depth %d", bppc);
1560 }
1561 if (red_shift > 0)
1562 r = (pixel & red_mask) >> red_shift;
1563 else
1564 r = (pixel & red_mask) << -red_shift;
1565 if (green_shift > 0)
1566 g = (pixel & green_mask) >> green_shift;
1567 else
1568 g = (pixel & green_mask) << -green_shift;
1569 if (blue_shift > 0)
1570 b = (pixel & blue_mask) >> blue_shift;
1571 else
1572 b = (pixel & blue_mask) << -blue_shift;
1573
1574 if (red_bits < 8)
1575 r = red_scale_table[r];
1576 if (green_bits < 8)
1577 g = green_scale_table[g];
1578 if (blue_bits < 8)
1579 b = blue_scale_table[b];
1580
1581 if (x11_mask) {
1582 if (ale) {
1583 *dst++ = (asrc[x >> 3] & (1 << (x & 7))) ? qRgba(r, g, b, 0xff) : 0;
1584 } else {
1585 *dst++ = (asrc[x >> 3] & (0x80 >> (x & 7))) ? qRgba(r, g, b, 0xff) : 0;
1586 }
1587 } else {
1588 *dst++ = qRgb(r, g, b);
1589 }
1590 }
1591 }
1592 } else if (xi->bits_per_pixel == d) { // compatible depth
1593 char *xidata = xi->data; // copy each scanline
1594 int bpl = qMin(image.bytesPerLine(),xi->bytes_per_line);
1595 for (int y=0; y<h; y++) {
1596 memcpy(image.scanLine(y), xidata, bpl);
1597 xidata += xi->bytes_per_line;
1598 }
1599 } else {
1600 /* Typically 2 or 4 bits display depth */
1601 qWarning("QPixmap::convertToImage: Display not supported (bpp=%d)",
1602 xi->bits_per_pixel);
1603 return QImage();
1604 }
1605
1606 if (d == 1) { // bitmap
1607 image.setNumColors(2);
1608 image.setColor(0, qRgb(255,255,255));
1609 image.setColor(1, qRgb(0,0,0));
1610 } else if (!trucol) { // pixmap with colormap
1611 register uchar *p;
1612 uchar *end;
1613 uchar use[256]; // pixel-in-use table
1614 uchar pix[256]; // pixel translation table
1615 int ncols, bpl;
1616 memset(use, 0, 256);
1617 memset(pix, 0, 256);
1618 bpl = image.bytesPerLine();
1619
1620 if (x11_mask) { // which pixels are used?
1621 for (int i = 0; i < h; i++) {
1622 uchar* asrc = alpha.scanLine(i);
1623 p = image.scanLine(i);
1624 if (ale) {
1625 for (int x = 0; x < w; x++) {
1626 if (asrc[x >> 3] & (1 << (x & 7)))
1627 use[*p] = 1;
1628 ++p;
1629 }
1630 } else {
1631 for (int x = 0; x < w; x++) {
1632 if (asrc[x >> 3] & (0x80 >> (x & 7)))
1633 use[*p] = 1;
1634 ++p;
1635 }
1636 }
1637 }
1638 } else {
1639 for (int i = 0; i < h; i++) {
1640 p = image.scanLine(i);
1641 end = p + bpl;
1642 while (p < end)
1643 use[*p++] = 1;
1644 }
1645 }
1646 ncols = 0;
1647 for (int i = 0; i < 256; i++) { // build translation table
1648 if (use[i])
1649 pix[i] = ncols++;
1650 }
1651 for (int i = 0; i < h; i++) { // translate pixels
1652 p = image.scanLine(i);
1653 end = p + bpl;
1654 while (p < end) {
1655 *p = pix[*p];
1656 p++;
1657 }
1658 }
1659 if (x11_mask) {
1660 int trans;
1661 if (ncols < 256) {
1662 trans = ncols++;
1663 image.setNumColors(ncols); // create color table
1664 image.setColor(trans, 0x00000000);
1665 } else {
1666 image.setNumColors(ncols); // create color table
1667 // oh dear... no spare "transparent" pixel.
1668 // use first pixel in image (as good as any).
1669 trans = image.scanLine(0)[0];
1670 }
1671 for (int i = 0; i < h; i++) {
1672 uchar* asrc = alpha.scanLine(i);
1673 p = image.scanLine(i);
1674 if (ale) {
1675 for (int x = 0; x < w; x++) {
1676 if (!(asrc[x >> 3] & (1 << (x & 7))))
1677 *p = trans;
1678 ++p;
1679 }
1680 } else {
1681 for (int x = 0; x < w; x++) {
1682 if (!(asrc[x >> 3] & (1 << (7 -(x & 7)))))
1683 *p = trans;
1684 ++p;
1685 }
1686 }
1687 }
1688 } else {
1689 image.setNumColors(ncols); // create color table
1690 }
1691 QVector<QColor> colors = QColormap::instance(xinfo.screen()).colormap();
1692 int j = 0;
1693 for (int i=0; i<colors.size(); i++) { // translate pixels
1694 if (use[i])
1695 image.setColor(j++, 0xff000000 | colors.at(i).rgb());
1696 }
1697 }
1698
1699 qSafeXDestroyImage(xi);
1700
1701 return image;
1702}
1703
1704/*!
1705 Returns a copy of the pixmap that is transformed using the given
1706 transformation \a matrix and transformation \a mode. The original
1707 pixmap is not changed.
1708
1709 The transformation \a matrix is internally adjusted to compensate
1710 for unwanted translation; i.e. the pixmap produced is the smallest
1711 pixmap that contains all the transformed points of the original
1712 pixmap. Use the trueMatrix() function to retrieve the actual
1713 matrix used for transforming the pixmap.
1714
1715 This function is slow because it involves transformation to a
1716 QImage, non-trivial computations and a transformation back to a
1717 QPixmap.
1718
1719 \sa trueMatrix(), {QPixmap#Pixmap Transformations}{Pixmap
1720 Transformations}
1721*/
1722QPixmap QX11PixmapData::transformed(const QTransform &transform,
1723 Qt::TransformationMode mode ) const
1724{
1725 if (mode == Qt::SmoothTransformation || transform.type() >= QTransform::TxProject) {
1726 QImage image = toImage();
1727 return QPixmap::fromImage(image.transformed(transform, mode));
1728 }
1729
1730 uint w = 0;
1731 uint h = 0; // size of target pixmap
1732 uint ws, hs; // size of source pixmap
1733 uchar *dptr; // data in target pixmap
1734 uint dbpl, dbytes; // bytes per line/bytes total
1735 uchar *sptr; // data in original pixmap
1736 int sbpl; // bytes per line in original
1737 int bpp; // bits per pixel
1738 bool depth1 = depth() == 1;
1739 Display *dpy = X11->display;
1740
1741 ws = width();
1742 hs = height();
1743
1744 QTransform mat(transform.m11(), transform.m12(), transform.m13(),
1745 transform.m21(), transform.m22(), transform.m23(),
1746 0., 0., 1);
1747 bool complex_xform = false;
1748 qreal scaledWidth;
1749 qreal scaledHeight;
1750
1751 if (mat.type() <= QTransform::TxScale) {
1752 scaledHeight = qAbs(mat.m22()) * hs + 0.9999;
1753 scaledWidth = qAbs(mat.m11()) * ws + 0.9999;
1754 h = qAbs(int(scaledHeight));
1755 w = qAbs(int(scaledWidth));
1756 } else { // rotation or shearing
1757 QPolygonF a(QRectF(0, 0, ws, hs));
1758 a = mat.map(a);
1759 QRect r = a.boundingRect().toAlignedRect();
1760 w = r.width();
1761 h = r.height();
1762 scaledWidth = w;
1763 scaledHeight = h;
1764 complex_xform = true;
1765 }
1766 mat = QPixmap::trueMatrix(mat, ws, hs); // true matrix
1767
1768 bool invertible;
1769 mat = mat.inverted(&invertible); // invert matrix
1770
1771 if (h == 0 || w == 0 || !invertible
1772 || qAbs(scaledWidth) >= 32768 || qAbs(scaledHeight) >= 32768 )
1773 // error, return null pixmap
1774 return QPixmap();
1775
1776#if defined(QT_MITSHM)
1777 static bool try_once = true;
1778 if (try_once) {
1779 try_once = false;
1780 if (!xshminit)
1781 qt_create_mitshm_buffer(this, 800, 600);
1782 }
1783
1784 bool use_mitshm = xshmimg && !depth1 &&
1785 xshmimg->width >= w && xshmimg->height >= h;
1786#endif
1787 XImage *xi = XGetImage(X11->display, handle(), 0, 0, ws, hs, AllPlanes,
1788 depth1 ? XYPixmap : ZPixmap);
1789
1790 if (!xi)
1791 return QPixmap();
1792
1793 sbpl = xi->bytes_per_line;
1794 sptr = (uchar *)xi->data;
1795 bpp = xi->bits_per_pixel;
1796
1797 if (depth1)
1798 dbpl = (w+7)/8;
1799 else
1800 dbpl = ((w*bpp+31)/32)*4;
1801 dbytes = dbpl*h;
1802
1803#if defined(QT_MITSHM)
1804 if (use_mitshm) {
1805 dptr = (uchar *)xshmimg->data;
1806 uchar fillbyte = bpp == 8 ? white.pixel() : 0xff;
1807 for (int y=0; y<h; y++)
1808 memset(dptr + y*xshmimg->bytes_per_line, fillbyte, dbpl);
1809 } else {
1810#endif
1811 dptr = (uchar *)malloc(dbytes); // create buffer for bits
1812 Q_CHECK_PTR(dptr);
1813 if (depth1) // fill with zeros
1814 memset(dptr, 0, dbytes);
1815 else if (bpp == 8) // fill with background color
1816 memset(dptr, WhitePixel(X11->display, xinfo.screen()), dbytes);
1817 else
1818 memset(dptr, 0, dbytes);
1819#if defined(QT_MITSHM)
1820 }
1821#endif
1822
1823 // #define QT_DEBUG_XIMAGE
1824#if defined(QT_DEBUG_XIMAGE)
1825 qDebug("----IMAGE--INFO--------------");
1826 qDebug("width............. %d", xi->width);
1827 qDebug("height............ %d", xi->height);
1828 qDebug("xoffset........... %d", xi->xoffset);
1829 qDebug("format............ %d", xi->format);
1830 qDebug("byte order........ %d", xi->byte_order);
1831 qDebug("bitmap unit....... %d", xi->bitmap_unit);
1832 qDebug("bitmap bit order.. %d", xi->bitmap_bit_order);
1833 qDebug("depth............. %d", xi->depth);
1834 qDebug("bytes per line.... %d", xi->bytes_per_line);
1835 qDebug("bits per pixel.... %d", xi->bits_per_pixel);
1836#endif
1837
1838 int type;
1839 if (xi->bitmap_bit_order == MSBFirst)
1840 type = QT_XFORM_TYPE_MSBFIRST;
1841 else
1842 type = QT_XFORM_TYPE_LSBFIRST;
1843 int xbpl, p_inc;
1844 if (depth1) {
1845 xbpl = (w+7)/8;
1846 p_inc = dbpl - xbpl;
1847 } else {
1848 xbpl = (w*bpp)/8;
1849 p_inc = dbpl - xbpl;
1850#if defined(QT_MITSHM)
1851 if (use_mitshm)
1852 p_inc = xshmimg->bytes_per_line - xbpl;
1853#endif
1854 }
1855
1856 if (!qt_xForm_helper(mat, xi->xoffset, type, bpp, dptr, xbpl, p_inc, h, sptr, sbpl, ws, hs)){
1857 qWarning("QPixmap::transform: display not supported (bpp=%d)",bpp);
1858 QPixmap pm;
1859 return pm;
1860 }
1861
1862 qSafeXDestroyImage(xi);
1863
1864 if (depth1) { // mono bitmap
1865 QBitmap bm = QBitmap::fromData(QSize(w, h), dptr,
1866 BitmapBitOrder(X11->display) == MSBFirst
1867 ? QImage::Format_Mono
1868 : QImage::Format_MonoLSB);
1869 free(dptr);
1870 return bm;
1871 } else { // color pixmap
1872 QPixmap pm;
1873 QX11PixmapData *x11Data = static_cast<QX11PixmapData*>(pm.data);
1874 x11Data->uninit = false;
1875 x11Data->xinfo = xinfo;
1876 x11Data->d = d;
1877 x11Data->w = w;
1878 x11Data->h = h;
1879 x11Data->hd = (Qt::HANDLE)XCreatePixmap(X11->display,
1880 RootWindow(X11->display, xinfo.screen()),
1881 w, h, d);
1882#ifndef QT_NO_XRENDER
1883 if (X11->use_xrender) {
1884 XRenderPictFormat *format = x11Data->d == 32
1885 ? XRenderFindStandardFormat(X11->display, PictStandardARGB32)
1886 : XRenderFindVisualFormat(X11->display, (Visual *) x11Data->xinfo.visual());
1887 x11Data->picture = XRenderCreatePicture(X11->display, x11Data->hd, format, 0, 0);
1888 }
1889#endif // QT_NO_XRENDER
1890
1891 GC gc = XCreateGC(X11->display, x11Data->hd, 0, 0);
1892#if defined(QT_MITSHM)
1893 if (use_mitshm) {
1894 XCopyArea(dpy, xshmpm, x11Data->hd, gc, 0, 0, w, h, 0, 0);
1895 } else
1896#endif
1897 {
1898 xi = XCreateImage(dpy, (Visual*)x11Data->xinfo.visual(),
1899 x11Data->d,
1900 ZPixmap, 0, (char *)dptr, w, h, 32, 0);
1901 XPutImage(dpy, pm.handle(), gc, xi, 0, 0, 0, 0, w, h);
1902 qSafeXDestroyImage(xi);
1903 }
1904 XFreeGC(X11->display, gc);
1905
1906 if (x11_mask) { // xform mask, too
1907 pm.setMask(mask_to_bitmap(xinfo.screen()).transformed(transform));
1908 } else if (d != 32 && complex_xform) { // need a mask!
1909 QBitmap mask(ws, hs);
1910 mask.fill(Qt::color1);
1911 pm.setMask(mask.transformed(transform));
1912 }
1913 return pm;
1914 }
1915}
1916
1917/*!
1918 \internal
1919*/
1920int QPixmap::x11SetDefaultScreen(int screen)
1921{
1922 int old = defaultScreen;
1923 defaultScreen = screen;
1924 return old;
1925}
1926
1927/*!
1928 \internal
1929*/
1930void QPixmap::x11SetScreen(int screen)
1931{
1932 if (paintingActive()) {
1933 qWarning("QPixmap::x11SetScreen(): Cannot change screens during painting");
1934 return;
1935 }
1936
1937 if (data->classId() != QPixmapData::X11Class)
1938 return;
1939
1940 if (screen < 0)
1941 screen = QX11Info::appScreen();
1942
1943 QX11PixmapData *x11Data = static_cast<QX11PixmapData*>(data);
1944 if (screen == x11Data->xinfo.screen())
1945 return; // nothing to do
1946
1947 if (isNull()) {
1948 QX11InfoData* xd = x11Data->xinfo.getX11Data(true);
1949 xd->screen = screen;
1950 xd->depth = QX11Info::appDepth(screen);
1951 xd->cells = QX11Info::appCells(screen);
1952 xd->colormap = QX11Info::appColormap(screen);
1953 xd->defaultColormap = QX11Info::appDefaultColormap(screen);
1954 xd->visual = (Visual *)QX11Info::appVisual(screen);
1955 xd->defaultVisual = QX11Info::appDefaultVisual(screen);
1956 x11Data->xinfo.setX11Data(xd);
1957 return;
1958 }
1959#if 0
1960 qDebug("QPixmap::x11SetScreen for %p from %d to %d. Size is %d/%d", x11Data, x11Data->xinfo.screen(), screen, width(), height());
1961#endif
1962
1963 x11SetDefaultScreen(screen);
1964 *this = qt_toX11Pixmap(toImage());
1965}
1966
1967QPixmap QPixmap::grabWindow(WId window, int x, int y, int w, int h)
1968{
1969 if (w == 0 || h == 0)
1970 return QPixmap();
1971
1972 Display *dpy = X11->display;
1973 XWindowAttributes window_attr;
1974 if (!XGetWindowAttributes(dpy, window, &window_attr))
1975 return QPixmap();
1976
1977 if (w < 0)
1978 w = window_attr.width - x;
1979 if (h < 0)
1980 h = window_attr.height - y;
1981
1982 // determine the screen
1983 int scr;
1984 for (scr = 0; scr < ScreenCount(dpy); ++scr) {
1985 if (window_attr.root == RootWindow(dpy, scr)) // found it
1986 break;
1987 }
1988 if (scr >= ScreenCount(dpy)) // sanity check
1989 return QPixmap();
1990
1991
1992 // get the depth of the root window
1993 XWindowAttributes root_attr;
1994 if (!XGetWindowAttributes(dpy, window_attr.root, &root_attr))
1995 return QPixmap();
1996
1997 if (window_attr.depth == root_attr.depth) {
1998 // if the depth of the specified window and the root window are the
1999 // same, grab pixels from the root window (so that we get the any
2000 // overlapping windows and window manager frames)
2001
2002 // map x and y to the root window
2003 WId unused;
2004 if (!XTranslateCoordinates(dpy, window, window_attr.root, x, y,
2005 &x, &y, &unused))
2006 return QPixmap();
2007
2008 window = window_attr.root;
2009 window_attr = root_attr;
2010 }
2011
2012 QX11PixmapData *data = new QX11PixmapData(QPixmapData::PixmapType);
2013
2014 void qt_x11_getX11InfoForWindow(QX11Info * xinfo, const XWindowAttributes &a);
2015 qt_x11_getX11InfoForWindow(&data->xinfo,window_attr);
2016
2017 data->resize(w, h);
2018
2019 QPixmap pm(data);
2020
2021 data->uninit = false;
2022 pm.x11SetScreen(scr);
2023
2024 GC gc = XCreateGC(dpy, pm.handle(), 0, 0);
2025 XSetSubwindowMode(dpy, gc, IncludeInferiors);
2026 XCopyArea(dpy, window, pm.handle(), gc, x, y, w, h, 0, 0);
2027 XFreeGC(dpy, gc);
2028
2029 return pm;
2030}
2031
2032bool QX11PixmapData::hasAlphaChannel() const
2033{
2034 return d == 32;
2035}
2036
2037/*!
2038 Returns information about the configuration of the X display used to display
2039 the widget.
2040
2041 \warning This function is only available on X11.
2042
2043 \sa {QPixmap#Pixmap Information}{Pixmap Information}
2044*/
2045const QX11Info &QPixmap::x11Info() const
2046{
2047 if (data->classId() == QPixmapData::X11Class)
2048 return static_cast<QX11PixmapData*>(data)->xinfo;
2049 else {
2050 static QX11Info nullX11Info;
2051 return nullX11Info;
2052 }
2053}
2054
2055#if !defined(QT_NO_XRENDER)
2056static XRenderPictFormat *qt_renderformat_for_depth(const QX11Info &xinfo, int depth)
2057{
2058 if (depth == 1)
2059 return XRenderFindStandardFormat(X11->display, PictStandardA1);
2060 else if (depth == 32)
2061 return XRenderFindStandardFormat(X11->display, PictStandardARGB32);
2062 else
2063 return XRenderFindVisualFormat(X11->display, (Visual *)xinfo.visual());
2064}
2065#endif
2066
2067QPaintEngine* QX11PixmapData::paintEngine() const
2068{
2069 QX11PixmapData *that = const_cast<QX11PixmapData*>(this);
2070
2071 if (read_only && share_mode == QPixmap::ImplicitlyShared) {
2072 // if someone wants to draw onto us, copy the shared contents
2073 // and turn it into a fully fledged QPixmap
2074 ::Pixmap hd_copy = XCreatePixmap(X11->display, RootWindow(X11->display, xinfo.screen()),
2075 w, h, d);
2076#if !defined(QT_NO_XRENDER)
2077 XRenderPictFormat *format = qt_renderformat_for_depth(xinfo, d);
2078 ::Picture picture_copy = XRenderCreatePicture(X11->display, hd_copy, format, 0, 0);
2079
2080 if (picture && d == 32) {
2081 XRenderComposite(X11->display, PictOpSrc, picture, 0, picture_copy,
2082 0, 0, 0, 0, 0, 0, w, h);
2083 XRenderFreePicture(X11->display, picture);
2084 that->picture = picture_copy;
2085 } else
2086#endif
2087 {
2088 GC gc = XCreateGC(X11->display, hd_copy, 0, 0);
2089 XCopyArea(X11->display, hd, hd_copy, gc, 0, 0, w, h, 0, 0);
2090 XFreeGC(X11->display, gc);
2091 }
2092 that->hd = hd_copy;
2093 that->read_only = false;
2094 }
2095
2096 if (!that->pengine)
2097 that->pengine = new QX11PaintEngine;
2098 return that->pengine;
2099}
2100
2101/*!
2102 Returns the X11 Picture handle of the pixmap for XRender
2103 support.
2104
2105 This function will return 0 if XRender support is not compiled
2106 into Qt, if the XRender extension is not supported on the X11
2107 display, or if the handle could not be created. Use of this
2108 function is not portable.
2109
2110 \warning This function is only available on X11.
2111
2112 \sa {QPixmap#Pixmap Information}{Pixmap Information}
2113*/
2114
2115Qt::HANDLE QPixmap::x11PictureHandle() const
2116{
2117#ifndef QT_NO_XRENDER
2118 if (data->classId() == QPixmapData::X11Class)
2119 return static_cast<QX11PixmapData*>(data)->picture;
2120 else
2121 return 0;
2122#else
2123 return 0;
2124#endif // QT_NO_XRENDER
2125}
2126
2127Qt::HANDLE QX11PixmapData::x11ConvertToDefaultDepth()
2128{
2129#ifndef QT_NO_XRENDER
2130 if (d == QX11Info::appDepth() || !X11->use_xrender)
2131 return hd;
2132 if (!hd2) {
2133 hd2 = XCreatePixmap(xinfo.display(), hd, w, h, QX11Info::appDepth());
2134 XRenderPictFormat *format = XRenderFindVisualFormat(xinfo.display(),
2135 (Visual*) xinfo.visual());
2136 Picture pic = XRenderCreatePicture(xinfo.display(), hd2, format, 0, 0);
2137 XRenderComposite(xinfo.display(), PictOpSrc, picture,
2138 XNone, pic, 0, 0, 0, 0, 0, 0, w, h);
2139 XRenderFreePicture(xinfo.display(), pic);
2140 }
2141 return hd2;
2142#else
2143 return hd;
2144#endif
2145}
2146
2147void QX11PixmapData::copy(const QPixmapData *data, const QRect &rect)
2148{
2149 if (data->pixelType() == BitmapType) {
2150 fromImage(data->toImage().copy(rect), Qt::AutoColor);
2151 return;
2152 }
2153
2154 const QX11PixmapData *x11Data = static_cast<const QX11PixmapData*>(data);
2155
2156 setSerialNumber(++qt_pixmap_serial);
2157
2158 uninit = false;
2159 xinfo = x11Data->xinfo;
2160 d = x11Data->d;
2161 w = rect.width();
2162 h = rect.height();
2163 hd = (Qt::HANDLE)XCreatePixmap(X11->display,
2164 RootWindow(X11->display, x11Data->xinfo.screen()),
2165 w, h, d);
2166#ifndef QT_NO_XRENDER
2167 if (X11->use_xrender) {
2168 XRenderPictFormat *format = d == 32
2169 ? XRenderFindStandardFormat(X11->display, PictStandardARGB32)
2170 : XRenderFindVisualFormat(X11->display, (Visual *)xinfo.visual());
2171 picture = XRenderCreatePicture(X11->display, hd, format, 0, 0);
2172 }
2173#endif // QT_NO_XRENDER
2174 if (x11Data->x11_mask) {
2175 x11_mask = XCreatePixmap(X11->display, hd, w, h, 1);
2176#ifndef QT_NO_XRENDER
2177 if (X11->use_xrender) {
2178 mask_picture = XRenderCreatePicture(X11->display, x11_mask,
2179 XRenderFindStandardFormat(X11->display, PictStandardA1), 0, 0);
2180 XRenderPictureAttributes attrs;
2181 attrs.alpha_map = x11Data->mask_picture;
2182 XRenderChangePicture(X11->display, x11Data->picture, CPAlphaMap, &attrs);
2183 }
2184#endif
2185 }
2186
2187#if !defined(QT_NO_XRENDER)
2188 if (x11Data->picture && x11Data->d == 32) {
2189 XRenderComposite(X11->display, PictOpSrc,
2190 x11Data->picture, 0, picture,
2191 rect.x(), rect.y(), 0, 0, 0, 0, w, h);
2192 } else
2193#endif
2194 {
2195 GC gc = XCreateGC(X11->display, hd, 0, 0);
2196 XCopyArea(X11->display, x11Data->hd, hd, gc,
2197 rect.x(), rect.y(), w, h, 0, 0);
2198 if (x11Data->x11_mask) {
2199 GC monogc = XCreateGC(X11->display, x11_mask, 0, 0);
2200 XCopyArea(X11->display, x11Data->x11_mask, x11_mask, monogc,
2201 rect.x(), rect.y(), w, h, 0, 0);
2202 XFreeGC(X11->display, monogc);
2203 }
2204 XFreeGC(X11->display, gc);
2205 }
2206}
2207
2208#if !defined(QT_NO_XRENDER)
2209void QX11PixmapData::convertToARGB32(bool preserveContents)
2210{
2211 if (!X11->use_xrender)
2212 return;
2213
2214 // Q_ASSERT(count == 1);
2215 if (read_only && share_mode == QPixmap::ExplicitlyShared)
2216 return;
2217
2218 Pixmap pm = XCreatePixmap(X11->display, RootWindow(X11->display, xinfo.screen()),
2219 w, h, 32);
2220 Picture p = XRenderCreatePicture(X11->display, pm,
2221 XRenderFindStandardFormat(X11->display, PictStandardARGB32), 0, 0);
2222 if (picture) {
2223 if (preserveContents)
2224 XRenderComposite(X11->display, PictOpSrc, picture, 0, p, 0, 0, 0, 0, 0, 0, w, h);
2225 if (!read_only)
2226 XRenderFreePicture(X11->display, picture);
2227 }
2228 if (hd && !read_only)
2229 XFreePixmap(X11->display, hd);
2230 if (x11_mask) {
2231 XFreePixmap(X11->display, x11_mask);
2232 if (mask_picture)
2233 XRenderFreePicture(X11->display, mask_picture);
2234 x11_mask = 0;
2235 mask_picture = 0;
2236 }
2237 hd = pm;
2238 picture = p;
2239 d = 32;
2240}
2241#endif
2242
2243QPixmap QPixmap::fromX11Pixmap(Qt::HANDLE pixmap, QPixmap::ShareMode mode)
2244{
2245 Window root;
2246 int x;
2247 int y;
2248 uint width;
2249 uint height;
2250 uint border_width;
2251 uint depth;
2252 XWindowAttributes win_attribs;
2253 int num_screens = ScreenCount(X11->display);
2254 int screen = 0;
2255
2256 XGetGeometry(X11->display, pixmap, &root, &x, &y, &width, &height, &border_width, &depth);
2257 XGetWindowAttributes(X11->display, root, &win_attribs);
2258
2259 for (; screen < num_screens; ++screen) {
2260 if (win_attribs.screen == ScreenOfDisplay(X11->display, screen))
2261 break;
2262 }
2263
2264 QX11PixmapData *data = new QX11PixmapData(depth == 1 ? QPixmapData::BitmapType : QPixmapData::PixmapType);
2265 data->setSerialNumber(++qt_pixmap_serial);
2266 data->read_only = true;
2267 data->share_mode = mode;
2268 data->uninit = false;
2269 data->w = width;
2270 data->h = height;
2271 data->d = depth;
2272 data->hd = pixmap;
2273
2274 if (defaultScreen >= 0 && defaultScreen != screen) {
2275 QX11InfoData* xd = data->xinfo.getX11Data(true);
2276 xd->screen = defaultScreen;
2277 xd->depth = QX11Info::appDepth(xd->screen);
2278 xd->cells = QX11Info::appCells(xd->screen);
2279 xd->colormap = QX11Info::appColormap(xd->screen);
2280 xd->defaultColormap = QX11Info::appDefaultColormap(xd->screen);
2281 xd->visual = (Visual *)QX11Info::appVisual(xd->screen);
2282 xd->defaultVisual = QX11Info::appDefaultVisual(xd->screen);
2283 data->xinfo.setX11Data(xd);
2284 }
2285
2286#ifndef QT_NO_XRENDER
2287 if (X11->use_xrender) {
2288 XRenderPictFormat *format = qt_renderformat_for_depth(data->xinfo, depth);
2289 data->picture = XRenderCreatePicture(X11->display, data->hd, format, 0, 0);
2290 }
2291#endif // QT_NO_XRENDER
2292
2293 return QPixmap(data);
2294}
2295
2296
2297QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.