1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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"
38 #include "saldata.hxx"
39 #include "saldisp.hxx"
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 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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" );
70 // -----------------------------------------------------------------------------
72 #if (OSL_DEBUG_LEVEL > 1) && defined SALGDI2_TESTTRANS
73 #define DBG_TESTTRANS( _def_drawable ) \
75 XCopyArea( pXDisp, _def_drawable, aDrawable, GetCopyGC(), \
77 pPosAry->mnDestWidth, pPosAry->mnDestHeight, \
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
,
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
);
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
);
109 XPutImage( pDisplay
, aDest
, aDestGC
, pImage
,
110 0, 0, dest_x
, dest_y
, w
, h
);
112 XDestroyImage( pImage
);
114 pLib
->PopXErrorLevel();
120 aBM
.ImplCreateFromDrawable( aSrc
, nScreenSrc
, nSrcDepth
, src_x
, src_y
, w
, h
);
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
)
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
)
151 pMonoGC_
= CreateGC( hPixmap
);
155 SetClipRegion( pMonoGC_
);
162 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
163 inline GC
X11SalGraphics::GetCopyGC()
165 if( bXORMode_
) return GetInvertGC();
168 pCopyGC_
= CreateGC( GetDrawable() );
172 SetClipRegion( pCopyGC_
);
178 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
179 GC
X11SalGraphics::GetInvertGC()
182 pInvertGC_
= CreateGC( GetDrawable(),
190 SetClipRegion( pInvertGC_
);
196 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
197 GC
X11SalGraphics::GetInvert50GC()
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
=
219 char* pEnv
= getenv( "SAL_DO_NOT_USE_INVERT50" );
220 if( pEnv
&& ! strcasecmp( pEnv
, "true" ) )
222 values
.fill_style
= FillSolid
;
223 nValueMask
&= ~ GCStipple
;
227 values
.fill_style
= FillStippled
;
228 values
.stipple
= GetDisplay()->GetInvert50( m_nScreen
);
231 pInvert50GC_
= XCreateGC( GetXDisplay(), GetDrawable(),
238 SetClipRegion( pInvert50GC_
);
244 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
245 inline GC
X11SalGraphics::GetStippleGC()
248 pStippleGC_
= CreateGC( GetDrawable(),
255 XSetFunction( GetXDisplay(), pStippleGC_
, bXORMode_
? GXxor
: GXcopy
);
256 SetClipRegion( pStippleGC_
);
263 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
264 int X11SalGraphics::Clip( XLIB_Region pRegion
,
273 XClipBox( pRegion
, &aRect
);
275 if( int(nX
+ nDX
) <= int(aRect
.x
) || nX
>= int(aRect
.x
+ aRect
.width
) )
277 if( int(nY
+ nDY
) <= int(aRect
.y
) || nY
>= int(aRect
.y
+ aRect
.height
) )
282 nSrcX
+= aRect
.x
- nX
;
286 else if( int(nX
+ nDX
) > int(aRect
.x
+ aRect
.width
) )
287 nDX
= aRect
.x
+ aRect
.width
- nX
;
291 nSrcY
+= aRect
.y
- nY
;
295 else if( int(nY
+ nDY
) > int(aRect
.y
+ aRect
.height
) )
296 nDY
= aRect
.y
+ aRect
.height
- nY
;
301 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
302 int X11SalGraphics::Clip( int &nX
,
311 && RectangleOut
== Clip( pPaintRegion_
, nX
, nY
, nDX
, nDY
, nSrcX
, nSrcY
) )
315 && RectangleOut
== Clip( pClipRegion_
, nX
, nY
, nDX
, nDY
, nSrcX
, nSrcY
) )
321 nPaint
= XRectInRegion( pPaintRegion_
, nX
, nY
, nDX
, nDY
);
322 if( RectangleOut
== nPaint
)
326 nPaint
= RectangleIn
;
331 nClip
= XRectInRegion( pClipRegion_
, nX
, nY
, nDX
, nDY
);
332 if( RectangleOut
== nClip
)
338 return RectangleIn
== nClip
&& RectangleIn
== nPaint
343 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
344 GC
X11SalGraphics::SetMask( int &nX
,
352 int n
= Clip( nX
, nY
, nDX
, nDY
, nSrcX
, nSrcY
);
353 if( RectangleOut
== n
)
356 Display
*pDisplay
= GetXDisplay();
359 pMaskGC_
= CreateGC( GetDrawable() );
361 if( RectangleIn
== n
)
363 XSetClipMask( pDisplay
, pMaskGC_
, hClipMask
);
364 XSetClipOrigin( pDisplay
, pMaskGC_
, nX
- nSrcX
, nY
- nSrcY
);
368 // - - - - create alternate clip pixmap for region clipping - - - -
369 Pixmap hPixmap
= XCreatePixmap( pDisplay
, hClipMask
, nDX
, nDY
, 1 );
373 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
374 fprintf( stderr
, "X11SalGraphics::SetMask !hPixmap\n" );
379 // - - - - reset pixmap; all 0 - - - - - - - - - - - - - - - - - - -
380 XFillRectangle( pDisplay
,
382 GetDisplay()->GetMonoGC( m_nScreen
),
386 // - - - - copy pixmap only within region - - - - - - - - - - - - -
387 GC pMonoGC
= GetMonoGC( hPixmap
);
388 XSetClipOrigin( pDisplay
, pMonoGC
, -nX
, -nY
);
391 hPixmap
, // Destination
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
);
404 // -=-= SalGraphics =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
405 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
409 static Bool
GraphicsExposePredicate( Display
*, XEvent
* pEvent
, XPointer pFrameWindow
)
412 if( (pEvent
->type
== GraphicsExpose
|| pEvent
->type
== NoExpose
) &&
413 pEvent
->xnoexpose
.drawable
== (Drawable
)pFrameWindow
)
422 void X11SalGraphics::YieldGraphicsExpose()
424 // get frame if necessary
425 SalFrame
* pFrame
= m_pFrame
;
426 Display
* pDisplay
= GetXDisplay();
427 XLIB_Window aWindow
= GetDrawable();
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
)
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
454 if( aEvent
.type
== NoExpose
)
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
)
472 if( pPosAry
->mnSrcWidth
<= 0
473 || pPosAry
->mnSrcHeight
<= 0
474 || pPosAry
->mnDestWidth
<= 0
475 || pPosAry
->mnDestHeight
<= 0 )
481 if( pSrcGraphics
== this )
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
494 n
= 1; // printer or other display
496 else if( pSrcGraphics
->bVirDev_
)
498 // printer compatible virtual device
500 n
= 2; // printer or compatible virtual device == same display
502 n
= 1; // window or compatible virtual device
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 &&
517 pSrcGraphics
->bWindow_
);
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(),
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(),
546 GetDrawable(), // destination
547 GetInvertGC(), // destination clipping
549 pPosAry
->mnSrcWidth
, pPosAry
->mnSrcHeight
,
550 pPosAry
->mnDestX
, pPosAry
->mnDestY
);
551 XFreePixmap( GetXDisplay(), hPixmap
);
555 pCopyGC
= GetCopyGC();
557 if( bNeedGraphicsExposures
)
558 XSetGraphicsExposures( GetXDisplay(),
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();
576 XSetGraphicsExposures( GetXDisplay(),
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
,
589 pPosAry
->mnSrcHeight
);
593 stderr0( "SalGraphics::CopyBits !pSrcGraphics->GetBitmap()\n" );
597 SalTwoRect
aPosAry( *pPosAry
);
599 aPosAry
.mnSrcX
= 0, aPosAry
.mnSrcY
= 0;
600 drawBitmap( &aPosAry
, *pDDB
);
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
,
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
);
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
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
) );
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
,
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
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
,
746 pPosAry
->mnDestWidth
, pPosAry
->mnDestHeight
,
748 DBG_TESTTRANS( aBG
);
750 // #105055# Disable XOR temporarily
751 BOOL
bOldXORMode( bXORMode_
);
754 // copy pixmap #2 (result) to background
755 XCopyArea( pXDisp
, aBG
, aDrawable
, GetCopyGC(),
757 pPosAry
->mnDestWidth
, pPosAry
->mnDestHeight
,
758 pPosAry
->mnDestX
, pPosAry
->mnDestY
);
760 DBG_TESTTRANS( aBG
);
762 bXORMode_
= bOldXORMode
;
764 XFreeGC( pXDisp
, aTmpGC
);
768 drawBitmap( pPosAry
, rSalBitmap
);
771 XFreePixmap( pXDisp
, aFG
);
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 )
785 // horizontal mirroring not implemented yet
786 if( rTR
.mnDestWidth
< 0 )
789 // stretched conversion is not implemented yet
790 if( rTR
.mnDestWidth
!= rTR
.mnSrcWidth
)
792 if( rTR
.mnDestHeight
!= rTR
.mnSrcHeight
)
795 XRenderPeer
& rPeer
= XRenderPeer::GetInstance();
796 if( rPeer
.GetVersion() < 0x02 )
799 // create destination picture
800 Picture aDstPic
= GetXRenderPicture();
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
);
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() )
822 Pixmap aSrcPM
= pSrcDDB
->ImplGetPixmap();
826 // create source picture
827 // TODO: use scoped picture
828 Visual
* pSrcXVisual
= rSalVis
.GetVisual();
829 XRenderPictFormat
* pSrcVisFmt
= rPeer
.FindVisualFormat( pSrcXVisual
);
832 Picture aSrcPic
= rPeer
.CreatePicture( aSrcPM
, pSrcVisFmt
, 0, NULL
);
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
);
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
)
863 char* pCDst
= (char*)pLDst
;
864 for( int i
= nImageSize
& (sizeof(long)-1); --i
>= 0; ++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 );
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
);
882 if( pAlphaBits
!= (char*)pAlphaBuffer
->mpBits
)
885 const_cast<SalBitmap
&>(rAlphaBmp
).ReleaseBuffer( pAlphaBuffer
, TRUE
);
887 XRenderPictureAttributes aAttr
;
889 Picture aAlphaPic
= rPeer
.CreatePicture( aAlphaPM
, pAlphaFormat
, CPRepeat
, &aAttr
);
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
);
909 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
910 bool X11SalGraphics::drawAlphaRect( long nX
, long nY
, long nWidth
,
911 long nHeight
, sal_uInt8 nTransparency
)
913 if( ! m_pFrame
&& ! m_pVDev
)
916 if( bPenGC_
|| !bBrushGC_
|| bXORMode_
)
917 return false; // can only perform solid fills without XOR.
919 if( m_pVDev
&& m_pVDev
->GetDepth() < 8 )
922 XRenderPeer
& rPeer
= XRenderPeer::GetInstance();
923 if( rPeer
.GetVersion() < 0x02 ) // TODO: replace with better test
926 Picture aDstPic
= GetXRenderPicture();
930 const double fTransparency
= (100 - nTransparency
) * (1.0/100);
931 const XRenderColor aRenderColor
= GetXRenderColor( nBrushColor_
, fTransparency
);
933 rPeer
.FillRectangle( PictOpOver
,
942 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
943 void X11SalGraphics::drawBitmap( const SalTwoRect
*,
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 ) );
964 SalTwoRect
aTwoRect( *pPosAry
); aTwoRect
.mnDestX
= aTwoRect
.mnDestY
= 0;
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
,
985 pPosAry
->mnDestWidth
, pPosAry
->mnDestHeight
);
986 XFreePixmap( pXDisp
, aStipple
);
990 drawBitmap( pPosAry
, rSalBitmap
);
993 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
994 SalBitmap
*X11SalGraphics::getBitmap( long nX
, long nY
, long nDX
, long nDY
)
996 if( bPrinter_
&& !bVirDev_
)
999 bool bFakeWindowBG
= false;
1013 if( bWindow_
&& !bVirDev_
)
1015 XWindowAttributes aAttrib
;
1017 XGetWindowAttributes( GetXDisplay(), GetDrawable(), &aAttrib
);
1018 if( aAttrib
.map_state
!= IsViewable
)
1019 bFakeWindowBG
= true;
1022 long nOrgDX
= nDX
, nOrgDY
= nDY
;
1024 // clip to window size
1035 if( nX
+ nDX
> aAttrib
.width
)
1036 nDX
= aAttrib
.width
- nX
;
1037 if( nY
+ nDY
> aAttrib
.height
)
1038 nDY
= aAttrib
.height
- nY
;
1041 if( nDX
<= 0 || nDY
<= 0 )
1043 bFakeWindowBG
= true;
1050 X11SalBitmap
* pSalBitmap
= new X11SalBitmap
;
1051 USHORT nBitCount
= GetBitCount();
1053 if( &GetDisplay()->GetColormap( m_nScreen
) != &GetColormap() )
1056 if( ! bFakeWindowBG
)
1057 pSalBitmap
->ImplCreateFromDrawable( GetDrawable(), m_nScreen
, nBitCount
, nX
, nY
, nDX
, nDY
);
1059 pSalBitmap
->Create( Size( nDX
, nDY
), (nBitCount
> 8) ? 24 : nBitCount
, BitmapPalette( nBitCount
> 8 ? nBitCount
: 0 ) );
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" );
1079 XImage
*pXImage
= XGetImage( GetXDisplay(),
1087 stderr0( "X11SalGraphics::GetPixel !XGetImage()\n" );
1093 aXColor
.pixel
= XGetPixel( pXImage
, 0, 0 );
1094 XDestroyImage( pXImage
);
1096 return GetColormap().GetColor( aXColor
.pixel
);
1099 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1100 void X11SalGraphics::invert( long nX
,
1107 if( SAL_INVERT_50
& nFlags
)
1109 pGC
= GetInvert50GC();
1110 XFillRectangle( GetXDisplay(), GetDrawable(), pGC
, nX
, nY
, nDX
, nDY
);
1114 if ( SAL_INVERT_TRACKFRAME
& nFlags
)
1116 pGC
= GetTrackingGC();
1117 XDrawRectangle( GetXDisplay(), GetDrawable(), pGC
, nX
, nY
, nDX
, nDY
);
1121 pGC
= GetInvertGC();
1122 XFillRectangle( GetXDisplay(), GetDrawable(), pGC
, nX
, nY
, nDX
, nDY
);
1127 bool X11SalGraphics::supportsOperation( OutDevSupportType eType
) const
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
);