diff options
Diffstat (limited to 'src/kernel/tqpaintdevice_x11.cpp')
-rw-r--r-- | src/kernel/tqpaintdevice_x11.cpp | 1173 |
1 files changed, 1173 insertions, 0 deletions
diff --git a/src/kernel/tqpaintdevice_x11.cpp b/src/kernel/tqpaintdevice_x11.cpp new file mode 100644 index 000000000..7bfbdf239 --- /dev/null +++ b/src/kernel/tqpaintdevice_x11.cpp @@ -0,0 +1,1173 @@ +/**************************************************************************** +** +** Implementation of TQPaintDevice class for X11 +** +** Created : 940721 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the kernel module of the TQt 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 TQt 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.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** 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 "tqpaintdevice.h" +#include "tqpaintdevicemetrics.h" +#include "tqpainter.h" +#include "tqwidget.h" +#include "tqbitmap.h" +#include "ntqapplication.h" +#include "qt_x11_p.h" + + +/*! + \class TQPaintDevice tqpaintdevice.h + \brief The TQPaintDevice 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 TQPainter. The drawing capabilities are + implemented by the subclasses TQWidget, TQPixmap, TQPicture and + TQPrinter. + + 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 TQPainter::setWorldMatrix(). + + Example (draw on a paint device): + \code + void MyWidget::paintEvent( TQPaintEvent * ) + { + TQPainter 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 TQt requires that a TQApplication 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 TQColor::initialize() +// + +Display *TQPaintDevice::x_appdisplay = 0; +int TQPaintDevice::x_appscreen; + +int TQPaintDevice::x_appdepth; +int TQPaintDevice::x_appcells; +TQt::HANDLE TQPaintDevice::x_approotwindow; +TQt::HANDLE TQPaintDevice::x_appcolormap; +bool TQPaintDevice::x_appdefcolormap; +void *TQPaintDevice::x_appvisual; +bool TQPaintDevice::x_appdefvisual; + +// ### in 4.0, remove the above, and use the below +int *TQPaintDevice::x_appdepth_arr; +int *TQPaintDevice::x_appcells_arr; +TQt::HANDLE *TQPaintDevice::x_approotwindow_arr; +TQt::HANDLE *TQPaintDevice::x_appcolormap_arr; +bool *TQPaintDevice::x_appdefcolormap_arr; +void **TQPaintDevice::x_appvisual_arr; +bool *TQPaintDevice::x_appdefvisual_arr; + +/*! + \enum TQPaintDevice::PDevCmd + \internal +*/ + +/*! + Constructs a paint device with internal flags \a devflags. This + constructor can be invoked only from TQPaintDevice subclasses. +*/ + +TQPaintDevice::TQPaintDevice( uint devflags ) +{ + if ( !tqApp ) { // global constructor +#if defined(QT_CHECK_STATE) + tqFatal( "TQPaintDevice: Must construct a TQApplication before a " + "TQPaintDevice" ); +#endif + return; + } + devFlags = devflags; + painters = 0; + hd = 0; + rendhd = 0; + x11Data = 0; +} + +/*! + Destroys the paint device and frees window system resources. +*/ + +TQPaintDevice::~TQPaintDevice() +{ +#if defined(QT_CHECK_STATE) + if ( paintingActive() ) + tqWarning( "TQPaintDevice: 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 TQPaintDevice::copyX11Data( const TQPaintDevice *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 TQPaintDevice::cloneX11Data( const TQPaintDevice *fromDevice ) +{ + if ( fromDevice && fromDevice->x11Data ) { + TQPaintDeviceX11Data *d = new TQPaintDeviceX11Data; + *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 TQPaintDevice::setX11Data( const TQPaintDeviceX11Data* d ) +{ + if ( x11Data && x11Data->deref() ) + delete x11Data; + x11Data = (TQPaintDeviceX11Data*)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 TQPaintDeviceX11Data 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 TQPaintDeviceX11Data* is 0. +*/ + +TQPaintDeviceX11Data* TQPaintDevice::getX11Data( bool def ) const +{ + TQPaintDeviceX11Data* res = 0; + if ( def ) { + res = new TQPaintDeviceX11Data; + 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 TQPaintDeviceX11Data; + *res = *x11Data; + res->count = 0; + } + return res; +} + + +/*! + \fn int TQPaintDevice::devType() const + + \internal + + Returns the device type identifier, which is \c TQInternal::Widget + if the device is a TQWidget, \c TQInternal::Pixmap if it's a + TQPixmap, \c TQInternal::Printer if it's a TQPrinter, \c + TQInternal::Picture if it's a TQPicture or \c + TQInternal::UndefinedDevice in other cases (which should never + happen). +*/ + +/*! + \fn bool TQPaintDevice::isExtDev() const + + Returns TRUE if the device is an external paint device; otherwise + returns FALSE. + + External paint devices cannot be bitBlt()'ed from. TQPicture and + TQPrinter 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 tqpaintdevice.h and + \c ntqwindowdefs.h for details. + + \sa x11Display() +*/ +TQt::HANDLE TQPaintDevice::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 TQt, if the + XRender extension is not supported on the X11 display, or if the + handle could not be created. +*/ +TQt::HANDLE TQPaintDevice::x11RenderHandle() const +{ +#ifndef TQT_NO_XFTFREETYPE + return rendhd ? XftDrawPicture( (XftDraw *) rendhd ) : 0; +#else + return 0; +#endif // TQT_NO_XFTFREETYPE +} + + +/*! + \fn Display *TQPaintDevice::x11AppDisplay() + + Returns a pointer to the X display global to the application (X11 + only). Using this function is not portable. + + \sa handle() +*/ + +/*! + \fn int TQPaintDevice::x11AppScreen() + + Returns the screen number on the X display global to the + application (X11 only). Using this function is not portable. +*/ + +/*! + \overload + \fn int TQPaintDevice::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 TQPixmap::defaultDepth() +*/ + +/*! + \fn int TQPaintDevice::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 TQPaintDevice::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 TQPaintDevice::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 TQPaintDevice::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* TQPaintDevice::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 TQPaintDevice::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 TQPaintDevice::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 TQPixmap::defaultDepth() +*/ + +/*! + \overload + \fn int TQPaintDevice::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 TQPaintDevice::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 TQPaintDevice::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 TQPaintDevice::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* TQPaintDevice::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 TQPaintDevice::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 *TQPaintDevice::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 TQPaintDevice::x11Screen () const + + Returns the screen number on the X display for the paint device + (X11 only). Using this function is not portable. +*/ + +/*! + \fn int TQPaintDevice::x11Depth () const + + Returns the depth of the X display for the paint device (X11 + only). Using this function is not portable. + + \sa TQPixmap::defaultDepth() +*/ + +/*! + \fn int TQPaintDevice::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 TQPaintDevice::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 TQPaintDevice::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* TQPaintDevice::x11Visual () const + + Returns the Visual of the X display for the paint device (X11 + only). Using this function is not portable. +*/ + +/*! + \fn bool TQPaintDevice::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 = TQPaintDevice::x11AppDisplay(); + if ( ! dpy ) + return; + + int i, screens = ScreenCount( dpy ); + dpisX = new int[ screens ]; + dpisY = new int[ screens ]; + TQ_CHECK_PTR( dpisX ); + TQ_CHECK_PTR( dpisY ); + for ( i = 0; i < screens; i++ ) { + if (DisplayWidthMM(dpy,i) < 1) + dpisX[ i ] = 75; // default the dpi to 75. + else + dpisX[ i ] = (DisplayWidth(dpy,i) * 254 + DisplayWidthMM(dpy,i)*5) + / (DisplayWidthMM(dpy,i)*10); + if (DisplayHeightMM(dpy,i) < 1) + dpisY[ i ] = 75; // default the dpi to 75. + else + 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 TQPaintDevice::x11SetAppDpiX(int dpi, int screen) +{ + create_dpis(); + if ( ! dpisX ) + return; + if ( screen < 0 ) + screen = TQPaintDevice::x11AppScreen(); + if ( screen > ScreenCount( TQPaintDevice::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 TQPaintDevice::x11SetAppDpiX( int dpi ) +{ + TQPaintDevice::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 TQPaintDevice::x11SetAppDpiY(int dpi, int screen) +{ + create_dpis(); + if ( ! dpisY ) + return; + if ( screen < 0 ) + screen = TQPaintDevice::x11AppScreen(); + if ( screen > ScreenCount( TQPaintDevice::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 TQPaintDevice::x11SetAppDpiY( int dpi ) +{ + TQPaintDevice::x11SetAppDpiY( dpi, -1 ); +} + +/*! + Returns the horizontal DPI of the X display (X11 only) for screen + \a screen. Using this function is not portable. See + TQPaintDeviceMetrics for portable access to related information. + Using this function is not portable. + + \sa x11AppDpiY(), x11SetAppDpiX(), TQPaintDeviceMetrics::logicalDpiX() +*/ +int TQPaintDevice::x11AppDpiX(int screen) +{ + create_dpis(); + if ( ! dpisX ) + return 0; + if ( screen < 0 ) + screen = TQPaintDevice::x11AppScreen(); + if ( screen > ScreenCount( TQPaintDevice::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 + TQPaintDeviceMetrics for portable access to related information. + Using this function is not portable. +*/ +int TQPaintDevice::x11AppDpiX() +{ + return TQPaintDevice::x11AppDpiX( -1 ); +} + +/*! + Returns the vertical DPI of the X11 display (X11 only) for screen + \a screen. Using this function is not portable. See + TQPaintDeviceMetrics for portable access to related information. + Using this function is not portable. + + \sa x11AppDpiX(), x11SetAppDpiY(), TQPaintDeviceMetrics::logicalDpiY() +*/ +int TQPaintDevice::x11AppDpiY( int screen ) +{ + create_dpis(); + if ( ! dpisY ) + return 0; + if ( screen < 0 ) + screen = TQPaintDevice::x11AppScreen(); + if ( screen > ScreenCount( TQPaintDevice::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 + TQPaintDeviceMetrics for portable access to related information. + Using this function is not portable. + + \sa x11AppDpiX(), x11SetAppDpiY(), TQPaintDeviceMetrics::logicalDpiY() +*/ +int TQPaintDevice::x11AppDpiY() +{ + return TQPaintDevice::x11AppDpiY( -1 ); +} + +/*! + \fn bool TQPaintDevice::paintingActive() const + + Returns TRUE if the device is being painted, i.e. someone has + called TQPainter::begin() but not yet called TQPainter::end() for + this device; otherwise returns FALSE. + + \sa TQPainter::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, TQPicture). +*/ + +bool TQPaintDevice::cmd( int, TQPainter *, TQPDevCmdParam * ) +{ +#if defined(QT_CHECK_STATE) + tqWarning( "TQPaintDevice::cmd: Device has no command interface" ); +#endif + return FALSE; +} + +/*! + \internal + + Internal virtual function that returns paint device metrics. + + Please use the TQPaintDeviceMetrics class instead. +*/ + +int TQPaintDevice::metric( int ) const +{ +#if defined(QT_CHECK_STATE) + tqWarning( "TQPaintDevice::metrics: Device has no metric information" ); +#endif + return 0; +} + +/*! + \internal + + Internal virtual function. Reserved for future use. + + Please use the TQFontMetrics class instead. +*/ + +int TQPaintDevice::fontMet( TQFont *, int, const char *, int ) const +{ + return 0; +} + +/*! + \internal + + Internal virtual function. Reserved for future use. + + Please use the TQFontInfo class instead. +*/ + +int TQPaintDevice::fontInf( TQFont *, 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 = TQPaintDevice::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; + tqAddPostRoutine( 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 TQPaintDevice + + Copies a block of pixels from \a src to \a dst, perhaps merging + each pixel according to the \link TQt::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 + TQt::RasterOp documentation defines all the possible values. + + If \a ignoreMask is FALSE (the default) and \a src is a + masked TQPixmap, 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 TQWidget or TQPixmap. You cannot blit from a + TQPrinter, 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( TQPaintDevice *dst, int dx, int dy, + const TQPaintDevice *src, int sx, int sy, int sw, int sh, + TQt::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; + + TQPaintDevice *pdev = TQPainter::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( TQPaintDeviceMetrics::PdmWidth ) - sx; + else + return; + } + if ( sh <= 0 ) { // special height + if ( sh < 0 ) + sh = src->metric( TQPaintDeviceMetrics::PdmHeight ) - sy; + else + return; + } + + if ( dst->paintingActive() && dst->isExtDev() ) { + TQPixmap *pm; // output to picture/printer + bool tmp_pm = TRUE; + if ( ts == TQInternal::Pixmap ) { + pm = (TQPixmap*)src; + if ( sx != 0 || sy != 0 || + sw != pm->width() || sh != pm->height() || ignoreMask ) { + TQPixmap *tmp = new TQPixmap( sw, sh, pm->depth() ); + bitBlt( tmp, 0, 0, pm, sx, sy, sw, sh, TQt::CopyROP, TRUE ); + if ( pm->mask() && !ignoreMask ) { + TQBitmap mask( sw, sh ); + bitBlt( &mask, 0, 0, pm->mask(), sx, sy, sw, sh, + TQt::CopyROP, TRUE ); + tmp->setMask( mask ); + } + pm = tmp; + } else { + tmp_pm = FALSE; + } + } else if ( ts == TQInternal::Widget ) {// bitBlt to temp pixmap + pm = new TQPixmap( sw, sh ); + TQ_CHECK_PTR( pm ); + bitBlt( pm, 0, 0, src, sx, sy, sw, sh ); + } else { +#if defined(QT_CHECK_RANGE) + tqWarning( "bitBlt: Cannot bitBlt from device" ); +#endif + return; + } + TQPDevCmdParam param[3]; + TQRect r(dx, dy, pm->width(), pm->height()); + param[0].rect = &r; + param[1].pixmap = pm; + dst->cmd( TQPaintDevice::PdcDrawPixmap, 0, param ); + if ( tmp_pm ) + delete pm; + return; + } + + switch ( ts ) { + case TQInternal::Widget: + case TQInternal::Pixmap: + case TQInternal::System: // OK, can blt from these + break; + default: +#if defined(QT_CHECK_RANGE) + tqWarning( "bitBlt: Cannot bitBlt from device type %x", ts ); +#endif + return; + } + switch ( td ) { + case TQInternal::Widget: + case TQInternal::Pixmap: + case TQInternal::System: // OK, can blt to these + break; + default: +#if defined(QT_CHECK_RANGE) + tqWarning( "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 > TQt::LastROP ) { +#if defined(QT_CHECK_RANGE) + tqWarning( "bitBlt: Invalid ROP code" ); +#endif + return; + } + + if ( dst->handle() == 0 ) { +#if defined(QT_CHECK_NULL) + tqWarning( "bitBlt: Cannot bitBlt to device" ); +#endif + return; + } + + bool mono_src; + bool mono_dst; + bool include_inferiors = FALSE; + bool graphics_exposure = FALSE; + TQPixmap *src_pm; + TQBitmap *mask; + + if ( ts == TQInternal::Pixmap ) { + src_pm = (TQPixmap*)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 = ((TQWidget*)src)->testWFlags(TQt::WPaintUnclipped); + graphics_exposure = td == TQInternal::Widget; + } + if ( td == TQInternal::Pixmap ) { + if ( dst->x11Screen() != src->x11Screen() ) + ((TQPixmap*)dst)->x11SetScreen( src->x11Screen() ); + mono_dst = ((TQPixmap*)dst)->depth() == 1; + ((TQPixmap*)dst)->detach(); // changes shared pixmap + } else { + mono_dst = FALSE; + include_inferiors = include_inferiors || + ((TQWidget*)dst)->testWFlags(TQt::WPaintUnclipped); + } + + if ( mono_dst && !mono_src ) { // dest is 1-bit pixmap, source is not +#if defined(QT_CHECK_RANGE) + tqWarning( "bitBlt: Incompatible destination pixmap" ); +#endif + return; + } + +#ifndef TQT_NO_XRENDER + if (src_pm && !mono_src && src_pm->data->alphapm && !ignoreMask ) { + // use RENDER to do the blit + TQPixmap *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() == TQPixmap::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() == TQPixmap::BestOptim ) { + mask->data->maskgc = gc; + } else { + temp_gc = TRUE; + } + } + } + XSetClipOrigin( dpy, gc, dx-sx, dy-sy ); + if ( rop != TQt::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 != TQt::CopyROP ) // restore ROP + XSetFunction( dpy, gc, GXcopy ); + return; + } + + gc = tqt_xget_temp_gc( dst->x11Screen(), mono_dst ); // get a reusable GC + + if ( rop != TQt::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 == TQInternal::Widget ) { // set GC colors + TQWidget *w = (TQWidget *)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 = TQt::white.pixel( dst->x11Screen() ); + gcvals.foreground = TQt::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 ( ((TQPixmap*)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 != TQt::CopyROP ) // restore ROP + XSetFunction( dpy, gc, GXcopy ); +} + + +/*! + \relates TQPaintDevice + + \overload void bitBlt( TQPaintDevice *dst, const TQPoint &dp, const TQPaintDevice *src, const TQRect &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 TQPrinter for all +// paintdevices without breaking bin compatibility. +void TQPaintDevice::setResolution( int ) +{ +} + +/*!\internal +*/ +int TQPaintDevice::resolution() const +{ + return metric( TQPaintDeviceMetrics::PdmDpiY ); +} |