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