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