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