📄 qpixmap_x11.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/// 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_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 <stdlib.h>#if defined(Q_CC_MIPS)# define for if(0){}else for#endif// 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 QPixmapData::mask_to_bitmap(int screen) const{ if (!x11_mask) return QBitmap(); QPixmap::x11SetDefaultScreen(screen); QBitmap bm(w, h); GC gc = XCreateGC(X11->display, bm.data->hd, 0, 0); XCopyArea(X11->display, x11_mask, bm.data->hd, gc, 0, 0, bm.data->w, bm.data->h, 0, 0); XFreeGC(X11->display, gc); return bm;}Qt::HANDLE QPixmapData::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->w, bm.data->h, 1); GC gc = XCreateGC(X11->display, mask, 0, 0); XCopyArea(X11->display, bm.data->hd, mask, gc, 0, 0, bm.data->w, bm.data->h, 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 nonestatic 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 -1static 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 *****************************************************************************/static int qt_pixmap_serial = 0;int Q_GUI_EXPORT qt_x11_preferred_pixmap_depth = 0;/*! \internal Initializes the pixmap data.*/void QPixmap::init(int w, int h, Type type){ if (!qApp) { qFatal("QPixmap: Must construct a QApplication before a QPaintDevice"); return; } if (qApp->type() == QApplication::Tty) { qWarning("QPixmap: Cannot create a QPixmap when no GUI is being used"); } data = new QPixmapData; memset(data, 0, sizeof(QPixmapData)); data->type = type; data->count = 1; data->uninit = true; data->ser_no = ++qt_pixmap_serial; data->detach_no = 0; data->picture = 0; data->x11_mask = 0; data->mask_picture = 0; if (defaultScreen >= 0 && defaultScreen != data->xinfo.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); } int dd = data->xinfo.depth(); if (qt_x11_preferred_pixmap_depth) dd = qt_x11_preferred_pixmap_depth; bool make_null = w == 0 || h == 0; // create null pixmap data->d = (type == PixmapType) ? dd : 1; if (make_null || w < 0 || h < 0 || data->d == 0) { data->hd = 0; data->picture = 0; if (!make_null) qWarning("QPixmap: Invalid pixmap parameters"); return; } data->w = w; data->h = h; data->hd = (Qt::HANDLE)XCreatePixmap(X11->display, RootWindow(X11->display, data->xinfo.screen()), w, h, data->d);#ifndef QT_NO_XRENDER if (X11->use_xrender) { XRenderPictFormat *format = data->d == 1 ? XRenderFindStandardFormat(X11->display, PictStandardA1) : XRenderFindVisualFormat(X11->display, (Visual *) data->xinfo.visual()); data->picture = XRenderCreatePicture(X11->display, data->hd, format, 0, 0); }#endif // QT_NO_XRENDER}QPixmapData::~QPixmapData(){ if (!qApp) 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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -