diff options
Diffstat (limited to 'tqtinterface/qt4/src/kernel/tqpainter_x11.cpp')
-rw-r--r-- | tqtinterface/qt4/src/kernel/tqpainter_x11.cpp | 3410 |
1 files changed, 0 insertions, 3410 deletions
diff --git a/tqtinterface/qt4/src/kernel/tqpainter_x11.cpp b/tqtinterface/qt4/src/kernel/tqpainter_x11.cpp deleted file mode 100644 index f5ad348..0000000 --- a/tqtinterface/qt4/src/kernel/tqpainter_x11.cpp +++ /dev/null @@ -1,3410 +0,0 @@ -/**************************************************************************** -** -** Implementation of TQPainter class for X11 -** -** Created : 940112 -** -** Copyright (C) 2010 Timothy Pearson and (C) 1992-2008 Trolltech ASA. -** -** 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 "tqplatformdefs.h" - -#ifdef USE_QT4 -#include <Qt/qtextstream.h> -#endif // USE_QT4 - -#include "tqfont.h" -#include "tqpainter.h" -#include "tqwidget.h" -#include "tqbitmap.h" -#include "tqpixmapcache.h" -#include "tqtextcodec.h" -#include "tqpaintdevicemetrics.h" - -#include "tqt_x11_p.h" - -#include "tqtextlayout_p.h" -#include "tqfontdata_p.h" -#include "tqfontengine_p.h" -#include "tqtextengine_p.h" - -#include <math.h> - -#ifdef USE_QT4 - -/*! \internal - Draws the text item \a ti at position \a (x, y ). - - This method ignores the painters background mode and - color. drawText and qt_format_text have to do it themselves, as - only they know the extents of the complete string. - - It ignores the font set on the painter as the text item has one of its own. - - The underline and strikeout parameters of the text items font are - ignored as well. You'll need to pass in the correct flags to get - underlining and strikeout. -*/ -void TQPainter::tqdrawTextItem( int x, int y, const TQTextItem &ti, int textFlags ) -{ - ti.tqt_tqdrawTextItem( const_cast<TQPainter*>(this), x, y, ti, textFlags ); -} - -/*! - Sets the \link TQt::RasterOp raster operation \endlink to \a r. - The default is \c CopyROP. - - \sa rasterOp() TQt::RasterOp -*/ - -void TQPainter::setRasterOp( TQt::RasterOp r ) -{ - if ( !isActive() ) { -#if defined(TQT_CHECK_STATE) - qWarning( "TQPainter::setRasterOp: Call begin() first" ); -#endif - return; - } - if ( (uint)r > TQt::LastROP ) { -#if defined(TQT_CHECK_RANGE) - qWarning( "TQPainter::setRasterOp: Invalid ROP code" ); -#endif - return; - } - rop = r; - -// [FIXME] -// This needs to be implemented for Qt4 -// See http://lists.trolltech.com/qt-interest/2007-05/thread00975-0.html -// printf("[WARNING] TQPainter::setRasterOp( TQt::RasterOp r ) unimplemented [Was attempting to use raster operation %d\n\r", rop); - -// An attempt to work around this on X11 only -// See http://doc.qt.nokia.com/latest/qpainter.html#CompositionMode-enum - - QPainter::CompositionMode cm; - switch (rop) { - case CopyROP: - cm=QPainter::CompositionMode_SourceOver; - break; - case OrROP: - cm=QPainter::RasterOp_SourceOrDestination; - break; - case XorROP: - cm=QPainter::RasterOp_SourceXorDestination; - break; - case NotAndROP: - cm=QPainter::RasterOp_NotSourceAndDestination; - break; -// case EraseROP: -// cm=QPainter::RasterOp_NotSourceAndDestination; -// break; - case NotCopyROP: - cm=QPainter::RasterOp_NotSource; - break; - case NotOrROP: - printf("[WARNING] TQPainter::setRasterOp( TQt::RasterOp r ) unimplemented [Was attempting to use raster operation %d\n\r", rop); - return; - break; - case NotXorROP: - cm=QPainter::RasterOp_NotSourceXorDestination; - break; - case AndROP: - cm=QPainter::RasterOp_SourceAndDestination; - break; -// case NotEraseROP: -// cm=QPainter::RasterOp_SourceAndDestination; -// break; - case NotROP: - cm=QPainter::RasterOp_SourceAndNotDestination; // [WARNING] This may not be a correct substitute for NotROP! - break; - case ClearROP: - cm=QPainter::CompositionMode_Clear; - break; - case SetROP: - printf("[WARNING] TQPainter::setRasterOp( TQt::RasterOp r ) unimplemented [Was attempting to use raster operation %d\n\r", rop); - return; - break; - case NopROP: - cm=QPainter::CompositionMode_Destination; - break; - case AndNotROP: - cm=QPainter::RasterOp_SourceAndNotDestination; - break; - case OrNotROP: - printf("[WARNING] TQPainter::setRasterOp( TQt::RasterOp r ) unimplemented [Was attempting to use raster operation %d\n\r", rop); - return; - break; - case NandROP: - cm=QPainter::RasterOp_NotSourceOrNotDestination; - break; - case NorROP: - cm=QPainter::RasterOp_NotSourceAndNotDestination; - break; - } - - setCompositionMode(cm); - -// if ( testf(ExtDev) ) { -// TQPDevCmdParam param[1]; -// param[0].ival = r; -// if ( !pdev->cmd( TQPaintDevice::PdcSetROP, this, param ) || !hd ) -// return; -// } -// if ( penRef ) -// updatePen(); // get non-cached pen GC -// if ( brushRef ) -// updateBrush(); // get non-cached brush GC -// XSetFunction( dpy, gc, ropCodes[rop] ); -// XSetFunction( dpy, gc_brush, ropCodes[rop] ); -} - -/*! - \internal -*/ - -void TQPainter::drawWinFocusRect( int x, int y, int w, int h, bool xorPaint, const QColor &bgColor ) -{ - if ( !isActive() /*|| txop == TxRotShear*/ ) - return; - static char winfocus_line[] = { 1, 1 }; - - TQPen old_pen = pen(); - RasterOp old_rop = (RasterOp)rasterOp(); - - if ( xorPaint ) { - if ( TQColor::numBitPlanes() <= 8 ) - setPen( color1 ); - else - setPen( white ); - setRasterOp( XorROP ); - } else { - if ( tqGray( bgColor.rgb() ) < 128 ) - setPen( white ); - else - setPen( black ); - } - - if ( testf(ExtDev|VxF|WxF) ) { - if ( testf(ExtDev) ) { -// TQPDevCmdParam param[1]; -// TQRect r( x, y, w, h ); -// param[0].rect = &r; -// if ( !pdev->cmd( TQPaintDevice::PdcDrawRect, this, param ) || !hd) { -// setRasterOp( old_rop ); -// setPen( old_pen ); -// return; -// } - printf("[FIXME] TQPainter::drawWinFocusRect not yet supported on external paint devices\n\r"); - } - map( x, y, w, h, &x, &y, &w, &h ); - } -// if ( w <= 0 || h <= 0 ) { -// if ( w == 0 || h == 0 ) -// return; -// fix_neg_rect( &x, &y, &w, &h ); -// } - -// XSetDashes( dpy, gc, 0, winfocus_line, 2 ); -// XSetLineAttributes( dpy, gc, 1, LineOnOffDash, CapButt, JoinMiter ); -// XDrawRectangle( dpy, hd, gc, x, y, w-1, h-1 ); -// XSetLineAttributes( dpy, gc, 0, LineSolid, CapButt, JoinMiter ); - - printf("[WARNING] TQPainter::drawWinFocusRect may not draw the correct rectangle in all cases [due to shift from Xorg to Qt painting]\n\r"); -// drawRect( x, y, w-1, h-1 ); - drawRect( x, y, w, h ); - - setRasterOp( old_rop ); - setPen( old_pen ); -} - -/*! - Draws the polyline defined by the \a npoints points in \a a - starting at \a a[index]. (\a index defaults to 0.) - - If \a npoints is -1 (the default) all points until the end of the - array are used (i.e. a.size()-index-1 line segments are drawn). - - \warning On X11, coordinates that do not fit into 16-bit signed - values are truncated. This limitation is expected to go away in - TQt 4. - - \sa drawLineSegments(), drawPolygon(), TQPen -*/ - -void TQPainter::tqdrawPolyline( const TQPointArray &a, int index, int npoints ) -{ - if ( npoints < 0 ) - npoints = a.size() - index; - if ( index + npoints > (int)a.size() ) - npoints = a.size() - index; - if ( !isActive() || npoints < 2 || index < 0 ) - return; - TQPointArray pa = a; - if ( testf(ExtDev|VxF|WxF) ) { - if ( testf(ExtDev) ) { -// if ( npoints != (int)pa.size() ) { -// pa = TQPointArray( npoints ); -// for ( int i=0; i<npoints; i++ ) -// pa.setPoint( i, a.point(index+i) ); -// index = 0; -// } -// TQPDevCmdParam param[1]; -// param[0].ptarr = (TQPointArray*)&pa; -// if ( !pdev->cmd(TQPaintDevice::PdcDrawPolyline, this, param) || !hd ) -// return; - printf("[FIXME] TQPainter::drawPolyline not yet supported on external paint devices\n\r"); - } -#if 0 - if ( txop != TxNone ) { - pa = xForm( pa, index, npoints ); - if ( pa.size() != a.size() ) { - index = 0; - npoints = pa.size(); - } - } - } - if ( cpen.style() != Qt::NoPen ) { - while(npoints>65535) { - XDrawLines( dpy, hd, gc, (XPoint*)(pa.shortPoints( index, 65535 )), - 65535, CoordModeOrigin ); - npoints-=65535; - index+=65535; - } - XDrawLines( dpy, hd, gc, (XPoint*)(pa.shortPoints( index, npoints )), - npoints, CoordModeOrigin ); - } -#else - } - printf("[WARNING] TQPainter::tqdrawPolyline UNIMPLEMENTED\n\r"); -#endif -} - -#else // USE_QT4 - -// paintevent magic to provide Windows semantics on X11 -static TQRegion* paintEventClipRegion = 0; -static TQPaintDevice* paintEventDevice = 0; - -void qt_set_paintevent_clipping( TQPaintDevice* dev, const TQRegion& region) -{ - if ( !paintEventClipRegion ) - paintEventClipRegion = new TQRegion( region ); - else - *paintEventClipRegion = region; - paintEventDevice = dev; -} - -void qt_clear_paintevent_clipping() -{ - delete paintEventClipRegion; - paintEventClipRegion = 0; - paintEventDevice = 0; -} - -class TQWFlagWidget : public TQWidget -{ -public: - void setWState( WFlags f ) { TQWidget::setWState(f); } - void clearWState( WFlags f ) { TQWidget::clearWState(f); } - void setWFlags( WFlags f ) { TQWidget::setWFlags(f); } - void clearWFlags( WFlags f ) { TQWidget::clearWFlags(f); } -}; - -void qt_erase_region( TQWidget* w, const TQRegion& region) -{ - TQRegion reg = region; - - if ( TQPainter::redirect(w) || (!w->isTopLevel() && w->backgroundPixmap() - && w->backgroundOrigin() != TQWidget::WidgetOrigin) ) { - TQPoint offset = w->backgroundOffset(); - int ox = offset.x(); - int oy = offset.y(); - - bool unclipped = w->testWFlags( TQt::WPaintUnclipped ); - if ( unclipped ) - ((TQWFlagWidget*)w)->clearWFlags( TQt::WPaintUnclipped ); - TQPainter p( w ); - p.setClipRegion( region ); // automatically includes paintEventDevice if required - if ( w->backgroundPixmap() ) - p.drawTiledPixmap( 0, 0, w->width(), w->height(), - *w->backgroundPixmap(), ox, oy ); - else - p.fillRect( w->rect(), w->eraseColor() ); - if ( unclipped ) - ((TQWFlagWidget*)w)->setWFlags( TQt::WPaintUnclipped ); - return; - } - - if ( w == paintEventDevice && paintEventClipRegion ) - reg = paintEventClipRegion->intersect( reg ); - - TQMemArray<TQRect> r = reg.rects(); - for (uint i=0; i<r.size(); i++) { - const TQRect& rr = r[(int)i]; - XClearArea( w->x11Display(), w->winId(), - rr.x(), rr.y(), rr.width(), rr.height(), False ); - } -} - -void qt_erase_rect( TQWidget* w, const TQRect& r) -{ - if ( TQPainter::redirect(w) || w == paintEventDevice - || w->backgroundOrigin() != TQWidget::WidgetOrigin ) - qt_erase_region( w, r ); - else - XClearArea( w->x11Display(), w->winId(), r.x(), r.y(), r.width(), r.height(), False ); - -} - -#ifdef TQT_NO_XFTFREETYPE -static const TQt::HANDLE rendhd = 0; -#endif - -// hack, so we don't have to make TQRegion::clipRectangles() public or include -// X11 headers in tqregion.h -inline void *qt_getClipRects( const TQRegion &r, int &num ) -{ - return r.clipRectangles( num ); -} - -static inline void x11SetClipRegion(Display *dpy, GC gc, GC gc2, TQt::HANDLE draw, const TQRegion &r) -{ - int num; - XRectangle *rects = (XRectangle *)qt_getClipRects( r, num ); - - if (gc) - XSetClipRectangles( dpy, gc, 0, 0, rects, num, YXBanded ); - if (gc2) - XSetClipRectangles( dpy, gc2, 0, 0, rects, num, YXBanded ); - -#ifndef TQT_NO_XFTFREETYPE - if (draw) - XftDrawSetClipRectangles((XftDraw *) draw, 0, 0, rects, num); -#else - TQ_UNUSED(draw); -#endif // TQT_NO_XFTFREETYPE -} - -static inline void x11ClearClipRegion(Display *dpy, GC gc, GC gc2, TQt::HANDLE draw) -{ - if (gc) - XSetClipMask(dpy, gc, None); - if (gc2) - XSetClipMask(dpy, gc2, None); - -#ifndef TQT_NO_XFTFREETYPE - if (draw) { -# ifdef TQT_XFT2 - XftDrawSetClip((XftDraw *) draw, None); -# else - // stupid Xft1 - Picture pict = XftDrawPicture((XftDraw *) draw); - XRenderPictureAttributes pattr; - pattr.clip_mask = None; - XRenderChangePicture(dpy, pict, CPClipMask, &pattr); -# endif // TQT_XFT2 - } -#else - TQ_UNUSED(draw); -#endif // TQT_NO_XFTFREETYPE -} - - -/***************************************************************************** - Trigonometric function for TQPainter - - We have implemented simple sine and cosine function that are called from - TQPainter::drawPie() and TQPainter::drawChord() when drawing the outline of - pies and chords. - These functions are slower and less accurate than math.h sin() and cos(), - but with still around 1/70000th sec. execution time (on a 486DX2-66) and - 8 digits accuracy, it should not be the bottleneck in drawing these tqshapes. - The advantage is that you don't have to link in the math library. - *****************************************************************************/ - -const double TQ_PI = 3.14159265358979323846; // pi -const double TQ_2PI = 6.28318530717958647693; // 2*pi -const double TQ_PI2 = 1.57079632679489661923; // pi/2 - - -#if defined(TQ_CC_GNU) && defined(TQ_OS_AIX) -// AIX 4.2 gcc 2.7.2.3 gets internal error. -static int tqRoundAIX( double d ) -{ - return tqRound(d); -} -#define tqRound tqRoundAIX -#endif - - -#if defined(TQ_CC_GNU) && defined(__i386__) - -inline double qcos( double a ) -{ - double r; - __asm__ ( - "fcos" - : "=t" (r) : "0" (a) ); - return(r); -} - -inline double qsin( double a ) -{ - double r; - __asm__ ( - "fsin" - : "=t" (r) : "0" (a) ); - return(r); -} - -double qsincos( double a, bool calcCos=FALSE ) -{ - return calcCos ? qcos(a) : qsin(a); -} - -#else - -double qsincos( double a, bool calcCos=FALSE ) -{ - if ( calcCos ) // calculate cosine - a -= TQ_PI2; - if ( a >= TQ_2PI || a <= -TQ_2PI ) { // fix range: -2*pi < a < 2*pi - int m = (int)(a/TQ_2PI); - a -= TQ_2PI*m; - } - if ( a < 0.0 ) // 0 <= a < 2*pi - a += TQ_2PI; - int sign = a > TQ_PI ? -1 : 1; - if ( a >= TQ_PI ) - a = TQ_2PI - a; - if ( a >= TQ_PI2 ) - a = TQ_PI - a; - if ( calcCos ) - sign = -sign; - double a2 = a*a; // here: 0 <= a < pi/4 - double a3 = a2*a; // make taylor sin sum - double a5 = a3*a2; - double a7 = a5*a2; - double a9 = a7*a2; - double a11 = a9*a2; - return (a-a3/6+a5/120-a7/5040+a9/362880-a11/39916800)*sign; -} - -inline double qsin( double a ) { return qsincos(a, FALSE); } -inline double qcos( double a ) { return qsincos(a, TRUE); } - -#endif - - -/***************************************************************************** - TQPainter internal GC (Graphics Context) allocator. - - The GC allocator offers two functions; alloc_gc() and free_gc() that - reuse GC objects instead of calling XCreateGC() and XFreeGC(), which - are a whole lot slower. - *****************************************************************************/ - -struct TQGC -{ - GC gc; - char in_use; - bool mono; - int scrn; -}; - -const int gc_array_size = 256; -static TQGC gc_array[gc_array_size]; // array of GCs -static bool gc_array_init = FALSE; - - -static void init_gc_array() -{ - if ( !gc_array_init ) { - memset( gc_array, 0, gc_array_size*sizeof(TQGC) ); - gc_array_init = TRUE; - } -} - -static void cleanup_gc_array( Display *dpy ) -{ - register TQGC *p = gc_array; - int i = gc_array_size; - if ( gc_array_init ) { - while ( i-- ) { - if ( p->gc ) // destroy GC - XFreeGC( dpy, p->gc ); - p++; - } - gc_array_init = FALSE; - } -} - -// #define DONT_USE_GC_ARRAY - -static GC alloc_gc( Display *dpy, int scrn, Drawable hd, bool monochrome=FALSE, - bool privateGC = FALSE ) -{ -#if defined(DONT_USE_GC_ARRAY) - privateGC = TRUE; // will be slower -#endif - if ( privateGC ) { - GC gc = XCreateGC( dpy, hd, 0, 0 ); - XSetGraphicsExposures( dpy, gc, False ); - return gc; - } - register TQGC *p = gc_array; - int i = gc_array_size; - if ( !gc_array_init ) // not initialized - init_gc_array(); - while ( i-- ) { - if ( !p->gc ) { // create GC (once) - p->gc = XCreateGC( dpy, hd, 0, 0 ); - p->scrn = scrn; - XSetGraphicsExposures( dpy, p->gc, False ); - p->in_use = FALSE; - p->mono = monochrome; - } - if ( !p->in_use && p->mono == monochrome && p->scrn == scrn ) { - p->in_use = TRUE; // available/compatible GC - return p->gc; - } - p++; - } -#if defined(TQT_CHECK_NULL) - qWarning( "TQPainter: Internal error; no available GC" ); -#endif - GC gc = XCreateGC( dpy, hd, 0, 0 ); - XSetGraphicsExposures( dpy, gc, False ); - return gc; -} - -static void free_gc( Display *dpy, GC gc, bool privateGC = FALSE ) -{ -#if defined(DONT_USE_GC_ARRAY) - privateGC = TRUE; // will be slower -#endif - if ( privateGC ) { - TQ_ASSERT( dpy != 0 ); - XFreeGC( dpy, gc ); - return; - } - register TQGC *p = gc_array; - int i = gc_array_size; - if ( gc_array_init ) { - while ( i-- ) { - if ( p->gc == gc ) { - p->in_use = FALSE; // set available - XSetClipMask( dpy, gc, None ); // make it reusable - XSetFunction( dpy, gc, GXcopy ); - XSetFillStyle( dpy, gc, FillSolid ); - XSetTSOrigin( dpy, gc, 0, 0 ); - return; - } - p++; - } - } - - // not found in gc_array - XFreeGC(dpy, gc); -} - - -/***************************************************************************** - TQPainter internal GC (Graphics Context) cache for solid pens and - brushes. - - The GC cache makes a significant contribution to speeding up - drawing. Setting new pen and brush colors will make the painter - look for another GC with the same color instead of changing the - color value of the GC currently in use. The cache structure is - optimized for fast lookup. Only solid line pens with line width 0 - and solid brushes are cached. - - In addition, stored GCs may have an implicit clipping region - set. This prevents any drawing outside paint events. Both - updatePen() and updateBrush() keep track of the validity of this - clipping region by storing the clip_serial number in the cache. - -*****************************************************************************/ - -struct TQGCC // cached GC -{ - GC gc; - uint pix; - int count; - int hits; - uint clip_serial; - int scrn; -}; - -const int gc_cache_size = 29; // multiply by 4 -static TQGCC *gc_cache_buf; -static TQGCC *gc_cache[4*gc_cache_size]; -static bool gc_cache_init = FALSE; -static uint gc_cache_clip_serial = 0; - - -static void init_gc_cache() -{ - if ( !gc_cache_init ) { - gc_cache_init = TRUE; - gc_cache_clip_serial = 0; - TQGCC *g = gc_cache_buf = new TQGCC[4*gc_cache_size]; - memset( g, 0, 4*gc_cache_size*sizeof(TQGCC) ); - for ( int i=0; i<4*gc_cache_size; i++ ) - gc_cache[i] = g++; - } -} - - -// #define GC_CACHE_STAT -#if defined(GC_CACHE_STAT) -#include "tqtextstream.h" -#include "tqbuffer.h" - -static int g_numhits = 0; -static int g_numcreates = 0; -static int g_numfaults = 0; -#endif - - -static void cleanup_gc_cache() -{ - if ( !gc_cache_init ) - return; -#if defined(GC_CACHE_STAT) - qDebug( "Number of cache hits = %d", g_numhits ); - qDebug( "Number of cache creates = %d", g_numcreates ); - qDebug( "Number of cache faults = %d", g_numfaults ); - for ( int i=0; i<gc_cache_size; i++ ) { - TQCString str; - TQBuffer buf( str ); - buf.open(IO_ReadWrite); - TQTextStream s(&buf); - s << i << ": "; - for ( int j=0; j<4; j++ ) { - TQGCC *g = gc_cache[i*4+j]; - s << (g->gc ? 'X' : '-') << ',' << g->hits << ',' - << g->count << '\t'; - } - s << '\0'; - qDebug( str ); - buf.close(); - } -#endif - delete [] gc_cache_buf; - gc_cache_init = FALSE; -} - - -static bool obtain_gc( void **ref, GC *gc, uint pix, Display *dpy, int scrn, - TQt::HANDLE hd, uint painter_clip_serial ) -{ - if ( !gc_cache_init ) - init_gc_cache(); - - int k = (pix % gc_cache_size) * 4; - TQGCC *g = gc_cache[k]; - TQGCC *prev = 0; - -#define NOMATCH (g->gc && (g->pix != pix || g->scrn != scrn || \ - (g->clip_serial > 0 && g->clip_serial != painter_clip_serial))) - - if ( NOMATCH ) { - prev = g; - g = gc_cache[++k]; - if ( NOMATCH ) { - prev = g; - g = gc_cache[++k]; - if ( NOMATCH ) { - prev = g; - g = gc_cache[++k]; - if ( NOMATCH ) { - if ( g->count == 0 && g->scrn == scrn) { // steal this GC - g->pix = pix; - g->count = 1; - g->hits = 1; - g->clip_serial = 0; - XSetForeground( dpy, g->gc, pix ); - XSetClipMask(dpy, g->gc, None); - gc_cache[k] = prev; - gc_cache[k-1] = g; - *ref = (void *)g; - *gc = g->gc; - return TRUE; - } else { // all GCs in use -#if defined(GC_CACHE_STAT) - g_numfaults++; -#endif - *ref = 0; - return FALSE; - } - } - } - } - } - -#undef NOMATCH - - *ref = (void *)g; - - if ( g->gc ) { // reuse existing GC -#if defined(GC_CACHE_STAT) - g_numhits++; -#endif - *gc = g->gc; - g->count++; - g->hits++; - if ( prev && g->hits > prev->hits ) { // maintain LRU order - gc_cache[k] = prev; - gc_cache[k-1] = g; - } - return TRUE; - } else { // create new GC -#if defined(GC_CACHE_STAT) - g_numcreates++; -#endif - g->gc = alloc_gc( dpy, scrn, hd, FALSE ); - g->scrn = scrn; - g->pix = pix; - g->count = 1; - g->hits = 1; - g->clip_serial = 0; - *gc = g->gc; - return FALSE; - } -} - -static inline void release_gc( void *ref ) -{ - ((TQGCC*)ref)->count--; -} - -/***************************************************************************** - TQPainter member functions - *****************************************************************************/ - -/*! - \internal - - Internal function that initializes the painter. -*/ - -void TQPainter::initialize() -{ - init_gc_array(); - init_gc_cache(); -} - -/*! - \internal - - Internal function that cleans up the painter. -*/ - -void TQPainter::cleanup() -{ - cleanup_gc_cache(); - cleanup_gc_array( TQPaintDevice::x11AppDisplay() ); - TQPointArray::cleanBuffers(); -} - -/*! - \internal - - Internal function that destroys up the painter. -*/ - -void TQPainter::destroy() -{ - -} - -void TQPainter::init() -{ - d = 0; - flags = IsStartingUp; - bg_col = white; // default background color - bg_mode = TransparentMode; // default background mode - rop = CopyROP; // default ROP - tabstops = 0; // default tabbing - tabarray = 0; - tabarraylen = 0; - ps_stack = 0; - wm_stack = 0; - gc = gc_brush = 0; - pdev = 0; - dpy = 0; - txop = txinv = 0; - penRef = brushRef = 0; - clip_serial = 0; - pfont = 0; - block_ext = FALSE; -} - - -/*! - \fn const TQFont &TQPainter::font() const - - Returns the currently set painter font. - - \sa setFont(), TQFont -*/ - -/*! - Sets the painter's font to \a font. - - This font is used by subsequent drawText() functions. The text - color is the same as the pen color. - - \sa font(), drawText() -*/ - -void TQPainter::setFont( const TQFont &font ) -{ -#if defined(TQT_CHECK_STATE) - if ( !isActive() ) - qWarning( "TQPainter::setFont: Will be reset by begin()" ); -#endif - if ( cfont.d != font.d ) { - cfont = font; - cfont.x11SetScreen( scrn ); - setf(DirtyFont); - } -} - - -void TQPainter::updateFont() -{ - if (!isActive()) - return; - - clearf(DirtyFont); - if ( testf(ExtDev) ) { - if (pdev->devType() == TQInternal::Printer) { - if ( pfont ) delete pfont; - pfont = new TQFont( cfont.d, pdev ); - } - TQPDevCmdParam param[1]; - param[0].font = &cfont; - if ( !pdev->cmd( TQPaintDevice::PdcSetFont, this, param ) || !hd ) - return; - } - setf(NoCache); - if ( penRef ) - updatePen(); // force a non-cached GC -} - - -void TQPainter::updatePen() -{ - if (!isActive()) - return; - - if ( testf(ExtDev) ) { - TQPDevCmdParam param[1]; - param[0].pen = &cpen; - if ( !pdev->cmd( TQPaintDevice::PdcSetPen, this, param ) || !hd ) - return; - } - - int ps = cpen.style(); - bool cacheIt = !testf(ClipOn|MonoDev|NoCache) && - (ps == NoPen || ps == SolidLine) && - cpen.width() == 0 && rop == CopyROP; - - bool obtained = FALSE; - bool internclipok = hasClipping(); - if ( cacheIt ) { - if ( gc ) { - if ( penRef ) - release_gc( penRef ); - else - free_gc( dpy, gc ); - } - obtained = obtain_gc(&penRef, &gc, cpen.color().pixel(scrn), dpy, scrn, - hd, clip_serial); - if ( !obtained && !penRef ) - gc = alloc_gc( dpy, scrn, hd, FALSE ); - } else { - if ( gc ) { - if ( penRef ) { - release_gc( penRef ); - penRef = 0; - gc = alloc_gc( dpy, scrn, hd, testf(MonoDev) ); - } else { - internclipok = TRUE; - } - } else { - gc = alloc_gc( dpy, scrn, hd, testf(MonoDev), testf(UsePrivateCx) ); - } - } - - if ( !internclipok ) { - if ( pdev == paintEventDevice && paintEventClipRegion ) { - if ( penRef &&((TQGCC*)penRef)->clip_serial < gc_cache_clip_serial ) { - x11SetClipRegion( dpy, gc, 0, rendhd, *paintEventClipRegion ); - ((TQGCC*)penRef)->clip_serial = gc_cache_clip_serial; - } else if ( !penRef ) { - x11SetClipRegion( dpy, gc, 0, rendhd, *paintEventClipRegion ); - } - } else if (penRef && ((TQGCC*)penRef)->clip_serial ) { - x11ClearClipRegion(dpy, gc, 0, rendhd); - ((TQGCC*)penRef)->clip_serial = 0; - } - } - - if ( obtained ) - return; - - char dashes[10]; // custom pen dashes - int dash_len = 0; // length of dash list - int s = LineSolid; - int cp = CapButt; - int jn = JoinMiter; - - /* - We are emulating Windows here. Windows treats cpen.width() == 1 - (or 0) as a very special case. The fudge variable unifies this - case with the general case. - */ - int dot = cpen.width(); // width of a dot - int fudge = 1; - bool allow_zero_lw = TRUE; - if ( dot <= 1 ) { - dot = 3; - fudge = 2; - } - - switch( ps ) { - case NoPen: - case SolidLine: - s = LineSolid; - break; - case DashLine: - dashes[0] = fudge * 3 * dot; - dashes[1] = fudge * dot; - dash_len = 2; - allow_zero_lw = FALSE; - break; - case DotLine: - dashes[0] = dot; - dashes[1] = dot; - dash_len = 2; - allow_zero_lw = FALSE; - break; - case DashDotLine: - dashes[0] = 3 * dot; - dashes[1] = fudge * dot; - dashes[2] = dot; - dashes[3] = fudge * dot; - dash_len = 4; - allow_zero_lw = FALSE; - break; - case DashDotDotLine: - dashes[0] = 3 * dot; - dashes[1] = dot; - dashes[2] = dot; - dashes[3] = dot; - dashes[4] = dot; - dashes[5] = dot; - dash_len = 6; - allow_zero_lw = FALSE; - } - TQ_ASSERT( dash_len <= (int) sizeof(dashes) ); - - switch ( cpen.capStyle() ) { - case SquareCap: - cp = CapProjecting; - break; - case RoundCap: - cp = CapRound; - break; - case FlatCap: - default: - cp = CapButt; - break; - } - switch ( cpen.joinStyle() ) { - case BevelJoin: - jn = JoinBevel; - break; - case RoundJoin: - jn = JoinRound; - break; - case MiterJoin: - default: - jn = JoinMiter; - break; - } - - XSetForeground( dpy, gc, cpen.color().pixel(scrn) ); - XSetBackground( dpy, gc, bg_col.pixel(scrn) ); - - if ( dash_len ) { // make dash list - XSetDashes( dpy, gc, 0, dashes, dash_len ); - s = bg_mode == TransparentMode ? LineOnOffDash : LineDoubleDash; - } - XSetLineAttributes( dpy, gc, - (! allow_zero_lw && cpen.width() == 0) ? 1 : cpen.width(), - s, cp, jn ); -} - - -void TQPainter::updateBrush() -{ - if (!isActive()) - return; - - static const uchar dense1_pat[] = { 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff }; - static const uchar dense2_pat[] = { 0x77, 0xff, 0xdd, 0xff, 0x77, 0xff, 0xdd, 0xff }; - static const uchar dense3_pat[] = { 0x55, 0xbb, 0x55, 0xee, 0x55, 0xbb, 0x55, 0xee }; - static const uchar dense4_pat[] = { 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa }; - static const uchar dense5_pat[] = { 0xaa, 0x44, 0xaa, 0x11, 0xaa, 0x44, 0xaa, 0x11 }; - static const uchar dense6_pat[] = { 0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00 }; - static const uchar dense7_pat[] = { 0x00, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00 }; - static const uchar hor_pat[] = { // horizontal pattern - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - static const uchar ver_pat[] = { // vertical pattern - 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, - 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, - 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, - 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, - 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, - 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20 }; - static const uchar cross_pat[] = { // cross pattern - 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0xff, 0xff, 0xff, - 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, - 0x08, 0x82, 0x20, 0xff, 0xff, 0xff, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, - 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0xff, 0xff, 0xff, - 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, - 0x08, 0x82, 0x20, 0xff, 0xff, 0xff, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20 }; - static const uchar bdiag_pat[] = { // backward diagonal pattern - 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x01, 0x01, - 0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, - 0x02, 0x02, 0x01, 0x01, 0x80, 0x80, 0x40, 0x40 }; - static const uchar fdiag_pat[] = { // forward diagonal pattern - 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, - 0x80, 0x80, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, - 0x20, 0x20, 0x40, 0x40, 0x80, 0x80, 0x01, 0x01 }; - static const uchar dcross_pat[] = { // diagonal cross pattern - 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x14, 0x14, 0x22, 0x22, 0x41, 0x41, - 0x80, 0x80, 0x41, 0x41, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x14, 0x14, - 0x22, 0x22, 0x41, 0x41, 0x80, 0x80, 0x41, 0x41 }; - static const uchar * const pat_tbl[] = { - dense1_pat, dense2_pat, dense3_pat, dense4_pat, dense5_pat, - dense6_pat, dense7_pat, - hor_pat, ver_pat, cross_pat, bdiag_pat, fdiag_pat, dcross_pat }; - - if ( testf(ExtDev) ) { - TQPDevCmdParam param[1]; - param[0].brush = &cbrush; - if ( !pdev->cmd( TQPaintDevice::PdcSetBrush, this, param ) || !hd ) - return; - } - - int bs = cbrush.style(); - bool cacheIt = !testf(ClipOn|MonoDev|NoCache) && - (bs == NoBrush || bs == SolidPattern) && - bro.x() == 0 && bro.y() == 0 && rop == CopyROP; - - bool obtained = FALSE; - bool internclipok = hasClipping(); - if ( cacheIt ) { - if ( gc_brush ) { - if ( brushRef ) - release_gc( brushRef ); - else - free_gc( dpy, gc_brush ); - } - obtained = obtain_gc(&brushRef, &gc_brush, cbrush.color().pixel(scrn), dpy, - scrn, hd, clip_serial); - if ( !obtained && !brushRef ) - gc_brush = alloc_gc( dpy, scrn, hd, FALSE ); - } else { - if ( gc_brush ) { - if ( brushRef ) { - release_gc( brushRef ); - brushRef = 0; - gc_brush = alloc_gc( dpy, scrn, hd, testf(MonoDev) ); - } else { - internclipok = TRUE; - } - } else { - gc_brush = alloc_gc( dpy, scrn, hd, testf(MonoDev), testf(UsePrivateCx)); - } - } - - if ( !internclipok ) { - if ( pdev == paintEventDevice && paintEventClipRegion ) { - if ( brushRef &&((TQGCC*)brushRef)->clip_serial < gc_cache_clip_serial ) { - x11SetClipRegion( dpy, gc_brush, 0, rendhd, *paintEventClipRegion ); - ((TQGCC*)brushRef)->clip_serial = gc_cache_clip_serial; - } else if ( !brushRef ){ - x11SetClipRegion( dpy, gc_brush, 0, rendhd, *paintEventClipRegion ); - } - } else if (brushRef && ((TQGCC*)brushRef)->clip_serial ) { - x11ClearClipRegion(dpy, gc_brush, 0, rendhd); - ((TQGCC*)brushRef)->clip_serial = 0; - } - } - - if ( obtained ) - return; - - const uchar *pat = 0; // pattern - int d = 0; // defalt pattern size: d*d - int s = FillSolid; - if ( bs >= Dense1Pattern && bs <= DiagCrossPattern ) { - pat = pat_tbl[ bs-Dense1Pattern ]; - if ( bs <= Dense7Pattern ) - d = 8; - else if ( bs <= CrossPattern ) - d = 24; - else - d = 16; - } - - XSetLineAttributes( dpy, gc_brush, 0, LineSolid, CapButt, JoinMiter ); - XSetForeground( dpy, gc_brush, cbrush.color().pixel(scrn) ); - XSetBackground( dpy, gc_brush, bg_col.pixel(scrn) ); - - if ( bs == CustomPattern || pat ) { - TQPixmap *pm; - if ( pat ) { - TQString key; - key.sprintf( "$qt-brush$%d", bs ); - pm = TQPixmapCache::find( key ); - bool del = FALSE; - if ( !pm ) { // not already in pm dict - pm = new TQBitmap( d, d, pat, TRUE ); - TQ_CHECK_PTR( pm ); - del = !TQPixmapCache::insert( key, pm ); - } - if ( cbrush.data->pixmap ) - delete cbrush.data->pixmap; - cbrush.data->pixmap = new TQPixmap( *pm ); - if (del) delete pm; - } - pm = cbrush.data->pixmap; - pm->x11SetScreen( scrn ); - if ( pm->depth() == 1 ) { - XSetStipple( dpy, gc_brush, pm->handle() ); - s = bg_mode == TransparentMode ? FillStippled : FillOpaqueStippled; - } else { - XSetTile( dpy, gc_brush, pm->handle() ); - s = FillTiled; - } - } - XSetFillStyle( dpy, gc_brush, s ); -} - - -/*! - Begins painting the paint tqdevice \a pd and returns TRUE if - successful; otherwise returns FALSE. If \a unclipped is TRUE, the - painting will not be clipped at the paint tqdevice's boundaries, - (although this is not supported by all platforms). - - The errors that can occur are serious problems, such as these: - - \code - p->begin( 0 ); // impossible - paint tqdevice cannot be 0 - - TQPixmap pm( 0, 0 ); - p->begin( pm ); // impossible - pm.isNull(); - - p->begin( myWidget ); - p2->begin( myWidget ); // impossible - only one painter at a time - \endcode - - Note that most of the time, you can use one of the constructors - instead of begin(), and that end() is automatically done at - destruction. - - \warning A paint tqdevice can only be painted by one painter at a - time. - - \sa end(), flush() -*/ - -bool TQPainter::begin( const TQPaintDevice *pd, bool unclipped ) -{ - if ( isActive() ) { // already active painting -#if defined(TQT_CHECK_STATE) - qWarning( "TQPainter::begin: Painter is already active." - "\n\tYou must end() the painter before a second begin()" ); -#endif - return FALSE; - } - if ( pd == 0 ) { -#if defined(TQT_CHECK_NULL) - qWarning( "TQPainter::begin: Paint tqdevice cannot be null" ); -#endif - return FALSE; - } - - TQPixmap::x11SetDefaultScreen( pd->x11Screen() ); - - const TQWidget *copyFrom = 0; - pdev = redirect( (TQPaintDevice*)pd ); - if ( pdev ) { // redirected paint tqdevice? - if ( pd->devType() == TQInternal::Widget ) - copyFrom = (const TQWidget *)pd; // copy widget settings - } else { - pdev = (TQPaintDevice*)pd; - } - - if ( pdev->isExtDev() && pdev->paintingActive() ) { - // somebody else is already painting -#if defined(TQT_CHECK_STATE) - qWarning( "TQPainter::begin: Another TQPainter is already painting " - "this tqdevice;\n\tAn extended paint tqdevice can only be " - "painted by one TQPainter at a time." ); -#endif - return FALSE; - } - - bool reinit = flags != IsStartingUp; // 2nd or 3rd etc. time called - flags = IsActive | DirtyFont; // init flags - int dt = pdev->devType(); // get the tqdevice type - - if ( (pdev->devFlags & TQInternal::ExternalDevice) != 0 ) - setf(ExtDev); - else if ( dt == TQInternal::Pixmap ) // tqdevice is a pixmap - ((TQPixmap*)pdev)->detach(); // will modify it - - dpy = pdev->x11Display(); // get display variable - scrn = pdev->x11Screen(); // get screen variable - hd = pdev->handle(); // get handle to drawable - rendhd = pdev->rendhd; - - if ( testf(ExtDev) ) { // external tqdevice - if ( !pdev->cmd( TQPaintDevice::PdcBegin, this, 0 ) ) { - // could not begin painting - if ( reinit ) - clearf( IsActive | DirtyFont ); - else - flags = IsStartingUp; - pdev = 0; - return FALSE; - } - if ( tabstops ) // update tabstops for tqdevice - setTabStops( tabstops ); - if ( tabarray ) // update tabarray for tqdevice - setTabArray( tabarray ); - } - - if ( pdev->x11Depth() != pdev->x11AppDepth( scrn ) ) { // non-standard depth - setf(NoCache); - setf(UsePrivateCx); - } - - pdev->painters++; // also tell paint tqdevice - bro = curPt = TQPoint( 0, 0 ); - if ( reinit ) { - bg_mode = TransparentMode; // default background mode - rop = CopyROP; // default ROP - wxmat.reset(); // reset world xform matrix - xmat.reset(); - ixmat.reset(); - txop = txinv = 0; - if ( dt != TQInternal::Widget ) { - TQFont defaultFont; // default drawing tools - TQPen defaultPen; - TQBrush defaultBrush; - cfont = defaultFont; // set these drawing tools - cpen = defaultPen; - cbrush = defaultBrush; - bg_col = white; // default background color - } - } - wx = wy = vx = vy = 0; // default view origins - - if ( dt == TQInternal::Widget ) { // tqdevice is a widget - TQWidget *w = (TQWidget*)pdev; - cfont = w->font(); // use widget font - cpen = TQPen( w->foregroundColor() ); // use widget fg color - if ( reinit ) { - TQBrush defaultBrush; - cbrush = defaultBrush; - } - bg_col = w->backgroundColor(); // use widget bg color - ww = vw = w->width(); // default view size - wh = vh = w->height(); - if ( unclipped || w->testWFlags( WPaintUnclipped ) ) { // paint direct on tqdevice - setf( NoCache ); - setf(UsePrivateCx); - updatePen(); - updateBrush(); - XSetSubwindowMode( dpy, gc, IncludeInferiors ); - XSetSubwindowMode( dpy, gc_brush, IncludeInferiors ); -#ifndef TQT_NO_XFTFREETYPE - if (rendhd) - XftDrawSetSubwindowMode((XftDraw *) rendhd, IncludeInferiors); -#endif - } - } else if ( dt == TQInternal::Pixmap ) { // tqdevice is a pixmap - TQPixmap *pm = (TQPixmap*)pdev; - if ( pm->isNull() ) { -#if defined(TQT_CHECK_NULL) - qWarning( "TQPainter::begin: Cannot paint null pixmap" ); -#endif - end(); - return FALSE; - } - bool mono = pm->depth() == 1; // monochrome bitmap - if ( mono ) { - setf( MonoDev ); - bg_col = color0; - cpen.setColor( color1 ); - } - ww = vw = pm->width(); // default view size - wh = vh = pm->height(); - } else if ( testf(ExtDev) ) { // external tqdevice - ww = vw = pdev->metric( TQPaintDeviceMetrics::PdmWidth ); - wh = vh = pdev->metric( TQPaintDeviceMetrics::PdmHeight ); - } - if ( ww == 0 ) - ww = wh = vw = vh = 1024; - if ( copyFrom ) { // copy redirected widget - cfont = copyFrom->font(); - cpen = TQPen( copyFrom->foregroundColor() ); - bg_col = copyFrom->backgroundColor(); - } - if ( testf(ExtDev) ) { // external tqdevice - setBackgroundColor( bg_col ); // default background color - setBackgroundMode( TransparentMode ); // default background mode - setRasterOp( CopyROP ); // default raster operation - } - clip_serial = gc_cache_clip_serial++; - updateBrush(); - updatePen(); - return TRUE; -} - -/*! - Ends painting. Any resources used while painting are released. - - Note that while you mostly don't need to call end(), the - destructor will do it, there is at least one common case when it - is needed, namely double buffering. - - \code - TQPainter p( myPixmap, this ) - // ... - p.end(); // stops drawing on myPixmap - p.begin( this ); - p.drawPixmap( 0, 0, myPixmap ); - \endcode - - Since you can't draw a TQPixmap while it is being painted, it is - necessary to close the active painter. - - \sa begin(), isActive() -*/ - -bool TQPainter::end() // end painting -{ - if ( !isActive() ) { -#if defined(TQT_CHECK_STATE) - qWarning( "TQPainter::end: Missing begin() or begin() failed" ); -#endif - return FALSE; - } - killPStack(); - - //#### This should not be necessary: - if ( pdev->devType() == TQInternal::Widget && // ##### - ((TQWidget*)pdev)->testWFlags(WPaintUnclipped) ) { - if ( gc ) - XSetSubwindowMode( dpy, gc, ClipByChildren ); - if ( gc_brush ) - XSetSubwindowMode( dpy, gc_brush, ClipByChildren ); - } - - if ( gc_brush ) { // restore brush gc - if ( brushRef ) { - release_gc( brushRef ); - brushRef = 0; - } else { - free_gc( dpy, gc_brush, testf(UsePrivateCx) ); - } - gc_brush = 0; - - } - if ( gc ) { // restore pen gc - if ( penRef ) { - release_gc( penRef ); - penRef = 0; - } else { - free_gc( dpy, gc, testf(UsePrivateCx) ); - } - gc = 0; - } - - if ( testf(ExtDev) ) - pdev->cmd( TQPaintDevice::PdcEnd, this, 0 ); - -#ifndef TQT_NO_XFTFREETYPE - if (rendhd) { - // reset clipping/subwindow mode on our render picture - XftDrawSetClip((XftDraw *) rendhd, None); - XftDrawSetSubwindowMode((XftDraw *) rendhd, ClipByChildren); - } -#endif // TQT_NO_XFTFREETYPE - - if ( pfont ) { - delete pfont; - pfont = 0; - } - - flags = 0; - pdev->painters--; - pdev = 0; - dpy = 0; - return TRUE; -} - -/*! - Flushes any buffered drawing operations inside the region \a - region using clipping mode \a cm. - - The flush may update the whole tqdevice if the platform does not - support flushing to a specified region. - - \sa flush() CoordinateMode -*/ - -void TQPainter::flush(const TQRegion &, CoordinateMode) -{ - flush(); -} - - -/*! - \overload - - Flushes any buffered drawing operations. -*/ - -void TQPainter::flush() -{ - if ( isActive() && dpy ) - XFlush( dpy ); -} - - -/*! - Sets the background color of the painter to \a c. - - The background color is the color that is filled in when drawing - opaque text, stippled lines and bitmaps. The background color has - no effect in transparent background mode (which is the default). - - \sa backgroundColor() setBackgroundMode() BackgroundMode -*/ - -void TQPainter::setBackgroundColor( const TQColor &c ) -{ - if ( !isActive() ) { -#if defined(TQT_CHECK_STATE) - qWarning( "TQPainter::setBackgroundColor: Call begin() first" ); -#endif - return; - } - bg_col = c; - if ( testf(ExtDev) ) { - TQPDevCmdParam param[1]; - param[0].color = &bg_col; - if ( !pdev->cmd( TQPaintDevice::PdcSetBkColor, this, param ) || !hd ) - return; - } - if ( !penRef ) - updatePen(); // update pen setting - if ( !brushRef ) - updateBrush(); // update brush setting -} - -/*! - Sets the background mode of the painter to \a m, which must be - either \c TransparentMode (the default) or \c OpaqueMode. - - Transparent mode draws stippled lines and text without setting the - background pixels. Opaque mode fills these space with the current - background color. - - Note that in order to draw a bitmap or pixmap transparently, you - must use TQPixmap::setMask(). - - \sa backgroundMode(), setBackgroundColor() -*/ - -void TQPainter::setBackgroundMode( BGMode m ) -{ - if ( !isActive() ) { -#if defined(TQT_CHECK_STATE) - qWarning( "TQPainter::setBackgroundMode: Call begin() first" ); -#endif - return; - } - if ( m != TransparentMode && m != OpaqueMode ) { -#if defined(TQT_CHECK_RANGE) - qWarning( "TQPainter::setBackgroundMode: Invalid mode" ); -#endif - return; - } - bg_mode = m; - if ( testf(ExtDev) ) { - TQPDevCmdParam param[1]; - param[0].ival = m; - if ( !pdev->cmd( TQPaintDevice::PdcSetBkMode, this, param ) || !hd ) - return; - } - if ( !penRef ) - updatePen(); // update pen setting - if ( !brushRef ) - updateBrush(); // update brush setting -} - -static const short ropCodes[] = { // ROP translation table - GXcopy, // CopyROP - GXor, // OrROP - GXxor, // XorROP - GXandInverted, // NotAndROP EraseROP - GXcopyInverted, // NotCopyROP - GXorInverted, // NotOrROP - GXequiv, // NotXorROP - GXand, // AndROP - GXinvert, // NotROP - GXclear, // ClearROP - GXset, // SetROP - GXnoop, // NopROP - GXandReverse, // AndNotROP - GXorReverse, // OrNotROP - GXnand, // NandROP - GXnor // NorROP -}; - - -/*! - Sets the \link TQt::RasterOp raster operation \endlink to \a r. - The default is \c CopyROP. - - \sa rasterOp() TQt::RasterOp -*/ - -void TQPainter::setRasterOp( RasterOp r ) -{ - if ( !isActive() ) { -#if defined(TQT_CHECK_STATE) - qWarning( "TQPainter::setRasterOp: Call begin() first" ); -#endif - return; - } - if ( (uint)r > LastROP ) { -#if defined(TQT_CHECK_RANGE) - qWarning( "TQPainter::setRasterOp: Invalid ROP code" ); -#endif - return; - } - rop = r; - if ( testf(ExtDev) ) { - TQPDevCmdParam param[1]; - param[0].ival = r; - if ( !pdev->cmd( TQPaintDevice::PdcSetROP, this, param ) || !hd ) - return; - } - if ( penRef ) - updatePen(); // get non-cached pen GC - if ( brushRef ) - updateBrush(); // get non-cached brush GC - XSetFunction( dpy, gc, ropCodes[rop] ); - XSetFunction( dpy, gc_brush, ropCodes[rop] ); -} - -// ### matthias - true? - -/*! - Sets the brush origin to \a (x, y). - - The brush origin specifies the (0, 0) coordinate of the painter's - brush. This setting only applies to pattern brushes and pixmap - brushes. - - \sa brushOrigin() -*/ - -void TQPainter::setBrushOrigin( int x, int y ) -{ - if ( !isActive() ) { -#if defined(TQT_CHECK_STATE) - qWarning( "TQPainter::setBrushOrigin: Call begin() first" ); -#endif - return; - } - bro = TQPoint(x, y); - if ( testf(ExtDev) ) { - TQPDevCmdParam param[1]; - param[0].point = &bro; - if ( !pdev->cmd( TQPaintDevice::PdcSetBrushOrigin, this, param ) || - !hd ) - return; - } - if ( brushRef ) - updateBrush(); // get non-cached brush GC - XSetTSOrigin( dpy, gc_brush, x, y ); -} - - -/*! - Enables clipping if \a enable is TRUE, or disables clipping if \a - enable is FALSE. - - \sa hasClipping(), setClipRect(), setClipRegion() -*/ - -void TQPainter::setClipping( bool enable ) -{ - if ( !isActive() ) { -#if defined(TQT_CHECK_STATE) - qWarning( "TQPainter::setClipping: Will be reset by begin()" ); -#endif - return; - } - - if ( enable == testf(ClipOn) ) - return; - - setf( ClipOn, enable ); - if ( testf(ExtDev) ) { - if ( block_ext ) - return; - TQPDevCmdParam param[1]; - param[0].ival = enable; - if ( !pdev->cmd( TQPaintDevice::PdcSetClip, this, param ) || !hd ) - return; - } - if ( enable ) { - TQRegion rgn = crgn; - if ( pdev == paintEventDevice && paintEventClipRegion ) - rgn = rgn.intersect( *paintEventClipRegion ); - if ( penRef ) - updatePen(); - if ( brushRef ) - updateBrush(); - x11SetClipRegion( dpy, gc, gc_brush, rendhd, rgn ); - } else { - if ( pdev == paintEventDevice && paintEventClipRegion ) { - x11SetClipRegion( dpy, gc, gc_brush , rendhd, *paintEventClipRegion ); - } else { - x11ClearClipRegion(dpy, gc, gc_brush, rendhd); - } - } -} - - -/*! - \overload - - Sets the clip region to the rectangle \a r and enables clipping. - The clip mode is set to \a m. - - \sa CoordinateMode -*/ - -void TQPainter::setClipRect( const TQRect &r, CoordinateMode m ) -{ - setClipRegion( TQRegion( r ), m ); -} - -/*! - Sets the clip region to \a rgn and enables clipping. The clip mode - is set to \a m. - - Note that the clip region is given in physical tqdevice coordinates - and \e not subject to any \link coordsys.html coordinate - transformation.\endlink - - \sa setClipRect(), clipRegion(), setClipping() CoordinateMode -*/ - -void TQPainter::setClipRegion( const TQRegion &rgn, CoordinateMode m ) -{ -#if defined(TQT_CHECK_STATE) - if ( !isActive() ) - qWarning( "TQPainter::setClipRegion: Will be reset by begin()" ); -#endif - if ( m == CoordDevice ) - crgn = rgn; - else - crgn = xmat * rgn; - - if ( testf(ExtDev) ) { - if ( block_ext ) - return; - TQPDevCmdParam param[2]; - param[0].rgn = &rgn; - param[1].ival = m; - if ( !pdev->cmd( TQPaintDevice::PdcSetClipRegion, this, param ) ) - return; // tqdevice cannot clip - } - clearf( ClipOn ); // be sure to update clip rgn - setClipping( TRUE ); -} - - -/*! - \internal - - Internal function for drawing a polygon. -*/ - -void TQPainter::drawPolyInternal( const TQPointArray &a, bool close ) -{ - if ( a.size() < 2 ) - return; - - int x1, y1, x2, y2; // connect last to first point - a.point( a.size()-1, &x1, &y1 ); - a.point( 0, &x2, &y2 ); - bool do_close = close && !(x1 == x2 && y1 == y2); - - if ( close && cbrush.style() != NoBrush ) { // draw filled polygon - XFillPolygon( dpy, hd, gc_brush, (XPoint*)a.shortPoints(), a.size(), - Nonconvex, CoordModeOrigin ); - if ( cpen.style() == NoPen ) { // draw fake outline - XDrawLines( dpy, hd, gc_brush, (XPoint*)a.shortPoints(), a.size(), - CoordModeOrigin ); - if ( do_close ) - XDrawLine( dpy, hd, gc_brush, x1, y1, x2, y2 ); - } - } - if ( cpen.style() != NoPen ) { // draw outline - XDrawLines( dpy, hd, gc, (XPoint*)a.shortPoints(), a.size(), - CoordModeOrigin); - if ( do_close ) - XDrawLine( dpy, hd, gc, x1, y1, x2, y2 ); - } -} - - -/*! - Draws/plots a single point at \a (x, y) using the current pen. - - \sa TQPen -*/ - -void TQPainter::drawPoint( int x, int y ) -{ - if ( !isActive() ) - return; - if ( testf(ExtDev|VxF|WxF) ) { - if ( testf(ExtDev) ) { - TQPDevCmdParam param[1]; - TQPoint p( x, y ); - param[0].point = &p; - if ( !pdev->cmd( TQPaintDevice::PdcDrawPoint, this, param ) || - !hd ) - return; - } - map( x, y, &x, &y ); - } - if ( cpen.style() != NoPen ) - XDrawPoint( dpy, hd, gc, x, y ); -} - - -/*! - Draws/plots an array of points, \a a, using the current pen. - - If \a index is non-zero (the default is zero) only points from \a - index are drawn. If \a npoints is negative (the default) the rest - of the points from \a index are drawn. If \a npoints is zero or - greater, \a npoints points are drawn. - - \warning On X11, coordinates that do not fit into 16-bit signed - values are truncated. This limitation is expected to go away in - TQt 4. -*/ - -void TQPainter::drawPoints( const TQPointArray& a, int index, int npoints ) -{ - if ( npoints < 0 ) - npoints = a.size() - index; - if ( index + npoints > (int)a.size() ) - npoints = a.size() - index; - if ( !isActive() || npoints < 1 || index < 0 ) - return; - TQPointArray pa = a; - if ( testf(ExtDev|VxF|WxF) ) { - if ( testf(ExtDev) ) { - TQPDevCmdParam param[1]; - for (int i=0; i<npoints; i++) { - TQPoint p( pa[index+i].x(), pa[index+i].y() ); - param[0].point = &p; - if ( !pdev->cmd( TQPaintDevice::PdcDrawPoint, this, param )) - return; - } - if ( !hd ) return; - } - if ( txop != TxNone ) { - pa = xForm( a, index, npoints ); - if ( pa.size() != a.size() ) { - index = 0; - npoints = pa.size(); - } - } - } - if ( cpen.style() != NoPen ) - XDrawPoints( dpy, hd, gc, (XPoint*)(pa.shortPoints( index, npoints )), - npoints, CoordModeOrigin ); -} - - -/*! \obsolete - Sets the current pen position to \a (x, y) - - \sa lineTo(), pos() -*/ - -void TQPainter::moveTo( int x, int y ) -{ - if ( !isActive() ) - return; - if ( testf(ExtDev|VxF|WxF) ) { - if ( testf(ExtDev) ) { - TQPDevCmdParam param[1]; - TQPoint p( x, y ); - param[0].point = &p; - if ( !pdev->cmd( TQPaintDevice::PdcMoveTo, this, param ) || !hd ) - return; - } - } - curPt = TQPoint( x, y ); -} - -/*! \obsolete - Use drawLine() instead. - - Draws a line from the current pen position to \a (x, y) and sets - \a (x, y) to be the new current pen position. - - \sa TQPen moveTo(), drawLine(), pos() -*/ - -void TQPainter::lineTo( int x, int y ) -{ - if ( !isActive() ) - return; - int cx = curPt.x(), cy = curPt.y(); - curPt = TQPoint( x, y ); - if ( testf(ExtDev|VxF|WxF) ) { - if ( testf(ExtDev) ) { - TQPDevCmdParam param[1]; - TQPoint p( x, y ); - param[0].point = &p; - if ( !pdev->cmd( TQPaintDevice::PdcLineTo, this, param ) || !hd ) - return; - } - map( x, y, &x, &y ); - map( cx, cy, &cx, &cy ); - } - if ( cpen.style() != NoPen ) - XDrawLine( dpy, hd, gc, cx, cy, x, y ); -} - -/*! - Draws a line from (\a x1, \a y1) to (\a x2, \a y2) and sets the - current pen position to (\a x2, \a y2). - - \sa pen() -*/ - -void TQPainter::drawLine( int x1, int y1, int x2, int y2 ) -{ - if ( !isActive() ) - return; - curPt = TQPoint( x2, y2 ); - if ( testf(ExtDev|VxF|WxF) ) { - if ( testf(ExtDev) ) { - TQPDevCmdParam param[2]; - TQPoint p1(x1, y1), p2(x2, y2); - param[0].point = &p1; - param[1].point = &p2; - if ( !pdev->cmd( TQPaintDevice::PdcDrawLine, this, param ) || !hd ) - return; - } - map( x1, y1, &x1, &y1 ); - map( x2, y2, &x2, &y2 ); - } - if ( cpen.style() != NoPen ) - XDrawLine( dpy, hd, gc, x1, y1, x2, y2 ); -} - - - -/*! - Draws a rectangle with upper left corner at \a (x, y) and with - width \a w and height \a h. - - \sa TQPen, drawRoundRect() -*/ - -void TQPainter::drawRect( int x, int y, int w, int h ) -{ - if ( !isActive() ) - return; - if ( testf(ExtDev|VxF|WxF) ) { - if ( testf(ExtDev) ) { - TQPDevCmdParam param[1]; - TQRect r( x, y, w, h ); - param[0].rect = &r; - if ( !pdev->cmd( TQPaintDevice::PdcDrawRect, this, param ) || !hd ) - return; - } - if ( txop == TxRotShear ) { // rotate/shear polygon - TQPointArray pa = xmat.mapToPolygon( TQRect(x, y, w, h) ); - pa.resize( 5 ); - pa.setPoint( 4, pa.point( 0 ) ); - drawPolyInternal( pa ); - return; - } - map( x, y, w, h, &x, &y, &w, &h ); - } - if ( w <= 0 || h <= 0 ) { - if ( w == 0 || h == 0 ) - return; - fix_neg_rect( &x, &y, &w, &h ); - } - if ( cbrush.style() != NoBrush ) { - if ( cpen.style() == NoPen ) { - XFillRectangle( dpy, hd, gc_brush, x, y, w, h ); - return; - } - int lw = cpen.width(); - int lw2 = (lw+1)/2; - if ( w > lw && h > lw ) - XFillRectangle( dpy, hd, gc_brush, x+lw2, y+lw2, w-lw-1, h-lw-1 ); - } - if ( cpen.style() != NoPen ) - XDrawRectangle( dpy, hd, gc, x, y, w-1, h-1 ); -} - -/*! - \overload - - Draws a Windows focus rectangle with upper left corner at (\a x, - \a y) and with width \a w and height \a h. - - This function draws a stippled XOR rectangle that is used to - indicate keyboard focus (when TQApplication::style() is \c - WindowStyle). - - \warning This function draws nothing if the coordinate system has - been \link rotate() rotated\endlink or \link shear() - sheared\endlink. - - \sa drawRect(), TQApplication::style() -*/ - -void TQPainter::drawWinFocusRect( int x, int y, int w, int h ) -{ - drawWinFocusRect( x, y, w, h, TRUE, color0 ); -} - -/*! - Draws a Windows focus rectangle with upper left corner at (\a x, - \a y) and with width \a w and height \a h using a pen color that - contrasts with \a bgColor. - - This function draws a stippled rectangle (XOR is not used) that is - used to indicate keyboard focus (when the TQApplication::style() is - \c WindowStyle). - - The pen color used to draw the rectangle is either white or black - depending on the color of \a bgColor (see TQColor::gray()). - - \warning This function draws nothing if the coordinate system has - been \link rotate() rotated\endlink or \link shear() - sheared\endlink. - - \sa drawRect(), TQApplication::style() -*/ - -void TQPainter::drawWinFocusRect( int x, int y, int w, int h, - const TQColor &bgColor ) -{ - drawWinFocusRect( x, y, w, h, FALSE, bgColor ); -} - - -/*! - \internal -*/ - -void TQPainter::drawWinFocusRect( int x, int y, int w, int h, - bool xorPaint, const TQColor &bgColor ) -{ - if ( !isActive() || txop == TxRotShear ) - return; - static char winfocus_line[] = { 1, 1 }; - - TQPen old_pen = cpen; - RasterOp old_rop = (RasterOp)rop; - - if ( xorPaint ) { - if ( TQColor::numBitPlanes() <= 8 ) - setPen( color1 ); - else - setPen( white ); - setRasterOp( XorROP ); - } else { - if ( tqGray( bgColor.rgb() ) < 128 ) - setPen( white ); - else - setPen( black ); - } - - if ( testf(ExtDev|VxF|WxF) ) { - if ( testf(ExtDev) ) { - TQPDevCmdParam param[1]; - TQRect r( x, y, w, h ); - param[0].rect = &r; - if ( !pdev->cmd( TQPaintDevice::PdcDrawRect, this, param ) || !hd) { - setRasterOp( old_rop ); - setPen( old_pen ); - return; - } - } - map( x, y, w, h, &x, &y, &w, &h ); - } - if ( w <= 0 || h <= 0 ) { - if ( w == 0 || h == 0 ) - return; - fix_neg_rect( &x, &y, &w, &h ); - } - XSetDashes( dpy, gc, 0, winfocus_line, 2 ); - XSetLineAttributes( dpy, gc, 1, LineOnOffDash, CapButt, JoinMiter ); - - XDrawRectangle( dpy, hd, gc, x, y, w-1, h-1 ); - XSetLineAttributes( dpy, gc, 0, LineSolid, CapButt, JoinMiter ); - setRasterOp( old_rop ); - setPen( old_pen ); -} - - -/*! - Draws a rectangle with rounded corners at \a (x, y), with width \a - w and height \a h. - - The \a xRnd and \a yRnd arguments specify how rounded the corners - should be. 0 is angled corners, 99 is maximum roundedness. - - The width and height include all of the drawn lines. - - \sa drawRect(), TQPen -*/ - -void TQPainter::drawRoundRect( int x, int y, int w, int h, int xRnd, int yRnd ) -{ - if ( !isActive() ) - return; - if ( xRnd <= 0 || yRnd <= 0 ) { - drawRect( x, y, w, h ); // draw normal rectangle - return; - } - if ( xRnd >= 100 ) // fix ranges - xRnd = 99; - if ( yRnd >= 100 ) - yRnd = 99; - if ( testf(ExtDev|VxF|WxF) ) { - if ( testf(ExtDev) ) { - TQPDevCmdParam param[3]; - TQRect r( x, y, w, h ); - param[0].rect = &r; - param[1].ival = xRnd; - param[2].ival = yRnd; - if ( !pdev->cmd( TQPaintDevice::PdcDrawRoundRect, this, param ) || - !hd ) - return; - } - if ( txop == TxRotShear ) { // rotate/shear polygon - if ( w <= 0 || h <= 0 ) - fix_neg_rect( &x, &y, &w, &h ); - w--; - h--; - int rxx = w*xRnd/200; - int ryy = h*yRnd/200; - // were there overflows? - if ( rxx < 0 ) - rxx = w/200*xRnd; - if ( ryy < 0 ) - ryy = h/200*yRnd; - int rxx2 = 2*rxx; - int ryy2 = 2*ryy; - TQPointArray a[4]; - a[0].makeArc( x, y, rxx2, ryy2, 1*16*90, 16*90, xmat ); - a[1].makeArc( x, y+h-ryy2, rxx2, ryy2, 2*16*90, 16*90, xmat ); - a[2].makeArc( x+w-rxx2, y+h-ryy2, rxx2, ryy2, 3*16*90, 16*90, xmat ); - a[3].makeArc( x+w-rxx2, y, rxx2, ryy2, 0*16*90, 16*90, xmat ); - // ### is there a better way to join TQPointArrays? - TQPointArray aa; - aa.resize( a[0].size() + a[1].size() + a[2].size() + a[3].size() ); - uint j = 0; - for ( int k=0; k<4; k++ ) { - for ( uint i=0; i<a[k].size(); i++ ) { - aa.setPoint( j, a[k].point(i) ); - j++; - } - } - drawPolyInternal( aa ); - return; - } - map( x, y, w, h, &x, &y, &w, &h ); - } - w--; - h--; - if ( w <= 0 || h <= 0 ) { - if ( w == 0 || h == 0 ) - return; - fix_neg_rect( &x, &y, &w, &h ); - } - int rx = (w*xRnd)/200; - int ry = (h*yRnd)/200; - int rx2 = 2*rx; - int ry2 = 2*ry; - if ( cbrush.style() != NoBrush ) { // draw filled round rect - int dp, ds; - if ( cpen.style() == NoPen ) { - dp = 0; - ds = 1; - } - else { - dp = 1; - ds = 0; - } -#define SET_ARC(px, py, w, h, a1, a2) \ - a->x=px; a->y=py; a->width=w; a->height=h; a->angle1=a1; a->angle2=a2; a++ - XArc arcs[4]; - XArc *a = arcs; - SET_ARC( x+w-rx2, y, rx2, ry2, 0, 90*64 ); - SET_ARC( x, y, rx2, ry2, 90*64, 90*64 ); - SET_ARC( x, y+h-ry2, rx2, ry2, 180*64, 90*64 ); - SET_ARC( x+w-rx2, y+h-ry2, rx2, ry2, 270*64, 90*64 ); - XFillArcs( dpy, hd, gc_brush, arcs, 4 ); -#undef SET_ARC -#define SET_RCT(px, py, w, h) \ - r->x=px; r->y=py; r->width=w; r->height=h; r++ - XRectangle rects[3]; - XRectangle *r = rects; - SET_RCT( x+rx, y+dp, w-rx2, ry ); - SET_RCT( x+dp, y+ry, w+ds, h-ry2 ); - SET_RCT( x+rx, y+h-ry, w-rx2, ry+ds ); - XFillRectangles( dpy, hd, gc_brush, rects, 3 ); -#undef SET_RCT - } - if ( cpen.style() != NoPen ) { // draw outline -#define SET_ARC(px, py, w, h, a1, a2) \ - a->x=px; a->y=py; a->width=w; a->height=h; a->angle1=a1; a->angle2=a2; a++ - XArc arcs[4]; - XArc *a = arcs; - SET_ARC( x+w-rx2, y, rx2, ry2, 0, 90*64 ); - SET_ARC( x, y, rx2, ry2, 90*64, 90*64 ); - SET_ARC( x, y+h-ry2, rx2, ry2, 180*64, 90*64 ); - SET_ARC( x+w-rx2, y+h-ry2, rx2, ry2, 270*64, 90*64 ); - XDrawArcs( dpy, hd, gc, arcs, 4 ); -#undef SET_ARC -#define SET_SEG(xp1, yp1, xp2, yp2) \ - s->x1=xp1; s->y1=yp1; s->x2=xp2; s->y2=yp2; s++ - XSegment segs[4]; - XSegment *s = segs; - SET_SEG( x+rx, y, x+w-rx, y ); - SET_SEG( x+rx, y+h, x+w-rx, y+h ); - SET_SEG( x, y+ry, x, y+h-ry ); - SET_SEG( x+w, y+ry, x+w, y+h-ry ); - XDrawSegments( dpy, hd, gc, segs, 4 ); -#undef SET_SET - } -} - -/*! - Draws an ellipse with center at \a (x + w/2, y + h/2) and size \a - (w, h). -*/ - -void TQPainter::drawEllipse( int x, int y, int w, int h ) -{ - if ( !isActive() ) - return; - if ( testf(ExtDev|VxF|WxF) ) { - if ( testf(ExtDev) ) { - TQPDevCmdParam param[1]; - TQRect r( x, y, w, h ); - param[0].rect = &r; - if ( !pdev->cmd( TQPaintDevice::PdcDrawEllipse, this, param ) || - !hd ) - return; - } - if ( txop == TxRotShear ) { // rotate/shear polygon - TQPointArray a; - a.makeArc( x, y, w, h, 0, 360*16, xmat ); - drawPolyInternal( a ); - return; - } - map( x, y, w, h, &x, &y, &w, &h ); - } - if ( w <= 0 || h <= 0 ) { - if ( w == 0 || h == 0 ) - return; - fix_neg_rect( &x, &y, &w, &h ); - } - if ( w == 1 && h == 1 ) { - XDrawPoint( dpy, hd, (cpen.style() == NoPen)?gc_brush:gc, x, y ); - return; - } - w--; - h--; - if ( cbrush.style() != NoBrush ) { // draw filled ellipse - XFillArc( dpy, hd, gc_brush, x, y, w, h, 0, 360*64 ); - if ( cpen.style() == NoPen ) { - XDrawArc( dpy, hd, gc_brush, x, y, w, h, 0, 360*64 ); - return; - } - } - if ( cpen.style() != NoPen ) // draw outline - XDrawArc( dpy, hd, gc, x, y, w, h, 0, 360*64 ); -} - - -/*! - Draws an arc defined by the rectangle \a (x, y, w, h), the start - angle \a a and the arc length \a alen. - - The angles \a a and \a alen are 1/16th of a degree, i.e. a full - circle equals 5760 (16*360). Positive values of \a a and \a alen - mean counter-clockwise while negative values mean the clockwise - direction. Zero degrees is at the 3 o'clock position. - - Example: - \code - TQPainter p( myWidget ); - p.drawArc( 10,10, 70,100, 100*16, 160*16 ); // draws a "(" arc - \endcode - - \sa drawPie(), drawChord() -*/ - -void TQPainter::drawArc( int x, int y, int w, int h, int a, int alen ) -{ - if ( !isActive() ) - return; - if ( testf(ExtDev|VxF|WxF) ) { - if ( testf(ExtDev) ) { - TQPDevCmdParam param[3]; - TQRect r( x, y, w, h ); - param[0].rect = &r; - param[1].ival = a; - param[2].ival = alen; - if ( !pdev->cmd( TQPaintDevice::PdcDrawArc, this, param ) || - !hd ) - return; - } - if ( txop == TxRotShear ) { // rotate/shear - TQPointArray pa; - pa.makeArc( x, y, w, h, a, alen, xmat ); // arc polyline - drawPolyInternal( pa, FALSE ); - return; - } - map( x, y, w, h, &x, &y, &w, &h ); - } - w--; - h--; - if ( w <= 0 || h <= 0 ) { - if ( w == 0 || h == 0 ) - return; - fix_neg_rect( &x, &y, &w, &h ); - } - if ( cpen.style() != NoPen ) - XDrawArc( dpy, hd, gc, x, y, w, h, a*4, alen*4 ); -} - - -/*! - Draws a pie defined by the rectangle \a (x, y, w, h), the start - angle \a a and the arc length \a alen. - - The pie is filled with the current brush(). - - The angles \a a and \a alen are 1/16th of a degree, i.e. a full - circle equals 5760 (16*360). Positive values of \a a and \a alen - mean counter-clockwise while negative values mean the clockwise - direction. Zero degrees is at the 3 o'clock position. - - \sa drawArc(), drawChord() -*/ - -void TQPainter::drawPie( int x, int y, int w, int h, int a, int alen ) -{ - // Make sure "a" is 0..360*16, as otherwise a*4 may overflow 16 bits. - if ( a > (360*16) ) { - a = a % (360*16); - } else if ( a < 0 ) { - a = a % (360*16); - if ( a < 0 ) a += (360*16); - } - - if ( !isActive() ) - return; - if ( testf(ExtDev|VxF|WxF) ) { - if ( testf(ExtDev) ) { - TQPDevCmdParam param[3]; - TQRect r( x, y, w, h ); - param[0].rect = &r; - param[1].ival = a; - param[2].ival = alen; - if ( !pdev->cmd( TQPaintDevice::PdcDrawPie, this, param ) || !hd ) - return; - } - if ( txop == TxRotShear ) { // rotate/shear - TQPointArray pa; - pa.makeArc( x, y, w, h, a, alen, xmat ); // arc polyline - int n = pa.size(); - int cx, cy; - xmat.map(x+w/2, y+h/2, &cx, &cy); - pa.resize( n+2 ); - pa.setPoint( n, cx, cy ); // add legs - pa.setPoint( n+1, pa.at(0) ); - drawPolyInternal( pa ); - return; - } - map( x, y, w, h, &x, &y, &w, &h ); - } - XSetArcMode( dpy, gc_brush, ArcPieSlice ); - w--; - h--; - if ( w <= 0 || h <= 0 ) { - if ( w == 0 || h == 0 ) - return; - fix_neg_rect( &x, &y, &w, &h ); - } - - GC g = gc; - bool nopen = cpen.style() == NoPen; - - if ( cbrush.style() != NoBrush ) { // draw filled pie - XFillArc( dpy, hd, gc_brush, x, y, w, h, a*4, alen*4 ); - if ( nopen ) { - g = gc_brush; - nopen = FALSE; - } - } - if ( !nopen ) { // draw pie outline - double w2 = 0.5*w; // with, height in ellipsis - double h2 = 0.5*h; - double xc = (double)x+w2; - double yc = (double)y+h2; - double ra1 = TQ_PI/2880.0*a; // convert a, alen to radians - double ra2 = ra1 + TQ_PI/2880.0*alen; - int xic = tqRound(xc); - int yic = tqRound(yc); - XDrawLine( dpy, hd, g, xic, yic, - tqRound(xc + qcos(ra1)*w2), tqRound(yc - qsin(ra1)*h2)); - XDrawLine( dpy, hd, g, xic, yic, - tqRound(xc + qcos(ra2)*w2), tqRound(yc - qsin(ra2)*h2)); - XDrawArc( dpy, hd, g, x, y, w, h, a*4, alen*4 ); - } -} - - -/*! - Draws a chord defined by the rectangle \a (x, y, w, h), the start - angle \a a and the arc length \a alen. - - The chord is filled with the current brush(). - - The angles \a a and \a alen are 1/16th of a degree, i.e. a full - circle equals 5760 (16*360). Positive values of \a a and \a alen - mean counter-clockwise while negative values mean the clockwise - direction. Zero degrees is at the 3 o'clock position. - - \sa drawArc(), drawPie() -*/ - -void TQPainter::drawChord( int x, int y, int w, int h, int a, int alen ) -{ - if ( !isActive() ) - return; - if ( testf(ExtDev|VxF|WxF) ) { - if ( testf(ExtDev) ) { - TQPDevCmdParam param[3]; - TQRect r( x, y, w, h ); - param[0].rect = &r; - param[1].ival = a; - param[2].ival = alen; - if ( !pdev->cmd(TQPaintDevice::PdcDrawChord, this, param) || !hd ) - return; - } - if ( txop == TxRotShear ) { // rotate/shear - TQPointArray pa; - pa.makeArc( x, y, w-1, h-1, a, alen, xmat ); // arc polygon - int n = pa.size(); - pa.resize( n+1 ); - pa.setPoint( n, pa.at(0) ); // connect endpoints - drawPolyInternal( pa ); - return; - } - map( x, y, w, h, &x, &y, &w, &h ); - } - XSetArcMode( dpy, gc_brush, ArcChord ); - w--; - h--; - if ( w <= 0 || h <= 0 ) { - if ( w == 0 || h == 0 ) - return; - fix_neg_rect( &x, &y, &w, &h ); - } - - GC g = gc; - bool nopen = cpen.style() == NoPen; - - if ( cbrush.style() != NoBrush ) { // draw filled chord - XFillArc( dpy, hd, gc_brush, x, y, w, h, a*4, alen*4 ); - if ( nopen ) { - g = gc_brush; - nopen = FALSE; - } - } - if ( !nopen ) { // draw chord outline - double w2 = 0.5*w; // with, height in ellipsis - double h2 = 0.5*h; - double xc = (double)x+w2; - double yc = (double)y+h2; - double ra1 = TQ_PI/2880.0*a; // convert a, alen to radians - double ra2 = ra1 + TQ_PI/2880.0*alen; - XDrawLine( dpy, hd, g, - tqRound(xc + qcos(ra1)*w2), tqRound(yc - qsin(ra1)*h2), - tqRound(xc + qcos(ra2)*w2), tqRound(yc - qsin(ra2)*h2)); - XDrawArc( dpy, hd, g, x, y, w, h, a*4, alen*4 ); - } - XSetArcMode( dpy, gc_brush, ArcPieSlice ); -} - - -/*! - Draws \a nlines separate lines from points defined in \a a, - starting at \a a[index] (\a index defaults to 0). If \a nlines is - -1 (the default) all points until the end of the array are used - (i.e. (a.size()-index)/2 lines are drawn). - - Draws the 1st line from \a a[index] to \a a[index+1]. Draws the - 2nd line from \a a[index+2] to \a a[index+3] etc. - - \warning On X11, coordinates that do not fit into 16-bit signed - values are truncated. This limitation is expected to go away in - TQt 4. - - \sa drawPolyline(), drawPolygon(), TQPen -*/ - -void TQPainter::drawLineSegments( const TQPointArray &a, int index, int nlines ) -{ - if ( nlines < 0 ) - nlines = a.size()/2 - index/2; - if ( index + nlines*2 > (int)a.size() ) - nlines = (a.size() - index)/2; - if ( !isActive() || nlines < 1 || index < 0 ) - return; - TQPointArray pa = a; - if ( testf(ExtDev|VxF|WxF) ) { - if ( testf(ExtDev) ) { - if ( 2*nlines != (int)pa.size() ) { - pa = TQPointArray( nlines*2 ); - for ( int i=0; i<nlines*2; i++ ) - pa.setPoint( i, a.point(index+i) ); - index = 0; - } - TQPDevCmdParam param[1]; - param[0].ptarr = (TQPointArray*)&pa; - if ( !pdev->cmd(TQPaintDevice::PdcDrawLineSegments, this, param) || - !hd ) - return; - } - if ( txop != TxNone ) { - pa = xForm( a, index, nlines*2 ); - if ( pa.size() != a.size() ) { - index = 0; - nlines = pa.size()/2; - } - } - } - if ( cpen.style() != NoPen ) - XDrawSegments( dpy, hd, gc, - (XSegment*)(pa.shortPoints( index, nlines*2 )), nlines ); -} - - -/*! - Draws the polyline defined by the \a npoints points in \a a - starting at \a a[index]. (\a index defaults to 0.) - - If \a npoints is -1 (the default) all points until the end of the - array are used (i.e. a.size()-index-1 line segments are drawn). - - \warning On X11, coordinates that do not fit into 16-bit signed - values are truncated. This limitation is expected to go away in - TQt 4. - - \sa drawLineSegments(), drawPolygon(), TQPen -*/ - -void TQPainter::drawPolyline( const TQPointArray &a, int index, int npoints ) -{ - if ( npoints < 0 ) - npoints = a.size() - index; - if ( index + npoints > (int)a.size() ) - npoints = a.size() - index; - if ( !isActive() || npoints < 2 || index < 0 ) - return; - TQPointArray pa = a; - if ( testf(ExtDev|VxF|WxF) ) { - if ( testf(ExtDev) ) { - if ( npoints != (int)pa.size() ) { - pa = TQPointArray( npoints ); - for ( int i=0; i<npoints; i++ ) - pa.setPoint( i, a.point(index+i) ); - index = 0; - } - TQPDevCmdParam param[1]; - param[0].ptarr = (TQPointArray*)&pa; - if ( !pdev->cmd(TQPaintDevice::PdcDrawPolyline, this, param) || !hd ) - return; - } - if ( txop != TxNone ) { - pa = xForm( pa, index, npoints ); - if ( pa.size() != a.size() ) { - index = 0; - npoints = pa.size(); - } - } - } - if ( cpen.style() != NoPen ) { - while(npoints>65535) { - XDrawLines( dpy, hd, gc, (XPoint*)(pa.shortPoints( index, 65535 )), - 65535, CoordModeOrigin ); - npoints-=65535; - index+=65535; - } - XDrawLines( dpy, hd, gc, (XPoint*)(pa.shortPoints( index, npoints )), - npoints, CoordModeOrigin ); - } -} - -static int global_polygon_tqshape = Complex; - -/*! - Draws the polygon defined by the \a npoints points in \a a - starting at \a a[index]. (\a index defaults to 0.) - - If \a npoints is -1 (the default) all points until the end of the - array are used (i.e. a.size()-index line segments define the - polygon). - - The first point is always connected to the last point. - - The polygon is filled with the current brush(). If \a winding is - TRUE, the polygon is filled using the winding fill algorithm. If - \a winding is FALSE, the polygon is filled using the even-odd - (alternative) fill algorithm. - - \warning On X11, coordinates that do not fit into 16-bit signed - values are truncated. This limitation is expected to go away in - TQt 4. - - \sa drawLineSegments(), drawPolyline(), TQPen -*/ - -void TQPainter::drawPolygon( const TQPointArray &a, bool winding, - int index, int npoints ) -{ - if ( npoints < 0 ) - npoints = a.size() - index; - if ( index + npoints > (int)a.size() ) - npoints = a.size() - index; - if ( !isActive() || npoints < 2 || index < 0 ) - return; - TQPointArray pa = a; - if ( testf(ExtDev|VxF|WxF) ) { - if ( testf(ExtDev) ) { - if ( npoints != (int)a.size() ) { - pa = TQPointArray( npoints ); - for ( int i=0; i<npoints; i++ ) - pa.setPoint( i, a.point(index+i) ); - index = 0; - } - TQPDevCmdParam param[2]; - param[0].ptarr = (TQPointArray*)&pa; - param[1].ival = winding; - if ( !pdev->cmd(TQPaintDevice::PdcDrawPolygon, this, param) || !hd ) - return; - } - if ( txop != TxNone ) { - pa = xForm( a, index, npoints ); - if ( pa.size() != a.size() ) { - index = 0; - npoints = pa.size(); - } - } - } - if ( winding ) // set to winding fill rule - XSetFillRule( dpy, gc_brush, WindingRule ); - - if ( pa[index] != pa[index+npoints-1] ){ // close open pointarray - pa.detach(); - pa.resize( index+npoints+1 ); - pa.setPoint( index+npoints, pa[index] ); - npoints++; - } - - if ( cbrush.style() != NoBrush ) { // draw filled polygon - XFillPolygon( dpy, hd, gc_brush, - (XPoint*)(pa.shortPoints( index, npoints )), - npoints, global_polygon_tqshape, CoordModeOrigin ); - } - if ( cpen.style() != NoPen ) { // draw outline - XDrawLines( dpy, hd, gc, (XPoint*)(pa.shortPoints( index, npoints )), - npoints, CoordModeOrigin ); - } - if ( winding ) // set to normal fill rule - XSetFillRule( dpy, gc_brush, EvenOddRule ); -} - -/*! - Draws the convex polygon defined by the \a npoints points in \a pa - starting at \a pa[index] (\a index defaults to 0). - - If the supplied polygon is not convex, the results are undefined. - - On some platforms (e.g. X Window), this is faster than - drawPolygon(). - - \warning On X11, coordinates that do not fit into 16-bit signed - values are truncated. This limitation is expected to go away in - TQt 4. -*/ -void TQPainter::drawConvexPolygon( const TQPointArray &pa, - int index, int npoints ) -{ - global_polygon_tqshape = Convex; - drawPolygon(pa, FALSE, index, npoints); - global_polygon_tqshape = Complex; -} - - - -/*! - Draws a cubic Bezier curve defined by the control points in \a a, - starting at \a a[index] (\a index defaults to 0). - - Control points after \a a[index + 3] are ignored. Nothing happens - if there aren't enough control points. - - \warning On X11, coordinates that do not fit into 16-bit signed - values are truncated. This limitation is expected to go away in - TQt 4. -*/ - -void TQPainter::drawCubicBezier( const TQPointArray &a, int index ) -{ - if ( !isActive() ) - return; - if ( a.size() - index < 4 ) { -#if defined(TQT_CHECK_RANGE) - qWarning( "TQPainter::drawCubicBezier: Cubic Bezier needs 4 control " - "points" ); -#endif - return; - } - TQPointArray pa( a ); - if ( index != 0 || a.size() > 4 ) { - pa = TQPointArray( 4 ); - for ( int i=0; i<4; i++ ) - pa.setPoint( i, a.point(index+i) ); - } - if ( testf(ExtDev|VxF|WxF) ) { - if ( testf(ExtDev) ) { - TQPDevCmdParam param[1]; - param[0].ptarr = (TQPointArray*)&pa; - if ( !pdev->cmd(TQPaintDevice::PdcDrawCubicBezier, this, param) || - !hd ) - return; - } - if ( txop != TxNone ) - pa = xForm( pa ); - } - if ( cpen.style() != NoPen ) { - pa = pa.cubicBezier(); - XDrawLines( dpy, hd, gc, (XPoint*)pa.shortPoints(), pa.size(), - CoordModeOrigin ); - } -} - - -/*! - Draws a pixmap at \a (x, y) by copying a part of \a pixmap into - the paint tqdevice. - - \a (x, y) specifies the top-left point in the paint tqdevice that is - to be drawn onto. \a (sx, sy) specifies the top-left point in \a - pixmap that is to be drawn. The default is (0, 0). - - \a (sw, sh) specifies the size of the pixmap that is to be drawn. - The default, (-1, -1), means all the way to the bottom right of - the pixmap. - - Currently the mask of the pixmap or it's alpha channel are ignored - when painting on a TQPrinter. - - \sa bitBlt(), TQPixmap::setMask() -*/ - -void TQPainter::drawPixmap( int x, int y, const TQPixmap &pixmap, - int sx, int sy, int sw, int sh ) -{ - if ( !isActive() || pixmap.isNull() ) - return; - - // right/bottom - if ( sw < 0 ) - sw = pixmap.width() - sx; - if ( sh < 0 ) - sh = pixmap.height() - sy; - - // Sanity-check clipping - if ( sx < 0 ) { - x -= sx; - sw += sx; - sx = 0; - } - if ( sw + sx > pixmap.width() ) - sw = pixmap.width() - sx; - if ( sy < 0 ) { - y -= sy; - sh += sy; - sy = 0; - } - if ( sh + sy > pixmap.height() ) - sh = pixmap.height() - sy; - - if ( sw <= 0 || sh <= 0 ) - return; - - if ( pdev->x11Screen() != pixmap.x11Screen() ) { - TQPixmap* p = (TQPixmap*) &pixmap; - p->x11SetScreen( pdev->x11Screen() ); - } - - TQPixmap::x11SetDefaultScreen( pixmap.x11Screen() ); - - if ( testf(ExtDev|VxF|WxF) ) { - if ( testf(ExtDev) || txop == TxScale || txop == TxRotShear ) { - if ( sx != 0 || sy != 0 || - sw != pixmap.width() || sh != pixmap.height() ) { - TQPixmap tmp( sw, sh, pixmap.depth() ); - bitBlt( &tmp, 0, 0, &pixmap, sx, sy, sw, sh, CopyROP, TRUE ); - if ( pixmap.mask() ) { - TQBitmap mask( sw, sh ); - bitBlt( &mask, 0, 0, pixmap.mask(), sx, sy, sw, sh, - CopyROP, TRUE ); - tmp.setMask( mask ); - } - drawPixmap( x, y, tmp ); - return; - } - if ( testf(ExtDev) ) { - TQPDevCmdParam param[2]; - TQRect r(x, y, pixmap.width(), pixmap.height()); - param[0].rect = &r; - param[1].pixmap = &pixmap; - if ( !pdev->cmd(TQPaintDevice::PdcDrawPixmap, this, param) || !hd ) - return; - } - if ( txop == TxScale || txop == TxRotShear ) { - TQWMatrix mat( m11(), m12(), - m21(), m22(), - dx(), dy() ); - mat = TQPixmap::trueMatrix( mat, sw, sh ); - TQPixmap pm = pixmap.xForm( mat ); - if ( !pm.mask() && txop == TxRotShear ) { - TQBitmap bm_clip( sw, sh, 1 ); - bm_clip.fill( color1 ); - pm.setMask( bm_clip.xForm(mat) ); - } - map( x, y, &x, &y ); // compute position of pixmap - int dx, dy; - mat.map( 0, 0, &dx, &dy ); - uint save_flags = flags; - flags = IsActive | (save_flags & ClipOn); - drawPixmap( x-dx, y-dy, pm ); - flags = save_flags; - return; - } - } - map( x, y, &x, &y ); - } - - TQBitmap *mask = (TQBitmap *)pixmap.mask(); - bool mono = pixmap.depth() == 1; - - if ( mask && !hasClipping() && pdev != paintEventDevice ) { - if ( mono ) { // needs GCs pen color - bool selfmask = pixmap.data->selfmask; - if ( selfmask ) { - XSetFillStyle( dpy, gc, FillStippled ); - XSetStipple( dpy, gc, pixmap.handle() ); - } else { - XSetFillStyle( dpy, gc, FillOpaqueStippled ); - XSetStipple( dpy, gc, pixmap.handle() ); - XSetClipMask( dpy, gc, mask->handle() ); - XSetClipOrigin( dpy, gc, x-sx, y-sy ); - } - XSetTSOrigin( dpy, gc, x-sx, y-sy ); - XFillRectangle( dpy, hd, gc, x, y, sw, sh ); - XSetTSOrigin( dpy, gc, 0, 0 ); - XSetFillStyle( dpy, gc, FillSolid ); - if ( !selfmask ) { - if ( pdev == paintEventDevice && paintEventClipRegion ) { - x11SetClipRegion( dpy, gc, 0, rendhd, *paintEventClipRegion ); - } else { - x11ClearClipRegion(dpy, gc, 0, rendhd); - } - } - } else { - bitBlt( pdev, x, y, &pixmap, sx, sy, sw, sh, (RasterOp)rop ); - } - return; - } - - TQRegion rgn = crgn; - - if ( mask ) { // pixmap has clip mask - // Implies that clipping is on, either explicit or implicit - // Create a new mask that combines the mask with the clip region - - if ( pdev == paintEventDevice && paintEventClipRegion ) { - if ( hasClipping() ) - rgn = rgn.intersect( *paintEventClipRegion ); - else - rgn = *paintEventClipRegion; - } - - TQBitmap *comb = new TQBitmap( sw, sh ); - comb->detach(); - GC cgc = qt_xget_temp_gc( pixmap.x11Screen(), TRUE ); // get temporary mono GC - XSetForeground( dpy, cgc, 0 ); - XFillRectangle( dpy, comb->handle(), cgc, 0, 0, sw, sh ); - XSetBackground( dpy, cgc, 0 ); - XSetForeground( dpy, cgc, 1 ); - int num; - XRectangle *rects = (XRectangle *)qt_getClipRects( rgn, num ); - XSetClipRectangles( dpy, cgc, -x, -y, rects, num, YXBanded ); - XSetFillStyle( dpy, cgc, FillOpaqueStippled ); - XSetStipple( dpy, cgc, mask->handle() ); - XSetTSOrigin( dpy, cgc, -sx, -sy ); - XFillRectangle( dpy, comb->handle(), cgc, 0, 0, sw, sh ); - XSetTSOrigin( dpy, cgc, 0, 0 ); // restore cgc - XSetFillStyle( dpy, cgc, FillSolid ); - XSetClipMask( dpy, cgc, None ); - mask = comb; // it's deleted below - - XSetClipMask( dpy, gc, mask->handle() ); - XSetClipOrigin( dpy, gc, x, y ); - } - - if ( mono ) { - XSetBackground( dpy, gc, bg_col.pixel(scrn) ); - XSetFillStyle( dpy, gc, FillOpaqueStippled ); - XSetStipple( dpy, gc, pixmap.handle() ); - XSetTSOrigin( dpy, gc, x-sx, y-sy ); - XFillRectangle( dpy, hd, gc, x, y, sw, sh ); - XSetTSOrigin( dpy, gc, 0, 0 ); - XSetFillStyle( dpy, gc, FillSolid ); - } else { -#if !defined(TQT_NO_XFTFREETYPE) && !defined(TQT_NO_XRENDER) - Picture pict = rendhd ? XftDrawPicture((XftDraw *) rendhd) : None; - TQPixmap *alpha = pixmap.data->alphapm; - - if ( pict && pixmap.x11RenderHandle() && - alpha && alpha->x11RenderHandle()) { - XRenderComposite(dpy, PictOpOver, pixmap.x11RenderHandle(), - alpha->x11RenderHandle(), pict, - sx, sy, sx, sy, x, y, sw, sh); - } else -#endif // !TQT_NO_XFTFREETYPE && !TQT_NO_XRENDER - { - XCopyArea( dpy, pixmap.handle(), hd, gc, sx, sy, sw, sh, x, y ); - } - } - - if ( mask ) { // restore clipping - XSetClipOrigin( dpy, gc, 0, 0 ); - XSetRegion( dpy, gc, rgn.handle() ); - delete mask; // delete comb, created above - } -} - - -/* Internal, used by drawTiledPixmap */ - -static void drawTile( TQPainter *p, int x, int y, int w, int h, - const TQPixmap &pixmap, int xOffset, int yOffset ) -{ - int yPos, xPos, drawH, drawW, yOff, xOff; - yPos = y; - yOff = yOffset; - while( yPos < y + h ) { - drawH = pixmap.height() - yOff; // Cropping first row - if ( yPos + drawH > y + h ) // Cropping last row - drawH = y + h - yPos; - xPos = x; - xOff = xOffset; - while( xPos < x + w ) { - drawW = pixmap.width() - xOff; // Cropping first column - if ( xPos + drawW > x + w ) // Cropping last column - drawW = x + w - xPos; - p->drawPixmap( xPos, yPos, pixmap, xOff, yOff, drawW, drawH ); - xPos += drawW; - xOff = 0; - } - yPos += drawH; - yOff = 0; - } -} - -#if 0 // see comment in drawTiledPixmap -/* Internal, used by drawTiledPixmap */ - -static void fillTile( TQPixmap *tile, const TQPixmap &pixmap ) -{ - bitBlt( tile, 0, 0, &pixmap, 0, 0, -1, -1, TQt::CopyROP, TRUE ); - int x = pixmap.width(); - while ( x < tile->width() ) { - bitBlt( tile, x,0, tile, 0,0, x,pixmap.height(), TQt::CopyROP, TRUE ); - x *= 2; - } - int y = pixmap.height(); - while ( y < tile->height() ) { - bitBlt( tile, 0,y, tile, 0,0, tile->width(),y, TQt::CopyROP, TRUE ); - y *= 2; - } -} -#endif - -/*! - Draws a tiled \a pixmap in the specified rectangle. - - \a (x, y) specifies the top-left point in the paint tqdevice that is - to be drawn onto; with the width and height given by \a w and \a - h. \a (sx, sy) specifies the top-left point in \a pixmap that is - to be drawn. The default is (0, 0). - - Calling drawTiledPixmap() is similar to calling drawPixmap() - several times to fill (tile) an area with a pixmap, but is - potentially much more efficient depending on the underlying window - system. - - \sa drawPixmap() -*/ - -void TQPainter::drawTiledPixmap( int x, int y, int w, int h, - const TQPixmap &pixmap, int sx, int sy ) -{ - int sw = pixmap.width(); - int sh = pixmap.height(); - if (!sw || !sh ) - return; - if ( sx < 0 ) - sx = sw - -sx % sw; - else - sx = sx % sw; - if ( sy < 0 ) - sy = sh - -sy % sh; - else - sy = sy % sh; - /* - Requirements for optimizing tiled pixmaps: - - not an external tqdevice - - not scale or rotshear - - not mono pixmap - - no mask - */ - TQBitmap *mask = (TQBitmap *)pixmap.mask(); - if ( !testf(ExtDev) && txop <= TxTranslate && pixmap.depth() > 1 && - mask == 0 ) { - if ( txop == TxTranslate ) - map( x, y, &x, &y ); - -#if !defined(TQT_NO_XFTFREETYPE) && !defined(TQT_NO_XRENDER) - Picture pict = rendhd ? XftDrawPicture((XftDraw *) rendhd) : None; - TQPixmap *alpha = pixmap.data->alphapm; - - if (pict && pixmap.x11RenderHandle() && alpha && alpha->x11RenderHandle()) { - // this is essentially drawTile() from above, inlined for - // the XRenderComposite call - int yPos, xPos, drawH, drawW, yOff, xOff; - yPos = y; - yOff = sy; - while( yPos < y + h ) { - drawH = pixmap.height() - yOff; // Cropping first row - if ( yPos + drawH > y + h ) // Cropping last row - drawH = y + h - yPos; - xPos = x; - xOff = sx; - while( xPos < x + w ) { - drawW = pixmap.width() - xOff; // Cropping first column - if ( xPos + drawW > x + w ) // Cropping last column - drawW = x + w - xPos; - XRenderComposite(dpy, PictOpOver, pixmap.x11RenderHandle(), - alpha->x11RenderHandle(), pict, - xOff, yOff, xOff, yOff, xPos, yPos, drawW, drawH); - xPos += drawW; - xOff = 0; - } - yPos += drawH; - yOff = 0; - } - return; - } -#endif // !TQT_NO_XFTFREETYPE && !TQT_NO_XRENDER - - XSetTile( dpy, gc, pixmap.handle() ); - XSetFillStyle( dpy, gc, FillTiled ); - XSetTSOrigin( dpy, gc, x-sx, y-sy ); - XFillRectangle( dpy, hd, gc, x, y, w, h ); - XSetTSOrigin( dpy, gc, 0, 0 ); - XSetFillStyle( dpy, gc, FillSolid ); - return; - } - -#if 0 - // maybe there'll be point in this again, but for the time all it - // does is make trouble for the postscript code. - if ( sw*sh < 8192 && sw*sh < 16*w*h ) { - int tw = sw; - int th = sh; - while( th * tw < 4096 && ( th < h || tw < w ) ) { - if ( h/th > w/tw ) - th *= 2; - else - tw *= 2; - } - TQPixmap tile( tw, th, pixmap.depth(), TQPixmap::NormalOptim ); - fillTile( &tile, pixmap ); - if ( mask ) { - TQBitmap tilemask( tw, th, TQPixmap::NormalOptim ); - fillTile( &tilemask, *mask ); - tile.setMask( tilemask ); - } - drawTile( this, x, y, w, h, tile, sx, sy ); - } else { - drawTile( this, x, y, w, h, pixmap, sx, sy ); - } -#else - // for now we'll just output the original and let the postscript - // code make what it can of it. qpicture will be unhappy. - drawTile( this, x, y, w, h, pixmap, sx, sy ); -#endif -} - -#if 0 -// -// Generate a string that describes a transformed bitmap. This string is used -// to insert and find bitmaps in the global pixmap cache. -// - -static TQString gen_text_bitmap_key( const TQWMatrix &m, const TQFont &font, - const TQString &str, int pos, int len ) -{ - TQString fk = font.key(); - int sz = 4*2 + len*2 + fk.length()*2 + sizeof(double)*6; - TQByteArray buf(sz); - uchar *p = (uchar *)buf.data(); - *((double*)p)=m.m11(); p+=sizeof(double); - *((double*)p)=m.m12(); p+=sizeof(double); - *((double*)p)=m.m21(); p+=sizeof(double); - *((double*)p)=m.m22(); p+=sizeof(double); - *((double*)p)=m.dx(); p+=sizeof(double); - *((double*)p)=m.dy(); p+=sizeof(double); - TQChar h1( '$' ); - TQChar h2( 'q' ); - TQChar h3( 't' ); - TQChar h4( '$' ); - *((TQChar*)p)=h1; p+=2; - *((TQChar*)p)=h2; p+=2; - *((TQChar*)p)=h3; p+=2; - *((TQChar*)p)=h4; p+=2; - memcpy( (char*)p, (char*)(str.tqunicode()+pos), len*2 ); p += len*2; - memcpy( (char*)p, (char*)fk.tqunicode(), fk.length()*2 ); p += fk.length()*2; - return TQString( (TQChar*)buf.data(), buf.size()/2 ); -} - -static TQBitmap *get_text_bitmap( const TQString &key ) -{ - return (TQBitmap*)TQPixmapCache::find( key ); -} - -static void ins_text_bitmap( const TQString &key, TQBitmap *bm ) -{ - if ( !TQPixmapCache::insert(key, bm) ) // cannot insert pixmap - delete bm; -} -#endif - -void qt_draw_transformed_rect( TQPainter *p, int x, int y, int w, int h, bool fill ) -{ - XPoint points[5]; - int xp = x, yp = y; - p->map( xp, yp, &xp, &yp ); - points[0].x = xp; - points[0].y = yp; - xp = x + w; yp = y; - p->map( xp, yp, &xp, &yp ); - points[1].x = xp; - points[1].y = yp; - xp = x + w; yp = y + h; - p->map( xp, yp, &xp, &yp ); - points[2].x = xp; - points[2].y = yp; - xp = x; yp = y + h; - p->map( xp, yp, &xp, &yp ); - points[3].x = xp; - points[3].y = yp; - points[4] = points[0]; - - if ( fill ) - XFillPolygon( p->dpy, p->hd, p->gc, points, 4, Convex, CoordModeOrigin ); - else - XDrawLines( p->dpy, p->hd, p->gc, points, 5, CoordModeOrigin ); -} - -void qt_draw_background( TQPainter *p, int x, int y, int w, int h ) -{ - if (p->testf(TQPainter::ExtDev)) { - if (p->pdev->devType() == TQInternal::Printer) - p->fillRect(x, y, w, h, p->bg_col); - return; - } - XSetForeground( p->dpy, p->gc, p->bg_col.pixel(p->scrn) ); - qt_draw_transformed_rect( p, x, y, w, h, TRUE); - XSetForeground( p->dpy, p->gc, p->cpen.color().pixel(p->scrn) ); -} - -/*! - Draws at most \a len characters of the string \a str at position - \a (x, y). - - \a (x, y) is the base line position. Note that the meaning of \a y - is not the same for the two drawText() varieties. -*/ -void TQPainter::drawText( int x, int y, const TQString &str, int len, TQPainter::TextDirection dir ) -{ - drawText( x, y, str, 0, len, dir ); -} - -/*! - Draws at most \a len characters starting at position \a pos from the - string \a str to position \a (x, y). - - \a (x, y) is the base line position. Note that the meaning of \a y - is not the same for the two drawText() varieties. -*/ -void TQPainter::drawText( int x, int y, const TQString &str, int pos, int len, TQPainter::TextDirection dir ) -{ - if ( !isActive() ) - return; - if (len < 0) - len = str.length() - pos; - if ( len <= 0 || pos >= (int)str.length() ) // empty string - return; - if ( pos + len > (int)str.length() ) - len = str.length() - pos; - - if ( testf(DirtyFont) ) { - updateFont(); - } - - if ( testf(ExtDev) && pdev->devType() != TQInternal::Printer ) { - TQPDevCmdParam param[3]; - TQPoint p(x, y); - TQString string = str.mid( pos, len ); - param[0].point = &p; - param[1].str = &string; - param[2].ival = TQFont::Latin; - if ( !pdev->cmd(TQPaintDevice::PdcDrawText2, this, param) || !hd ) - return; - } - - bool simple = (dir == TQPainter::Auto) && str.simpleText(); - // we can't take the complete string here as we would otherwise - // get quadratic behaviour when drawing long strings in parts. - // we do however need some chars around the part we paint to get arabic shaping correct. - // ### maybe possible to remove after cursor restrictions work in TQRT - int start; - int end; - if ( simple ) { - start = pos; - end = pos+len; - } else { - start = TQMAX( 0, pos - 8 ); - end = TQMIN( (int)str.length(), pos + len + 8 ); - } - TQConstString cstr( str.tqunicode() + start, end - start ); - pos -= start; - - TQTextEngine engine( cstr.string(), pfont ? pfont->d : cfont.d ); - TQTextLayout tqlayout( &engine ); - - // this is actually what beginLayout does. Inlined here, so we can - // avoid the bidi algorithm if we don't need it. - engine.itemize( simple ? TQTextEngine::NoBidi|TQTextEngine::SingleLine : TQTextEngine::Full|TQTextEngine::SingleLine ); - engine.currentItem = 0; - engine.firstItemInLine = -1; - - if ( dir != Auto ) { - int level = dir == RTL ? 1 : 0; - for ( int i = engine.items.size(); i >= 0; i-- ) - engine.items[i].analysis.bidiLevel = level; - } - - if ( !simple ) { - tqlayout.setBoundary( pos ); - tqlayout.setBoundary( pos + len ); - } - - // small hack to force skipping of unneeded items - start = 0; - while ( engine.items[start].position < pos ) - ++start; - engine.currentItem = start; - tqlayout.beginLine( 0xfffffff ); - end = start; - while ( !tqlayout.atEnd() && tqlayout.currentItem().from() < pos + len ) { - tqlayout.addCurrentItem(); - end++; - } - TQFontMetrics fm(fontMetrics()); - int ascent = fm.ascent(), descent = fm.descent(); - int left, right; - tqlayout.endLine( 0, 0, TQt::SingleLine|TQt::AlignLeft, &ascent, &descent, &left, &right ); - - // do _not_ call endLayout() here, as it would clean up the tqshaped items and we would do shaping another time - // for painting. - - int textFlags = 0; - if ( cfont.d->underline ) textFlags |= TQt::Underline; - if ( cfont.d->overline ) textFlags |= TQt::Overline; - if ( cfont.d->strikeOut ) textFlags |= TQt::StrikeOut; - - if ( bg_mode == OpaqueMode ) - qt_draw_background( this, x, y-ascent, right-left, ascent+descent+1); - - for ( int i = start; i < end; i++ ) { - TQTextItem ti; - ti.item = i; - ti.engine = &engine; - - tqdrawTextItem( x, y - ascent, ti, textFlags ); - } - tqlayout.d = 0; -} - - -/*! \internal - Draws the text item \a ti at position \a (x, y ). - - This method ignores the painters background mode and - color. drawText and qt_format_text have to do it themselves, as - only they know the extents of the complete string. - - It ignores the font set on the painter as the text item has one of its own. - - The underline and strikeout parameters of the text items font are - ignored aswell. You'll need to pass in the correct flags to get - underlining and strikeout. -*/ -void TQPainter::tqdrawTextItem( int x, int y, const TQTextItem &ti, int textFlags ) -{ - if ( testf(ExtDev) ) { - TQPDevCmdParam param[2]; - TQPoint p(x, y); - param[0].point = &p; - param[1].textItem = &ti; - bool retval = pdev->cmd(TQPaintDevice::PdcDrawTextItem, this, param); - if ( !retval || !hd ) - return; - } - - TQTextEngine *engine = ti.engine; - TQScriptItem *si = &engine->items[ti.item]; - - engine->tqshape( ti.item ); - TQFontEngine *fe = si->fontEngine; - assert( fe != 0 ); - - x += si->x; - y += si->y; - - fe->draw( this, x, y, engine, si, textFlags ); -} - -#if TQT_VERSION >= 0x040000 -#error "remove current position and associated methods" -#endif -/*! - \obsolete - Returns the current position of the pen. - - \sa moveTo() - */ -TQPoint TQPainter::pos() const -{ - return curPt; -} - -#endif // USE_QT4 |