xref: /aoo41x/main/vcl/unx/generic/gdi/salgdi2.cxx (revision 5f27b83c)
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 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
CopyScreenArea(Display * pDisplay,Drawable aSrc,int nScreenSrc,int nSrcDepth,Drawable aDest,int nScreenDest,int nDestDepth,GC aDestGC,int src_x,int src_y,unsigned int w,unsigned int h,int dest_x,int dest_y)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 
CreateGC(Drawable hDrawable,unsigned long nMask)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 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
GetMonoGC(Pixmap hPixmap)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 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
GetCopyGC()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 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
GetInvertGC()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 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
GetInvert50GC()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 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
GetStippleGC()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 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Clip(XLIB_Region pRegion,int & nX,int & nY,unsigned int & nDX,unsigned int & nDY,int & nSrcX,int & nSrcY) const259 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 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Clip(int & nX,int & nY,unsigned int & nDX,unsigned int & nDY,int & nSrcX,int & nSrcY) const297 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 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SetMask(int & nX,int & nY,unsigned int & nDX,unsigned int & nDY,int & nSrcX,int & nSrcY,Pixmap hClipMask)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 {
GraphicsExposePredicate(Display *,XEvent * pEvent,XPointer pFrameWindow)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 
YieldGraphicsExpose()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 
copyBits(const SalTwoRect & rPosAry,SalGraphics * pSSrcGraphics)460 void X11SalGraphics::copyBits( const SalTwoRect& rPosAry,
461 								  SalGraphics	   *pSSrcGraphics )
462 {
463     X11SalGraphics* pSrcGraphics = pSSrcGraphics
464         ? static_cast<X11SalGraphics*>(pSSrcGraphics)
465         : this;
466 
467     if( rPosAry.mnSrcWidth <= 0
468         || rPosAry.mnSrcHeight <= 0
469         || rPosAry.mnDestWidth <= 0
470         || rPosAry.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         && rPosAry.mnSrcWidth	== rPosAry.mnDestWidth
504         && rPosAry.mnSrcHeight == rPosAry.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                                             rPosAry.mnSrcWidth, rPosAry.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                        rPosAry.mnSrcX,     rPosAry.mnSrcY,
537                        rPosAry.mnSrcWidth, rPosAry.mnSrcHeight,
538                        0,    				0 );			// destination
539             XCopyArea( GetXDisplay(),
540                        hPixmap,								// source
541                        GetDrawable(),						// destination
542                        GetInvertGC(),		// destination clipping
543                        0,				    0,				// source
544                        rPosAry.mnSrcWidth, rPosAry.mnSrcHeight,
545                        rPosAry.mnDestX,    rPosAry.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                        rPosAry.mnSrcX,     rPosAry.mnSrcY,
562                        rPosAry.mnSrcWidth, rPosAry.mnSrcHeight,
563                        rPosAry.mnDestX,    rPosAry.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( rPosAry.mnSrcX,
582                                                    rPosAry.mnSrcY,
583                                                    rPosAry.mnSrcWidth,
584                                                    rPosAry.mnSrcHeight );
585 
586         if( !pDDB )
587         {
588             stderr0( "SalGraphics::CopyBits !pSrcGraphics->GetBitmap()\n" );
589             return;
590         }
591 
592         SalTwoRect aPosAry( rPosAry );
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 
copyArea(long nDestX,long nDestY,long nSrcX,long nSrcY,long nSrcWidth,long nSrcHeight,sal_uInt16)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 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
drawBitmap(const SalTwoRect & rPosAry,const SalBitmap & rSalBitmap)627 void X11SalGraphics::drawBitmap( const SalTwoRect& rPosAry, 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, rPosAry, aGC );
647 
648     if( rSalBitmap.GetBitCount() == 1 )
649         XChangeGC( pXDisp, aGC, nValues, &aOldVal );
650     XFlush( pXDisp );
651 }
652 
653 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
654 
drawBitmap(const SalTwoRect & rPosAry,const SalBitmap & rSrcBitmap,const SalBitmap & rMaskBitmap)655 void X11SalGraphics::drawBitmap( const SalTwoRect& rPosAry,
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( rPosAry, rSrcBitmap, rMaskBitmap );
669     }
670 
671     drawMaskedBitmap( rPosAry, rSrcBitmap, rMaskBitmap );
672 }
673 
674 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
675 
drawMaskedBitmap(const SalTwoRect & rPosAry,const SalBitmap & rSalBitmap,const SalBitmap & rTransBitmap)676 void X11SalGraphics::drawMaskedBitmap( const SalTwoRect& rPosAry,
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, rPosAry.mnDestWidth,
691                                         rPosAry.mnDestHeight, nDepth ) );
692     Pixmap			aBG( XCreatePixmap( pXDisp, aDrawable, rPosAry.mnDestWidth,
693                                         rPosAry.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( rPosAry ); 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                    rPosAry.mnDestX, rPosAry.mnDestY,
713                    rPosAry.mnDestWidth, rPosAry.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                    rPosAry.mnDestWidth, rPosAry.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                    rPosAry.mnDestWidth, rPosAry.mnDestHeight,
753                    rPosAry.mnDestX, rPosAry.mnDestY );
754 
755         DBG_TESTTRANS( aBG );
756 
757         bXORMode_ = bOldXORMode;
758 
759         XFreeGC( pXDisp, aTmpGC );
760         XFlush( pXDisp );
761     }
762     else
763         drawBitmap( rPosAry, rSalBitmap );
764 
765     if( aFG )
766         XFreePixmap( pXDisp, aFG );
767 
768     if( aBG )
769         XFreePixmap( pXDisp, aBG );
770 }
771 
772 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
drawAlphaBitmap(const SalTwoRect & rTR,const SalBitmap & rSrcBitmap,const SalBitmap & rAlphaBmp)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 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
drawTransformedBitmap(const basegfx::B2DPoint & rNull,const basegfx::B2DPoint & rX,const basegfx::B2DPoint & rY,const SalBitmap & rSourceBitmap,const SalBitmap * pAlphaBitmap)905 bool X11SalGraphics::drawTransformedBitmap(
906     const basegfx::B2DPoint& rNull,
907     const basegfx::B2DPoint& rX,
908     const basegfx::B2DPoint& rY,
909     const SalBitmap& rSourceBitmap,
910     const SalBitmap* pAlphaBitmap)
911 {
912     // here direct support for transformed bitmaps can be impemented
913     (void)rNull; (void)rX; (void)rY; (void)rSourceBitmap; (void)pAlphaBitmap;
914     return false;
915 }
916 
917 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
drawAlphaRect(long nX,long nY,long nWidth,long nHeight,sal_uInt8 nTransparency)918 bool X11SalGraphics::drawAlphaRect( long nX, long nY, long nWidth,
919                                     long nHeight, sal_uInt8 nTransparency )
920 {
921     if( ! m_pFrame && ! m_pVDev )
922         return false;
923 
924     if( bPenGC_ || !bBrushGC_ || bXORMode_ )
925         return false; // can only perform solid fills without XOR.
926 
927     if( m_pVDev && m_pVDev->GetDepth() < 8 )
928         return false;
929 
930     XRenderPeer& rPeer = XRenderPeer::GetInstance();
931     if( rPeer.GetVersion() < 0x02 ) // TODO: replace with better test
932         return false;
933 
934     Picture aDstPic = GetXRenderPicture();
935     if( !aDstPic )
936         return false;
937 
938 	const double fTransparency = (100 - nTransparency) * (1.0/100);
939 	const XRenderColor aRenderColor = GetXRenderColor( nBrushColor_ , fTransparency);
940 
941     rPeer.FillRectangle( PictOpOver,
942                          aDstPic,
943                          &aRenderColor,
944                          nX, nY,
945                          nWidth, nHeight );
946 
947     return true;
948 }
949 
950 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
drawBitmap(const SalTwoRect &,const SalBitmap &,SalColor)951 void X11SalGraphics::drawBitmap( const SalTwoRect&,
952                                  const SalBitmap&,
953                                  SalColor )
954 {
955     DBG_ERROR( "::DrawBitmap with transparent color not supported" );
956 }
957 
958 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
drawMask(const SalTwoRect & rPosAry,const SalBitmap & rSalBitmap,SalColor nMaskColor)959 void X11SalGraphics::drawMask( const SalTwoRect& rPosAry,
960                                const SalBitmap &rSalBitmap,
961                                SalColor nMaskColor )
962 {
963     const SalDisplay*   pSalDisp = GetDisplay();
964     Display*	        pXDisp = pSalDisp->GetDisplay();
965     Drawable            aDrawable( GetDrawable() );
966     Pixmap              aStipple( XCreatePixmap( pXDisp, aDrawable,
967                                                  rPosAry.mnDestWidth,
968                                                  rPosAry.mnDestHeight, 1 ) );
969 
970     if( aStipple )
971     {
972         SalTwoRect	aTwoRect( rPosAry ); aTwoRect.mnDestX = aTwoRect.mnDestY = 0;
973         GC			aTmpGC;
974         XGCValues	aValues;
975 
976         // create a stipple bitmap first (set bits are changed to unset bits and vice versa)
977         aValues.function = GXcopyInverted;
978         aValues.foreground = 1, aValues.background = 0;
979         aTmpGC = XCreateGC( pXDisp, aStipple, GCFunction | GCForeground | GCBackground, &aValues );
980         static_cast<const X11SalBitmap&>(rSalBitmap).ImplDraw( aStipple, m_nScreen, 1, aTwoRect, aTmpGC );
981 
982         XFreeGC( pXDisp, aTmpGC );
983 
984         // Set stipple and draw rectangle
985         GC	aStippleGC( GetStippleGC() );
986         int	nX = rPosAry.mnDestX, nY = rPosAry.mnDestY;
987 
988         XSetStipple( pXDisp, aStippleGC, aStipple );
989         XSetTSOrigin( pXDisp, aStippleGC, nX, nY );
990         XSetForeground( pXDisp, aStippleGC, GetPixel( nMaskColor ) );
991         XFillRectangle( pXDisp, aDrawable, aStippleGC,
992                         nX, nY,
993                         rPosAry.mnDestWidth, rPosAry.mnDestHeight );
994         XFreePixmap( pXDisp, aStipple );
995         XFlush( pXDisp );
996     }
997     else
998         drawBitmap( rPosAry, rSalBitmap );
999 }
1000 
1001 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
getBitmap(long nX,long nY,long nDX,long nDY)1002 SalBitmap *X11SalGraphics::getBitmap( long nX, long nY, long nDX, long nDY )
1003 {
1004     if( bPrinter_ && !bVirDev_ )
1005         return NULL;
1006 
1007     bool bFakeWindowBG = false;
1008 
1009     // normalize
1010     if( nDX < 0 )
1011     {
1012         nX += nDX;
1013         nDX = -nDX;
1014     }
1015     if ( nDY < 0 )
1016     {
1017         nY += nDY;
1018         nDY = -nDY;
1019     }
1020 
1021     if( bWindow_ && !bVirDev_ )
1022     {
1023         XWindowAttributes aAttrib;
1024 
1025         XGetWindowAttributes( GetXDisplay(), GetDrawable(), &aAttrib );
1026         if( aAttrib.map_state != IsViewable )
1027             bFakeWindowBG = true;
1028         else
1029         {
1030             long nOrgDX = nDX, nOrgDY = nDY;
1031 
1032             // clip to window size
1033             if ( nX < 0 )
1034             {
1035                 nDX += nX;
1036                 nX   = 0;
1037             }
1038             if ( nY < 0 )
1039             {
1040                 nDY += nY;
1041                 nY   = 0;
1042             }
1043             if( nX + nDX > aAttrib.width )
1044                 nDX = aAttrib.width  - nX;
1045             if( nY + nDY > aAttrib.height )
1046                 nDY = aAttrib.height - nY;
1047 
1048             // inside ?
1049             if( nDX <= 0 || nDY <= 0 )
1050             {
1051                 bFakeWindowBG = true;
1052                 nDX = nOrgDX;
1053                 nDY = nOrgDY;
1054             }
1055         }
1056     }
1057 
1058     X11SalBitmap*	pSalBitmap = new X11SalBitmap;
1059     sal_uInt16			nBitCount = GetBitCount();
1060 
1061     if( &GetDisplay()->GetColormap( m_nScreen ) != &GetColormap() )
1062         nBitCount = 1;
1063 
1064     if( ! bFakeWindowBG )
1065         pSalBitmap->ImplCreateFromDrawable( GetDrawable(), m_nScreen, nBitCount, nX, nY, nDX, nDY );
1066     else
1067         pSalBitmap->Create( Size( nDX, nDY ), (nBitCount > 8) ? 24 : nBitCount, BitmapPalette( nBitCount > 8 ? nBitCount : 0 ) );
1068 
1069     return pSalBitmap;
1070 }
1071 
1072 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
getPixel(long nX,long nY)1073 SalColor X11SalGraphics::getPixel( long nX, long nY )
1074 {
1075     if( bWindow_ && !bVirDev_ )
1076     {
1077         XWindowAttributes aAttrib;
1078 
1079         XGetWindowAttributes( GetXDisplay(), GetDrawable(), &aAttrib );
1080         if( aAttrib.map_state != IsViewable )
1081         {
1082             stderr0( "X11SalGraphics::GetPixel drawable not viewable\n" );
1083             return 0;
1084         }
1085     }
1086 
1087     XImage *pXImage = XGetImage( GetXDisplay(),
1088                                      GetDrawable(),
1089                                  nX, nY,
1090                                  1,  1,
1091                                  AllPlanes,
1092                                  ZPixmap );
1093     if( !pXImage )
1094     {
1095         stderr0( "X11SalGraphics::GetPixel !XGetImage()\n" );
1096         return 0;
1097     }
1098 
1099     XColor aXColor;
1100 
1101     aXColor.pixel = XGetPixel( pXImage, 0, 0 );
1102     XDestroyImage( pXImage );
1103 
1104     return GetColormap().GetColor( aXColor.pixel );
1105 }
1106 
1107 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
invert(long nX,long nY,long nDX,long nDY,SalInvert nFlags)1108 void X11SalGraphics::invert( long		nX,
1109 								long		nY,
1110 								long		nDX,
1111 								long		nDY,
1112 								SalInvert	nFlags )
1113 {
1114     GC pGC;
1115     if( SAL_INVERT_50 & nFlags )
1116     {
1117         pGC = GetInvert50GC();
1118         XFillRectangle( GetXDisplay(), GetDrawable(), pGC, nX, nY, nDX, nDY );
1119     }
1120     else
1121     {
1122         if ( SAL_INVERT_TRACKFRAME & nFlags )
1123         {
1124             pGC = GetTrackingGC();
1125             XDrawRectangle( GetXDisplay(), GetDrawable(),  pGC, nX, nY, nDX, nDY );
1126         }
1127         else
1128         {
1129             pGC = GetInvertGC();
1130             XFillRectangle( GetXDisplay(), GetDrawable(),  pGC, nX, nY, nDX, nDY );
1131         }
1132     }
1133 }
1134 
supportsOperation(OutDevSupportType eType) const1135 bool X11SalGraphics::supportsOperation( OutDevSupportType eType ) const
1136 {
1137     bool bRet = false;
1138     switch( eType )
1139     {
1140     case OutDevSupport_TransparentRect:
1141     case OutDevSupport_B2DDraw:
1142         {
1143             XRenderPeer& rPeer = XRenderPeer::GetInstance();
1144             if( rPeer.GetVersion() >= 0x02 )
1145             {
1146                 const SalDisplay* pSalDisp = GetDisplay();
1147                 const SalVisual& rSalVis = pSalDisp->GetVisual( m_nScreen );
1148 
1149                 Visual* pDstXVisual = rSalVis.GetVisual();
1150                 XRenderPictFormat* pDstVisFmt = rPeer.FindVisualFormat( pDstXVisual );
1151                 if( pDstVisFmt )
1152                     bRet = true;
1153             }
1154         }
1155         break;
1156     default: break;
1157     }
1158     return bRet;
1159 }
1160 
1161