summaryrefslogtreecommitdiffstats
path: root/src/gui/image/qpixmap_x11.cpp
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2011-05-04 14:37:50 +0200
committerLars Knoll <lars.knoll@nokia.com>2011-05-04 14:39:19 +0200
commitbd8d12b7f68ea8aa05a86cc9ed65dd660a6b075d (patch)
treea2da73cfac60aa2b86fee223b5c28d813dcc69cd /src/gui/image/qpixmap_x11.cpp
parentdc0f9f02a5c390f4a7919db4c32d22cebaf71d1c (diff)
move platform specific files out of the way
Keep the files as reference to implement the lighthouse plugins, but move them away from the main directory hierachy as they won't be part of Qt5 in any case.
Diffstat (limited to 'src/gui/image/qpixmap_x11.cpp')
-rw-r--r--src/gui/image/qpixmap_x11.cpp2419
1 files changed, 0 insertions, 2419 deletions
diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp
deleted file mode 100644
index bc468cb7ec..0000000000
--- a/src/gui/image/qpixmap_x11.cpp
+++ /dev/null
@@ -1,2419 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-// Uncomment the next line to enable the MIT Shared Memory extension
-//
-// WARNING: This has some problems:
-//
-// 1. Consumes a 800x600 pixmap
-// 2. Qt does not handle the ShmCompletion message, so you will
-// get strange effects if you xForm() repeatedly.
-//
-// #define QT_MITSHM
-
-#if defined(Q_OS_WIN32) && defined(QT_MITSHM)
-#undef QT_MITSHM
-#endif
-
-#include "qplatformdefs.h"
-
-#include "qdebug.h"
-#include "qiodevice.h"
-#include "qpixmap_x11_p.h"
-#include "qbitmap.h"
-#include "qcolormap.h"
-#include "qimage.h"
-#include "qmatrix.h"
-#include "qapplication.h"
-#include <private/qpaintengine_x11_p.h>
-#include <private/qt_x11_p.h>
-#include "qx11info_x11.h"
-#include <private/qdrawhelper_p.h>
-#include <private/qimage_p.h>
-#include <private/qimagepixmapcleanuphooks_p.h>
-
-#include <stdlib.h>
-
-#if defined(Q_CC_MIPS)
-# define for if(0){}else for
-#endif
-
-QT_BEGIN_NAMESPACE
-
-QPixmap qt_toX11Pixmap(const QImage &image)
-{
- QPixmapData *data =
- new QX11PixmapData(image.depth() == 1
- ? QPixmapData::BitmapType
- : QPixmapData::PixmapType);
-
- data->fromImage(image, Qt::AutoColor);
-
- return QPixmap(data);
-}
-
-QPixmap qt_toX11Pixmap(const QPixmap &pixmap)
-{
- if (pixmap.isNull())
- return QPixmap();
-
- if (QPixmap(pixmap).data_ptr()->classId() == QPixmapData::X11Class)
- return pixmap;
-
- return qt_toX11Pixmap(pixmap.toImage());
-}
-
-// For thread-safety:
-// image->data does not belong to X11, so we must free it ourselves.
-
-inline static void qSafeXDestroyImage(XImage *x)
-{
- if (x->data) {
- free(x->data);
- x->data = 0;
- }
- XDestroyImage(x);
-}
-
-QBitmap QX11PixmapData::mask_to_bitmap(int screen) const
-{
- if (!x11_mask)
- return QBitmap();
- QPixmap::x11SetDefaultScreen(screen);
- QBitmap bm(w, h);
- GC gc = XCreateGC(X11->display, bm.handle(), 0, 0);
- XCopyArea(X11->display, x11_mask, bm.handle(), gc, 0, 0,
- bm.data->width(), bm.data->height(), 0, 0);
- XFreeGC(X11->display, gc);
- return bm;
-}
-
-Qt::HANDLE QX11PixmapData::bitmap_to_mask(const QBitmap &bitmap, int screen)
-{
- if (bitmap.isNull())
- return 0;
- QBitmap bm = bitmap;
- bm.x11SetScreen(screen);
-
- Pixmap mask = XCreatePixmap(X11->display, RootWindow(X11->display, screen),
- bm.data->width(), bm.data->height(), 1);
- GC gc = XCreateGC(X11->display, mask, 0, 0);
- XCopyArea(X11->display, bm.handle(), mask, gc, 0, 0,
- bm.data->width(), bm.data->height(), 0, 0);
- XFreeGC(X11->display, gc);
- return mask;
-}
-
-
-/*****************************************************************************
- MIT Shared Memory Extension support: makes xForm noticeably (~20%) faster.
- *****************************************************************************/
-
-#if defined(QT_MITSHM)
-
-static bool xshminit = false;
-static XShmSegmentInfo xshminfo;
-static XImage *xshmimg = 0;
-static Pixmap xshmpm = 0;
-
-static void qt_cleanup_mitshm()
-{
- if (xshmimg == 0)
- return;
- Display *dpy = QX11Info::appDisplay();
- if (xshmpm) {
- XFreePixmap(dpy, xshmpm);
- xshmpm = 0;
- }
- XShmDetach(dpy, &xshminfo); xshmimg->data = 0;
- qSafeXDestroyImage(xshmimg); xshmimg = 0;
- shmdt(xshminfo.shmaddr);
- shmctl(xshminfo.shmid, IPC_RMID, 0);
-}
-
-static bool qt_create_mitshm_buffer(const QPaintDevice* dev, int w, int h)
-{
- static int major, minor;
- static Bool pixmaps_ok;
- Display *dpy = dev->data->xinfo->display();
- int dd = dev->x11Depth();
- Visual *vis = (Visual*)dev->x11Visual();
-
- if (xshminit) {
- qt_cleanup_mitshm();
- } else {
- if (!XShmQueryVersion(dpy, &major, &minor, &pixmaps_ok))
- return false; // MIT Shm not supported
- qAddPostRoutine(qt_cleanup_mitshm);
- xshminit = true;
- }
-
- xshmimg = XShmCreateImage(dpy, vis, dd, ZPixmap, 0, &xshminfo, w, h);
- if (!xshmimg)
- return false;
-
- bool ok;
- xshminfo.shmid = shmget(IPC_PRIVATE,
- xshmimg->bytes_per_line * xshmimg->height,
- IPC_CREAT | 0777);
- ok = xshminfo.shmid != -1;
- if (ok) {
- xshmimg->data = (char*)shmat(xshminfo.shmid, 0, 0);
- xshminfo.shmaddr = xshmimg->data;
- ok = (xshminfo.shmaddr != (char*)-1);
- }
- xshminfo.readOnly = false;
- if (ok)
- ok = XShmAttach(dpy, &xshminfo);
- if (!ok) {
- qSafeXDestroyImage(xshmimg);
- xshmimg = 0;
- if (xshminfo.shmaddr)
- shmdt(xshminfo.shmaddr);
- if (xshminfo.shmid != -1)
- shmctl(xshminfo.shmid, IPC_RMID, 0);
- return false;
- }
- if (pixmaps_ok)
- xshmpm = XShmCreatePixmap(dpy, DefaultRootWindow(dpy), xshmimg->data,
- &xshminfo, w, h, dd);
-
- return true;
-}
-
-#else
-
-// If extern, need a dummy.
-//
-// static bool qt_create_mitshm_buffer(QPaintDevice*, int, int)
-// {
-// return false;
-// }
-
-#endif // QT_MITSHM
-
-
-/*****************************************************************************
- Internal functions
- *****************************************************************************/
-
-extern const uchar *qt_get_bitflip_array(); // defined in qimage.cpp
-
-// Returns position of highest bit set or -1 if none
-static int highest_bit(uint v)
-{
- int i;
- uint b = (uint)1 << 31;
- for (i=31; ((b & v) == 0) && i>=0; i--)
- b >>= 1;
- return i;
-}
-
-// Returns position of lowest set bit in 'v' as an integer (0-31), or -1
-static int lowest_bit(uint v)
-{
- int i;
- ulong lb;
- lb = 1;
- for (i=0; ((v & lb) == 0) && i<32; i++, lb<<=1) {}
- return i==32 ? -1 : i;
-}
-
-// Counts the number of bits set in 'v'
-static uint n_bits(uint v)
-{
- int i = 0;
- while (v) {
- v = v & (v - 1);
- i++;
- }
- return i;
-}
-
-static uint *red_scale_table = 0;
-static uint *green_scale_table = 0;
-static uint *blue_scale_table = 0;
-
-static void cleanup_scale_tables()
-{
- delete[] red_scale_table;
- delete[] green_scale_table;
- delete[] blue_scale_table;
-}
-
-/*
- Could do smart bitshifting, but the "obvious" algorithm only works for
- nBits >= 4. This is more robust.
-*/
-static void build_scale_table(uint **table, uint nBits)
-{
- if (nBits > 7) {
- qWarning("build_scale_table: internal error, nBits = %i", nBits);
- return;
- }
- if (!*table) {
- static bool firstTable = true;
- if (firstTable) {
- qAddPostRoutine(cleanup_scale_tables);
- firstTable = false;
- }
- *table = new uint[256];
- }
- int maxVal = (1 << nBits) - 1;
- int valShift = 8 - nBits;
- int i;
- for(i = 0 ; i < maxVal + 1 ; i++)
- (*table)[i << valShift] = i*255/maxVal;
-}
-
-static int defaultScreen = -1;
-
-/*****************************************************************************
- QPixmap member functions
- *****************************************************************************/
-
-QBasicAtomicInt qt_pixmap_serial = Q_BASIC_ATOMIC_INITIALIZER(0);
-int Q_GUI_EXPORT qt_x11_preferred_pixmap_depth = 0;
-
-QX11PixmapData::QX11PixmapData(PixelType type)
- : QPixmapData(type, X11Class), gl_surface(0), hd(0),
- flags(Uninitialized), x11_mask(0), picture(0), mask_picture(0), hd2(0),
- share_mode(QPixmap::ImplicitlyShared), pengine(0)
-{
-}
-
-QPixmapData *QX11PixmapData::createCompatiblePixmapData() const
-{
- return new QX11PixmapData(pixelType());
-}
-
-void QX11PixmapData::resize(int width, int height)
-{
- setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1));
-
- w = width;
- h = height;
- is_null = (w <= 0 || h <= 0);
-
- if (defaultScreen >= 0 && defaultScreen != xinfo.screen()) {
- QX11InfoData* xd = xinfo.getX11Data(true);
- xd->screen = defaultScreen;
- xd->depth = QX11Info::appDepth(xd->screen);
- xd->cells = QX11Info::appCells(xd->screen);
- xd->colormap = QX11Info::appColormap(xd->screen);
- xd->defaultColormap = QX11Info::appDefaultColormap(xd->screen);
- xd->visual = (Visual *)QX11Info::appVisual(xd->screen);
- xd->defaultVisual = QX11Info::appDefaultVisual(xd->screen);
- xinfo.setX11Data(xd);
- }
-
- int dd = xinfo.depth();
-
- if (qt_x11_preferred_pixmap_depth)
- dd = qt_x11_preferred_pixmap_depth;
-
- bool make_null = w <= 0 || h <= 0; // create null pixmap
- d = (pixelType() == BitmapType ? 1 : dd);
- if (make_null || d == 0) {
- w = 0;
- h = 0;
- is_null = true;
- hd = 0;
- picture = 0;
- d = 0;
- if (!make_null)
- qWarning("QPixmap: Invalid pixmap parameters");
- return;
- }
- hd = (Qt::HANDLE)XCreatePixmap(X11->display,
- RootWindow(X11->display, xinfo.screen()),
- w, h, d);
-#ifndef QT_NO_XRENDER
- if (X11->use_xrender) {
- XRenderPictFormat *format = d == 1
- ? XRenderFindStandardFormat(X11->display, PictStandardA1)
- : XRenderFindVisualFormat(X11->display, (Visual *)xinfo.visual());
- picture = XRenderCreatePicture(X11->display, hd, format, 0, 0);
- }
-#endif // QT_NO_XRENDER
-}
-
-struct QX11AlphaDetector
-{
- bool hasAlpha() const {
- if (checked)
- return has;
- // Will implicitly also check format and return quickly for opaque types...
- checked = true;
- has = image->isNull() ? false : const_cast<QImage *>(image)->data_ptr()->checkForAlphaPixels();
- return has;
- }
-
- bool hasXRenderAndAlpha() const {
- if (!X11->use_xrender)
- return false;
- return hasAlpha();
- }
-
- QX11AlphaDetector(const QImage *i, Qt::ImageConversionFlags flags)
- : image(i), checked(false), has(false)
- {
- if (flags & Qt::NoOpaqueDetection) {
- checked = true;
- has = image->hasAlphaChannel();
- }
- }
-
- const QImage *image;
- mutable bool checked;
- mutable bool has;
-};
-
-void QX11PixmapData::fromImage(const QImage &img,
- Qt::ImageConversionFlags flags)
-{
- setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1));
-
- w = img.width();
- h = img.height();
- d = img.depth();
- is_null = (w <= 0 || h <= 0);
-
- if (is_null) {
- w = h = 0;
- return;
- }
-
- if (defaultScreen >= 0 && defaultScreen != xinfo.screen()) {
- QX11InfoData* xd = xinfo.getX11Data(true);
- xd->screen = defaultScreen;
- xd->depth = QX11Info::appDepth(xd->screen);
- xd->cells = QX11Info::appCells(xd->screen);
- xd->colormap = QX11Info::appColormap(xd->screen);
- xd->defaultColormap = QX11Info::appDefaultColormap(xd->screen);
- xd->visual = (Visual *)QX11Info::appVisual(xd->screen);
- xd->defaultVisual = QX11Info::appDefaultVisual(xd->screen);
- xinfo.setX11Data(xd);
- }
-
- if (pixelType() == BitmapType) {
- bitmapFromImage(img);
- return;
- }
-
- if (uint(w) >= 32768 || uint(h) >= 32768) {
- w = h = 0;
- is_null = true;
- return;
- }
-
- QX11AlphaDetector alphaCheck(&img, flags);
- int dd = alphaCheck.hasXRenderAndAlpha() ? 32 : xinfo.depth();
-
- if (qt_x11_preferred_pixmap_depth)
- dd = qt_x11_preferred_pixmap_depth;
-
- QImage image = img;
-
- // must be monochrome
- if (dd == 1 || (flags & Qt::ColorMode_Mask) == Qt::MonoOnly) {
- if (d != 1) {
- // dither
- image = image.convertToFormat(QImage::Format_MonoLSB, flags);
- d = 1;
- }
- } else { // can be both
- bool conv8 = false;
- if (d > 8 && dd <= 8) { // convert to 8 bit
- if ((flags & Qt::DitherMode_Mask) == Qt::AutoDither)
- flags = (flags & ~Qt::DitherMode_Mask)
- | Qt::PreferDither;
- conv8 = true;
- } else if ((flags & Qt::ColorMode_Mask) == Qt::ColorOnly) {
- conv8 = (d == 1); // native depth wanted
- } else if (d == 1) {
- if (image.colorCount() == 2) {
- QRgb c0 = image.color(0); // Auto: convert to best
- QRgb c1 = image.color(1);
- conv8 = qMin(c0,c1) != qRgb(0,0,0) || qMax(c0,c1) != qRgb(255,255,255);
- } else {
- // eg. 1-color monochrome images (they do exist).
- conv8 = true;
- }
- }
- if (conv8) {
- image = image.convertToFormat(QImage::Format_Indexed8, flags);
- d = 8;
- }
- }
-
- if (d == 1 || d == 16 || d == 24) {
- image = image.convertToFormat(QImage::Format_RGB32, flags);
- fromImage(image, Qt::AutoColor);
- return;
- }
-
- Display *dpy = X11->display;
- Visual *visual = (Visual *)xinfo.visual();
- XImage *xi = 0;
- bool trucol = (visual->c_class >= TrueColor);
- int nbytes = image.byteCount();
- uchar *newbits= 0;
-
-#ifndef QT_NO_XRENDER
- if (alphaCheck.hasXRenderAndAlpha()) {
- const QImage &cimage = image;
-
- d = 32;
-
- if (QX11Info::appDepth() != d) {
- if (xinfo.x11data) {
- xinfo.x11data->depth = d;
- } else {
- QX11InfoData *xd = xinfo.getX11Data(true);
- xd->screen = QX11Info::appScreen();
- xd->depth = d;
- xd->cells = QX11Info::appCells();
- xd->colormap = QX11Info::appColormap();
- xd->defaultColormap = QX11Info::appDefaultColormap();
- xd->visual = (Visual *)QX11Info::appVisual();
- xd->defaultVisual = QX11Info::appDefaultVisual();
- xinfo.setX11Data(xd);
- }
- }
-
- hd = (Qt::HANDLE)XCreatePixmap(dpy, RootWindow(dpy, xinfo.screen()),
- w, h, d);
- picture = XRenderCreatePicture(X11->display, hd,
- XRenderFindStandardFormat(X11->display, PictStandardARGB32), 0, 0);
-
- xi = XCreateImage(dpy, visual, d, ZPixmap, 0, 0, w, h, 32, 0);
- Q_CHECK_PTR(xi);
- newbits = (uchar *)malloc(xi->bytes_per_line*h);
- Q_CHECK_PTR(newbits);
- xi->data = (char *)newbits;
-
- switch(cimage.format()) {
- case QImage::Format_Indexed8: {
- QVector<QRgb> colorTable = cimage.colorTable();
- uint *xidata = (uint *)xi->data;
- for (int y = 0; y < h; ++y) {
- const uchar *p = cimage.scanLine(y);
- for (int x = 0; x < w; ++x) {
- const QRgb rgb = colorTable[p[x]];
- const int a = qAlpha(rgb);
- if (a == 0xff)
- *xidata = rgb;
- else
- // RENDER expects premultiplied alpha
- *xidata = qRgba(qt_div_255(qRed(rgb) * a),
- qt_div_255(qGreen(rgb) * a),
- qt_div_255(qBlue(rgb) * a),
- a);
- ++xidata;
- }
- }
- }
- break;
- case QImage::Format_RGB32: {
- uint *xidata = (uint *)xi->data;
- for (int y = 0; y < h; ++y) {
- const QRgb *p = (const QRgb *) cimage.scanLine(y);
- for (int x = 0; x < w; ++x)
- *xidata++ = p[x] | 0xff000000;
- }
- }
- break;
- case QImage::Format_ARGB32: {
- uint *xidata = (uint *)xi->data;
- for (int y = 0; y < h; ++y) {
- const QRgb *p = (const QRgb *) cimage.scanLine(y);
- for (int x = 0; x < w; ++x) {
- const QRgb rgb = p[x];
- const int a = qAlpha(rgb);
- if (a == 0xff)
- *xidata = rgb;
- else
- // RENDER expects premultiplied alpha
- *xidata = qRgba(qt_div_255(qRed(rgb) * a),
- qt_div_255(qGreen(rgb) * a),
- qt_div_255(qBlue(rgb) * a),
- a);
- ++xidata;
- }
- }
-
- }
- break;
- case QImage::Format_ARGB32_Premultiplied: {
- uint *xidata = (uint *)xi->data;
- for (int y = 0; y < h; ++y) {
- const QRgb *p = (const QRgb *) cimage.scanLine(y);
- memcpy(xidata, p, w*sizeof(QRgb));
- xidata += w;
- }
- }
- break;
- default:
- Q_ASSERT(false);
- }
-
- if ((xi->byte_order == MSBFirst) != (QSysInfo::ByteOrder == QSysInfo::BigEndian)) {
- uint *xidata = (uint *)xi->data;
- uint *xiend = xidata + w*h;
- while (xidata < xiend) {
- *xidata = (*xidata >> 24)
- | ((*xidata >> 8) & 0xff00)
- | ((*xidata << 8) & 0xff0000)
- | (*xidata << 24);
- ++xidata;
- }
- }
-
- GC gc = XCreateGC(dpy, hd, 0, 0);
- XPutImage(dpy, hd, gc, xi, 0, 0, 0, 0, w, h);
- XFreeGC(dpy, gc);
-
- qSafeXDestroyImage(xi);
-
- return;
- }
-#endif // QT_NO_XRENDER
-
- if (trucol) { // truecolor display
- if (image.format() == QImage::Format_ARGB32_Premultiplied)
- image = image.convertToFormat(QImage::Format_ARGB32);
-
- const QImage &cimage = image;
- QRgb pix[256]; // pixel translation table
- const bool d8 = (d == 8);
- const uint red_mask = (uint)visual->red_mask;
- const uint green_mask = (uint)visual->green_mask;
- const uint blue_mask = (uint)visual->blue_mask;
- const int red_shift = highest_bit(red_mask) - 7;
- const int green_shift = highest_bit(green_mask) - 7;
- const int blue_shift = highest_bit(blue_mask) - 7;
- const uint rbits = highest_bit(red_mask) - lowest_bit(red_mask) + 1;
- const uint gbits = highest_bit(green_mask) - lowest_bit(green_mask) + 1;
- const uint bbits = highest_bit(blue_mask) - lowest_bit(blue_mask) + 1;
-
- if (d8) { // setup pixel translation
- QVector<QRgb> ctable = cimage.colorTable();
- for (int i=0; i < cimage.colorCount(); i++) {
- int r = qRed (ctable[i]);
- int g = qGreen(ctable[i]);
- int b = qBlue (ctable[i]);
- r = red_shift > 0 ? r << red_shift : r >> -red_shift;
- g = green_shift > 0 ? g << green_shift : g >> -green_shift;
- b = blue_shift > 0 ? b << blue_shift : b >> -blue_shift;
- pix[i] = (b & blue_mask) | (g & green_mask) | (r & red_mask)
- | ~(blue_mask | green_mask | red_mask);
- }
- }
-
- xi = XCreateImage(dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0);
- Q_CHECK_PTR(xi);
- newbits = (uchar *)malloc(xi->bytes_per_line*h);
- Q_CHECK_PTR(newbits);
- if (!newbits) // no memory
- return;
- int bppc = xi->bits_per_pixel;
-
- bool contig_bits = n_bits(red_mask) == rbits &&
- n_bits(green_mask) == gbits &&
- n_bits(blue_mask) == bbits;
- bool dither_tc =
- // Want it?
- (flags & Qt::Dither_Mask) != Qt::ThresholdDither &&
- (flags & Qt::DitherMode_Mask) != Qt::AvoidDither &&
- // Need it?
- bppc < 24 && !d8 &&
- // Can do it? (Contiguous bits?)
- contig_bits;
-
- static bool init=false;
- static int D[16][16];
- if (dither_tc && !init) {
- // I also contributed this code to XV - WWA.
- /*
- The dither matrix, D, is obtained with this formula:
-
- D2 = [0 2]
- [3 1]
-
-
- D2*n = [4*Dn 4*Dn+2*Un]
- [4*Dn+3*Un 4*Dn+1*Un]
- */
- int n,i,j;
- init=1;
-
- /* Set D2 */
- D[0][0]=0;
- D[1][0]=2;
- D[0][1]=3;
- D[1][1]=1;
-
- /* Expand using recursive definition given above */
- for (n=2; n<16; n*=2) {
- for (i=0; i<n; i++) {
- for (j=0; j<n; j++) {
- D[i][j]*=4;
- D[i+n][j]=D[i][j]+2;
- D[i][j+n]=D[i][j]+3;
- D[i+n][j+n]=D[i][j]+1;
- }
- }
- }
- init=true;
- }
-
- enum { BPP8,
- BPP16_565, BPP16_555,
- BPP16_MSB, BPP16_LSB,
- BPP24_888,
- BPP24_MSB, BPP24_LSB,
- BPP32_8888,
- BPP32_MSB, BPP32_LSB
- } mode = BPP8;
-
- bool same_msb_lsb = (xi->byte_order == MSBFirst) == (QSysInfo::ByteOrder == QSysInfo::BigEndian);
-
- if(bppc == 8) // 8 bit
- mode = BPP8;
- else if(bppc == 16) { // 16 bit MSB/LSB
- if(red_shift == 8 && green_shift == 3 && blue_shift == -3 && !d8 && same_msb_lsb)
- mode = BPP16_565;
- else if(red_shift == 7 && green_shift == 2 && blue_shift == -3 && !d8 && same_msb_lsb)
- mode = BPP16_555;
- else
- mode = (xi->byte_order == LSBFirst) ? BPP16_LSB : BPP16_MSB;
- } else if(bppc == 24) { // 24 bit MSB/LSB
- if (red_shift == 16 && green_shift == 8 && blue_shift == 0 && !d8 && same_msb_lsb)
- mode = BPP24_888;
- else
- mode = (xi->byte_order == LSBFirst) ? BPP24_LSB : BPP24_MSB;
- } else if(bppc == 32) { // 32 bit MSB/LSB
- if(red_shift == 16 && green_shift == 8 && blue_shift == 0 && !d8 && same_msb_lsb)
- mode = BPP32_8888;
- else
- mode = (xi->byte_order == LSBFirst) ? BPP32_LSB : BPP32_MSB;
- } else
- qFatal("Logic error 3");
-
-#define GET_PIXEL \
- uint pixel; \
- if (d8) pixel = pix[*src++]; \
- else { \
- int r = qRed (*p); \
- int g = qGreen(*p); \
- int b = qBlue (*p++); \
- r = red_shift > 0 \
- ? r << red_shift : r >> -red_shift; \
- g = green_shift > 0 \
- ? g << green_shift : g >> -green_shift; \
- b = blue_shift > 0 \
- ? b << blue_shift : b >> -blue_shift; \
- pixel = (r & red_mask)|(g & green_mask) | (b & blue_mask) \
- | ~(blue_mask | green_mask | red_mask); \
- }
-
-#define GET_PIXEL_DITHER_TC \
- int r = qRed (*p); \
- int g = qGreen(*p); \
- int b = qBlue (*p++); \
- const int thres = D[x%16][y%16]; \
- if (r <= (255-(1<<(8-rbits))) && ((r<<rbits) & 255) \
- > thres) \
- r += (1<<(8-rbits)); \
- if (g <= (255-(1<<(8-gbits))) && ((g<<gbits) & 255) \
- > thres) \
- g += (1<<(8-gbits)); \
- if (b <= (255-(1<<(8-bbits))) && ((b<<bbits) & 255) \
- > thres) \
- b += (1<<(8-bbits)); \
- r = red_shift > 0 \
- ? r << red_shift : r >> -red_shift; \
- g = green_shift > 0 \
- ? g << green_shift : g >> -green_shift; \
- b = blue_shift > 0 \
- ? b << blue_shift : b >> -blue_shift; \
- uint pixel = (r & red_mask)|(g & green_mask) | (b & blue_mask);
-
-// again, optimized case
-// can't be optimized that much :(
-#define GET_PIXEL_DITHER_TC_OPT(red_shift,green_shift,blue_shift,red_mask,green_mask,blue_mask, \
- rbits,gbits,bbits) \
- const int thres = D[x%16][y%16]; \
- int r = qRed (*p); \
- if (r <= (255-(1<<(8-rbits))) && ((r<<rbits) & 255) \
- > thres) \
- r += (1<<(8-rbits)); \
- int g = qGreen(*p); \
- if (g <= (255-(1<<(8-gbits))) && ((g<<gbits) & 255) \
- > thres) \
- g += (1<<(8-gbits)); \
- int b = qBlue (*p++); \
- if (b <= (255-(1<<(8-bbits))) && ((b<<bbits) & 255) \
- > thres) \
- b += (1<<(8-bbits)); \
- uint pixel = ((r red_shift) & red_mask) \
- | ((g green_shift) & green_mask) \
- | ((b blue_shift) & blue_mask);
-
-#define CYCLE(body) \
- for (int y=0; y<h; y++) { \
- const uchar* src = cimage.scanLine(y); \
- uchar* dst = newbits + xi->bytes_per_line*y; \
- const QRgb* p = (const QRgb *)src; \
- body \
- }
-
- if (dither_tc) {
- switch (mode) {
- case BPP16_565:
- CYCLE(
- quint16* dst16 = (quint16*)dst;
- for (int x=0; x<w; x++) {
- GET_PIXEL_DITHER_TC_OPT(<<8,<<3,>>3,0xf800,0x7e0,0x1f,5,6,5)
- *dst16++ = pixel;
- }
- )
- break;
- case BPP16_555:
- CYCLE(
- quint16* dst16 = (quint16*)dst;
- for (int x=0; x<w; x++) {
- GET_PIXEL_DITHER_TC_OPT(<<7,<<2,>>3,0x7c00,0x3e0,0x1f,5,5,5)
- *dst16++ = pixel;
- }
- )
- break;
- case BPP16_MSB: // 16 bit MSB
- CYCLE(
- for (int x=0; x<w; x++) {
- GET_PIXEL_DITHER_TC
- *dst++ = (pixel >> 8);
- *dst++ = pixel;
- }
- )
- break;
- case BPP16_LSB: // 16 bit LSB
- CYCLE(
- for (int x=0; x<w; x++) {
- GET_PIXEL_DITHER_TC
- *dst++ = pixel;
- *dst++ = pixel >> 8;
- }
- )
- break;
- default:
- qFatal("Logic error");
- }
- } else {
- switch (mode) {
- case BPP8: // 8 bit
- CYCLE(
- Q_UNUSED(p);
- for (int x=0; x<w; x++)
- *dst++ = pix[*src++];
- )
- break;
- case BPP16_565:
- CYCLE(
- quint16* dst16 = (quint16*)dst;
- for (int x = 0; x < w; x++) {
- *dst16++ = ((*p >> 8) & 0xf800)
- | ((*p >> 5) & 0x7e0)
- | ((*p >> 3) & 0x1f);
- ++p;
- }
- )
- break;
- case BPP16_555:
- CYCLE(
- quint16* dst16 = (quint16*)dst;
- for (int x=0; x<w; x++) {
- *dst16++ = ((*p >> 9) & 0x7c00)
- | ((*p >> 6) & 0x3e0)
- | ((*p >> 3) & 0x1f);
- ++p;
- }
- )
- break;
- case BPP16_MSB: // 16 bit MSB
- CYCLE(
- for (int x=0; x<w; x++) {
- GET_PIXEL
- *dst++ = (pixel >> 8);
- *dst++ = pixel;
- }
- )
- break;
- case BPP16_LSB: // 16 bit LSB
- CYCLE(
- for (int x=0; x<w; x++) {
- GET_PIXEL
- *dst++ = pixel;
- *dst++ = pixel >> 8;
- }
- )
- break;
- case BPP24_888: // 24 bit MSB
- CYCLE(
- for (int x=0; x<w; x++) {
- *dst++ = qRed (*p);
- *dst++ = qGreen(*p);
- *dst++ = qBlue (*p++);
- }
- )
- break;
- case BPP24_MSB: // 24 bit MSB
- CYCLE(
- for (int x=0; x<w; x++) {
- GET_PIXEL
- *dst++ = pixel >> 16;
- *dst++ = pixel >> 8;
- *dst++ = pixel;
- }
- )
- break;
- case BPP24_LSB: // 24 bit LSB
- CYCLE(
- for (int x=0; x<w; x++) {
- GET_PIXEL
- *dst++ = pixel;
- *dst++ = pixel >> 8;
- *dst++ = pixel >> 16;
- }
- )
- break;
- case BPP32_8888:
- CYCLE(
- memcpy(dst, p, w * 4);
- )
- break;
- case BPP32_MSB: // 32 bit MSB
- CYCLE(
- for (int x=0; x<w; x++) {
- GET_PIXEL
- *dst++ = pixel >> 24;
- *dst++ = pixel >> 16;
- *dst++ = pixel >> 8;
- *dst++ = pixel;
- }
- )
- break;
- case BPP32_LSB: // 32 bit LSB
- CYCLE(
- for (int x=0; x<w; x++) {
- GET_PIXEL
- *dst++ = pixel;
- *dst++ = pixel >> 8;
- *dst++ = pixel >> 16;
- *dst++ = pixel >> 24;
- }
- )
- break;
- default:
- qFatal("Logic error 2");
- }
- }
- xi->data = (char *)newbits;
- }
-
- if (d == 8 && !trucol) { // 8 bit pixmap
- int pop[256]; // pixel popularity
-
- if (image.colorCount() == 0)
- image.setColorCount(1);
-
- const QImage &cimage = image;
- memset(pop, 0, sizeof(int)*256); // reset popularity array
- for (int i = 0; i < h; i++) { // for each scanline...
- const uchar* p = cimage.scanLine(i);
- const uchar *end = p + w;
- while (p < end) // compute popularity
- pop[*p++]++;
- }
-
- newbits = (uchar *)malloc(nbytes); // copy image into newbits
- Q_CHECK_PTR(newbits);
- if (!newbits) // no memory
- return;
- uchar* p = newbits;
- memcpy(p, cimage.bits(), nbytes); // copy image data into newbits
-
- /*
- * The code below picks the most important colors. It is based on the
- * diversity algorithm, implemented in XV 3.10. XV is (C) by John Bradley.
- */
-
- struct PIX { // pixel sort element
- uchar r,g,b,n; // color + pad
- int use; // popularity
- int index; // index in colormap
- int mindist;
- };
- int ncols = 0;
- for (int i=0; i< cimage.colorCount(); i++) { // compute number of colors
- if (pop[i] > 0)
- ncols++;
- }
- for (int i = cimage.colorCount(); i < 256; i++) // ignore out-of-range pixels
- pop[i] = 0;
-
- // works since we make sure above to have at least
- // one color in the image
- if (ncols == 0)
- ncols = 1;
-
- PIX pixarr[256]; // pixel array
- PIX pixarr_sorted[256]; // pixel array (sorted)
- memset(pixarr, 0, ncols*sizeof(PIX));
- PIX *px = &pixarr[0];
- int maxpop = 0;
- int maxpix = 0;
- uint j = 0;
- QVector<QRgb> ctable = cimage.colorTable();
- for (int i = 0; i < 256; i++) { // init pixel array
- if (pop[i] > 0) {
- px->r = qRed (ctable[i]);
- px->g = qGreen(ctable[i]);
- px->b = qBlue (ctable[i]);
- px->n = 0;
- px->use = pop[i];
- if (pop[i] > maxpop) { // select most popular entry
- maxpop = pop[i];
- maxpix = j;
- }
- px->index = i;
- px->mindist = 1000000;
- px++;
- j++;
- }
- }
- pixarr_sorted[0] = pixarr[maxpix];
- pixarr[maxpix].use = 0;
-
- for (int i = 1; i < ncols; i++) { // sort pixels
- int minpix = -1, mindist = -1;
- px = &pixarr_sorted[i-1];
- int r = px->r;
- int g = px->g;
- int b = px->b;
- int dist;
- if ((i & 1) || i<10) { // sort on max distance
- for (int j=0; j<ncols; j++) {
- px = &pixarr[j];
- if (px->use) {
- dist = (px->r - r)*(px->r - r) +
- (px->g - g)*(px->g - g) +
- (px->b - b)*(px->b - b);
- if (px->mindist > dist)
- px->mindist = dist;
- if (px->mindist > mindist) {
- mindist = px->mindist;
- minpix = j;
- }
- }
- }
- } else { // sort on max popularity
- for (int j=0; j<ncols; j++) {
- px = &pixarr[j];
- if (px->use) {
- dist = (px->r - r)*(px->r - r) +
- (px->g - g)*(px->g - g) +
- (px->b - b)*(px->b - b);
- if (px->mindist > dist)
- px->mindist = dist;
- if (px->use > mindist) {
- mindist = px->use;
- minpix = j;
- }
- }
- }
- }
- pixarr_sorted[i] = pixarr[minpix];
- pixarr[minpix].use = 0;
- }
-
- QColormap cmap = QColormap::instance(xinfo.screen());
- uint pix[256]; // pixel translation table
- px = &pixarr_sorted[0];
- for (int i = 0; i < ncols; i++) { // allocate colors
- QColor c(px->r, px->g, px->b);
- pix[px->index] = cmap.pixel(c);
- px++;
- }
-
- p = newbits;
- for (int i = 0; i < nbytes; i++) { // translate pixels
- *p = pix[*p];
- p++;
- }
- }
-
- if (!xi) { // X image not created
- xi = XCreateImage(dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0);
- if (xi->bits_per_pixel == 16) { // convert 8 bpp ==> 16 bpp
- ushort *p2;
- int p2inc = xi->bytes_per_line/sizeof(ushort);
- ushort *newerbits = (ushort *)malloc(xi->bytes_per_line * h);
- Q_CHECK_PTR(newerbits);
- if (!newerbits) // no memory
- return;
- uchar* p = newbits;
- for (int y = 0; y < h; y++) { // OOPS: Do right byte order!!
- p2 = newerbits + p2inc*y;
- for (int x = 0; x < w; x++)
- *p2++ = *p++;
- }
- free(newbits);
- newbits = (uchar *)newerbits;
- } else if (xi->bits_per_pixel != 8) {
- qWarning("QPixmap::fromImage: Display not supported "
- "(bpp=%d)", xi->bits_per_pixel);
- }
- xi->data = (char *)newbits;
- }
-
- hd = (Qt::HANDLE)XCreatePixmap(X11->display,
- RootWindow(X11->display, xinfo.screen()),
- w, h, dd);
-
- GC gc = XCreateGC(dpy, hd, 0, 0);
- XPutImage(dpy, hd, gc, xi, 0, 0, 0, 0, w, h);
- XFreeGC(dpy, gc);
-
- qSafeXDestroyImage(xi);
- d = dd;
-
-#ifndef QT_NO_XRENDER
- if (X11->use_xrender) {
- XRenderPictFormat *format = d == 1
- ? XRenderFindStandardFormat(X11->display, PictStandardA1)
- : XRenderFindVisualFormat(X11->display, (Visual *)xinfo.visual());
- picture = XRenderCreatePicture(X11->display, hd, format, 0, 0);
- }
-#endif
-
- if (alphaCheck.hasAlpha()) {
- QBitmap m = QBitmap::fromImage(image.createAlphaMask(flags));
- setMask(m);
- }
-}
-
-Qt::HANDLE QX11PixmapData::createBitmapFromImage(const QImage &image)
-{
- QImage img = image.convertToFormat(QImage::Format_MonoLSB);
- const QRgb c0 = QColor(Qt::black).rgb();
- const QRgb c1 = QColor(Qt::white).rgb();
- if (img.color(0) == c0 && img.color(1) == c1) {
- img.invertPixels();
- img.setColor(0, c1);
- img.setColor(1, c0);
- }
-
- char *bits;
- uchar *tmp_bits;
- int w = img.width();
- int h = img.height();
- int bpl = (w + 7) / 8;
- int ibpl = img.bytesPerLine();
- if (bpl != ibpl) {
- tmp_bits = new uchar[bpl*h];
- bits = (char *)tmp_bits;
- uchar *p, *b;
- int y;
- b = tmp_bits;
- p = img.scanLine(0);
- for (y = 0; y < h; y++) {
- memcpy(b, p, bpl);
- b += bpl;
- p += ibpl;
- }
- } else {
- bits = (char *)img.bits();
- tmp_bits = 0;
- }
- Qt::HANDLE hd = (Qt::HANDLE)XCreateBitmapFromData(X11->display,
- QX11Info::appRootWindow(),
- bits, w, h);
- if (tmp_bits) // Avoid purify complaint
- delete [] tmp_bits;
- return hd;
-}
-
-void QX11PixmapData::bitmapFromImage(const QImage &image)
-{
- w = image.width();
- h = image.height();
- d = 1;
- is_null = (w <= 0 || h <= 0);
- hd = createBitmapFromImage(image);
-#ifndef QT_NO_XRENDER
- if (X11->use_xrender)
- picture = XRenderCreatePicture(X11->display, hd,
- XRenderFindStandardFormat(X11->display, PictStandardA1), 0, 0);
-#endif // QT_NO_XRENDER
-}
-
-void QX11PixmapData::fill(const QColor &fillColor)
-{
- if (fillColor.alpha() != 255) {
-#ifndef QT_NO_XRENDER
- if (X11->use_xrender) {
- if (!picture || d != 32)
- convertToARGB32(/*preserveContents = */false);
-
- ::Picture src = X11->getSolidFill(xinfo.screen(), fillColor);
- XRenderComposite(X11->display, PictOpSrc, src, 0, picture,
- 0, 0, width(), height(),
- 0, 0, width(), height());
- } else
-#endif
- {
- QImage im(width(), height(), QImage::Format_ARGB32_Premultiplied);
- im.fill(PREMUL(fillColor.rgba()));
- release();
- fromImage(im, Qt::AutoColor | Qt::OrderedAlphaDither);
- }
- return;
- }
-
- GC gc = XCreateGC(X11->display, hd, 0, 0);
- if (depth() == 1) {
- XSetForeground(X11->display, gc, qGray(fillColor.rgb()) > 127 ? 0 : 1);
- } else if (X11->use_xrender && d >= 24) {
- XSetForeground(X11->display, gc, fillColor.rgba());
- } else {
- XSetForeground(X11->display, gc,
- QColormap::instance(xinfo.screen()).pixel(fillColor));
- }
- XFillRectangle(X11->display, hd, gc, 0, 0, width(), height());
- XFreeGC(X11->display, gc);
-}
-
-QX11PixmapData::~QX11PixmapData()
-{
- // Cleanup hooks have to be called before the handles are freed
- if (is_cached) {
- QImagePixmapCleanupHooks::executePixmapDataDestructionHooks(this);
- is_cached = false;
- }
-
- release();
-}
-
-void QX11PixmapData::release()
-{
- delete pengine;
- pengine = 0;
-
- if (!X11) {
- // At this point, the X server will already have freed our resources,
- // so there is nothing to do.
- return;
- }
-
- if (x11_mask) {
-#ifndef QT_NO_XRENDER
- if (mask_picture)
- XRenderFreePicture(X11->display, mask_picture);
- mask_picture = 0;
-#endif
- XFreePixmap(X11->display, x11_mask);
- x11_mask = 0;
- }
-
- if (hd) {
-#ifndef QT_NO_XRENDER
- if (picture) {
- XRenderFreePicture(X11->display, picture);
- picture = 0;
- }
-#endif // QT_NO_XRENDER
-
- if (hd2) {
- XFreePixmap(xinfo.display(), hd2);
- hd2 = 0;
- }
- if (!(flags & Readonly))
- XFreePixmap(xinfo.display(), hd);
- hd = 0;
- }
-}
-
-QPixmap QX11PixmapData::alphaChannel() const
-{
- if (!hasAlphaChannel()) {
- QPixmap pm(w, h);
- pm.fill(Qt::white);
- return pm;
- }
- QImage im(toImage());
- return QPixmap::fromImage(im.alphaChannel(), Qt::OrderedDither);
-}
-
-void QX11PixmapData::setAlphaChannel(const QPixmap &alpha)
-{
- QImage image(toImage());
- image.setAlphaChannel(alpha.toImage());
- release();
- fromImage(image, Qt::OrderedDither | Qt::OrderedAlphaDither);
-}
-
-
-QBitmap QX11PixmapData::mask() const
-{
- QBitmap mask;
-#ifndef QT_NO_XRENDER
- if (picture && d == 32) {
- // #### slow - there must be a better way..
- mask = QBitmap::fromImage(toImage().createAlphaMask());
- } else
-#endif
- if (d == 1) {
- QX11PixmapData *that = const_cast<QX11PixmapData*>(this);
- mask = QPixmap(that);
- } else {
- mask = mask_to_bitmap(xinfo.screen());
- }
- return mask;
-}
-
-/*!
- Sets a mask bitmap.
-
- The \a newmask bitmap defines the clip mask for this pixmap. Every
- pixel in \a newmask corresponds to a pixel in this pixmap. Pixel
- value 1 means opaque and pixel value 0 means transparent. The mask
- must have the same size as this pixmap.
-
- \warning Setting the mask on a pixmap will cause any alpha channel
- data to be cleared. For example:
- \snippet doc/src/snippets/image/image.cpp 2
- Now, alpha and alphacopy are visually different.
-
- Setting a null mask resets the mask.
-
- The effect of this function is undefined when the pixmap is being
- painted on.
-
- \sa mask(), {QPixmap#Pixmap Transformations}{Pixmap
- Transformations}, QBitmap
-*/
-void QX11PixmapData::setMask(const QBitmap &newmask)
-{
- if (newmask.isNull()) { // clear mask
-#ifndef QT_NO_XRENDER
- if (picture && d == 32) {
- QX11PixmapData newData(pixelType());
- newData.resize(w, h);
- newData.fill(Qt::black);
- XRenderComposite(X11->display, PictOpOver,
- picture, 0, newData.picture,
- 0, 0, 0, 0, 0, 0, w, h);
- release();
- *this = newData;
- // the new QX11PixmapData object isn't referenced yet, so
- // ref it
- ref.ref();
-
- // the below is to make sure the QX11PixmapData destructor
- // doesn't delete our newly created render picture
- newData.hd = 0;
- newData.x11_mask = 0;
- newData.picture = 0;
- newData.mask_picture = 0;
- newData.hd2 = 0;
- } else
-#endif
- if (x11_mask) {
-#ifndef QT_NO_XRENDER
- if (picture) {
- XRenderPictureAttributes attrs;
- attrs.alpha_map = 0;
- XRenderChangePicture(X11->display, picture, CPAlphaMap,
- &attrs);
- }
- if (mask_picture)
- XRenderFreePicture(X11->display, mask_picture);
- mask_picture = 0;
-#endif
- XFreePixmap(X11->display, x11_mask);
- x11_mask = 0;
- }
- return;
- }
-
-#ifndef QT_NO_XRENDER
- if (picture && d == 32) {
- XRenderComposite(X11->display, PictOpSrc,
- picture, newmask.x11PictureHandle(),
- picture, 0, 0, 0, 0, 0, 0, w, h);
- } else
-#endif
- if (depth() == 1) {
- XGCValues vals;
- vals.function = GXand;
- GC gc = XCreateGC(X11->display, hd, GCFunction, &vals);
- XCopyArea(X11->display, newmask.handle(), hd, gc, 0, 0,
- width(), height(), 0, 0);
- XFreeGC(X11->display, gc);
- } else {
- // ##### should or the masks together
- if (x11_mask) {
- XFreePixmap(X11->display, x11_mask);
-#ifndef QT_NO_XRENDER
- if (mask_picture)
- XRenderFreePicture(X11->display, mask_picture);
-#endif
- }
- x11_mask = QX11PixmapData::bitmap_to_mask(newmask, xinfo.screen());
-#ifndef QT_NO_XRENDER
- if (picture) {
- mask_picture = XRenderCreatePicture(X11->display, x11_mask,
- XRenderFindStandardFormat(X11->display, PictStandardA1), 0, 0);
- XRenderPictureAttributes attrs;
- attrs.alpha_map = mask_picture;
- XRenderChangePicture(X11->display, picture, CPAlphaMap, &attrs);
- }
-#endif
- }
-}
-
-int QX11PixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const
-{
- switch (metric) {
- case QPaintDevice::PdmWidth:
- return w;
- case QPaintDevice::PdmHeight:
- return h;
- case QPaintDevice::PdmNumColors:
- return 1 << d;
- case QPaintDevice::PdmDepth:
- return d;
- case QPaintDevice::PdmWidthMM: {
- const int screen = xinfo.screen();
- const int mm = DisplayWidthMM(X11->display, screen) * w
- / DisplayWidth(X11->display, screen);
- return mm;
- }
- case QPaintDevice::PdmHeightMM: {
- const int screen = xinfo.screen();
- const int mm = (DisplayHeightMM(X11->display, screen) * h)
- / DisplayHeight(X11->display, screen);
- return mm;
- }
- case QPaintDevice::PdmDpiX:
- case QPaintDevice::PdmPhysicalDpiX:
- return QX11Info::appDpiX(xinfo.screen());
- case QPaintDevice::PdmDpiY:
- case QPaintDevice::PdmPhysicalDpiY:
- return QX11Info::appDpiY(xinfo.screen());
- default:
- qWarning("QX11PixmapData::metric(): Invalid metric");
- return 0;
- }
-}
-
-struct QXImageWrapper
-{
- XImage *xi;
-};
-
-bool QX11PixmapData::canTakeQImageFromXImage(const QXImageWrapper &xiWrapper) const
-{
- XImage *xi = xiWrapper.xi;
-
- // ARGB32_Premultiplied
- if (picture && depth() == 32)
- return true;
-
- Visual *visual = (Visual *)xinfo.visual();
-
- // RGB32
- if (depth() == 24 && xi->bits_per_pixel == 32 && visual->red_mask == 0xff0000
- && visual->green_mask == 0xff00 && visual->blue_mask == 0xff)
- return true;
-
- // RGB16
- if (depth() == 16 && xi->bits_per_pixel == 16 && visual->red_mask == 0xf800
- && visual->green_mask == 0x7e0 && visual->blue_mask == 0x1f)
- return true;
-
- return false;
-}
-
-QImage QX11PixmapData::takeQImageFromXImage(const QXImageWrapper &xiWrapper) const
-{
- XImage *xi = xiWrapper.xi;
-
- QImage::Format format = QImage::Format_ARGB32_Premultiplied;
- if (depth() == 24)
- format = QImage::Format_RGB32;
- else if (depth() == 16)
- format = QImage::Format_RGB16;
-
- QImage image((uchar *)xi->data, xi->width, xi->height, xi->bytes_per_line, format);
- // take ownership
- image.data_ptr()->own_data = true;
- xi->data = 0;
-
- // we may have to swap the byte order
- if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && xi->byte_order == MSBFirst)
- || (QSysInfo::ByteOrder == QSysInfo::BigEndian && xi->byte_order == LSBFirst))
- {
- for (int i=0; i < image.height(); i++) {
- if (depth() == 16) {
- ushort *p = (ushort*)image.scanLine(i);
- ushort *end = p + image.width();
- while (p < end) {
- *p = ((*p << 8) & 0xff00) | ((*p >> 8) & 0x00ff);
- p++;
- }
- } else {
- uint *p = (uint*)image.scanLine(i);
- uint *end = p + image.width();
- while (p < end) {
- *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000)
- | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff);
- p++;
- }
- }
- }
- }
-
- // fix-up alpha channel
- if (format == QImage::Format_RGB32) {
- QRgb *p = (QRgb *)image.bits();
- for (int y = 0; y < xi->height; ++y) {
- for (int x = 0; x < xi->width; ++x)
- p[x] |= 0xff000000;
- p += xi->bytes_per_line / 4;
- }
- }
-
- XDestroyImage(xi);
- return image;
-}
-
-QImage QX11PixmapData::toImage(const QRect &rect) const
-{
- QXImageWrapper xiWrapper;
- xiWrapper.xi = XGetImage(X11->display, hd, rect.x(), rect.y(), rect.width(), rect.height(),
- AllPlanes, (depth() == 1) ? XYPixmap : ZPixmap);
-
- Q_CHECK_PTR(xiWrapper.xi);
- if (!xiWrapper.xi)
- return QImage();
-
- if (!x11_mask && canTakeQImageFromXImage(xiWrapper))
- return takeQImageFromXImage(xiWrapper);
-
- QImage image = toImage(xiWrapper, rect);
- qSafeXDestroyImage(xiWrapper.xi);
- return image;
-}
-
-/*!
- Converts the pixmap to a QImage. Returns a null image if the
- conversion fails.
-
- If the pixmap has 1-bit depth, the returned image will also be 1
- bit deep. If the pixmap has 2- to 8-bit depth, the returned image
- has 8-bit depth. If the pixmap has greater than 8-bit depth, the
- returned image has 32-bit depth.
-
- Note that for the moment, alpha masks on monochrome images are
- ignored.
-
- \sa fromImage(), {QImage#Image Formats}{Image Formats}
-*/
-
-QImage QX11PixmapData::toImage() const
-{
- return toImage(QRect(0, 0, w, h));
-}
-
-QImage QX11PixmapData::toImage(const QXImageWrapper &xiWrapper, const QRect &rect) const
-{
- XImage *xi = xiWrapper.xi;
-
- int d = depth();
- Visual *visual = (Visual *)xinfo.visual();
- bool trucol = (visual->c_class >= TrueColor) && d > 1;
-
- QImage::Format format = QImage::Format_Mono;
- if (d > 1 && d <= 8) {
- d = 8;
- format = QImage::Format_Indexed8;
- }
- // we could run into the situation where d == 8 AND trucol is true, which can
- // cause problems when converting to and from images. in this case, always treat
- // the depth as 32...
- if (d > 8 || trucol) {
- d = 32;
- format = QImage::Format_RGB32;
- }
-
- if (d == 1 && xi->bitmap_bit_order == LSBFirst)
- format = QImage::Format_MonoLSB;
- if (x11_mask && format == QImage::Format_RGB32)
- format = QImage::Format_ARGB32;
-
- QImage image(xi->width, xi->height, format);
- if (image.isNull()) // could not create image
- return image;
-
- QImage alpha;
- if (x11_mask) {
- if (rect.contains(QRect(0, 0, w, h)))
- alpha = mask().toImage();
- else
- alpha = mask().toImage().copy(rect);
- }
- bool ale = alpha.format() == QImage::Format_MonoLSB;
-
- if (trucol) { // truecolor
- const uint red_mask = (uint)visual->red_mask;
- const uint green_mask = (uint)visual->green_mask;
- const uint blue_mask = (uint)visual->blue_mask;
- const int red_shift = highest_bit(red_mask) - 7;
- const int green_shift = highest_bit(green_mask) - 7;
- const int blue_shift = highest_bit(blue_mask) - 7;
-
- const uint red_bits = n_bits(red_mask);
- const uint green_bits = n_bits(green_mask);
- const uint blue_bits = n_bits(blue_mask);
-
- static uint red_table_bits = 0;
- static uint green_table_bits = 0;
- static uint blue_table_bits = 0;
-
- if (red_bits < 8 && red_table_bits != red_bits) {
- build_scale_table(&red_scale_table, red_bits);
- red_table_bits = red_bits;
- }
- if (blue_bits < 8 && blue_table_bits != blue_bits) {
- build_scale_table(&blue_scale_table, blue_bits);
- blue_table_bits = blue_bits;
- }
- if (green_bits < 8 && green_table_bits != green_bits) {
- build_scale_table(&green_scale_table, green_bits);
- green_table_bits = green_bits;
- }
-
- int r, g, b;
-
- QRgb *dst;
- uchar *src;
- uint pixel;
- int bppc = xi->bits_per_pixel;
-
- if (bppc > 8 && xi->byte_order == LSBFirst)
- bppc++;
-
- for (int y = 0; y < xi->height; ++y) {
- uchar* asrc = x11_mask ? alpha.scanLine(y) : 0;
- dst = (QRgb *)image.scanLine(y);
- src = (uchar *)xi->data + xi->bytes_per_line*y;
- for (int x = 0; x < xi->width; x++) {
- switch (bppc) {
- case 8:
- pixel = *src++;
- break;
- case 16: // 16 bit MSB
- pixel = src[1] | (uint)src[0] << 8;
- src += 2;
- break;
- case 17: // 16 bit LSB
- pixel = src[0] | (uint)src[1] << 8;
- src += 2;
- break;
- case 24: // 24 bit MSB
- pixel = src[2] | (uint)src[1] << 8 | (uint)src[0] << 16;
- src += 3;
- break;
- case 25: // 24 bit LSB
- pixel = src[0] | (uint)src[1] << 8 | (uint)src[2] << 16;
- src += 3;
- break;
- case 32: // 32 bit MSB
- pixel = src[3] | (uint)src[2] << 8 | (uint)src[1] << 16 | (uint)src[0] << 24;
- src += 4;
- break;
- case 33: // 32 bit LSB
- pixel = src[0] | (uint)src[1] << 8 | (uint)src[2] << 16 | (uint)src[3] << 24;
- src += 4;
- break;
- default: // should not really happen
- x = xi->width; // leave loop
- y = xi->height;
- pixel = 0; // eliminate compiler warning
- qWarning("QPixmap::convertToImage: Invalid depth %d", bppc);
- }
- if (red_shift > 0)
- r = (pixel & red_mask) >> red_shift;
- else
- r = (pixel & red_mask) << -red_shift;
- if (green_shift > 0)
- g = (pixel & green_mask) >> green_shift;
- else
- g = (pixel & green_mask) << -green_shift;
- if (blue_shift > 0)
- b = (pixel & blue_mask) >> blue_shift;
- else
- b = (pixel & blue_mask) << -blue_shift;
-
- if (red_bits < 8)
- r = red_scale_table[r];
- if (green_bits < 8)
- g = green_scale_table[g];
- if (blue_bits < 8)
- b = blue_scale_table[b];
-
- if (x11_mask) {
- if (ale) {
- *dst++ = (asrc[x >> 3] & (1 << (x & 7))) ? qRgba(r, g, b, 0xff) : 0;
- } else {
- *dst++ = (asrc[x >> 3] & (0x80 >> (x & 7))) ? qRgba(r, g, b, 0xff) : 0;
- }
- } else {
- *dst++ = qRgb(r, g, b);
- }
- }
- }
- } else if (xi->bits_per_pixel == d) { // compatible depth
- char *xidata = xi->data; // copy each scanline
- int bpl = qMin(image.bytesPerLine(),xi->bytes_per_line);
- for (int y=0; y<xi->height; y++) {
- memcpy(image.scanLine(y), xidata, bpl);
- xidata += xi->bytes_per_line;
- }
- } else {
- /* Typically 2 or 4 bits display depth */
- qWarning("QPixmap::convertToImage: Display not supported (bpp=%d)",
- xi->bits_per_pixel);
- return QImage();
- }
-
- if (d == 1) { // bitmap
- image.setColorCount(2);
- image.setColor(0, qRgb(255,255,255));
- image.setColor(1, qRgb(0,0,0));
- } else if (!trucol) { // pixmap with colormap
- register uchar *p;
- uchar *end;
- uchar use[256]; // pixel-in-use table
- uchar pix[256]; // pixel translation table
- int ncols, bpl;
- memset(use, 0, 256);
- memset(pix, 0, 256);
- bpl = image.bytesPerLine();
-
- if (x11_mask) { // which pixels are used?
- for (int i = 0; i < xi->height; i++) {
- uchar* asrc = alpha.scanLine(i);
- p = image.scanLine(i);
- if (ale) {
- for (int x = 0; x < xi->width; x++) {
- if (asrc[x >> 3] & (1 << (x & 7)))
- use[*p] = 1;
- ++p;
- }
- } else {
- for (int x = 0; x < xi->width; x++) {
- if (asrc[x >> 3] & (0x80 >> (x & 7)))
- use[*p] = 1;
- ++p;
- }
- }
- }
- } else {
- for (int i = 0; i < xi->height; i++) {
- p = image.scanLine(i);
- end = p + bpl;
- while (p < end)
- use[*p++] = 1;
- }
- }
- ncols = 0;
- for (int i = 0; i < 256; i++) { // build translation table
- if (use[i])
- pix[i] = ncols++;
- }
- for (int i = 0; i < xi->height; i++) { // translate pixels
- p = image.scanLine(i);
- end = p + bpl;
- while (p < end) {
- *p = pix[*p];
- p++;
- }
- }
- if (x11_mask) {
- int trans;
- if (ncols < 256) {
- trans = ncols++;
- image.setColorCount(ncols); // create color table
- image.setColor(trans, 0x00000000);
- } else {
- image.setColorCount(ncols); // create color table
- // oh dear... no spare "transparent" pixel.
- // use first pixel in image (as good as any).
- trans = image.scanLine(0)[0];
- }
- for (int i = 0; i < xi->height; i++) {
- uchar* asrc = alpha.scanLine(i);
- p = image.scanLine(i);
- if (ale) {
- for (int x = 0; x < xi->width; x++) {
- if (!(asrc[x >> 3] & (1 << (x & 7))))
- *p = trans;
- ++p;
- }
- } else {
- for (int x = 0; x < xi->width; x++) {
- if (!(asrc[x >> 3] & (1 << (7 -(x & 7)))))
- *p = trans;
- ++p;
- }
- }
- }
- } else {
- image.setColorCount(ncols); // create color table
- }
- QVector<QColor> colors = QColormap::instance(xinfo.screen()).colormap();
- int j = 0;
- for (int i=0; i<colors.size(); i++) { // translate pixels
- if (use[i])
- image.setColor(j++, 0xff000000 | colors.at(i).rgb());
- }
- }
-
- return image;
-}
-
-/*!
- Returns a copy of the pixmap that is transformed using the given
- transformation \a matrix and transformation \a mode. The original
- pixmap is not changed.
-
- The transformation \a matrix is internally adjusted to compensate
- for unwanted translation; i.e. the pixmap produced is the smallest
- pixmap that contains all the transformed points of the original
- pixmap. Use the trueMatrix() function to retrieve the actual
- matrix used for transforming the pixmap.
-
- This function is slow because it involves transformation to a
- QImage, non-trivial computations and a transformation back to a
- QPixmap.
-
- \sa trueMatrix(), {QPixmap#Pixmap Transformations}{Pixmap
- Transformations}
-*/
-QPixmap QX11PixmapData::transformed(const QTransform &transform,
- Qt::TransformationMode mode ) const
-{
- if (mode == Qt::SmoothTransformation || transform.type() >= QTransform::TxProject) {
- QImage image = toImage();
- return QPixmap::fromImage(image.transformed(transform, mode));
- }
-
- uint w = 0;
- uint h = 0; // size of target pixmap
- uint ws, hs; // size of source pixmap
- uchar *dptr; // data in target pixmap
- uint dbpl, dbytes; // bytes per line/bytes total
- uchar *sptr; // data in original pixmap
- int sbpl; // bytes per line in original
- int bpp; // bits per pixel
- bool depth1 = depth() == 1;
- Display *dpy = X11->display;
-
- ws = width();
- hs = height();
-
- QTransform mat(transform.m11(), transform.m12(), transform.m13(),
- transform.m21(), transform.m22(), transform.m23(),
- 0., 0., 1);
- bool complex_xform = false;
- qreal scaledWidth;
- qreal scaledHeight;
-
- if (mat.type() <= QTransform::TxScale) {
- scaledHeight = qAbs(mat.m22()) * hs + 0.9999;
- scaledWidth = qAbs(mat.m11()) * ws + 0.9999;
- h = qAbs(int(scaledHeight));
- w = qAbs(int(scaledWidth));
- } else { // rotation or shearing
- QPolygonF a(QRectF(0, 0, ws, hs));
- a = mat.map(a);
- QRect r = a.boundingRect().toAlignedRect();
- w = r.width();
- h = r.height();
- scaledWidth = w;
- scaledHeight = h;
- complex_xform = true;
- }
- mat = QPixmap::trueMatrix(mat, ws, hs); // true matrix
-
- bool invertible;
- mat = mat.inverted(&invertible); // invert matrix
-
- if (h == 0 || w == 0 || !invertible
- || qAbs(scaledWidth) >= 32768 || qAbs(scaledHeight) >= 32768 )
- // error, return null pixmap
- return QPixmap();
-
-#if defined(QT_MITSHM)
- static bool try_once = true;
- if (try_once) {
- try_once = false;
- if (!xshminit)
- qt_create_mitshm_buffer(this, 800, 600);
- }
-
- bool use_mitshm = xshmimg && !depth1 &&
- xshmimg->width >= w && xshmimg->height >= h;
-#endif
- XImage *xi = XGetImage(X11->display, handle(), 0, 0, ws, hs, AllPlanes,
- depth1 ? XYPixmap : ZPixmap);
-
- if (!xi)
- return QPixmap();
-
- sbpl = xi->bytes_per_line;
- sptr = (uchar *)xi->data;
- bpp = xi->bits_per_pixel;
-
- if (depth1)
- dbpl = (w+7)/8;
- else
- dbpl = ((w*bpp+31)/32)*4;
- dbytes = dbpl*h;
-
-#if defined(QT_MITSHM)
- if (use_mitshm) {
- dptr = (uchar *)xshmimg->data;
- uchar fillbyte = bpp == 8 ? white.pixel() : 0xff;
- for (int y=0; y<h; y++)
- memset(dptr + y*xshmimg->bytes_per_line, fillbyte, dbpl);
- } else {
-#endif
- dptr = (uchar *)malloc(dbytes); // create buffer for bits
- Q_CHECK_PTR(dptr);
- if (depth1) // fill with zeros
- memset(dptr, 0, dbytes);
- else if (bpp == 8) // fill with background color
- memset(dptr, WhitePixel(X11->display, xinfo.screen()), dbytes);
- else
- memset(dptr, 0, dbytes);
-#if defined(QT_MITSHM)
- }
-#endif
-
- // #define QT_DEBUG_XIMAGE
-#if defined(QT_DEBUG_XIMAGE)
- qDebug("----IMAGE--INFO--------------");
- qDebug("width............. %d", xi->width);
- qDebug("height............ %d", xi->height);
- qDebug("xoffset........... %d", xi->xoffset);
- qDebug("format............ %d", xi->format);
- qDebug("byte order........ %d", xi->byte_order);
- qDebug("bitmap unit....... %d", xi->bitmap_unit);
- qDebug("bitmap bit order.. %d", xi->bitmap_bit_order);
- qDebug("depth............. %d", xi->depth);
- qDebug("bytes per line.... %d", xi->bytes_per_line);
- qDebug("bits per pixel.... %d", xi->bits_per_pixel);
-#endif
-
- int type;
- if (xi->bitmap_bit_order == MSBFirst)
- type = QT_XFORM_TYPE_MSBFIRST;
- else
- type = QT_XFORM_TYPE_LSBFIRST;
- int xbpl, p_inc;
- if (depth1) {
- xbpl = (w+7)/8;
- p_inc = dbpl - xbpl;
- } else {
- xbpl = (w*bpp)/8;
- p_inc = dbpl - xbpl;
-#if defined(QT_MITSHM)
- if (use_mitshm)
- p_inc = xshmimg->bytes_per_line - xbpl;
-#endif
- }
-
- if (!qt_xForm_helper(mat, xi->xoffset, type, bpp, dptr, xbpl, p_inc, h, sptr, sbpl, ws, hs)){
- qWarning("QPixmap::transform: display not supported (bpp=%d)",bpp);
- QPixmap pm;
- return pm;
- }
-
- qSafeXDestroyImage(xi);
-
- if (depth1) { // mono bitmap
- QBitmap bm = QBitmap::fromData(QSize(w, h), dptr,
- BitmapBitOrder(X11->display) == MSBFirst
- ? QImage::Format_Mono
- : QImage::Format_MonoLSB);
- free(dptr);
- return bm;
- } else { // color pixmap
- QX11PixmapData *x11Data = new QX11PixmapData(QPixmapData::PixmapType);
- QPixmap pm(x11Data);
- x11Data->flags &= ~QX11PixmapData::Uninitialized;
- x11Data->xinfo = xinfo;
- x11Data->d = d;
- x11Data->w = w;
- x11Data->h = h;
- x11Data->is_null = (w <= 0 || h <= 0);
- x11Data->hd = (Qt::HANDLE)XCreatePixmap(X11->display,
- RootWindow(X11->display, xinfo.screen()),
- w, h, d);
- x11Data->setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1));
-
-#ifndef QT_NO_XRENDER
- if (X11->use_xrender) {
- XRenderPictFormat *format = x11Data->d == 32
- ? XRenderFindStandardFormat(X11->display, PictStandardARGB32)
- : XRenderFindVisualFormat(X11->display, (Visual *) x11Data->xinfo.visual());
- x11Data->picture = XRenderCreatePicture(X11->display, x11Data->hd, format, 0, 0);
- }
-#endif // QT_NO_XRENDER
-
- GC gc = XCreateGC(X11->display, x11Data->hd, 0, 0);
-#if defined(QT_MITSHM)
- if (use_mitshm) {
- XCopyArea(dpy, xshmpm, x11Data->hd, gc, 0, 0, w, h, 0, 0);
- } else
-#endif
- {
- xi = XCreateImage(dpy, (Visual*)x11Data->xinfo.visual(),
- x11Data->d,
- ZPixmap, 0, (char *)dptr, w, h, 32, 0);
- XPutImage(dpy, pm.handle(), gc, xi, 0, 0, 0, 0, w, h);
- qSafeXDestroyImage(xi);
- }
- XFreeGC(X11->display, gc);
-
- if (x11_mask) { // xform mask, too
- pm.setMask(mask_to_bitmap(xinfo.screen()).transformed(transform));
- } else if (d != 32 && complex_xform) { // need a mask!
- QBitmap mask(ws, hs);
- mask.fill(Qt::color1);
- pm.setMask(mask.transformed(transform));
- }
- return pm;
- }
-}
-
-int QPixmap::x11SetDefaultScreen(int screen)
-{
- int old = defaultScreen;
- defaultScreen = screen;
- return old;
-}
-
-void QPixmap::x11SetScreen(int screen)
-{
- if (paintingActive()) {
- qWarning("QPixmap::x11SetScreen(): Cannot change screens during painting");
- return;
- }
-
- if (isNull())
- return;
-
- if (data->classId() != QPixmapData::X11Class)
- return;
-
- if (screen < 0)
- screen = QX11Info::appScreen();
-
- QX11PixmapData *x11Data = static_cast<QX11PixmapData*>(data.data());
- if (screen == x11Data->xinfo.screen())
- return; // nothing to do
-
- if (isNull()) {
- QX11InfoData* xd = x11Data->xinfo.getX11Data(true);
- xd->screen = screen;
- xd->depth = QX11Info::appDepth(screen);
- xd->cells = QX11Info::appCells(screen);
- xd->colormap = QX11Info::appColormap(screen);
- xd->defaultColormap = QX11Info::appDefaultColormap(screen);
- xd->visual = (Visual *)QX11Info::appVisual(screen);
- xd->defaultVisual = QX11Info::appDefaultVisual(screen);
- x11Data->xinfo.setX11Data(xd);
- return;
- }
-#if 0
- qDebug("QPixmap::x11SetScreen for %p from %d to %d. Size is %d/%d", x11Data, x11Data->xinfo.screen(), screen, width(), height());
-#endif
-
- x11SetDefaultScreen(screen);
- *this = qt_toX11Pixmap(toImage());
-}
-
-QPixmap QPixmap::grabWindow(WId window, int x, int y, int w, int h)
-{
- if (w == 0 || h == 0)
- return QPixmap();
-
- Display *dpy = X11->display;
- XWindowAttributes window_attr;
- if (!XGetWindowAttributes(dpy, window, &window_attr))
- return QPixmap();
-
- if (w < 0)
- w = window_attr.width - x;
- if (h < 0)
- h = window_attr.height - y;
-
- // determine the screen
- int scr;
- for (scr = 0; scr < ScreenCount(dpy); ++scr) {
- if (window_attr.root == RootWindow(dpy, scr)) // found it
- break;
- }
- if (scr >= ScreenCount(dpy)) // sanity check
- return QPixmap();
-
-
- // get the depth of the root window
- XWindowAttributes root_attr;
- if (!XGetWindowAttributes(dpy, window_attr.root, &root_attr))
- return QPixmap();
-
- if (window_attr.depth == root_attr.depth) {
- // if the depth of the specified window and the root window are the
- // same, grab pixels from the root window (so that we get the any
- // overlapping windows and window manager frames)
-
- // map x and y to the root window
- WId unused;
- if (!XTranslateCoordinates(dpy, window, window_attr.root, x, y,
- &x, &y, &unused))
- return QPixmap();
-
- window = window_attr.root;
- window_attr = root_attr;
- }
-
- QX11PixmapData *data = new QX11PixmapData(QPixmapData::PixmapType);
-
- void qt_x11_getX11InfoForWindow(QX11Info * xinfo, const XWindowAttributes &a);
- qt_x11_getX11InfoForWindow(&data->xinfo,window_attr);
-
- data->resize(w, h);
-
- QPixmap pm(data);
-
- data->flags &= ~QX11PixmapData::Uninitialized;
- pm.x11SetScreen(scr);
-
- GC gc = XCreateGC(dpy, pm.handle(), 0, 0);
- XSetSubwindowMode(dpy, gc, IncludeInferiors);
- XCopyArea(dpy, window, pm.handle(), gc, x, y, w, h, 0, 0);
- XFreeGC(dpy, gc);
-
- return pm;
-}
-
-bool QX11PixmapData::hasAlphaChannel() const
-{
- return d == 32;
-}
-
-const QX11Info &QPixmap::x11Info() const
-{
- if (data && data->classId() == QPixmapData::X11Class)
- return static_cast<QX11PixmapData*>(data.data())->xinfo;
- else {
- static QX11Info nullX11Info;
- return nullX11Info;
- }
-}
-
-#if !defined(QT_NO_XRENDER)
-static XRenderPictFormat *qt_renderformat_for_depth(const QX11Info &xinfo, int depth)
-{
- if (depth == 1)
- return XRenderFindStandardFormat(X11->display, PictStandardA1);
- else if (depth == 32)
- return XRenderFindStandardFormat(X11->display, PictStandardARGB32);
- else
- return XRenderFindVisualFormat(X11->display, (Visual *)xinfo.visual());
-}
-#endif
-
-QPaintEngine* QX11PixmapData::paintEngine() const
-{
- QX11PixmapData *that = const_cast<QX11PixmapData*>(this);
-
- if ((flags & Readonly) && share_mode == QPixmap::ImplicitlyShared) {
- // if someone wants to draw onto us, copy the shared contents
- // and turn it into a fully fledged QPixmap
- ::Pixmap hd_copy = XCreatePixmap(X11->display, RootWindow(X11->display, xinfo.screen()),
- w, h, d);
-#if !defined(QT_NO_XRENDER)
- XRenderPictFormat *format = qt_renderformat_for_depth(xinfo, d);
- ::Picture picture_copy = XRenderCreatePicture(X11->display, hd_copy, format, 0, 0);
-
- if (picture && d == 32) {
- XRenderComposite(X11->display, PictOpSrc, picture, 0, picture_copy,
- 0, 0, 0, 0, 0, 0, w, h);
- XRenderFreePicture(X11->display, picture);
- that->picture = picture_copy;
- } else
-#endif
- {
- GC gc = XCreateGC(X11->display, hd_copy, 0, 0);
- XCopyArea(X11->display, hd, hd_copy, gc, 0, 0, w, h, 0, 0);
- XFreeGC(X11->display, gc);
- }
- that->hd = hd_copy;
- that->flags &= ~QX11PixmapData::Readonly;
- }
-
- if (!that->pengine)
- that->pengine = new QX11PaintEngine;
- return that->pengine;
-}
-
-Qt::HANDLE QPixmap::x11PictureHandle() const
-{
-#ifndef QT_NO_XRENDER
- if (data && data->classId() == QPixmapData::X11Class)
- return static_cast<const QX11PixmapData*>(data.data())->picture;
- else
- return 0;
-#else
- return 0;
-#endif // QT_NO_XRENDER
-}
-
-Qt::HANDLE QX11PixmapData::x11ConvertToDefaultDepth()
-{
-#ifndef QT_NO_XRENDER
- if (d == QX11Info::appDepth() || !X11->use_xrender)
- return hd;
- if (!hd2) {
- hd2 = XCreatePixmap(xinfo.display(), hd, w, h, QX11Info::appDepth());
- XRenderPictFormat *format = XRenderFindVisualFormat(xinfo.display(),
- (Visual*) xinfo.visual());
- Picture pic = XRenderCreatePicture(xinfo.display(), hd2, format, 0, 0);
- XRenderComposite(xinfo.display(), PictOpSrc, picture,
- XNone, pic, 0, 0, 0, 0, 0, 0, w, h);
- XRenderFreePicture(xinfo.display(), pic);
- }
- return hd2;
-#else
- return hd;
-#endif
-}
-
-void QX11PixmapData::copy(const QPixmapData *data, const QRect &rect)
-{
- if (data->pixelType() == BitmapType) {
- fromImage(data->toImage().copy(rect), Qt::AutoColor);
- return;
- }
-
- const QX11PixmapData *x11Data = static_cast<const QX11PixmapData*>(data);
-
- setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1));
-
- flags &= ~Uninitialized;
- xinfo = x11Data->xinfo;
- d = x11Data->d;
- w = rect.width();
- h = rect.height();
- is_null = (w <= 0 || h <= 0);
- hd = (Qt::HANDLE)XCreatePixmap(X11->display,
- RootWindow(X11->display, x11Data->xinfo.screen()),
- w, h, d);
-#ifndef QT_NO_XRENDER
- if (X11->use_xrender) {
- XRenderPictFormat *format = d == 32
- ? XRenderFindStandardFormat(X11->display, PictStandardARGB32)
- : XRenderFindVisualFormat(X11->display, (Visual *)xinfo.visual());
- picture = XRenderCreatePicture(X11->display, hd, format, 0, 0);
- }
-#endif // QT_NO_XRENDER
- if (x11Data->x11_mask) {
- x11_mask = XCreatePixmap(X11->display, hd, w, h, 1);
-#ifndef QT_NO_XRENDER
- if (X11->use_xrender) {
- mask_picture = XRenderCreatePicture(X11->display, x11_mask,
- XRenderFindStandardFormat(X11->display, PictStandardA1), 0, 0);
- XRenderPictureAttributes attrs;
- attrs.alpha_map = x11Data->mask_picture;
- XRenderChangePicture(X11->display, x11Data->picture, CPAlphaMap, &attrs);
- }
-#endif
- }
-
-#if !defined(QT_NO_XRENDER)
- if (x11Data->picture && x11Data->d == 32) {
- XRenderComposite(X11->display, PictOpSrc,
- x11Data->picture, 0, picture,
- rect.x(), rect.y(), 0, 0, 0, 0, w, h);
- } else
-#endif
- {
- GC gc = XCreateGC(X11->display, hd, 0, 0);
- XCopyArea(X11->display, x11Data->hd, hd, gc,
- rect.x(), rect.y(), w, h, 0, 0);
- if (x11Data->x11_mask) {
- GC monogc = XCreateGC(X11->display, x11_mask, 0, 0);
- XCopyArea(X11->display, x11Data->x11_mask, x11_mask, monogc,
- rect.x(), rect.y(), w, h, 0, 0);
- XFreeGC(X11->display, monogc);
- }
- XFreeGC(X11->display, gc);
- }
-}
-
-bool QX11PixmapData::scroll(int dx, int dy, const QRect &rect)
-{
- GC gc = XCreateGC(X11->display, hd, 0, 0);
- XCopyArea(X11->display, hd, hd, gc,
- rect.left(), rect.top(), rect.width(), rect.height(),
- rect.left() + dx, rect.top() + dy);
- XFreeGC(X11->display, gc);
- return true;
-}
-
-#if !defined(QT_NO_XRENDER)
-void QX11PixmapData::convertToARGB32(bool preserveContents)
-{
- if (!X11->use_xrender)
- return;
-
- // Q_ASSERT(count == 1);
- if ((flags & Readonly) && share_mode == QPixmap::ExplicitlyShared)
- return;
-
- Pixmap pm = XCreatePixmap(X11->display, RootWindow(X11->display, xinfo.screen()),
- w, h, 32);
- Picture p = XRenderCreatePicture(X11->display, pm,
- XRenderFindStandardFormat(X11->display, PictStandardARGB32), 0, 0);
- if (picture) {
- if (preserveContents)
- XRenderComposite(X11->display, PictOpSrc, picture, 0, p, 0, 0, 0, 0, 0, 0, w, h);
- if (!(flags & Readonly))
- XRenderFreePicture(X11->display, picture);
- }
- if (hd && !(flags & Readonly))
- XFreePixmap(X11->display, hd);
- if (x11_mask) {
- XFreePixmap(X11->display, x11_mask);
- if (mask_picture)
- XRenderFreePicture(X11->display, mask_picture);
- x11_mask = 0;
- mask_picture = 0;
- }
- hd = pm;
- picture = p;
- d = 32;
-}
-#endif
-
-QPixmap QPixmap::fromX11Pixmap(Qt::HANDLE pixmap, QPixmap::ShareMode mode)
-{
- Window root;
- int x;
- int y;
- uint width;
- uint height;
- uint border_width;
- uint depth;
- XWindowAttributes win_attribs;
- int num_screens = ScreenCount(X11->display);
- int screen = 0;
-
- XGetGeometry(X11->display, pixmap, &root, &x, &y, &width, &height, &border_width, &depth);
- XGetWindowAttributes(X11->display, root, &win_attribs);
-
- for (; screen < num_screens; ++screen) {
- if (win_attribs.screen == ScreenOfDisplay(X11->display, screen))
- break;
- }
-
- QX11PixmapData *data = new QX11PixmapData(depth == 1 ? QPixmapData::BitmapType : QPixmapData::PixmapType);
- data->setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1));
- data->flags = QX11PixmapData::Readonly;
- data->share_mode = mode;
- data->w = width;
- data->h = height;
- data->is_null = (width <= 0 || height <= 0);
- data->d = depth;
- data->hd = pixmap;
-
- if (defaultScreen >= 0 && defaultScreen != screen) {
- QX11InfoData* xd = data->xinfo.getX11Data(true);
- xd->screen = defaultScreen;
- xd->depth = QX11Info::appDepth(xd->screen);
- xd->cells = QX11Info::appCells(xd->screen);
- xd->colormap = QX11Info::appColormap(xd->screen);
- xd->defaultColormap = QX11Info::appDefaultColormap(xd->screen);
- xd->visual = (Visual *)QX11Info::appVisual(xd->screen);
- xd->defaultVisual = QX11Info::appDefaultVisual(xd->screen);
- data->xinfo.setX11Data(xd);
- }
-
-#ifndef QT_NO_XRENDER
- if (X11->use_xrender) {
- XRenderPictFormat *format = qt_renderformat_for_depth(data->xinfo, depth);
- data->picture = XRenderCreatePicture(X11->display, data->hd, format, 0, 0);
- }
-#endif // QT_NO_XRENDER
-
- return QPixmap(data);
-}
-
-
-QT_END_NAMESPACE