xref: /aoo41x/main/vcl/unx/generic/gdi/salgdi2.cxx (revision c82f2877)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26 
27 #include <stdio.h>
28 #include <poll.h>
29 
30 #include "vcl/salbtype.hxx"
31 
32 #include "unx/salunx.h"
33 #include "unx/saldata.hxx"
34 #include "unx/saldisp.hxx"
35 #include "unx/salbmp.h"
36 #include "unx/salgdi.h"
37 #include "unx/salframe.h"
38 #include "unx/salvd.h"
39 #include "xrender_peer.hxx"
40 
41 #include "printergfx.hxx"
42 
43 #include "vcl/bmpacc.hxx"
44 
45 #undef SALGDI2_TESTTRANS
46 
47 // -=-= debugging =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
48 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
49 #if 0
50 
51 static void sal_PrintImage( char *s, XImage*p )
52 {
53 	fprintf( stderr, "%s %d %d %d\n", s, p->depth, p->width, p->height );
54 	int nW = Min( 64, p->width*p->bits_per_pixel >> 3 );
55 	for( int i = 0; i < Min( 16, p->height ); i++ )
56 	{
57 		for( int j = 0; j < nW; j++ )
58 			fprintf( stderr, "%02X", (UINT8)p->data[i*p->bytes_per_line+j] );
59 		fprintf( stderr, "\n" );
60 	}
61 }
62 
63 #endif // DBG_UTIL
64 
65 // -----------------------------------------------------------------------------
66 
67 #if (OSL_DEBUG_LEVEL > 1) && defined SALGDI2_TESTTRANS
68 #define DBG_TESTTRANS( _def_drawable )								\
69 {																	\
70 	XCopyArea( pXDisp, _def_drawable, aDrawable, GetCopyGC(),		\
71 			   0, 0,												\
72 			   pPosAry->mnDestWidth, pPosAry->mnDestHeight,			\
73 			   0, 0 );												\
74 }
75 #else // (OSL_DEBUG_LEVEL > 1) && defined SALGDI2_TESTTRANS
76 #define DBG_TESTTRANS( _def_drawable )
77 #endif // (OSL_DEBUG_LEVEL > 1) && defined SALGDI2_TESTTRANS
78 
79 // -=-= X11SalGraphics =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
80 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
81 void X11SalGraphics::CopyScreenArea( Display* pDisplay,
82                                Drawable aSrc, int nScreenSrc, int nSrcDepth,
83                                Drawable aDest, int nScreenDest, int nDestDepth,
84                                GC aDestGC,
85                                int src_x, int src_y,
86                                unsigned int w, unsigned int h,
87                                int dest_x, int dest_y )
88 {
89     if( nSrcDepth == nDestDepth )
90     {
91         if( nScreenSrc == nScreenDest )
92             XCopyArea( pDisplay, aSrc, aDest, aDestGC,
93                        src_x, src_y, w, h, dest_x, dest_y );
94         else
95         {
96             SalXLib* pLib = GetX11SalData()->GetDisplay()->GetXLib();
97             pLib->PushXErrorLevel( true );
98             XImage* pImage = XGetImage( pDisplay, aSrc, src_x, src_y, w, h,
99                                         AllPlanes, ZPixmap );
100             if( pImage )
101             {
102                 if( pImage->data )
103                 {
104                     XPutImage( pDisplay, aDest, aDestGC, pImage,
105                                0, 0, dest_x, dest_y, w, h );
106                 }
107                 XDestroyImage( pImage );
108             }
109             pLib->PopXErrorLevel();
110         }
111     }
112     else
113     {
114         X11SalBitmap aBM;
115         aBM.ImplCreateFromDrawable( aSrc, nScreenSrc, nSrcDepth, src_x, src_y, w, h );
116         SalTwoRect aTwoRect;
117         aTwoRect.mnSrcX = aTwoRect.mnSrcY = 0;
118         aTwoRect.mnSrcWidth = aTwoRect.mnDestWidth = w;
119         aTwoRect.mnSrcHeight = aTwoRect.mnDestHeight = h;
120         aTwoRect.mnDestX = dest_x;
121         aTwoRect.mnDestY = dest_y;
122         aBM.ImplDraw( aDest, nScreenDest, nDestDepth, aTwoRect,aDestGC );
123     }
124 }
125 
126 GC X11SalGraphics::CreateGC( Drawable hDrawable, unsigned long nMask )
127 {
128 	XGCValues values;
129 
130 	values.graphics_exposures	= False;
131 	values.foreground			= m_pColormap->GetBlackPixel()
132 		                          ^ m_pColormap->GetWhitePixel();
133 	values.function				= GXxor;
134 	values.line_width			= 1;
135 	values.fill_style			= FillStippled;
136 	values.stipple				= GetDisplay()->GetInvert50( m_nScreen );
137     values.subwindow_mode		= ClipByChildren;
138 
139 	return XCreateGC( GetXDisplay(), hDrawable, nMask | GCSubwindowMode, &values );
140 }
141 
142 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
143 inline GC X11SalGraphics::GetMonoGC( Pixmap hPixmap )
144 {
145 	if( !pMonoGC_ )
146 		pMonoGC_ = CreateGC( hPixmap );
147 
148 	if( !bMonoGC_ )
149 	{
150 		SetClipRegion( pMonoGC_ );
151 		bMonoGC_ = sal_True;
152 	}
153 
154 	return pMonoGC_;
155 }
156 
157 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
158 inline GC X11SalGraphics::GetCopyGC()
159 {
160 	if( bXORMode_ ) return GetInvertGC();
161 
162 	if( !pCopyGC_ )
163 		pCopyGC_ = CreateGC( GetDrawable() );
164 
165 	if( !bCopyGC_ )
166 	{
167 		SetClipRegion( pCopyGC_ );
168 		bCopyGC_ = sal_True;
169 	}
170 	return pCopyGC_;
171 }
172 
173 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
174 GC X11SalGraphics::GetInvertGC()
175 {
176 	if( !pInvertGC_ )
177 		pInvertGC_ = CreateGC( GetDrawable(),
178 							   GCGraphicsExposures
179 							   | GCForeground
180 							   | GCFunction
181 							   | GCLineWidth );
182 
183 	if( !bInvertGC_ )
184 	{
185 		SetClipRegion( pInvertGC_ );
186 		bInvertGC_ = sal_True;
187 	}
188 	return pInvertGC_;
189 }
190 
191 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
192 GC X11SalGraphics::GetInvert50GC()
193 {
194 	if( !pInvert50GC_ )
195 	{
196 		XGCValues values;
197 
198 		values.graphics_exposures	= False;
199 		values.foreground			= m_pColormap->GetWhitePixel();
200 		values.background			= m_pColormap->GetBlackPixel();
201 		values.function				= GXinvert;
202 		values.line_width			= 1;
203 		values.line_style			= LineSolid;
204 		unsigned long nValueMask =
205 								  GCGraphicsExposures
206 								  | GCForeground
207 								  | GCBackground
208 								  | GCFunction
209 								  | GCLineWidth
210 								  | GCLineStyle
211 								  | GCFillStyle
212 								  | GCStipple;
213 
214 		char* pEnv = getenv( "SAL_DO_NOT_USE_INVERT50" );
215 		if( pEnv && ! strcasecmp( pEnv, "true" ) )
216 		{
217 			values.fill_style = FillSolid;
218 			nValueMask &= ~ GCStipple;
219 		}
220 		else
221 		{
222 			values.fill_style			= FillStippled;
223 			values.stipple				= GetDisplay()->GetInvert50( m_nScreen );
224 		}
225 
226 		pInvert50GC_ = XCreateGC( GetXDisplay(), GetDrawable(),
227 								  nValueMask,
228 								  &values );
229 	}
230 
231 	if( !bInvert50GC_ )
232 	{
233 		SetClipRegion( pInvert50GC_ );
234 		bInvert50GC_ = sal_True;
235 	}
236 	return pInvert50GC_;
237 }
238 
239 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
240 inline GC X11SalGraphics::GetStippleGC()
241 {
242 	if( !pStippleGC_ )
243 		pStippleGC_ = CreateGC( GetDrawable(),
244 								GCGraphicsExposures
245 								| GCFillStyle
246 								| GCLineWidth );
247 
248 	if( !bStippleGC_ )
249 	{
250 		XSetFunction( GetXDisplay(), pStippleGC_, bXORMode_ ? GXxor : GXcopy );
251 		SetClipRegion( pStippleGC_ );
252 		bStippleGC_ = sal_True;
253 	}
254 
255 	return pStippleGC_;
256 }
257 
258 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
259 int X11SalGraphics::Clip( XLIB_Region   pRegion,
260 								 int          &nX,
261 								 int          &nY,
262 								 unsigned int &nDX,
263 								 unsigned int &nDY,
264 								 int          &nSrcX,
265 								 int          &nSrcY ) const
266 {
267 	XRectangle aRect;
268 	XClipBox( pRegion, &aRect );
269 
270 	if( int(nX + nDX) <= int(aRect.x) || nX >= int(aRect.x + aRect.width) )
271 		return RectangleOut;
272 	if( int(nY + nDY) <= int(aRect.y) || nY >= int(aRect.y + aRect.height) )
273 		return RectangleOut;
274 
275 	if( nX < aRect.x )
276 	{
277 		nSrcX += aRect.x - nX;
278 		nDX   -= aRect.x - nX;
279 		nX     = aRect.x;
280 	}
281 	else if( int(nX + nDX) > int(aRect.x + aRect.width) )
282 		nDX = aRect.x + aRect.width - nX;
283 
284 	if( nY < aRect.y )
285 	{
286 		nSrcY += aRect.y - nY;
287 		nDY   -= aRect.y - nY;
288 		nY     = aRect.y;
289 	}
290 	else if( int(nY + nDY) > int(aRect.y + aRect.height) )
291 		nDY = aRect.y + aRect.height - nY;
292 
293 	return RectangleIn;
294 }
295 
296 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
297 int X11SalGraphics::Clip( int          &nX,
298 								 int          &nY,
299 								 unsigned int &nDX,
300 								 unsigned int &nDY,
301 								 int          &nSrcX,
302 								 int          &nSrcY ) const
303 
304 {
305 	if( pPaintRegion_
306 		&& RectangleOut == Clip( pPaintRegion_, nX, nY, nDX, nDY, nSrcX, nSrcY ) )
307 		return RectangleOut;
308 
309 	if( mpClipRegion
310 		&& RectangleOut == Clip( mpClipRegion,  nX, nY, nDX, nDY, nSrcX, nSrcY ) )
311 		return RectangleOut;
312 
313 	int nPaint;
314 	if( pPaintRegion_ )
315 	{
316 		nPaint = XRectInRegion( pPaintRegion_, nX, nY, nDX, nDY );
317 		if( RectangleOut == nPaint )
318 			return RectangleOut;
319 	}
320 	else
321 		nPaint = RectangleIn;
322 
323 	int nClip;
324 	if( mpClipRegion )
325 	{
326 		nClip = XRectInRegion( mpClipRegion, nX, nY, nDX, nDY );
327 		if( RectangleOut == nClip )
328 			return RectangleOut;
329 	}
330 	else
331 		nClip = RectangleIn;
332 
333 	return RectangleIn == nClip && RectangleIn == nPaint
334 		   ? RectangleIn
335 		   : RectanglePart;
336 }
337 
338 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
339 GC X11SalGraphics::SetMask( int           &nX,
340 								   int           &nY,
341 								   unsigned int &nDX,
342 								   unsigned int &nDY,
343 								   int          &nSrcX,
344 								   int          &nSrcY,
345 								   Pixmap        hClipMask )
346 {
347 	int n = Clip( nX, nY, nDX, nDY, nSrcX, nSrcY );
348 	if( RectangleOut == n )
349 		return NULL;
350 
351 	Display *pDisplay = GetXDisplay();
352 
353 	if( !pMaskGC_ )
354 		pMaskGC_ = CreateGC( GetDrawable() );
355 
356 	if( RectangleIn == n )
357 	{
358 		XSetClipMask( pDisplay, pMaskGC_, hClipMask );
359 		XSetClipOrigin( pDisplay, pMaskGC_, nX - nSrcX, nY - nSrcY );
360 		return pMaskGC_;
361 	}
362 
363 	// - - - - create alternate clip pixmap for region clipping - - - -
364 	Pixmap hPixmap	= XCreatePixmap( pDisplay, hClipMask, nDX, nDY, 1 );
365 
366 	if( !hPixmap )
367 	{
368 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
369 		fprintf( stderr, "X11SalGraphics::SetMask !hPixmap\n" );
370 #endif
371 		return NULL;
372 	}
373 
374 	// - - - - reset pixmap; all 0 - - - - - - - - - - - - - - - - - - -
375 	XFillRectangle( pDisplay,
376 					hPixmap,
377 					GetDisplay()->GetMonoGC( m_nScreen ),
378 					0,   0,
379 					nDX, nDY );
380 
381 	// - - - - copy pixmap only within region - - - - - - - - - - - - -
382 	GC pMonoGC = GetMonoGC( hPixmap );
383 	XSetClipOrigin( pDisplay, pMonoGC, -nX, -nY );
384 	XCopyArea( pDisplay,
385 			   hClipMask,			// Source
386 			   hPixmap,				// Destination
387 			   pMonoGC,
388 			   nSrcX, nSrcY,		// Source
389 			   nDX,   nDY,			// Width & Height
390 			   0,     0 );			// Destination
391 
392 	XSetClipMask( pDisplay, pMaskGC_, hPixmap );
393 	XSetClipOrigin( pDisplay, pMaskGC_, nX, nY );
394 
395 	XFreePixmap( pDisplay, hPixmap );
396 	return pMaskGC_;
397 }
398 
399 // -=-= SalGraphics =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
400 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
401 
402 extern "C"
403 {
404     static Bool GraphicsExposePredicate( Display*, XEvent* pEvent, XPointer pFrameWindow )
405     {
406         Bool bRet = False;
407         if( (pEvent->type == GraphicsExpose || pEvent->type == NoExpose) &&
408             pEvent->xnoexpose.drawable == (Drawable)pFrameWindow )
409         {
410             bRet = True;
411         }
412         return bRet;
413     }
414 }
415 
416 
417 void X11SalGraphics::YieldGraphicsExpose()
418 {
419     // get frame if necessary
420     SalFrame* pFrame    = m_pFrame;
421     Display* pDisplay   = GetXDisplay();
422     XLIB_Window aWindow = GetDrawable();
423     if( ! pFrame )
424     {
425         const std::list< SalFrame* >& rFrames = GetX11SalData()->GetDisplay()->getFrames();
426         for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end() && ! pFrame; ++it )
427         {
428             const SystemEnvData* pEnvData = (*it)->GetSystemData();
429             if( Drawable(pEnvData->aWindow) == aWindow )
430                 pFrame = *it;
431         }
432         if( ! pFrame )
433             return;
434     }
435 
436     XEvent aEvent;
437     while( XCheckTypedWindowEvent( pDisplay, aWindow, Expose, &aEvent ) )
438     {
439         SalPaintEvent aPEvt( aEvent.xexpose.x, aEvent.xexpose.y, aEvent.xexpose.width+1, aEvent.xexpose.height+1 );
440         pFrame->CallCallback( SALEVENT_PAINT, &aPEvt );
441     }
442 
443     do
444     {
445         if( ! GetDisplay()->XIfEventWithTimeout( &aEvent, (XPointer)aWindow, GraphicsExposePredicate ) )
446             // this should not happen at all; still sometimes it happens
447             break;
448 
449         if( aEvent.type == NoExpose )
450             break;
451 
452         if( pFrame )
453         {
454             SalPaintEvent aPEvt( aEvent.xgraphicsexpose.x, aEvent.xgraphicsexpose.y, aEvent.xgraphicsexpose.width+1, aEvent.xgraphicsexpose.height+1 );
455             pFrame->CallCallback( SALEVENT_PAINT, &aPEvt );
456         }
457     } while( aEvent.xgraphicsexpose.count != 0 );
458 }
459 
460 void X11SalGraphics::copyBits( const SalTwoRect *pPosAry,
461 								  SalGraphics	   *pSSrcGraphics )
462 {
463     X11SalGraphics* pSrcGraphics = pSSrcGraphics
464         ? static_cast<X11SalGraphics*>(pSSrcGraphics)
465         : this;
466 
467     if( pPosAry->mnSrcWidth <= 0
468         || pPosAry->mnSrcHeight <= 0
469         || pPosAry->mnDestWidth <= 0
470         || pPosAry->mnDestHeight <= 0 )
471     {
472         return;
473     }
474 
475     int n;
476     if( pSrcGraphics == this )
477     {
478         n = 2;
479     }
480     else if( pSrcGraphics->bWindow_ )
481     {
482         // window or compatible virtual device
483         if( pSrcGraphics->GetDisplay() == GetDisplay() &&
484             pSrcGraphics->m_nScreen == m_nScreen &&
485             pSrcGraphics->GetVisual().GetDepth() == GetVisual().GetDepth()
486             )
487             n = 2; // same Display
488         else
489             n = 1; // printer or other display
490     }
491     else if( pSrcGraphics->bVirDev_ )
492     {
493         // printer compatible virtual device
494         if( bPrinter_ )
495             n = 2; // printer or compatible virtual device == same display
496         else
497             n = 1; // window or compatible virtual device
498     }
499     else
500         n = 0;
501 
502     if( n == 2
503         && pPosAry->mnSrcWidth	== pPosAry->mnDestWidth
504         && pPosAry->mnSrcHeight == pPosAry->mnDestHeight
505         )
506     {
507         // #i60699# Need to generate graphics exposures (to repaint
508         // obscured areas beneath overlapping windows), src and dest
509         // are the same window.
510         const bool bNeedGraphicsExposures( pSrcGraphics == this &&
511                                            !bVirDev_ &&
512                                            pSrcGraphics->bWindow_ );
513 
514         GC pCopyGC;
515 
516         if( bXORMode_
517             && !pSrcGraphics->bVirDev_
518             && (GetDisplay()->GetProperties() & PROPERTY_BUG_XCopyArea_GXxor) )
519         {
520             Pixmap hPixmap = XCreatePixmap( GetXDisplay(),
521                                             pSrcGraphics->GetDrawable(),		// source
522                                             pPosAry->mnSrcWidth, pPosAry->mnSrcHeight,
523                                             pSrcGraphics->GetBitCount() );
524 
525             pCopyGC = GetDisplay()->GetCopyGC( m_nScreen );
526 
527             if( bNeedGraphicsExposures )
528                 XSetGraphicsExposures( GetXDisplay(),
529                                        pCopyGC,
530                                        True );
531 
532             XCopyArea( GetXDisplay(),
533                        pSrcGraphics->GetDrawable(),		// source
534                        hPixmap,							// destination
535                        pCopyGC,							// no clipping
536                        pPosAry->mnSrcX,     pPosAry->mnSrcY,
537                        pPosAry->mnSrcWidth, pPosAry->mnSrcHeight,
538                        0,    				0 );			// destination
539             XCopyArea( GetXDisplay(),
540                        hPixmap,								// source
541                        GetDrawable(),						// destination
542                        GetInvertGC(),		// destination clipping
543                        0,				    0,				// source
544                        pPosAry->mnSrcWidth, pPosAry->mnSrcHeight,
545                        pPosAry->mnDestX,    pPosAry->mnDestY );
546             XFreePixmap( GetXDisplay(), hPixmap );
547         }
548         else
549         {
550             pCopyGC = GetCopyGC();
551 
552             if( bNeedGraphicsExposures )
553                 XSetGraphicsExposures( GetXDisplay(),
554                                        pCopyGC,
555                                        True );
556 
557             XCopyArea( GetXDisplay(),
558                        pSrcGraphics->GetDrawable(),		// source
559                        GetDrawable(),					// destination
560                        pCopyGC,							// destination clipping
561                        pPosAry->mnSrcX,     pPosAry->mnSrcY,
562                        pPosAry->mnSrcWidth, pPosAry->mnSrcHeight,
563                        pPosAry->mnDestX,    pPosAry->mnDestY );
564         }
565 
566         if( bNeedGraphicsExposures )
567         {
568             YieldGraphicsExpose();
569 
570             if( pCopyGC )
571                 XSetGraphicsExposures( GetXDisplay(),
572                                        pCopyGC,
573                                        False );
574         }
575     }
576     else if( n )
577     {
578         // #i60699# No chance to handle graphics exposures - we copy
579         // to a temp bitmap first, into which no repaints are
580         // technically possible.
581         SalBitmap *pDDB = pSrcGraphics->getBitmap( pPosAry->mnSrcX,
582                                                    pPosAry->mnSrcY,
583                                                    pPosAry->mnSrcWidth,
584                                                    pPosAry->mnSrcHeight );
585 
586         if( !pDDB )
587         {
588             stderr0( "SalGraphics::CopyBits !pSrcGraphics->GetBitmap()\n" );
589             return;
590         }
591 
592         SalTwoRect aPosAry( *pPosAry );
593 
594         aPosAry.mnSrcX = 0,	aPosAry.mnSrcY = 0;
595         drawBitmap( &aPosAry, *pDDB );
596 
597         delete pDDB;
598     }
599     else {
600         stderr0( "X11SalGraphics::CopyBits from Printer not yet implemented\n" );
601     }
602 }
603 
604 // --------------------------------------------------------------------------
605 
606 void X11SalGraphics::copyArea ( long nDestX,    long nDestY,
607                                 long nSrcX,     long nSrcY,
608                                 long nSrcWidth, long nSrcHeight,
609                                 sal_uInt16 )
610 {
611     SalTwoRect aPosAry;
612 
613     aPosAry.mnDestX = nDestX;
614     aPosAry.mnDestY = nDestY;
615     aPosAry.mnDestWidth  = nSrcWidth;
616     aPosAry.mnDestHeight = nSrcHeight;
617 
618     aPosAry.mnSrcX = nSrcX;
619     aPosAry.mnSrcY = nSrcY;
620     aPosAry.mnSrcWidth  = nSrcWidth;
621     aPosAry.mnSrcHeight = nSrcHeight;
622 
623     copyBits ( &aPosAry, 0 );
624 }
625 
626 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
627 void X11SalGraphics::drawBitmap( const SalTwoRect* pPosAry, const SalBitmap& rSalBitmap )
628 {
629     const SalDisplay*   pSalDisp = GetDisplay();
630     Display*			pXDisp = pSalDisp->GetDisplay();
631     const Drawable		aDrawable( GetDrawable() );
632     const SalColormap&	rColMap = pSalDisp->GetColormap( m_nScreen );
633     const long			nDepth = GetDisplay()->GetVisual( m_nScreen ).GetDepth();
634     GC					aGC( GetCopyGC() );
635     XGCValues			aOldVal, aNewVal;
636     int					nValues = GCForeground | GCBackground;
637 
638     if( rSalBitmap.GetBitCount() == 1 )
639     {
640         // set foreground/background values for 1Bit bitmaps
641         XGetGCValues( pXDisp, aGC, nValues, &aOldVal );
642         aNewVal.foreground = rColMap.GetWhitePixel(), aNewVal.background = rColMap.GetBlackPixel();
643         XChangeGC( pXDisp, aGC, nValues, &aNewVal );
644     }
645 
646     static_cast<const X11SalBitmap&>(rSalBitmap).ImplDraw( aDrawable, m_nScreen, nDepth, *pPosAry, aGC );
647 
648     if( rSalBitmap.GetBitCount() == 1 )
649         XChangeGC( pXDisp, aGC, nValues, &aOldVal );
650     XFlush( pXDisp );
651 }
652 
653 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
654 
655 void X11SalGraphics::drawBitmap( const SalTwoRect* pPosAry,
656                                  const SalBitmap& rSrcBitmap,
657                                  const SalBitmap& rMaskBitmap )
658 {
659     DBG_ASSERT( !bPrinter_, "Drawing of transparent bitmaps on printer devices is strictly forbidden" );
660 
661     // decide if alpha masking or transparency masking is needed
662     BitmapBuffer* pAlphaBuffer = const_cast<SalBitmap&>(rMaskBitmap).AcquireBuffer( sal_True );
663     if( pAlphaBuffer != NULL )
664     {
665         int nMaskFormat = pAlphaBuffer->mnFormat;
666         const_cast<SalBitmap&>(rMaskBitmap).ReleaseBuffer( pAlphaBuffer, sal_True );
667         if( nMaskFormat == BMP_FORMAT_8BIT_PAL )
668             drawAlphaBitmap( *pPosAry, rSrcBitmap, rMaskBitmap );
669     }
670 
671     drawMaskedBitmap( pPosAry, rSrcBitmap, rMaskBitmap );
672 }
673 
674 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
675 
676 void X11SalGraphics::drawMaskedBitmap( const SalTwoRect* pPosAry,
677                                        const SalBitmap& rSalBitmap,
678                                        const SalBitmap& rTransBitmap )
679 {
680     const SalDisplay*   pSalDisp = GetDisplay();
681     Display*            pXDisp = pSalDisp->GetDisplay();
682     Drawable            aDrawable( GetDrawable() );
683 
684     // figure work mode depth. If this is a VDev Drawable, use its
685     // bitdepth to create pixmaps for, otherwise, XCopyArea will
686     // refuse to work.
687     const sal_uInt16	nDepth( m_pVDev ?
688                             m_pVDev->GetDepth() :
689                             pSalDisp->GetVisual( m_nScreen ).GetDepth() );
690     Pixmap			aFG( XCreatePixmap( pXDisp, aDrawable, pPosAry->mnDestWidth,
691                                         pPosAry->mnDestHeight, nDepth ) );
692     Pixmap			aBG( XCreatePixmap( pXDisp, aDrawable, pPosAry->mnDestWidth,
693                                         pPosAry->mnDestHeight, nDepth ) );
694 
695     if( aFG && aBG )
696     {
697         GC					aTmpGC;
698         XGCValues			aValues;
699         const SalColormap&	rColMap = pSalDisp->GetColormap( m_nScreen );
700         const int			nBlack = rColMap.GetBlackPixel(), nWhite = rColMap.GetWhitePixel();
701         const int			nValues = GCFunction | GCForeground | GCBackground;
702         SalTwoRect			aTmpRect( *pPosAry ); aTmpRect.mnDestX = aTmpRect.mnDestY = 0;
703 
704         // draw paint bitmap in pixmap #1
705         aValues.function = GXcopy, aValues.foreground = nWhite, aValues.background = nBlack;
706         aTmpGC = XCreateGC( pXDisp, aFG, nValues, &aValues );
707         static_cast<const X11SalBitmap&>(rSalBitmap).ImplDraw( aFG, m_nScreen, nDepth, aTmpRect, aTmpGC );
708         DBG_TESTTRANS( aFG );
709 
710         // draw background in pixmap #2
711         XCopyArea( pXDisp, aDrawable, aBG, aTmpGC,
712                    pPosAry->mnDestX, pPosAry->mnDestY,
713                    pPosAry->mnDestWidth, pPosAry->mnDestHeight,
714                    0, 0 );
715 
716         DBG_TESTTRANS( aBG );
717 
718         // mask out paint bitmap in pixmap #1 (transparent areas 0)
719         aValues.function = GXand, aValues.foreground = 0x00000000, aValues.background = 0xffffffff;
720         XChangeGC( pXDisp, aTmpGC, nValues, &aValues );
721         static_cast<const X11SalBitmap&>(rTransBitmap).ImplDraw( aFG, m_nScreen, 1, aTmpRect, aTmpGC );
722 
723         DBG_TESTTRANS( aFG );
724 
725         // #105055# For XOR mode, keep background behind bitmap intact
726         if( !bXORMode_ )
727         {
728             // mask out background in pixmap #2 (nontransparent areas 0)
729             aValues.function = GXand, aValues.foreground = 0xffffffff, aValues.background = 0x00000000;
730             XChangeGC( pXDisp, aTmpGC, nValues, &aValues );
731             static_cast<const X11SalBitmap&>(rTransBitmap).ImplDraw( aBG, m_nScreen, 1, aTmpRect, aTmpGC );
732 
733             DBG_TESTTRANS( aBG );
734         }
735 
736         // merge pixmap #1 and pixmap #2 in pixmap #2
737         aValues.function = GXxor, aValues.foreground = 0xffffffff, aValues.background = 0x00000000;
738         XChangeGC( pXDisp, aTmpGC, nValues, &aValues );
739         XCopyArea( pXDisp, aFG, aBG, aTmpGC,
740                    0, 0,
741                    pPosAry->mnDestWidth, pPosAry->mnDestHeight,
742 				   0, 0 );
743         DBG_TESTTRANS( aBG );
744 
745         // #105055# Disable XOR temporarily
746         sal_Bool bOldXORMode( bXORMode_ );
747         bXORMode_ = sal_False;
748 
749         // copy pixmap #2 (result) to background
750         XCopyArea( pXDisp, aBG, aDrawable, GetCopyGC(),
751                    0, 0,
752                    pPosAry->mnDestWidth, pPosAry->mnDestHeight,
753                    pPosAry->mnDestX, pPosAry->mnDestY );
754 
755         DBG_TESTTRANS( aBG );
756 
757         bXORMode_ = bOldXORMode;
758 
759         XFreeGC( pXDisp, aTmpGC );
760         XFlush( pXDisp );
761     }
762     else
763         drawBitmap( pPosAry, rSalBitmap );
764 
765     if( aFG )
766         XFreePixmap( pXDisp, aFG );
767 
768     if( aBG )
769         XFreePixmap( pXDisp, aBG );
770 }
771 
772 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
773 bool X11SalGraphics::drawAlphaBitmap( const SalTwoRect& rTR,
774     const SalBitmap& rSrcBitmap, const SalBitmap& rAlphaBmp )
775 {
776     // non 8-bit alpha not implemented yet
777     if( rAlphaBmp.GetBitCount() != 8 )
778         return false;
779 
780     // horizontal mirroring not implemented yet
781     if( rTR.mnDestWidth < 0 )
782         return false;
783 
784     // stretched conversion is not implemented yet
785     if( rTR.mnDestWidth != rTR.mnSrcWidth )
786         return false;
787     if( rTR.mnDestHeight!= rTR.mnSrcHeight )
788         return false;
789 
790     XRenderPeer& rPeer = XRenderPeer::GetInstance();
791     if( rPeer.GetVersion() < 0x02 )
792         return false;
793 
794     // create destination picture
795     Picture aDstPic = GetXRenderPicture();
796     if( !aDstPic )
797         return false;
798 
799     const SalDisplay* pSalDisp = GetDisplay();
800     const SalVisual& rSalVis = pSalDisp->GetVisual( m_nScreen );
801     Display* pXDisplay = pSalDisp->GetDisplay();
802 
803     // create source Picture
804     int nDepth = m_pVDev ? m_pVDev->GetDepth() : rSalVis.GetDepth();
805     const X11SalBitmap& rSrcX11Bmp = static_cast<const X11SalBitmap&>( rSrcBitmap );
806     ImplSalDDB* pSrcDDB = rSrcX11Bmp.ImplGetDDB( hDrawable_, m_nScreen, nDepth, rTR );
807     if( !pSrcDDB )
808         return false;
809 
810     //#i75249# workaround for ImplGetDDB() giving us back a different depth than
811     // we requested. E.g. mask pixmaps are always compatible with the drawable
812     // TODO: find an appropriate picture format for these cases
813     //       then remove the workaround below and the one for #i75531#
814     if( nDepth != pSrcDDB->ImplGetDepth() )
815         return false;
816 
817     Pixmap aSrcPM = pSrcDDB->ImplGetPixmap();
818     if( !aSrcPM )
819         return false;
820 
821     // create source picture
822     // TODO: use scoped picture
823     Visual* pSrcXVisual = rSalVis.GetVisual();
824     XRenderPictFormat* pSrcVisFmt = rPeer.FindVisualFormat( pSrcXVisual );
825     if( !pSrcVisFmt )
826         return false;
827     Picture aSrcPic = rPeer.CreatePicture( aSrcPM, pSrcVisFmt, 0, NULL );
828     if( !aSrcPic )
829         return false;
830 
831     // create alpha Picture
832 
833     // TODO: use SalX11Bitmap functionality and caching for the Alpha Pixmap
834     // problem is that they don't provide an 8bit Pixmap on a non-8bit display
835     BitmapBuffer* pAlphaBuffer = const_cast<SalBitmap&>(rAlphaBmp).AcquireBuffer( sal_True );
836 
837     // an XImage needs its data top_down
838     // TODO: avoid wrongly oriented images in upper layers!
839     const int nImageSize = pAlphaBuffer->mnHeight * pAlphaBuffer->mnScanlineSize;
840     const char* pSrcBits = (char*)pAlphaBuffer->mpBits;
841     char* pAlphaBits = new char[ nImageSize ];
842     if( BMP_SCANLINE_ADJUSTMENT( pAlphaBuffer->mnFormat ) == BMP_FORMAT_TOP_DOWN )
843         memcpy( pAlphaBits, pSrcBits, nImageSize );
844     else
845     {
846         char* pDstBits = pAlphaBits + nImageSize;
847         const int nLineSize = pAlphaBuffer->mnScanlineSize;
848         for(; (pDstBits -= nLineSize) >= pAlphaBits; pSrcBits += nLineSize )
849             memcpy( pDstBits, pSrcBits, nLineSize );
850     }
851 
852     // the alpha values need to be inverted for XRender
853     // TODO: make upper layers use standard alpha
854     long* pLDst = (long*)pAlphaBits;
855     for( int i = nImageSize/sizeof(long); --i >= 0; ++pLDst )
856         *pLDst = ~*pLDst;
857 
858     char* pCDst = (char*)pLDst;
859     for( int i = nImageSize & (sizeof(long)-1); --i >= 0; ++pCDst )
860         *pCDst = ~*pCDst;
861 
862     const XRenderPictFormat* pAlphaFormat = rPeer.GetStandardFormatA8();
863     XImage* pAlphaImg = XCreateImage( pXDisplay, pSrcXVisual, 8, ZPixmap, 0,
864         pAlphaBits, pAlphaBuffer->mnWidth, pAlphaBuffer->mnHeight,
865         pAlphaFormat->depth, pAlphaBuffer->mnScanlineSize );
866 
867     Pixmap aAlphaPM = XCreatePixmap( pXDisplay, hDrawable_,
868         rTR.mnDestWidth, rTR.mnDestHeight, 8 );
869 
870     XGCValues aAlphaGCV;
871     aAlphaGCV.function = GXcopy;
872     GC aAlphaGC = XCreateGC( pXDisplay, aAlphaPM, GCFunction, &aAlphaGCV );
873     XPutImage( pXDisplay, aAlphaPM, aAlphaGC, pAlphaImg,
874         rTR.mnSrcX, rTR.mnSrcY, 0, 0, rTR.mnDestWidth, rTR.mnDestHeight );
875     XFreeGC( pXDisplay, aAlphaGC );
876     XFree( pAlphaImg );
877     if( pAlphaBits != (char*)pAlphaBuffer->mpBits )
878         delete[] pAlphaBits;
879 
880     const_cast<SalBitmap&>(rAlphaBmp).ReleaseBuffer( pAlphaBuffer, sal_True );
881 
882     XRenderPictureAttributes aAttr;
883     aAttr.repeat = true;
884     Picture aAlphaPic = rPeer.CreatePicture( aAlphaPM, pAlphaFormat, CPRepeat, &aAttr );
885     if( !aAlphaPic )
886         return false;
887 
888     // set clipping
889     if( mpClipRegion && !XEmptyRegion( mpClipRegion ) )
890         rPeer.SetPictureClipRegion( aDstPic, mpClipRegion );
891 
892     // paint source * mask over destination picture
893     rPeer.CompositePicture( PictOpOver, aSrcPic, aAlphaPic, aDstPic,
894         rTR.mnSrcX, rTR.mnSrcY, 0, 0,
895         rTR.mnDestX, rTR.mnDestY, rTR.mnDestWidth, rTR.mnDestHeight );
896 
897     // TODO: used ScopedPic
898     rPeer.FreePicture( aAlphaPic );
899     XFreePixmap(pXDisplay, aAlphaPM);
900     rPeer.FreePicture( aSrcPic );
901     return true;
902 }
903 
904 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
905 bool X11SalGraphics::drawAlphaRect( long nX, long nY, long nWidth,
906                                     long nHeight, sal_uInt8 nTransparency )
907 {
908     if( ! m_pFrame && ! m_pVDev )
909         return false;
910 
911     if( bPenGC_ || !bBrushGC_ || bXORMode_ )
912         return false; // can only perform solid fills without XOR.
913 
914     if( m_pVDev && m_pVDev->GetDepth() < 8 )
915         return false;
916 
917     XRenderPeer& rPeer = XRenderPeer::GetInstance();
918     if( rPeer.GetVersion() < 0x02 ) // TODO: replace with better test
919         return false;
920 
921     Picture aDstPic = GetXRenderPicture();
922     if( !aDstPic )
923         return false;
924 
925 	const double fTransparency = (100 - nTransparency) * (1.0/100);
926 	const XRenderColor aRenderColor = GetXRenderColor( nBrushColor_ , fTransparency);
927 
928     rPeer.FillRectangle( PictOpOver,
929                          aDstPic,
930                          &aRenderColor,
931                          nX, nY,
932                          nWidth, nHeight );
933 
934     return true;
935 }
936 
937 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
938 void X11SalGraphics::drawBitmap( const SalTwoRect*,
939                                  const SalBitmap&,
940                                  SalColor )
941 {
942     DBG_ERROR( "::DrawBitmap with transparent color not supported" );
943 }
944 
945 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
946 void X11SalGraphics::drawMask( const SalTwoRect* pPosAry,
947                                const SalBitmap &rSalBitmap,
948                                SalColor nMaskColor )
949 {
950     const SalDisplay*   pSalDisp = GetDisplay();
951     Display*	        pXDisp = pSalDisp->GetDisplay();
952     Drawable            aDrawable( GetDrawable() );
953     Pixmap              aStipple( XCreatePixmap( pXDisp, aDrawable,
954                                                  pPosAry->mnDestWidth,
955                                                  pPosAry->mnDestHeight, 1 ) );
956 
957     if( aStipple )
958     {
959         SalTwoRect	aTwoRect( *pPosAry ); aTwoRect.mnDestX = aTwoRect.mnDestY = 0;
960         GC			aTmpGC;
961         XGCValues	aValues;
962 
963         // create a stipple bitmap first (set bits are changed to unset bits and vice versa)
964         aValues.function = GXcopyInverted;
965         aValues.foreground = 1, aValues.background = 0;
966         aTmpGC = XCreateGC( pXDisp, aStipple, GCFunction | GCForeground | GCBackground, &aValues );
967         static_cast<const X11SalBitmap&>(rSalBitmap).ImplDraw( aStipple, m_nScreen, 1, aTwoRect, aTmpGC );
968 
969         XFreeGC( pXDisp, aTmpGC );
970 
971         // Set stipple and draw rectangle
972         GC	aStippleGC( GetStippleGC() );
973         int	nX = pPosAry->mnDestX, nY = pPosAry->mnDestY;
974 
975         XSetStipple( pXDisp, aStippleGC, aStipple );
976         XSetTSOrigin( pXDisp, aStippleGC, nX, nY );
977         XSetForeground( pXDisp, aStippleGC, GetPixel( nMaskColor ) );
978         XFillRectangle( pXDisp, aDrawable, aStippleGC,
979                         nX, nY,
980                         pPosAry->mnDestWidth, pPosAry->mnDestHeight );
981         XFreePixmap( pXDisp, aStipple );
982         XFlush( pXDisp );
983     }
984     else
985         drawBitmap( pPosAry, rSalBitmap );
986 }
987 
988 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
989 SalBitmap *X11SalGraphics::getBitmap( long nX, long nY, long nDX, long nDY )
990 {
991     if( bPrinter_ && !bVirDev_ )
992         return NULL;
993 
994     bool bFakeWindowBG = false;
995 
996     // normalize
997     if( nDX < 0 )
998     {
999         nX += nDX;
1000         nDX = -nDX;
1001     }
1002     if ( nDY < 0 )
1003     {
1004         nY += nDY;
1005         nDY = -nDY;
1006     }
1007 
1008     if( bWindow_ && !bVirDev_ )
1009     {
1010         XWindowAttributes aAttrib;
1011 
1012         XGetWindowAttributes( GetXDisplay(), GetDrawable(), &aAttrib );
1013         if( aAttrib.map_state != IsViewable )
1014             bFakeWindowBG = true;
1015         else
1016         {
1017             long nOrgDX = nDX, nOrgDY = nDY;
1018 
1019             // clip to window size
1020             if ( nX < 0 )
1021             {
1022                 nDX += nX;
1023                 nX   = 0;
1024             }
1025             if ( nY < 0 )
1026             {
1027                 nDY += nY;
1028                 nY   = 0;
1029             }
1030             if( nX + nDX > aAttrib.width )
1031                 nDX = aAttrib.width  - nX;
1032             if( nY + nDY > aAttrib.height )
1033                 nDY = aAttrib.height - nY;
1034 
1035             // inside ?
1036             if( nDX <= 0 || nDY <= 0 )
1037             {
1038                 bFakeWindowBG = true;
1039                 nDX = nOrgDX;
1040                 nDY = nOrgDY;
1041             }
1042         }
1043     }
1044 
1045     X11SalBitmap*	pSalBitmap = new X11SalBitmap;
1046     sal_uInt16			nBitCount = GetBitCount();
1047 
1048     if( &GetDisplay()->GetColormap( m_nScreen ) != &GetColormap() )
1049         nBitCount = 1;
1050 
1051     if( ! bFakeWindowBG )
1052         pSalBitmap->ImplCreateFromDrawable( GetDrawable(), m_nScreen, nBitCount, nX, nY, nDX, nDY );
1053     else
1054         pSalBitmap->Create( Size( nDX, nDY ), (nBitCount > 8) ? 24 : nBitCount, BitmapPalette( nBitCount > 8 ? nBitCount : 0 ) );
1055 
1056     return pSalBitmap;
1057 }
1058 
1059 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1060 SalColor X11SalGraphics::getPixel( long nX, long nY )
1061 {
1062     if( bWindow_ && !bVirDev_ )
1063     {
1064         XWindowAttributes aAttrib;
1065 
1066         XGetWindowAttributes( GetXDisplay(), GetDrawable(), &aAttrib );
1067         if( aAttrib.map_state != IsViewable )
1068         {
1069             stderr0( "X11SalGraphics::GetPixel drawable not viewable\n" );
1070             return 0;
1071         }
1072     }
1073 
1074     XImage *pXImage = XGetImage( GetXDisplay(),
1075                                      GetDrawable(),
1076                                  nX, nY,
1077                                  1,  1,
1078                                  AllPlanes,
1079                                  ZPixmap );
1080     if( !pXImage )
1081     {
1082         stderr0( "X11SalGraphics::GetPixel !XGetImage()\n" );
1083         return 0;
1084     }
1085 
1086     XColor aXColor;
1087 
1088     aXColor.pixel = XGetPixel( pXImage, 0, 0 );
1089     XDestroyImage( pXImage );
1090 
1091     return GetColormap().GetColor( aXColor.pixel );
1092 }
1093 
1094 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1095 void X11SalGraphics::invert( long		nX,
1096 								long		nY,
1097 								long		nDX,
1098 								long		nDY,
1099 								SalInvert	nFlags )
1100 {
1101     GC pGC;
1102     if( SAL_INVERT_50 & nFlags )
1103     {
1104         pGC = GetInvert50GC();
1105         XFillRectangle( GetXDisplay(), GetDrawable(), pGC, nX, nY, nDX, nDY );
1106     }
1107     else
1108     {
1109         if ( SAL_INVERT_TRACKFRAME & nFlags )
1110         {
1111             pGC = GetTrackingGC();
1112             XDrawRectangle( GetXDisplay(), GetDrawable(),  pGC, nX, nY, nDX, nDY );
1113         }
1114         else
1115         {
1116             pGC = GetInvertGC();
1117             XFillRectangle( GetXDisplay(), GetDrawable(),  pGC, nX, nY, nDX, nDY );
1118         }
1119     }
1120 }
1121 
1122 bool X11SalGraphics::supportsOperation( OutDevSupportType eType ) const
1123 {
1124     bool bRet = false;
1125     switch( eType )
1126     {
1127     case OutDevSupport_TransparentRect:
1128     case OutDevSupport_B2DDraw:
1129         {
1130             XRenderPeer& rPeer = XRenderPeer::GetInstance();
1131             if( rPeer.GetVersion() >= 0x02 )
1132             {
1133                 const SalDisplay* pSalDisp = GetDisplay();
1134                 const SalVisual& rSalVis = pSalDisp->GetVisual( m_nScreen );
1135 
1136                 Visual* pDstXVisual = rSalVis.GetVisual();
1137                 XRenderPictFormat* pDstVisFmt = rPeer.FindVisualFormat( pDstXVisual );
1138                 if( pDstVisFmt )
1139                     bRet = true;
1140             }
1141         }
1142         break;
1143     default: break;
1144     }
1145     return bRet;
1146 }
1147 
1148