diff options
author | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-07-10 15:24:15 -0500 |
---|---|---|
committer | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-07-10 15:24:15 -0500 |
commit | bd0f3345a938b35ce6a12f6150373b0955b8dd12 (patch) | |
tree | 7a520322212d48ebcb9fbe1087e7fca28b76185c /src/kernel/qpaintdevice_x11.cpp | |
download | qt3-bd0f3345a938b35ce6a12f6150373b0955b8dd12.tar.gz qt3-bd0f3345a938b35ce6a12f6150373b0955b8dd12.zip |
Add Qt3 development HEAD version
Diffstat (limited to 'src/kernel/qpaintdevice_x11.cpp')
-rw-r--r-- | src/kernel/qpaintdevice_x11.cpp | 1168 |
1 files changed, 1168 insertions, 0 deletions
diff --git a/src/kernel/qpaintdevice_x11.cpp b/src/kernel/qpaintdevice_x11.cpp new file mode 100644 index 0000000..a755c01 --- /dev/null +++ b/src/kernel/qpaintdevice_x11.cpp @@ -0,0 +1,1168 @@ +/**************************************************************************** +** +** Implementation of QPaintDevice class for X11 +** +** Created : 940721 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free Qt Foundation. +** +** 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. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.QPL +** included in the packaging of this file. Licensees holding valid Qt +** Commercial licenses may use this file in accordance with the Qt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "qpaintdevice.h" +#include "qpaintdevicemetrics.h" +#include "qpainter.h" +#include "qwidget.h" +#include "qbitmap.h" +#include "qapplication.h" +#include "qt_x11_p.h" + + +/*! + \class QPaintDevice qpaintdevice.h + \brief The QPaintDevice class is the base class of objects that + can be painted. + + \ingroup graphics + \ingroup images + + A paint device is an abstraction of a two-dimensional space that + can be drawn using a QPainter. The drawing capabilities are + implemented by the subclasses QWidget, QPixmap, QPicture and + QPrinter. + + The default coordinate system of a paint device has its origin + located at the top-left position. X increases to the right and Y + increases downward. The unit is one pixel. There are several ways + to set up a user-defined coordinate system using the painter, for + example, using QPainter::setWorldMatrix(). + + Example (draw on a paint device): + \code + void MyWidget::paintEvent( QPaintEvent * ) + { + QPainter p; // our painter + p.begin( this ); // start painting the widget + p.setPen( red ); // red outline + p.setBrush( yellow ); // yellow fill + p.drawEllipse( 10, 20, 100,100 ); // 100x100 ellipse at position (10, 20) + p.end(); // painting done + } + \endcode + + The bit block transfer is an extremely useful operation for + copying pixels from one paint device to another (or to itself). It + is implemented as the global function bitBlt(). + + Example (scroll widget contents 10 pixels to the right): + \code + bitBlt( myWidget, 10, 0, myWidget ); + \endcode + + \warning Qt requires that a QApplication object exists before + any paint devices can be created. Paint devices access window + system resources, and these resources are not initialized before + an application object is created. +*/ + + +// +// Some global variables - these are initialized by QColor::initialize() +// + +Display *QPaintDevice::x_appdisplay = 0; +int QPaintDevice::x_appscreen; + +int QPaintDevice::x_appdepth; +int QPaintDevice::x_appcells; +Qt::HANDLE QPaintDevice::x_approotwindow; +Qt::HANDLE QPaintDevice::x_appcolormap; +bool QPaintDevice::x_appdefcolormap; +void *QPaintDevice::x_appvisual; +bool QPaintDevice::x_appdefvisual; + +// ### in 4.0, remove the above, and use the below +int *QPaintDevice::x_appdepth_arr; +int *QPaintDevice::x_appcells_arr; +Qt::HANDLE *QPaintDevice::x_approotwindow_arr; +Qt::HANDLE *QPaintDevice::x_appcolormap_arr; +bool *QPaintDevice::x_appdefcolormap_arr; +void **QPaintDevice::x_appvisual_arr; +bool *QPaintDevice::x_appdefvisual_arr; + +/*! + \enum QPaintDevice::PDevCmd + \internal +*/ + +/*! + Constructs a paint device with internal flags \a devflags. This + constructor can be invoked only from QPaintDevice subclasses. +*/ + +QPaintDevice::QPaintDevice( uint devflags ) +{ + if ( !qApp ) { // global constructor +#if defined(QT_CHECK_STATE) + qFatal( "QPaintDevice: Must construct a QApplication before a " + "QPaintDevice" ); +#endif + return; + } + devFlags = devflags; + painters = 0; + hd = 0; + rendhd = 0; + x11Data = 0; +} + +/*! + Destroys the paint device and frees window system resources. +*/ + +QPaintDevice::~QPaintDevice() +{ +#if defined(QT_CHECK_STATE) + if ( paintingActive() ) + qWarning( "QPaintDevice: Cannot destroy paint device that is being " + "painted" ); +#endif + if ( x11Data && x11Data->deref() ) { + delete x11Data; + x11Data = 0; + } +} + + +/* + \internal + Makes a shallow copy of the X11-specific data of \a fromDevice, if it is not + null. Otherwise this function sets it to null. +*/ + +void QPaintDevice::copyX11Data( const QPaintDevice *fromDevice ) +{ + setX11Data( fromDevice ? fromDevice->x11Data : 0 ); +} + +/* + \internal + Makes a deep copy of the X11-specific data of \a fromDevice, if it is not + null. Otherwise this function sets it to null. +*/ + +void QPaintDevice::cloneX11Data( const QPaintDevice *fromDevice ) +{ + if ( fromDevice && fromDevice->x11Data ) { + QPaintDeviceX11Data *d = new QPaintDeviceX11Data; + *d = *fromDevice->x11Data; + d->count = 0; + setX11Data( d ); + } else { + setX11Data( 0 ); + } +} + +/* + \internal + Makes a shallow copy of the X11-specific data \a d and assigns it to this + class. This function increments the reference code of \a d. +*/ + +void QPaintDevice::setX11Data( const QPaintDeviceX11Data* d ) +{ + if ( x11Data && x11Data->deref() ) + delete x11Data; + x11Data = (QPaintDeviceX11Data*)d; + if ( x11Data ) + x11Data->ref(); +} + + +/* + \internal + If \a def is FALSE, returns a deep copy of the x11Data, or 0 if x11Data is 0. + If \a def is TRUE, makes a QPaintDeviceX11Data struct filled with the default + values. + + In either case the caller is responsible for deleting the returned + struct. But notice that the struct is a shared class, so other + classes might also have a reference to it. The reference count of + the returned QPaintDeviceX11Data* is 0. +*/ + +QPaintDeviceX11Data* QPaintDevice::getX11Data( bool def ) const +{ + QPaintDeviceX11Data* res = 0; + if ( def ) { + res = new QPaintDeviceX11Data; + res->x_display = x11AppDisplay(); + res->x_screen = x11AppScreen(); + res->x_depth = x11AppDepth(); + res->x_cells = x11AppCells(); + res->x_colormap = x11Colormap(); + res->x_defcolormap = x11AppDefaultColormap(); + res->x_visual = x11AppVisual(); + res->x_defvisual = x11AppDefaultVisual(); + res->deref(); + } else if ( x11Data ) { + res = new QPaintDeviceX11Data; + *res = *x11Data; + res->count = 0; + } + return res; +} + + +/*! + \fn int QPaintDevice::devType() const + + \internal + + Returns the device type identifier, which is \c QInternal::Widget + if the device is a QWidget, \c QInternal::Pixmap if it's a + QPixmap, \c QInternal::Printer if it's a QPrinter, \c + QInternal::Picture if it's a QPicture or \c + QInternal::UndefinedDevice in other cases (which should never + happen). +*/ + +/*! + \fn bool QPaintDevice::isExtDev() const + + Returns TRUE if the device is an external paint device; otherwise + returns FALSE. + + External paint devices cannot be bitBlt()'ed from. QPicture and + QPrinter are external paint devices. +*/ + +/*! + Returns the window system handle of the paint device, for + low-level access. Using this function is not portable. + + The HANDLE type varies with platform; see \c qpaintdevice.h and + \c qwindowdefs.h for details. + + \sa x11Display() +*/ +Qt::HANDLE QPaintDevice::handle() const +{ + return hd; +} + +/*! + Returns the window system handle of the paint device for XRender + support. Use of this function is not portable. This function will + return 0 if XRender support is not compiled into Qt, if the + XRender extension is not supported on the X11 display, or if the + handle could not be created. +*/ +Qt::HANDLE QPaintDevice::x11RenderHandle() const +{ +#ifndef QT_NO_XFTFREETYPE + return rendhd ? XftDrawPicture( (XftDraw *) rendhd ) : 0; +#else + return 0; +#endif // QT_NO_XFTFREETYPE +} + + +/*! + \fn Display *QPaintDevice::x11AppDisplay() + + Returns a pointer to the X display global to the application (X11 + only). Using this function is not portable. + + \sa handle() +*/ + +/*! + \fn int QPaintDevice::x11AppScreen() + + Returns the screen number on the X display global to the + application (X11 only). Using this function is not portable. +*/ + +/*! + \overload + \fn int QPaintDevice::x11AppDepth() + + Returns the depth for the default screen of the X display global + to the application (X11 only). Using this function is not + portable. + + \sa QPixmap::defaultDepth() +*/ + +/*! + \fn int QPaintDevice::x11AppCells() + + Returns the number of entries in the colormap for the default + screen of the X display global to the application (X11 + only). Using this function is not portable. + + \sa x11Colormap() +*/ + +/*! + \fn HANDLE QPaintDevice::x11AppRootWindow() + + Returns the root window for the default screen of the X display + global to the applicatoin (X11 only). Using this function is not + portable. +*/ + +/*! + \fn HANDLE QPaintDevice::x11AppColormap() + + Returns the colormap for the default screen of the X display + global to the application (X11 only). Using this function is not + portable. + + \sa x11Cells() +*/ + +/*! + \fn bool QPaintDevice::x11AppDefaultColormap () + + Returns the default colormap for the default screen of the X + display global to the application (X11 only). Using this function + is not portable. + + \sa x11Cells() +*/ + +/*! + \fn void* QPaintDevice::x11AppVisual () + + Returns the Visual for the default screen of the X display global + to the application (X11 only). Using this function is not + portable. +*/ + +/*! + \fn bool QPaintDevice::x11AppDefaultVisual () + + Returns TRUE if the Visual used is the default for the default + screen of the X display global to the application (X11 only); + otherwise returns FALSE. Using this function is not portable. +*/ + +/*! + \fn int QPaintDevice::x11AppDepth( int screen ) + + Returns the depth for screen \a screen of the X display global to + the application (X11 only). Using this function is not portable. + + \sa QPixmap::defaultDepth() +*/ + +/*! + \overload + \fn int QPaintDevice::x11AppCells( int screen ) + + Returns the number of entries in the colormap for screen \a screen + of the X display global to the application (X11 only). Using this + function is not portable. + + \sa x11Colormap() +*/ + +/*! + \overload + \fn HANDLE QPaintDevice::x11AppRootWindow( int screen ) + + Returns the root window for screen \a screen of the X display + global to the applicatoin (X11 only). Using this function is not + portable. +*/ + +/*! + \overload + \fn HANDLE QPaintDevice::x11AppColormap( int screen ) + + Returns the colormap for screen \a screen of the X display global + to the application (X11 only). Using this function is not + portable. + + \sa x11Cells() +*/ + +/*! + \overload + \fn bool QPaintDevice::x11AppDefaultColormap( int screen ) + + Returns the default colormap for screen \a screen of the X display + global to the application (X11 only). Using this function is not + portable. + + \sa x11Cells() +*/ + +/*! + \overload + \fn void* QPaintDevice::x11AppVisual( int screen ) + + Returns the Visual for screen \a screen of the X display global to + the application (X11 only). Using this function is not portable. +*/ + +/*! + \overload + \fn bool QPaintDevice::x11AppDefaultVisual( int screen ) + + Returns TRUE if the Visual used is the default for screen + \a screen of the X display global to the application (X11 only); + otherwise returns FALSE. Using this function is not portable. +*/ + + +/*! + \fn Display *QPaintDevice::x11Display() const + + Returns a pointer to the X display for the paint device (X11 + only). Using this function is not portable. + + \sa handle() +*/ + +/*! + \fn int QPaintDevice::x11Screen () const + + Returns the screen number on the X display for the paint device + (X11 only). Using this function is not portable. +*/ + +/*! + \fn int QPaintDevice::x11Depth () const + + Returns the depth of the X display for the paint device (X11 + only). Using this function is not portable. + + \sa QPixmap::defaultDepth() +*/ + +/*! + \fn int QPaintDevice::x11Cells () const + + Returns the number of entries in the colormap of the X display for + the paint device (X11 only). Using this function is not portable. + + \sa x11Colormap() +*/ + +/*! + \fn HANDLE QPaintDevice::x11Colormap () const + + Returns the colormap of the X display for the paint device (X11 + only). Using this function is not portable. + + \sa x11Cells() +*/ + +/*! + \fn bool QPaintDevice::x11DefaultColormap () const + + Returns the default colormap of the X display for the paint device + (X11 only). Using this function is not portable. + + \sa x11Cells() +*/ + +/*! + \fn void* QPaintDevice::x11Visual () const + + Returns the Visual of the X display for the paint device (X11 + only). Using this function is not portable. +*/ + +/*! + \fn bool QPaintDevice::x11DefaultVisual () const + + Returns the default Visual of the X display for the paint device + (X11 only). Using this function is not portable. +*/ + +static int *dpisX=0, *dpisY=0; +static void create_dpis() +{ + if ( dpisX ) + return; + + Display *dpy = QPaintDevice::x11AppDisplay(); + if ( ! dpy ) + return; + + int i, screens = ScreenCount( dpy ); + dpisX = new int[ screens ]; + dpisY = new int[ screens ]; + Q_CHECK_PTR( dpisX ); + Q_CHECK_PTR( dpisY ); + for ( i = 0; i < screens; i++ ) { + dpisX[ i ] = (DisplayWidth(dpy,i) * 254 + DisplayWidthMM(dpy,i)*5) + + / (DisplayWidthMM(dpy,i)*10); + dpisY[ i ] = (DisplayHeight(dpy,i) * 254 + DisplayHeightMM(dpy,i)*5) + / (DisplayHeightMM(dpy,i)*10); + } +} + +/*! + Sets the value returned by x11AppDpiX() to \a dpi for screen + \a screen. The default is determined by the display configuration. + Changing this value will alter the scaling of fonts and many other + metrics and is not recommended. Using this function is not + portable. + + \sa x11SetAppDpiY() +*/ +void QPaintDevice::x11SetAppDpiX(int dpi, int screen) +{ + create_dpis(); + if ( ! dpisX ) + return; + if ( screen < 0 ) + screen = QPaintDevice::x11AppScreen(); + if ( screen > ScreenCount( QPaintDevice::x11AppDisplay() ) ) + return; + dpisX[ screen ] = dpi; +} + +/*! + \overload + + Sets the value returned by x11AppDpiX() to \a dpi for the default + screen. The default is determined by the display configuration. + Changing this value will alter the scaling of fonts and many other + metrics and is not recommended. Using this function is not + portable. + +*/ +// ### REMOVE 4.0 +void QPaintDevice::x11SetAppDpiX( int dpi ) +{ + QPaintDevice::x11SetAppDpiX( dpi, -1 ); +} + +/*! + Sets the value returned by x11AppDpiY() to \a dpi for screen + \a screen. The default is determined by the display configuration. + Changing this value will alter the scaling of fonts and many other + metrics and is not recommended. Using this function is not + portable. + + \sa x11SetAppDpiX() +*/ +void QPaintDevice::x11SetAppDpiY(int dpi, int screen) +{ + create_dpis(); + if ( ! dpisY ) + return; + if ( screen < 0 ) + screen = QPaintDevice::x11AppScreen(); + if ( screen > ScreenCount( QPaintDevice::x11AppDisplay() ) ) + return; + dpisY[ screen ] = dpi; +} + +/*! + \overload + + Sets the value returned by x11AppDpiY() to \a dpi for the default + screen. The default is determined by the display configuration. + Changing this value will alter the scaling of fonts and many other + metrics and is not recommended. Using this function is not + portable. +*/ +// ### REMOVE 4.0 +void QPaintDevice::x11SetAppDpiY( int dpi ) +{ + QPaintDevice::x11SetAppDpiY( dpi, -1 ); +} + +/*! + Returns the horizontal DPI of the X display (X11 only) for screen + \a screen. Using this function is not portable. See + QPaintDeviceMetrics for portable access to related information. + Using this function is not portable. + + \sa x11AppDpiY(), x11SetAppDpiX(), QPaintDeviceMetrics::logicalDpiX() +*/ +int QPaintDevice::x11AppDpiX(int screen) +{ + create_dpis(); + if ( ! dpisX ) + return 0; + if ( screen < 0 ) + screen = QPaintDevice::x11AppScreen(); + if ( screen > ScreenCount( QPaintDevice::x11AppDisplay() ) ) + return 0; + return dpisX[ screen ]; +} + +/*! + \overload + + Returns the horizontal DPI of the X display (X11 only) for the + default screen. Using this function is not portable. See + QPaintDeviceMetrics for portable access to related information. + Using this function is not portable. +*/ +int QPaintDevice::x11AppDpiX() +{ + return QPaintDevice::x11AppDpiX( -1 ); +} + +/*! + Returns the vertical DPI of the X11 display (X11 only) for screen + \a screen. Using this function is not portable. See + QPaintDeviceMetrics for portable access to related information. + Using this function is not portable. + + \sa x11AppDpiX(), x11SetAppDpiY(), QPaintDeviceMetrics::logicalDpiY() +*/ +int QPaintDevice::x11AppDpiY( int screen ) +{ + create_dpis(); + if ( ! dpisY ) + return 0; + if ( screen < 0 ) + screen = QPaintDevice::x11AppScreen(); + if ( screen > ScreenCount( QPaintDevice::x11AppDisplay() ) ) + return 0; + return dpisY[ screen ]; +} + +/*! + \overload + + Returns the vertical DPI of the X11 display (X11 only) for the + default screen. Using this function is not portable. See + QPaintDeviceMetrics for portable access to related information. + Using this function is not portable. + + \sa x11AppDpiX(), x11SetAppDpiY(), QPaintDeviceMetrics::logicalDpiY() +*/ +int QPaintDevice::x11AppDpiY() +{ + return QPaintDevice::x11AppDpiY( -1 ); +} + +/*! + \fn bool QPaintDevice::paintingActive() const + + Returns TRUE if the device is being painted, i.e. someone has + called QPainter::begin() but not yet called QPainter::end() for + this device; otherwise returns FALSE. + + \sa QPainter::isActive() +*/ + +/*! + Internal virtual function that interprets drawing commands from + the painter. + + Implemented by subclasses that have no direct support for drawing + graphics (external paint devices, for example, QPicture). +*/ + +bool QPaintDevice::cmd( int, QPainter *, QPDevCmdParam * ) +{ +#if defined(QT_CHECK_STATE) + qWarning( "QPaintDevice::cmd: Device has no command interface" ); +#endif + return FALSE; +} + +/*! + \internal + + Internal virtual function that returns paint device metrics. + + Please use the QPaintDeviceMetrics class instead. +*/ + +int QPaintDevice::metric( int ) const +{ +#if defined(QT_CHECK_STATE) + qWarning( "QPaintDevice::metrics: Device has no metric information" ); +#endif + return 0; +} + +/*! + \internal + + Internal virtual function. Reserved for future use. + + Please use the QFontMetrics class instead. +*/ + +int QPaintDevice::fontMet( QFont *, int, const char *, int ) const +{ + return 0; +} + +/*! + \internal + + Internal virtual function. Reserved for future use. + + Please use the QFontInfo class instead. +*/ + +int QPaintDevice::fontInf( QFont *, int ) const +{ + return 0; +} + + +// +// Internal functions for simple GC caching for blt'ing masked pixmaps. +// This cache is used when the pixmap optimization is set to Normal +// and the pixmap size doesn't exceed 128x128. +// + +static bool init_mask_gc = FALSE; +static const int max_mask_gcs = 11; // suitable for hashing + +struct mask_gc { + GC gc; + int mask_no; +}; + +static mask_gc gc_vec[max_mask_gcs]; + + +static void cleanup_mask_gc() +{ + Display *dpy = QPaintDevice::x11AppDisplay(); + init_mask_gc = FALSE; + for ( int i=0; i<max_mask_gcs; i++ ) { + if ( gc_vec[i].gc ) + XFreeGC( dpy, gc_vec[i].gc ); + } +} + +static GC cache_mask_gc( Display *dpy, Drawable hd, int mask_no, Pixmap mask ) +{ + if ( !init_mask_gc ) { // first time initialization + init_mask_gc = TRUE; + qAddPostRoutine( cleanup_mask_gc ); + for ( int i=0; i<max_mask_gcs; i++ ) + gc_vec[i].gc = 0; + } + mask_gc *p = &gc_vec[mask_no % max_mask_gcs]; + if ( !p->gc || p->mask_no != mask_no ) { // not a perfect match + if ( !p->gc ) { // no GC + p->gc = XCreateGC( dpy, hd, 0, 0 ); + XSetGraphicsExposures( dpy, p->gc, False ); + } + XSetClipMask( dpy, p->gc, mask ); + p->mask_no = mask_no; + } + return p->gc; +} + + +/*! + \relates QPaintDevice + + Copies a block of pixels from \a src to \a dst, perhaps merging + each pixel according to the \link Qt::RasterOp raster operation \endlink + \a rop. \a sx, \a sy + is the top-left pixel in \a src (0, 0) by default, \a dx, \a dy is + the top-left position in \a dst and \a sw, \a sh is the size of + the copied block (all of \a src by default). + + The most common values for \a rop are CopyROP and XorROP; the \l + Qt::RasterOp documentation defines all the possible values. + + If \a ignoreMask is FALSE (the default) and \a src is a + masked QPixmap, the entire blit is masked by \a{src}->mask(). + + If \a src, \a dst, \a sw or \a sh is 0, bitBlt() does nothing. If + \a sw or \a sh is negative bitBlt() copies starting at \a sx (and + respectively, \a sy) and ending at the right end (respectively, + bottom) of \a src. + + \a src must be a QWidget or QPixmap. You cannot blit from a + QPrinter, for example. bitBlt() does nothing if you attempt to + blit from an unsupported device. + + bitBlt() does nothing if \a src has a greater depth than \e dst. + If you need to for example, draw a 24-bit pixmap on an 8-bit + widget, you must use drawPixmap(). +*/ + +void bitBlt( QPaintDevice *dst, int dx, int dy, + const QPaintDevice *src, int sx, int sy, int sw, int sh, + Qt::RasterOp rop, bool ignoreMask ) +{ + if ( !src || !dst ) { +#if defined(QT_CHECK_NULL) + Q_ASSERT( src != 0 ); + Q_ASSERT( dst != 0 ); +#endif + return; + } + if ( !src->handle() || src->isExtDev() ) + return; + + QPaintDevice *pdev = QPainter::redirect( dst ); + if ( pdev ) + dst = pdev; + + int ts = src->devType(); // from device type + int td = dst->devType(); // to device type + Display *dpy = src->x11Display(); + + if ( sw <= 0 ) { // special width + if ( sw < 0 ) + sw = src->metric( QPaintDeviceMetrics::PdmWidth ) - sx; + else + return; + } + if ( sh <= 0 ) { // special height + if ( sh < 0 ) + sh = src->metric( QPaintDeviceMetrics::PdmHeight ) - sy; + else + return; + } + + if ( dst->paintingActive() && dst->isExtDev() ) { + QPixmap *pm; // output to picture/printer + bool tmp_pm = TRUE; + if ( ts == QInternal::Pixmap ) { + pm = (QPixmap*)src; + if ( sx != 0 || sy != 0 || + sw != pm->width() || sh != pm->height() || ignoreMask ) { + QPixmap *tmp = new QPixmap( sw, sh, pm->depth() ); + bitBlt( tmp, 0, 0, pm, sx, sy, sw, sh, Qt::CopyROP, TRUE ); + if ( pm->mask() && !ignoreMask ) { + QBitmap mask( sw, sh ); + bitBlt( &mask, 0, 0, pm->mask(), sx, sy, sw, sh, + Qt::CopyROP, TRUE ); + tmp->setMask( mask ); + } + pm = tmp; + } else { + tmp_pm = FALSE; + } + } else if ( ts == QInternal::Widget ) {// bitBlt to temp pixmap + pm = new QPixmap( sw, sh ); + Q_CHECK_PTR( pm ); + bitBlt( pm, 0, 0, src, sx, sy, sw, sh ); + } else { +#if defined(QT_CHECK_RANGE) + qWarning( "bitBlt: Cannot bitBlt from device" ); +#endif + return; + } + QPDevCmdParam param[3]; + QRect r(dx, dy, pm->width(), pm->height()); + param[0].rect = &r; + param[1].pixmap = pm; + dst->cmd( QPaintDevice::PdcDrawPixmap, 0, param ); + if ( tmp_pm ) + delete pm; + return; + } + + switch ( ts ) { + case QInternal::Widget: + case QInternal::Pixmap: + case QInternal::System: // OK, can blt from these + break; + default: +#if defined(QT_CHECK_RANGE) + qWarning( "bitBlt: Cannot bitBlt from device type %x", ts ); +#endif + return; + } + switch ( td ) { + case QInternal::Widget: + case QInternal::Pixmap: + case QInternal::System: // OK, can blt to these + break; + default: +#if defined(QT_CHECK_RANGE) + qWarning( "bitBlt: Cannot bitBlt to device type %x", td ); +#endif + return; + } + + static const short ropCodes[] = { // ROP translation table + GXcopy, GXor, GXxor, GXandInverted, + GXcopyInverted, GXorInverted, GXequiv, GXand, + GXinvert, GXclear, GXset, GXnoop, + GXandReverse, GXorReverse, GXnand, GXnor + }; + if ( rop > Qt::LastROP ) { +#if defined(QT_CHECK_RANGE) + qWarning( "bitBlt: Invalid ROP code" ); +#endif + return; + } + + if ( dst->handle() == 0 ) { +#if defined(QT_CHECK_NULL) + qWarning( "bitBlt: Cannot bitBlt to device" ); +#endif + return; + } + + bool mono_src; + bool mono_dst; + bool include_inferiors = FALSE; + bool graphics_exposure = FALSE; + QPixmap *src_pm; + QBitmap *mask; + + if ( ts == QInternal::Pixmap ) { + src_pm = (QPixmap*)src; + if ( src_pm->x11Screen() != dst->x11Screen() ) + src_pm->x11SetScreen( dst->x11Screen() ); + mono_src = src_pm->depth() == 1; + mask = ignoreMask ? 0 : src_pm->data->mask; + } else { + src_pm = 0; + mono_src = FALSE; + mask = 0; + include_inferiors = ((QWidget*)src)->testWFlags(Qt::WPaintUnclipped); + graphics_exposure = td == QInternal::Widget; + } + if ( td == QInternal::Pixmap ) { + if ( dst->x11Screen() != src->x11Screen() ) + ((QPixmap*)dst)->x11SetScreen( src->x11Screen() ); + mono_dst = ((QPixmap*)dst)->depth() == 1; + ((QPixmap*)dst)->detach(); // changes shared pixmap + } else { + mono_dst = FALSE; + include_inferiors = include_inferiors || + ((QWidget*)dst)->testWFlags(Qt::WPaintUnclipped); + } + + if ( mono_dst && !mono_src ) { // dest is 1-bit pixmap, source is not +#if defined(QT_CHECK_RANGE) + qWarning( "bitBlt: Incompatible destination pixmap" ); +#endif + return; + } + +#ifndef QT_NO_XRENDER + if (src_pm && !mono_src && src_pm->data->alphapm && !ignoreMask ) { + // use RENDER to do the blit + QPixmap *alpha = src_pm->data->alphapm; + if (src->x11RenderHandle() && + alpha->x11RenderHandle() && + dst->x11RenderHandle()) { + XRenderPictureAttributes pattr; + ulong picmask = 0; + if (include_inferiors) { + pattr.subwindow_mode = IncludeInferiors; + picmask |= CPSubwindowMode; + } + if (graphics_exposure) { + pattr.graphics_exposures = TRUE; + picmask |= CPGraphicsExposure; + } + if (picmask) + XRenderChangePicture(dpy, dst->x11RenderHandle(), picmask, &pattr); + XRenderComposite(dpy, PictOpOver, src->x11RenderHandle(), + alpha->x11RenderHandle(), dst->x11RenderHandle(), + sx, sy, sx, sy, dx, dy, sw, sh); + // restore attributes + pattr.subwindow_mode = ClipByChildren; + pattr.graphics_exposures = FALSE; + if (picmask) + XRenderChangePicture(dpy, dst->x11RenderHandle(), picmask, &pattr); + return; + } + } +#endif + + GC gc; + + if ( mask && !mono_src ) { // fast masked blt + bool temp_gc = FALSE; + if ( mask->data->maskgc ) { + gc = (GC)mask->data->maskgc; // we have a premade mask GC + } else { + if ( FALSE && src_pm->optimization() == QPixmap::NormalOptim ) { // #### cache disabled + // Compete for the global cache + gc = cache_mask_gc( dpy, dst->handle(), + mask->data->ser_no, + mask->handle() ); + } else { + // Create a new mask GC. If BestOptim, we store the mask GC + // with the mask (not at the pixmap). This way, many pixmaps + // which have a common mask will be optimized at no extra cost. + gc = XCreateGC( dpy, dst->handle(), 0, 0 ); + XSetGraphicsExposures( dpy, gc, False ); + XSetClipMask( dpy, gc, mask->handle() ); + if ( src_pm->optimization() == QPixmap::BestOptim ) { + mask->data->maskgc = gc; + } else { + temp_gc = TRUE; + } + } + } + XSetClipOrigin( dpy, gc, dx-sx, dy-sy ); + if ( rop != Qt::CopyROP ) // use non-default ROP code + XSetFunction( dpy, gc, ropCodes[rop] ); + if ( include_inferiors ) { + XSetSubwindowMode( dpy, gc, IncludeInferiors ); + XCopyArea( dpy, src->handle(), dst->handle(), gc, sx, sy, sw, sh, + dx, dy ); + XSetSubwindowMode( dpy, gc, ClipByChildren ); + } else { + XCopyArea( dpy, src->handle(), dst->handle(), gc, sx, sy, sw, sh, + dx, dy ); + } + + if ( temp_gc ) // delete temporary GC + XFreeGC( dpy, gc ); + else if ( rop != Qt::CopyROP ) // restore ROP + XSetFunction( dpy, gc, GXcopy ); + return; + } + + gc = qt_xget_temp_gc( dst->x11Screen(), mono_dst ); // get a reusable GC + + if ( rop != Qt::CopyROP ) // use non-default ROP code + XSetFunction( dpy, gc, ropCodes[rop] ); + + if ( mono_src && mono_dst && src == dst ) { // dst and src are the same bitmap + XCopyArea( dpy, src->handle(), dst->handle(), gc, sx, sy, sw, sh, dx, dy ); + } else if ( mono_src ) { // src is bitmap + XGCValues gcvals; + ulong valmask = GCBackground | GCForeground | GCFillStyle | + GCStipple | GCTileStipXOrigin | GCTileStipYOrigin; + if ( td == QInternal::Widget ) { // set GC colors + QWidget *w = (QWidget *)dst; + gcvals.background = w->backgroundColor().pixel( dst->x11Screen() ); + gcvals.foreground = w->foregroundColor().pixel( dst->x11Screen() ); + if ( include_inferiors ) { + valmask |= GCSubwindowMode; + gcvals.subwindow_mode = IncludeInferiors; + } + } else if ( mono_dst ) { + gcvals.background = 0; + gcvals.foreground = 1; + } else { + gcvals.background = Qt::white.pixel( dst->x11Screen() ); + gcvals.foreground = Qt::black.pixel( dst->x11Screen() ); + } + + gcvals.fill_style = FillOpaqueStippled; + gcvals.stipple = src->handle(); + gcvals.ts_x_origin = dx - sx; + gcvals.ts_y_origin = dy - sy; + + bool clipmask = FALSE; + if ( mask ) { + if ( ((QPixmap*)src)->data->selfmask ) { + gcvals.fill_style = FillStippled; + } else { + XSetClipMask( dpy, gc, mask->handle() ); + XSetClipOrigin( dpy, gc, dx-sx, dy-sy ); + clipmask = TRUE; + } + } + + XChangeGC( dpy, gc, valmask, &gcvals ); + XFillRectangle( dpy,dst->handle(), gc, dx, dy, sw, sh ); + + valmask = GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin; + gcvals.fill_style = FillSolid; + gcvals.ts_x_origin = 0; + gcvals.ts_y_origin = 0; + if ( include_inferiors ) { + valmask |= GCSubwindowMode; + gcvals.subwindow_mode = ClipByChildren; + } + XChangeGC( dpy, gc, valmask, &gcvals ); + + if ( clipmask ) { + XSetClipOrigin( dpy, gc, 0, 0 ); + XSetClipMask( dpy, gc, None ); + } + + } else { // src is pixmap/widget + + if ( graphics_exposure ) // widget to widget + XSetGraphicsExposures( dpy, gc, True ); + if ( include_inferiors ) { + XSetSubwindowMode( dpy, gc, IncludeInferiors ); + XCopyArea( dpy, src->handle(), dst->handle(), gc, sx, sy, sw, sh, + dx, dy ); + XSetSubwindowMode( dpy, gc, ClipByChildren ); + } else { + XCopyArea( dpy, src->handle(), dst->handle(), gc, sx, sy, sw, sh, + dx, dy ); + } + if ( graphics_exposure ) // reset graphics exposure + XSetGraphicsExposures( dpy, gc, False ); + } + + if ( rop != Qt::CopyROP ) // restore ROP + XSetFunction( dpy, gc, GXcopy ); +} + + +/*! + \relates QPaintDevice + + \overload void bitBlt( QPaintDevice *dst, const QPoint &dp, const QPaintDevice *src, const QRect &sr, RasterOp rop ) + + Overloaded bitBlt() with the destination point \a dp and source + rectangle \a sr. +*/ + + +/*! + \internal +*/ +// makes it possible to add a setResolution as we have in QPrinter for all +// paintdevices without breaking bin compatibility. +void QPaintDevice::setResolution( int ) +{ +} + +/*!\internal +*/ +int QPaintDevice::resolution() const +{ + return metric( QPaintDeviceMetrics::PdmDpiY ); +} |