merge the formfield patch from ooo-build
[ooovba.git] / vcl / unx / source / gdi / salgdi2.cxx
blob99bae3ae82d3a9e4a0d49febb1c3721f88d31051
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salgdi2.cxx,v $
10 * $Revision: 1.47.16.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include <stdio.h>
35 #include <poll.h>
37 #include "salunx.h"
38 #include "saldata.hxx"
39 #include "saldisp.hxx"
40 #include "salbmp.h"
41 #include "salgdi.h"
42 #include "salframe.h"
43 #include "salvd.h"
44 #include "xrender_peer.hxx"
46 #include "vcl/salbtype.hxx"
47 #include "vcl/printergfx.hxx"
48 #include "vcl/bmpacc.hxx"
50 #undef SALGDI2_TESTTRANS
52 // -=-= debugging =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
53 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
54 #if 0
56 static void sal_PrintImage( char *s, XImage*p )
58 fprintf( stderr, "%s %d %d %d\n", s, p->depth, p->width, p->height );
59 int nW = Min( 64, p->width*p->bits_per_pixel >> 3 );
60 for( int i = 0; i < Min( 16, p->height ); i++ )
62 for( int j = 0; j < nW; j++ )
63 fprintf( stderr, "%02X", (UINT8)p->data[i*p->bytes_per_line+j] );
64 fprintf( stderr, "\n" );
68 #endif // DBG_UTIL
70 // -----------------------------------------------------------------------------
72 #if (OSL_DEBUG_LEVEL > 1) && defined SALGDI2_TESTTRANS
73 #define DBG_TESTTRANS( _def_drawable ) \
74 { \
75 XCopyArea( pXDisp, _def_drawable, aDrawable, GetCopyGC(), \
76 0, 0, \
77 pPosAry->mnDestWidth, pPosAry->mnDestHeight, \
78 0, 0 ); \
80 #else // (OSL_DEBUG_LEVEL > 1) && defined SALGDI2_TESTTRANS
81 #define DBG_TESTTRANS( _def_drawable )
82 #endif // (OSL_DEBUG_LEVEL > 1) && defined SALGDI2_TESTTRANS
84 // -=-= X11SalGraphics =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
85 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
86 void X11SalGraphics::CopyScreenArea( Display* pDisplay,
87 Drawable aSrc, int nScreenSrc, int nSrcDepth,
88 Drawable aDest, int nScreenDest, int nDestDepth,
89 GC aDestGC,
90 int src_x, int src_y,
91 unsigned int w, unsigned int h,
92 int dest_x, int dest_y )
94 if( nSrcDepth == nDestDepth )
96 if( nScreenSrc == nScreenDest )
97 XCopyArea( pDisplay, aSrc, aDest, aDestGC,
98 src_x, src_y, w, h, dest_x, dest_y );
99 else
101 SalXLib* pLib = GetX11SalData()->GetDisplay()->GetXLib();
102 pLib->PushXErrorLevel( true );
103 XImage* pImage = XGetImage( pDisplay, aSrc, src_x, src_y, w, h,
104 AllPlanes, ZPixmap );
105 if( pImage )
107 if( pImage->data )
109 XPutImage( pDisplay, aDest, aDestGC, pImage,
110 0, 0, dest_x, dest_y, w, h );
112 XDestroyImage( pImage );
114 pLib->PopXErrorLevel();
117 else
119 X11SalBitmap aBM;
120 aBM.ImplCreateFromDrawable( aSrc, nScreenSrc, nSrcDepth, src_x, src_y, w, h );
121 SalTwoRect aTwoRect;
122 aTwoRect.mnSrcX = aTwoRect.mnSrcY = 0;
123 aTwoRect.mnSrcWidth = aTwoRect.mnDestWidth = w;
124 aTwoRect.mnSrcHeight = aTwoRect.mnDestHeight = h;
125 aTwoRect.mnDestX = dest_x;
126 aTwoRect.mnDestY = dest_y;
127 aBM.ImplDraw( aDest, nScreenDest, nDestDepth, aTwoRect,aDestGC );
131 GC X11SalGraphics::CreateGC( Drawable hDrawable, unsigned long nMask )
133 XGCValues values;
135 values.graphics_exposures = False;
136 values.foreground = m_pColormap->GetBlackPixel()
137 ^ m_pColormap->GetWhitePixel();
138 values.function = GXxor;
139 values.line_width = 1;
140 values.fill_style = FillStippled;
141 values.stipple = GetDisplay()->GetInvert50( m_nScreen );
142 values.subwindow_mode = ClipByChildren;
144 return XCreateGC( GetXDisplay(), hDrawable, nMask | GCSubwindowMode, &values );
147 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
148 inline GC X11SalGraphics::GetMonoGC( Pixmap hPixmap )
150 if( !pMonoGC_ )
151 pMonoGC_ = CreateGC( hPixmap );
153 if( !bMonoGC_ )
155 SetClipRegion( pMonoGC_ );
156 bMonoGC_ = TRUE;
159 return pMonoGC_;
162 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
163 inline GC X11SalGraphics::GetCopyGC()
165 if( bXORMode_ ) return GetInvertGC();
167 if( !pCopyGC_ )
168 pCopyGC_ = CreateGC( GetDrawable() );
170 if( !bCopyGC_ )
172 SetClipRegion( pCopyGC_ );
173 bCopyGC_ = TRUE;
175 return pCopyGC_;
178 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
179 GC X11SalGraphics::GetInvertGC()
181 if( !pInvertGC_ )
182 pInvertGC_ = CreateGC( GetDrawable(),
183 GCGraphicsExposures
184 | GCForeground
185 | GCFunction
186 | GCLineWidth );
188 if( !bInvertGC_ )
190 SetClipRegion( pInvertGC_ );
191 bInvertGC_ = TRUE;
193 return pInvertGC_;
196 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
197 GC X11SalGraphics::GetInvert50GC()
199 if( !pInvert50GC_ )
201 XGCValues values;
203 values.graphics_exposures = False;
204 values.foreground = m_pColormap->GetWhitePixel();
205 values.background = m_pColormap->GetBlackPixel();
206 values.function = GXinvert;
207 values.line_width = 1;
208 values.line_style = LineSolid;
209 unsigned long nValueMask =
210 GCGraphicsExposures
211 | GCForeground
212 | GCBackground
213 | GCFunction
214 | GCLineWidth
215 | GCLineStyle
216 | GCFillStyle
217 | GCStipple;
219 char* pEnv = getenv( "SAL_DO_NOT_USE_INVERT50" );
220 if( pEnv && ! strcasecmp( pEnv, "true" ) )
222 values.fill_style = FillSolid;
223 nValueMask &= ~ GCStipple;
225 else
227 values.fill_style = FillStippled;
228 values.stipple = GetDisplay()->GetInvert50( m_nScreen );
231 pInvert50GC_ = XCreateGC( GetXDisplay(), GetDrawable(),
232 nValueMask,
233 &values );
236 if( !bInvert50GC_ )
238 SetClipRegion( pInvert50GC_ );
239 bInvert50GC_ = TRUE;
241 return pInvert50GC_;
244 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
245 inline GC X11SalGraphics::GetStippleGC()
247 if( !pStippleGC_ )
248 pStippleGC_ = CreateGC( GetDrawable(),
249 GCGraphicsExposures
250 | GCFillStyle
251 | GCLineWidth );
253 if( !bStippleGC_ )
255 XSetFunction( GetXDisplay(), pStippleGC_, bXORMode_ ? GXxor : GXcopy );
256 SetClipRegion( pStippleGC_ );
257 bStippleGC_ = TRUE;
260 return pStippleGC_;
263 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
264 int X11SalGraphics::Clip( XLIB_Region pRegion,
265 int &nX,
266 int &nY,
267 unsigned int &nDX,
268 unsigned int &nDY,
269 int &nSrcX,
270 int &nSrcY ) const
272 XRectangle aRect;
273 XClipBox( pRegion, &aRect );
275 if( int(nX + nDX) <= int(aRect.x) || nX >= int(aRect.x + aRect.width) )
276 return RectangleOut;
277 if( int(nY + nDY) <= int(aRect.y) || nY >= int(aRect.y + aRect.height) )
278 return RectangleOut;
280 if( nX < aRect.x )
282 nSrcX += aRect.x - nX;
283 nDX -= aRect.x - nX;
284 nX = aRect.x;
286 else if( int(nX + nDX) > int(aRect.x + aRect.width) )
287 nDX = aRect.x + aRect.width - nX;
289 if( nY < aRect.y )
291 nSrcY += aRect.y - nY;
292 nDY -= aRect.y - nY;
293 nY = aRect.y;
295 else if( int(nY + nDY) > int(aRect.y + aRect.height) )
296 nDY = aRect.y + aRect.height - nY;
298 return RectangleIn;
301 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
302 int X11SalGraphics::Clip( int &nX,
303 int &nY,
304 unsigned int &nDX,
305 unsigned int &nDY,
306 int &nSrcX,
307 int &nSrcY ) const
310 if( pPaintRegion_
311 && RectangleOut == Clip( pPaintRegion_, nX, nY, nDX, nDY, nSrcX, nSrcY ) )
312 return RectangleOut;
314 if( pClipRegion_
315 && RectangleOut == Clip( pClipRegion_, nX, nY, nDX, nDY, nSrcX, nSrcY ) )
316 return RectangleOut;
318 int nPaint;
319 if( pPaintRegion_ )
321 nPaint = XRectInRegion( pPaintRegion_, nX, nY, nDX, nDY );
322 if( RectangleOut == nPaint )
323 return RectangleOut;
325 else
326 nPaint = RectangleIn;
328 int nClip;
329 if( pClipRegion_ )
331 nClip = XRectInRegion( pClipRegion_, nX, nY, nDX, nDY );
332 if( RectangleOut == nClip )
333 return RectangleOut;
335 else
336 nClip = RectangleIn;
338 return RectangleIn == nClip && RectangleIn == nPaint
339 ? RectangleIn
340 : RectanglePart;
343 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
344 GC X11SalGraphics::SetMask( int &nX,
345 int &nY,
346 unsigned int &nDX,
347 unsigned int &nDY,
348 int &nSrcX,
349 int &nSrcY,
350 Pixmap hClipMask )
352 int n = Clip( nX, nY, nDX, nDY, nSrcX, nSrcY );
353 if( RectangleOut == n )
354 return NULL;
356 Display *pDisplay = GetXDisplay();
358 if( !pMaskGC_ )
359 pMaskGC_ = CreateGC( GetDrawable() );
361 if( RectangleIn == n )
363 XSetClipMask( pDisplay, pMaskGC_, hClipMask );
364 XSetClipOrigin( pDisplay, pMaskGC_, nX - nSrcX, nY - nSrcY );
365 return pMaskGC_;
368 // - - - - create alternate clip pixmap for region clipping - - - -
369 Pixmap hPixmap = XCreatePixmap( pDisplay, hClipMask, nDX, nDY, 1 );
371 if( !hPixmap )
373 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
374 fprintf( stderr, "X11SalGraphics::SetMask !hPixmap\n" );
375 #endif
376 return NULL;
379 // - - - - reset pixmap; all 0 - - - - - - - - - - - - - - - - - - -
380 XFillRectangle( pDisplay,
381 hPixmap,
382 GetDisplay()->GetMonoGC( m_nScreen ),
383 0, 0,
384 nDX, nDY );
386 // - - - - copy pixmap only within region - - - - - - - - - - - - -
387 GC pMonoGC = GetMonoGC( hPixmap );
388 XSetClipOrigin( pDisplay, pMonoGC, -nX, -nY );
389 XCopyArea( pDisplay,
390 hClipMask, // Source
391 hPixmap, // Destination
392 pMonoGC,
393 nSrcX, nSrcY, // Source
394 nDX, nDY, // Width & Height
395 0, 0 ); // Destination
397 XSetClipMask( pDisplay, pMaskGC_, hPixmap );
398 XSetClipOrigin( pDisplay, pMaskGC_, nX, nY );
400 XFreePixmap( pDisplay, hPixmap );
401 return pMaskGC_;
404 // -=-= SalGraphics =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
405 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
407 extern "C"
409 static Bool GraphicsExposePredicate( Display*, XEvent* pEvent, XPointer pFrameWindow )
411 Bool bRet = False;
412 if( (pEvent->type == GraphicsExpose || pEvent->type == NoExpose) &&
413 pEvent->xnoexpose.drawable == (Drawable)pFrameWindow )
415 bRet = True;
417 return bRet;
422 void X11SalGraphics::YieldGraphicsExpose()
424 // get frame if necessary
425 SalFrame* pFrame = m_pFrame;
426 Display* pDisplay = GetXDisplay();
427 XLIB_Window aWindow = GetDrawable();
428 if( ! pFrame )
430 const std::list< SalFrame* >& rFrames = GetX11SalData()->GetDisplay()->getFrames();
431 for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end() && ! pFrame; ++it )
433 const SystemEnvData* pEnvData = (*it)->GetSystemData();
434 if( Drawable(pEnvData->aWindow) == aWindow )
435 pFrame = *it;
437 if( ! pFrame )
438 return;
441 XEvent aEvent;
442 while( XCheckTypedWindowEvent( pDisplay, aWindow, Expose, &aEvent ) )
444 SalPaintEvent aPEvt( aEvent.xexpose.x, aEvent.xexpose.y, aEvent.xexpose.width+1, aEvent.xexpose.height+1 );
445 pFrame->CallCallback( SALEVENT_PAINT, &aPEvt );
450 if( ! GetDisplay()->XIfEventWithTimeout( &aEvent, (XPointer)aWindow, GraphicsExposePredicate ) )
451 // this should not happen at all; still sometimes it happens
452 break;
454 if( aEvent.type == NoExpose )
455 break;
457 if( pFrame )
459 SalPaintEvent aPEvt( aEvent.xgraphicsexpose.x, aEvent.xgraphicsexpose.y, aEvent.xgraphicsexpose.width+1, aEvent.xgraphicsexpose.height+1 );
460 pFrame->CallCallback( SALEVENT_PAINT, &aPEvt );
462 } while( aEvent.xgraphicsexpose.count != 0 );
465 void X11SalGraphics::copyBits( const SalTwoRect *pPosAry,
466 SalGraphics *pSSrcGraphics )
468 X11SalGraphics* pSrcGraphics = pSSrcGraphics
469 ? static_cast<X11SalGraphics*>(pSSrcGraphics)
470 : this;
472 if( pPosAry->mnSrcWidth <= 0
473 || pPosAry->mnSrcHeight <= 0
474 || pPosAry->mnDestWidth <= 0
475 || pPosAry->mnDestHeight <= 0 )
477 return;
480 int n;
481 if( pSrcGraphics == this )
483 n = 2;
485 else if( pSrcGraphics->bWindow_ )
487 // window or compatible virtual device
488 if( pSrcGraphics->GetDisplay() == GetDisplay() &&
489 pSrcGraphics->m_nScreen == m_nScreen &&
490 pSrcGraphics->GetVisual().GetDepth() == GetVisual().GetDepth()
492 n = 2; // same Display
493 else
494 n = 1; // printer or other display
496 else if( pSrcGraphics->bVirDev_ )
498 // printer compatible virtual device
499 if( bPrinter_ )
500 n = 2; // printer or compatible virtual device == same display
501 else
502 n = 1; // window or compatible virtual device
504 else
505 n = 0;
507 if( n == 2
508 && pPosAry->mnSrcWidth == pPosAry->mnDestWidth
509 && pPosAry->mnSrcHeight == pPosAry->mnDestHeight
512 // #i60699# Need to generate graphics exposures (to repaint
513 // obscured areas beneath overlapping windows), src and dest
514 // are the same window.
515 const bool bNeedGraphicsExposures( pSrcGraphics == this &&
516 !bVirDev_ &&
517 pSrcGraphics->bWindow_ );
519 GC pCopyGC;
521 if( bXORMode_
522 && !pSrcGraphics->bVirDev_
523 && (GetDisplay()->GetProperties() & PROPERTY_BUG_XCopyArea_GXxor) )
525 Pixmap hPixmap = XCreatePixmap( GetXDisplay(),
526 pSrcGraphics->GetDrawable(), // source
527 pPosAry->mnSrcWidth, pPosAry->mnSrcHeight,
528 pSrcGraphics->GetBitCount() );
530 pCopyGC = GetDisplay()->GetCopyGC( m_nScreen );
532 if( bNeedGraphicsExposures )
533 XSetGraphicsExposures( GetXDisplay(),
534 pCopyGC,
535 True );
537 XCopyArea( GetXDisplay(),
538 pSrcGraphics->GetDrawable(), // source
539 hPixmap, // destination
540 pCopyGC, // no clipping
541 pPosAry->mnSrcX, pPosAry->mnSrcY,
542 pPosAry->mnSrcWidth, pPosAry->mnSrcHeight,
543 0, 0 ); // destination
544 XCopyArea( GetXDisplay(),
545 hPixmap, // source
546 GetDrawable(), // destination
547 GetInvertGC(), // destination clipping
548 0, 0, // source
549 pPosAry->mnSrcWidth, pPosAry->mnSrcHeight,
550 pPosAry->mnDestX, pPosAry->mnDestY );
551 XFreePixmap( GetXDisplay(), hPixmap );
553 else
555 pCopyGC = GetCopyGC();
557 if( bNeedGraphicsExposures )
558 XSetGraphicsExposures( GetXDisplay(),
559 pCopyGC,
560 True );
562 XCopyArea( GetXDisplay(),
563 pSrcGraphics->GetDrawable(), // source
564 GetDrawable(), // destination
565 pCopyGC, // destination clipping
566 pPosAry->mnSrcX, pPosAry->mnSrcY,
567 pPosAry->mnSrcWidth, pPosAry->mnSrcHeight,
568 pPosAry->mnDestX, pPosAry->mnDestY );
571 if( bNeedGraphicsExposures )
573 YieldGraphicsExpose();
575 if( pCopyGC )
576 XSetGraphicsExposures( GetXDisplay(),
577 pCopyGC,
578 False );
581 else if( n )
583 // #i60699# No chance to handle graphics exposures - we copy
584 // to a temp bitmap first, into which no repaints are
585 // technically possible.
586 SalBitmap *pDDB = pSrcGraphics->getBitmap( pPosAry->mnSrcX,
587 pPosAry->mnSrcY,
588 pPosAry->mnSrcWidth,
589 pPosAry->mnSrcHeight );
591 if( !pDDB )
593 stderr0( "SalGraphics::CopyBits !pSrcGraphics->GetBitmap()\n" );
594 return;
597 SalTwoRect aPosAry( *pPosAry );
599 aPosAry.mnSrcX = 0, aPosAry.mnSrcY = 0;
600 drawBitmap( &aPosAry, *pDDB );
602 delete pDDB;
604 else {
605 stderr0( "X11SalGraphics::CopyBits from Printer not yet implemented\n" );
609 // --------------------------------------------------------------------------
611 void X11SalGraphics::copyArea ( long nDestX, long nDestY,
612 long nSrcX, long nSrcY,
613 long nSrcWidth, long nSrcHeight,
614 USHORT )
616 SalTwoRect aPosAry;
618 aPosAry.mnDestX = nDestX;
619 aPosAry.mnDestY = nDestY;
620 aPosAry.mnDestWidth = nSrcWidth;
621 aPosAry.mnDestHeight = nSrcHeight;
623 aPosAry.mnSrcX = nSrcX;
624 aPosAry.mnSrcY = nSrcY;
625 aPosAry.mnSrcWidth = nSrcWidth;
626 aPosAry.mnSrcHeight = nSrcHeight;
628 copyBits ( &aPosAry, 0 );
631 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
632 void X11SalGraphics::drawBitmap( const SalTwoRect* pPosAry, const SalBitmap& rSalBitmap )
634 const SalDisplay* pSalDisp = GetDisplay();
635 Display* pXDisp = pSalDisp->GetDisplay();
636 const Drawable aDrawable( GetDrawable() );
637 const SalColormap& rColMap = pSalDisp->GetColormap( m_nScreen );
638 const long nDepth = GetDisplay()->GetVisual( m_nScreen ).GetDepth();
639 GC aGC( GetCopyGC() );
640 XGCValues aOldVal, aNewVal;
641 int nValues = GCForeground | GCBackground;
643 if( rSalBitmap.GetBitCount() == 1 )
645 // set foreground/background values for 1Bit bitmaps
646 XGetGCValues( pXDisp, aGC, nValues, &aOldVal );
647 aNewVal.foreground = rColMap.GetWhitePixel(), aNewVal.background = rColMap.GetBlackPixel();
648 XChangeGC( pXDisp, aGC, nValues, &aNewVal );
651 static_cast<const X11SalBitmap&>(rSalBitmap).ImplDraw( aDrawable, m_nScreen, nDepth, *pPosAry, aGC );
653 if( rSalBitmap.GetBitCount() == 1 )
654 XChangeGC( pXDisp, aGC, nValues, &aOldVal );
655 XFlush( pXDisp );
658 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
660 void X11SalGraphics::drawBitmap( const SalTwoRect* pPosAry,
661 const SalBitmap& rSrcBitmap,
662 const SalBitmap& rMaskBitmap )
664 DBG_ASSERT( !bPrinter_, "Drawing of transparent bitmaps on printer devices is strictly forbidden" );
666 // decide if alpha masking or transparency masking is needed
667 BitmapBuffer* pAlphaBuffer = const_cast<SalBitmap&>(rMaskBitmap).AcquireBuffer( TRUE );
668 if( pAlphaBuffer != NULL )
670 int nMaskFormat = pAlphaBuffer->mnFormat;
671 const_cast<SalBitmap&>(rMaskBitmap).ReleaseBuffer( pAlphaBuffer, TRUE );
672 if( nMaskFormat == BMP_FORMAT_8BIT_PAL )
673 drawAlphaBitmap( *pPosAry, rSrcBitmap, rMaskBitmap );
676 drawMaskedBitmap( pPosAry, rSrcBitmap, rMaskBitmap );
679 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
681 void X11SalGraphics::drawMaskedBitmap( const SalTwoRect* pPosAry,
682 const SalBitmap& rSalBitmap,
683 const SalBitmap& rTransBitmap )
685 const SalDisplay* pSalDisp = GetDisplay();
686 Display* pXDisp = pSalDisp->GetDisplay();
687 Drawable aDrawable( GetDrawable() );
689 // figure work mode depth. If this is a VDev Drawable, use its
690 // bitdepth to create pixmaps for, otherwise, XCopyArea will
691 // refuse to work.
692 const USHORT nDepth( m_pVDev ?
693 m_pVDev->GetDepth() :
694 pSalDisp->GetVisual( m_nScreen ).GetDepth() );
695 Pixmap aFG( XCreatePixmap( pXDisp, aDrawable, pPosAry->mnDestWidth,
696 pPosAry->mnDestHeight, nDepth ) );
697 Pixmap aBG( XCreatePixmap( pXDisp, aDrawable, pPosAry->mnDestWidth,
698 pPosAry->mnDestHeight, nDepth ) );
700 if( aFG && aBG )
702 GC aTmpGC;
703 XGCValues aValues;
704 const SalColormap& rColMap = pSalDisp->GetColormap( m_nScreen );
705 const int nBlack = rColMap.GetBlackPixel(), nWhite = rColMap.GetWhitePixel();
706 const int nValues = GCFunction | GCForeground | GCBackground;
707 SalTwoRect aTmpRect( *pPosAry ); aTmpRect.mnDestX = aTmpRect.mnDestY = 0;
709 // draw paint bitmap in pixmap #1
710 aValues.function = GXcopy, aValues.foreground = nWhite, aValues.background = nBlack;
711 aTmpGC = XCreateGC( pXDisp, aFG, nValues, &aValues );
712 static_cast<const X11SalBitmap&>(rSalBitmap).ImplDraw( aFG, m_nScreen, nDepth, aTmpRect, aTmpGC );
713 DBG_TESTTRANS( aFG );
715 // draw background in pixmap #2
716 XCopyArea( pXDisp, aDrawable, aBG, aTmpGC,
717 pPosAry->mnDestX, pPosAry->mnDestY,
718 pPosAry->mnDestWidth, pPosAry->mnDestHeight,
719 0, 0 );
721 DBG_TESTTRANS( aBG );
723 // mask out paint bitmap in pixmap #1 (transparent areas 0)
724 aValues.function = GXand, aValues.foreground = 0x00000000, aValues.background = 0xffffffff;
725 XChangeGC( pXDisp, aTmpGC, nValues, &aValues );
726 static_cast<const X11SalBitmap&>(rTransBitmap).ImplDraw( aFG, m_nScreen, 1, aTmpRect, aTmpGC );
728 DBG_TESTTRANS( aFG );
730 // #105055# For XOR mode, keep background behind bitmap intact
731 if( !bXORMode_ )
733 // mask out background in pixmap #2 (nontransparent areas 0)
734 aValues.function = GXand, aValues.foreground = 0xffffffff, aValues.background = 0x00000000;
735 XChangeGC( pXDisp, aTmpGC, nValues, &aValues );
736 static_cast<const X11SalBitmap&>(rTransBitmap).ImplDraw( aBG, m_nScreen, 1, aTmpRect, aTmpGC );
738 DBG_TESTTRANS( aBG );
741 // merge pixmap #1 and pixmap #2 in pixmap #2
742 aValues.function = GXxor, aValues.foreground = 0xffffffff, aValues.background = 0x00000000;
743 XChangeGC( pXDisp, aTmpGC, nValues, &aValues );
744 XCopyArea( pXDisp, aFG, aBG, aTmpGC,
745 0, 0,
746 pPosAry->mnDestWidth, pPosAry->mnDestHeight,
747 0, 0 );
748 DBG_TESTTRANS( aBG );
750 // #105055# Disable XOR temporarily
751 BOOL bOldXORMode( bXORMode_ );
752 bXORMode_ = FALSE;
754 // copy pixmap #2 (result) to background
755 XCopyArea( pXDisp, aBG, aDrawable, GetCopyGC(),
756 0, 0,
757 pPosAry->mnDestWidth, pPosAry->mnDestHeight,
758 pPosAry->mnDestX, pPosAry->mnDestY );
760 DBG_TESTTRANS( aBG );
762 bXORMode_ = bOldXORMode;
764 XFreeGC( pXDisp, aTmpGC );
765 XFlush( pXDisp );
767 else
768 drawBitmap( pPosAry, rSalBitmap );
770 if( aFG )
771 XFreePixmap( pXDisp, aFG );
773 if( aBG )
774 XFreePixmap( pXDisp, aBG );
777 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
778 bool X11SalGraphics::drawAlphaBitmap( const SalTwoRect& rTR,
779 const SalBitmap& rSrcBitmap, const SalBitmap& rAlphaBmp )
781 // non 8-bit alpha not implemented yet
782 if( rAlphaBmp.GetBitCount() != 8 )
783 return false;
785 // horizontal mirroring not implemented yet
786 if( rTR.mnDestWidth < 0 )
787 return false;
789 // stretched conversion is not implemented yet
790 if( rTR.mnDestWidth != rTR.mnSrcWidth )
791 return false;
792 if( rTR.mnDestHeight!= rTR.mnSrcHeight )
793 return false;
795 XRenderPeer& rPeer = XRenderPeer::GetInstance();
796 if( rPeer.GetVersion() < 0x02 )
797 return false;
799 // create destination picture
800 Picture aDstPic = GetXRenderPicture();
801 if( !aDstPic )
802 return false;
804 const SalDisplay* pSalDisp = GetDisplay();
805 const SalVisual& rSalVis = pSalDisp->GetVisual( m_nScreen );
806 Display* pXDisplay = pSalDisp->GetDisplay();
808 // create source Picture
809 int nDepth = m_pVDev ? m_pVDev->GetDepth() : rSalVis.GetDepth();
810 const X11SalBitmap& rSrcX11Bmp = static_cast<const X11SalBitmap&>( rSrcBitmap );
811 ImplSalDDB* pSrcDDB = rSrcX11Bmp.ImplGetDDB( hDrawable_, m_nScreen, nDepth, rTR );
812 if( !pSrcDDB )
813 return false;
815 //#i75249# workaround for ImplGetDDB() giving us back a different depth than
816 // we requested. E.g. mask pixmaps are always compatible with the drawable
817 // TODO: find an appropriate picture format for these cases
818 // then remove the workaround below and the one for #i75531#
819 if( nDepth != pSrcDDB->ImplGetDepth() )
820 return false;
822 Pixmap aSrcPM = pSrcDDB->ImplGetPixmap();
823 if( !aSrcPM )
824 return false;
826 // create source picture
827 // TODO: use scoped picture
828 Visual* pSrcXVisual = rSalVis.GetVisual();
829 XRenderPictFormat* pSrcVisFmt = rPeer.FindVisualFormat( pSrcXVisual );
830 if( !pSrcVisFmt )
831 return false;
832 Picture aSrcPic = rPeer.CreatePicture( aSrcPM, pSrcVisFmt, 0, NULL );
833 if( !aSrcPic )
834 return false;
836 // create alpha Picture
838 // TODO: use SalX11Bitmap functionality and caching for the Alpha Pixmap
839 // problem is that they don't provide an 8bit Pixmap on a non-8bit display
840 BitmapBuffer* pAlphaBuffer = const_cast<SalBitmap&>(rAlphaBmp).AcquireBuffer( TRUE );
842 // an XImage needs its data top_down
843 // TODO: avoid wrongly oriented images in upper layers!
844 const int nImageSize = pAlphaBuffer->mnHeight * pAlphaBuffer->mnScanlineSize;
845 const char* pSrcBits = (char*)pAlphaBuffer->mpBits;
846 char* pAlphaBits = new char[ nImageSize ];
847 if( BMP_SCANLINE_ADJUSTMENT( pAlphaBuffer->mnFormat ) == BMP_FORMAT_TOP_DOWN )
848 memcpy( pAlphaBits, pSrcBits, nImageSize );
849 else
851 char* pDstBits = pAlphaBits + nImageSize;
852 const int nLineSize = pAlphaBuffer->mnScanlineSize;
853 for(; (pDstBits -= nLineSize) >= pAlphaBits; pSrcBits += nLineSize )
854 memcpy( pDstBits, pSrcBits, nLineSize );
857 // the alpha values need to be inverted for XRender
858 // TODO: make upper layers use standard alpha
859 long* pLDst = (long*)pAlphaBits;
860 for( int i = nImageSize/sizeof(long); --i >= 0; ++pLDst )
861 *pLDst = ~*pLDst;
863 char* pCDst = (char*)pLDst;
864 for( int i = nImageSize & (sizeof(long)-1); --i >= 0; ++pCDst )
865 *pCDst = ~*pCDst;
867 const XRenderPictFormat* pAlphaFormat = rPeer.GetStandardFormatA8();
868 XImage* pAlphaImg = XCreateImage( pXDisplay, pSrcXVisual, 8, ZPixmap, 0,
869 pAlphaBits, pAlphaBuffer->mnWidth, pAlphaBuffer->mnHeight,
870 pAlphaFormat->depth, pAlphaBuffer->mnScanlineSize );
872 Pixmap aAlphaPM = XCreatePixmap( pXDisplay, hDrawable_,
873 rTR.mnDestWidth, rTR.mnDestHeight, 8 );
875 XGCValues aAlphaGCV;
876 aAlphaGCV.function = GXcopy;
877 GC aAlphaGC = XCreateGC( pXDisplay, aAlphaPM, GCFunction, &aAlphaGCV );
878 XPutImage( pXDisplay, aAlphaPM, aAlphaGC, pAlphaImg,
879 rTR.mnSrcX, rTR.mnSrcY, 0, 0, rTR.mnDestWidth, rTR.mnDestHeight );
880 XFreeGC( pXDisplay, aAlphaGC );
881 XFree( pAlphaImg );
882 if( pAlphaBits != (char*)pAlphaBuffer->mpBits )
883 delete[] pAlphaBits;
885 const_cast<SalBitmap&>(rAlphaBmp).ReleaseBuffer( pAlphaBuffer, TRUE );
887 XRenderPictureAttributes aAttr;
888 aAttr.repeat = true;
889 Picture aAlphaPic = rPeer.CreatePicture( aAlphaPM, pAlphaFormat, CPRepeat, &aAttr );
890 if( !aAlphaPic )
891 return false;
893 // set clipping
894 if( pClipRegion_ && !XEmptyRegion( pClipRegion_ ) )
895 rPeer.SetPictureClipRegion( aDstPic, pClipRegion_ );
897 // paint source * mask over destination picture
898 rPeer.CompositePicture( PictOpOver, aSrcPic, aAlphaPic, aDstPic,
899 rTR.mnSrcX, rTR.mnSrcY, 0, 0,
900 rTR.mnDestX, rTR.mnDestY, rTR.mnDestWidth, rTR.mnDestHeight );
902 // TODO: used ScopedPic
903 rPeer.FreePicture( aAlphaPic );
904 XFreePixmap(pXDisplay, aAlphaPM);
905 rPeer.FreePicture( aSrcPic );
906 return true;
909 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
910 bool X11SalGraphics::drawAlphaRect( long nX, long nY, long nWidth,
911 long nHeight, sal_uInt8 nTransparency )
913 if( ! m_pFrame && ! m_pVDev )
914 return false;
916 if( bPenGC_ || !bBrushGC_ || bXORMode_ )
917 return false; // can only perform solid fills without XOR.
919 if( m_pVDev && m_pVDev->GetDepth() < 8 )
920 return false;
922 XRenderPeer& rPeer = XRenderPeer::GetInstance();
923 if( rPeer.GetVersion() < 0x02 ) // TODO: replace with better test
924 return false;
926 Picture aDstPic = GetXRenderPicture();
927 if( !aDstPic )
928 return false;
930 const double fTransparency = (100 - nTransparency) * (1.0/100);
931 const XRenderColor aRenderColor = GetXRenderColor( nBrushColor_ , fTransparency);
933 rPeer.FillRectangle( PictOpOver,
934 aDstPic,
935 &aRenderColor,
936 nX, nY,
937 nWidth, nHeight );
939 return true;
942 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
943 void X11SalGraphics::drawBitmap( const SalTwoRect*,
944 const SalBitmap&,
945 SalColor )
947 DBG_ERROR( "::DrawBitmap with transparent color not supported" );
950 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
951 void X11SalGraphics::drawMask( const SalTwoRect* pPosAry,
952 const SalBitmap &rSalBitmap,
953 SalColor nMaskColor )
955 const SalDisplay* pSalDisp = GetDisplay();
956 Display* pXDisp = pSalDisp->GetDisplay();
957 Drawable aDrawable( GetDrawable() );
958 Pixmap aStipple( XCreatePixmap( pXDisp, aDrawable,
959 pPosAry->mnDestWidth,
960 pPosAry->mnDestHeight, 1 ) );
962 if( aStipple )
964 SalTwoRect aTwoRect( *pPosAry ); aTwoRect.mnDestX = aTwoRect.mnDestY = 0;
965 GC aTmpGC;
966 XGCValues aValues;
968 // create a stipple bitmap first (set bits are changed to unset bits and vice versa)
969 aValues.function = GXcopyInverted;
970 aValues.foreground = 1, aValues.background = 0;
971 aTmpGC = XCreateGC( pXDisp, aStipple, GCFunction | GCForeground | GCBackground, &aValues );
972 static_cast<const X11SalBitmap&>(rSalBitmap).ImplDraw( aStipple, m_nScreen, 1, aTwoRect, aTmpGC );
974 XFreeGC( pXDisp, aTmpGC );
976 // Set stipple and draw rectangle
977 GC aStippleGC( GetStippleGC() );
978 int nX = pPosAry->mnDestX, nY = pPosAry->mnDestY;
980 XSetStipple( pXDisp, aStippleGC, aStipple );
981 XSetTSOrigin( pXDisp, aStippleGC, nX, nY );
982 XSetForeground( pXDisp, aStippleGC, GetPixel( nMaskColor ) );
983 XFillRectangle( pXDisp, aDrawable, aStippleGC,
984 nX, nY,
985 pPosAry->mnDestWidth, pPosAry->mnDestHeight );
986 XFreePixmap( pXDisp, aStipple );
987 XFlush( pXDisp );
989 else
990 drawBitmap( pPosAry, rSalBitmap );
993 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
994 SalBitmap *X11SalGraphics::getBitmap( long nX, long nY, long nDX, long nDY )
996 if( bPrinter_ && !bVirDev_ )
997 return NULL;
999 bool bFakeWindowBG = false;
1001 // normalize
1002 if( nDX < 0 )
1004 nX += nDX;
1005 nDX = -nDX;
1007 if ( nDY < 0 )
1009 nY += nDY;
1010 nDY = -nDY;
1013 if( bWindow_ && !bVirDev_ )
1015 XWindowAttributes aAttrib;
1017 XGetWindowAttributes( GetXDisplay(), GetDrawable(), &aAttrib );
1018 if( aAttrib.map_state != IsViewable )
1019 bFakeWindowBG = true;
1020 else
1022 long nOrgDX = nDX, nOrgDY = nDY;
1024 // clip to window size
1025 if ( nX < 0 )
1027 nDX += nX;
1028 nX = 0;
1030 if ( nY < 0 )
1032 nDY += nY;
1033 nY = 0;
1035 if( nX + nDX > aAttrib.width )
1036 nDX = aAttrib.width - nX;
1037 if( nY + nDY > aAttrib.height )
1038 nDY = aAttrib.height - nY;
1040 // inside ?
1041 if( nDX <= 0 || nDY <= 0 )
1043 bFakeWindowBG = true;
1044 nDX = nOrgDX;
1045 nDY = nOrgDY;
1050 X11SalBitmap* pSalBitmap = new X11SalBitmap;
1051 USHORT nBitCount = GetBitCount();
1053 if( &GetDisplay()->GetColormap( m_nScreen ) != &GetColormap() )
1054 nBitCount = 1;
1056 if( ! bFakeWindowBG )
1057 pSalBitmap->ImplCreateFromDrawable( GetDrawable(), m_nScreen, nBitCount, nX, nY, nDX, nDY );
1058 else
1059 pSalBitmap->Create( Size( nDX, nDY ), (nBitCount > 8) ? 24 : nBitCount, BitmapPalette( nBitCount > 8 ? nBitCount : 0 ) );
1061 return pSalBitmap;
1064 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1065 SalColor X11SalGraphics::getPixel( long nX, long nY )
1067 if( bWindow_ && !bVirDev_ )
1069 XWindowAttributes aAttrib;
1071 XGetWindowAttributes( GetXDisplay(), GetDrawable(), &aAttrib );
1072 if( aAttrib.map_state != IsViewable )
1074 stderr0( "X11SalGraphics::GetPixel drawable not viewable\n" );
1075 return 0;
1079 XImage *pXImage = XGetImage( GetXDisplay(),
1080 GetDrawable(),
1081 nX, nY,
1082 1, 1,
1083 AllPlanes,
1084 ZPixmap );
1085 if( !pXImage )
1087 stderr0( "X11SalGraphics::GetPixel !XGetImage()\n" );
1088 return 0;
1091 XColor aXColor;
1093 aXColor.pixel = XGetPixel( pXImage, 0, 0 );
1094 XDestroyImage( pXImage );
1096 return GetColormap().GetColor( aXColor.pixel );
1099 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1100 void X11SalGraphics::invert( long nX,
1101 long nY,
1102 long nDX,
1103 long nDY,
1104 SalInvert nFlags )
1106 GC pGC;
1107 if( SAL_INVERT_50 & nFlags )
1109 pGC = GetInvert50GC();
1110 XFillRectangle( GetXDisplay(), GetDrawable(), pGC, nX, nY, nDX, nDY );
1112 else
1114 if ( SAL_INVERT_TRACKFRAME & nFlags )
1116 pGC = GetTrackingGC();
1117 XDrawRectangle( GetXDisplay(), GetDrawable(), pGC, nX, nY, nDX, nDY );
1119 else
1121 pGC = GetInvertGC();
1122 XFillRectangle( GetXDisplay(), GetDrawable(), pGC, nX, nY, nDX, nDY );
1127 bool X11SalGraphics::supportsOperation( OutDevSupportType eType ) const
1129 bool bRet = false;
1130 switch( eType )
1132 case OutDevSupport_TransparentRect:
1133 case OutDevSupport_B2DDraw:
1135 XRenderPeer& rPeer = XRenderPeer::GetInstance();
1136 if( rPeer.GetVersion() >= 0x02 )
1138 const SalDisplay* pSalDisp = GetDisplay();
1139 const SalVisual& rSalVis = pSalDisp->GetVisual( m_nScreen );
1141 Visual* pDstXVisual = rSalVis.GetVisual();
1142 XRenderPictFormat* pDstVisFmt = rPeer.FindVisualFormat( pDstXVisual );
1143 if( pDstVisFmt )
1144 bRet = true;
1147 break;
1148 default: break;
1150 return bRet;