You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1174 lines
32 KiB
1174 lines
32 KiB
/****************************************************************************
|
|
**
|
|
** 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++ ) {
|
|
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 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 );
|
|
}
|