merge the formfield patch from ooo-build
[ooovba.git] / vcl / unx / source / gdi / salbmp.cxx
blob8f6fe1725f1508955c5dc34d2ac22a8030e212d7
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salbmp.cxx,v $
10 * $Revision: 1.32 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include <string.h>
35 #include <stdio.h>
36 #include <errno.h>
37 #ifdef FREEBSD
38 #include <sys/types.h>
39 #endif
40 #include <tools/prex.h>
41 #include "Xproto.h"
42 #include <tools/postx.h>
43 #include <salunx.h>
44 #include <osl/endian.h>
45 #include <rtl/memory.h>
46 #include <vcl/salbtype.hxx>
47 #include <saldata.hxx>
48 #include <saldisp.hxx>
49 #include <salgdi.h>
50 #include <salbmp.h>
51 #include <salinst.h>
52 #include <vcl/bitmap.hxx>
53 #include <com/sun/star/beans/XFastPropertySet.hpp>
55 // -----------
56 // - Defines -
57 // -----------
59 #define SAL_DRAWPIXMAP_MAX_EXT 4096
61 // -------------
62 // - SalBitmap -
63 // -------------
65 SalBitmap* X11SalInstance::CreateSalBitmap()
67 return new X11SalBitmap();
70 ImplSalBitmapCache* X11SalBitmap::mpCache = NULL;
71 ULONG X11SalBitmap::mnCacheInstCount = 0;
73 // -----------------------------------------------------------------------------
75 X11SalBitmap::X11SalBitmap() :
76 mpDIB( NULL ),
77 mpDDB( NULL ),
78 mbGrey( false )
82 // -----------------------------------------------------------------------------
84 X11SalBitmap::~X11SalBitmap()
86 Destroy();
89 // -----------------------------------------------------------------------------
91 void X11SalBitmap::ImplCreateCache()
93 if( !mnCacheInstCount++ )
94 mpCache = new ImplSalBitmapCache;
97 // -----------------------------------------------------------------------------
99 void X11SalBitmap::ImplDestroyCache()
101 DBG_ASSERT( mnCacheInstCount, "X11SalBitmap::ImplDestroyCache(): underflow" );
103 if( mnCacheInstCount && !--mnCacheInstCount )
104 delete mpCache, mpCache = NULL;
107 // -----------------------------------------------------------------------------
109 void X11SalBitmap::ImplRemovedFromCache()
111 if( mpDDB )
112 delete mpDDB, mpDDB = NULL;
115 // -----------------------------------------------------------------------------
117 BitmapBuffer* X11SalBitmap::ImplCreateDIB( const Size& rSize, USHORT nBitCount, const BitmapPalette& rPal )
119 DBG_ASSERT( nBitCount == 1 || nBitCount == 4 || nBitCount == 8 || nBitCount == 16 || nBitCount == 24, "Unsupported BitCount!" );
121 BitmapBuffer* pDIB = NULL;
123 if( rSize.Width() && rSize.Height() )
127 pDIB = new BitmapBuffer;
129 catch( std::bad_alloc& )
131 pDIB = NULL;
134 if( pDIB )
136 const USHORT nColors = ( nBitCount <= 8 ) ? ( 1 << nBitCount ) : 0;
138 pDIB->mnFormat = BMP_FORMAT_BOTTOM_UP;
140 switch( nBitCount )
142 case( 1 ): pDIB->mnFormat |= BMP_FORMAT_1BIT_MSB_PAL; break;
143 case( 4 ): pDIB->mnFormat |= BMP_FORMAT_4BIT_MSN_PAL; break;
144 case( 8 ): pDIB->mnFormat |= BMP_FORMAT_8BIT_PAL; break;
145 #ifdef OSL_BIGENDIAN
146 case(16 ):
147 pDIB->mnFormat|= BMP_FORMAT_16BIT_TC_MSB_MASK;
148 pDIB->maColorMask = ColorMask( 0xf800, 0x07e0, 0x001f );
149 break;
150 #else
151 case(16 ):
152 pDIB->mnFormat|= BMP_FORMAT_16BIT_TC_LSB_MASK;
153 pDIB->maColorMask = ColorMask( 0xf800, 0x07e0, 0x001f );
154 break;
155 #endif
156 default:
157 nBitCount = 24;
158 //fall through
159 case 24:
160 pDIB->mnFormat |= BMP_FORMAT_24BIT_TC_BGR;
161 break;
164 pDIB->mnWidth = rSize.Width();
165 pDIB->mnHeight = rSize.Height();
166 pDIB->mnScanlineSize = AlignedWidth4Bytes( pDIB->mnWidth * nBitCount );
167 pDIB->mnBitCount = nBitCount;
169 if( nColors )
171 pDIB->maPalette = rPal;
172 pDIB->maPalette.SetEntryCount( nColors );
177 pDIB->mpBits = new BYTE[ pDIB->mnScanlineSize * pDIB->mnHeight ];
179 catch(std::bad_alloc&)
181 delete pDIB;
182 pDIB = NULL;
186 else
187 pDIB = NULL;
189 return pDIB;
192 // -----------------------------------------------------------------------------
194 BitmapBuffer* X11SalBitmap::ImplCreateDIB( Drawable aDrawable,
195 int nScreen,
196 long nDrawableDepth,
197 long nX, long nY,
198 long nWidth, long nHeight,
199 bool bGrey )
201 BitmapBuffer* pDIB = NULL;
203 if( aDrawable && nWidth && nHeight && nDrawableDepth )
205 SalDisplay* pSalDisp = GetX11SalData()->GetDisplay();
206 SalXLib* pXLib = pSalDisp->GetXLib();
207 Display* pXDisp = pSalDisp->GetDisplay();
209 // do not die on XError here
210 // alternatively one could check the coordinates for being offscreen
211 // but this call can actually work on servers with backing store
212 // defaults even if the rectangle is offscreen
213 // so better catch the XError
214 pXLib->PushXErrorLevel( true );
215 XImage* pImage = XGetImage( pXDisp, aDrawable, nX, nY, nWidth, nHeight, AllPlanes, ZPixmap );
216 bool bWasError = pXLib->HasXErrorOccured() && pXLib->GetLastXErrorRequestCode() == X_GetImage;
217 pXLib->PopXErrorLevel();
219 if( ! bWasError && pImage && pImage->data )
221 const SalTwoRect aTwoRect = { 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight };
222 BitmapBuffer aSrcBuf;
223 ULONG nDstFormat = BMP_FORMAT_BOTTOM_UP;
224 const BitmapPalette* pDstPal = NULL;
226 aSrcBuf.mnFormat = BMP_FORMAT_TOP_DOWN;
227 aSrcBuf.mnWidth = nWidth;
228 aSrcBuf.mnHeight = nHeight;
229 aSrcBuf.mnBitCount = pImage->bits_per_pixel;
230 aSrcBuf.mnScanlineSize = pImage->bytes_per_line;
231 aSrcBuf.mpBits = (BYTE*) pImage->data;
233 pImage->red_mask = pSalDisp->GetVisual( nScreen ).red_mask;
234 pImage->green_mask = pSalDisp->GetVisual( nScreen ).green_mask;
235 pImage->blue_mask = pSalDisp->GetVisual( nScreen ).blue_mask;
237 switch( aSrcBuf.mnBitCount )
239 case( 1 ):
241 aSrcBuf.mnFormat |= ( LSBFirst == pImage->bitmap_bit_order ? BMP_FORMAT_1BIT_LSB_PAL : BMP_FORMAT_1BIT_MSB_PAL );
242 nDstFormat |= BMP_FORMAT_1BIT_MSB_PAL;
244 break;
246 case( 4 ):
248 aSrcBuf.mnFormat |= ( LSBFirst == pImage->bitmap_bit_order ? BMP_FORMAT_4BIT_LSN_PAL : BMP_FORMAT_4BIT_MSN_PAL );
249 nDstFormat |= BMP_FORMAT_4BIT_MSN_PAL;
251 break;
253 case( 8 ):
255 aSrcBuf.mnFormat |= BMP_FORMAT_8BIT_PAL;
256 nDstFormat |= BMP_FORMAT_8BIT_PAL;
258 break;
260 case( 16 ):
262 nDstFormat |= BMP_FORMAT_24BIT_TC_BGR;
263 aSrcBuf.maColorMask = ColorMask( pImage->red_mask, pImage->green_mask, pImage->blue_mask );
265 if( LSBFirst == pImage->byte_order )
267 aSrcBuf.mnFormat |= BMP_FORMAT_16BIT_TC_LSB_MASK;
269 else
271 aSrcBuf.mnFormat |= BMP_FORMAT_16BIT_TC_MSB_MASK;
272 // aSrcBuf.maColorMask = ColorMask( pImage->red_mask ), SWAPSHORT( pImage->green_mask ), SWAPSHORT( pImage->blue_mask ) );
275 break;
277 case( 24 ):
279 if( ( LSBFirst == pImage->byte_order ) && ( pImage->red_mask == 0xFF ) )
280 aSrcBuf.mnFormat |= BMP_FORMAT_24BIT_TC_RGB;
281 else
282 aSrcBuf.mnFormat |= BMP_FORMAT_24BIT_TC_BGR;
284 nDstFormat |= BMP_FORMAT_24BIT_TC_BGR;
286 break;
288 case( 32 ):
290 if( LSBFirst == pImage->byte_order )
291 aSrcBuf.mnFormat |= ( pSalDisp->GetVisual(nScreen).red_mask == 0xFF ? BMP_FORMAT_32BIT_TC_RGBA : BMP_FORMAT_32BIT_TC_BGRA );
292 else
293 aSrcBuf.mnFormat |= ( pSalDisp->GetVisual(nScreen).red_mask == 0xFF ? BMP_FORMAT_32BIT_TC_ABGR : BMP_FORMAT_32BIT_TC_ARGB );
295 nDstFormat |= BMP_FORMAT_24BIT_TC_BGR;
297 break;
300 BitmapPalette& rPal = aSrcBuf.maPalette;
302 if( aSrcBuf.mnBitCount == 1 )
304 rPal.SetEntryCount( 2 );
305 pDstPal = &rPal;
307 rPal[ 0 ] = Color( COL_BLACK );
308 rPal[ 1 ] = Color( COL_WHITE );
310 else if( pImage->depth == 8 && bGrey )
312 rPal.SetEntryCount( 256 );
313 pDstPal = &rPal;
315 for( USHORT i = 0; i < 256; i++ )
317 BitmapColor& rBmpCol = rPal[ i ];
319 rBmpCol.SetRed( i );
320 rBmpCol.SetGreen( i );
321 rBmpCol.SetBlue( i );
325 else if( aSrcBuf.mnBitCount <= 8 )
327 const SalColormap& rColMap = pSalDisp->GetColormap( nScreen );
328 const USHORT nCols = Min( (ULONG)rColMap.GetUsed(), (ULONG)(1 << nDrawableDepth) );
330 rPal.SetEntryCount( nCols );
331 pDstPal = &rPal;
333 for( USHORT i = 0; i < nCols; i++ )
335 const SalColor nColor( rColMap.GetColor( i ) );
336 BitmapColor& rBmpCol = rPal[ i ];
338 rBmpCol.SetRed( SALCOLOR_RED( nColor ) );
339 rBmpCol.SetGreen( SALCOLOR_GREEN( nColor ) );
340 rBmpCol.SetBlue( SALCOLOR_BLUE( nColor ) );
344 nDstFormat = aSrcBuf.mnFormat;
345 pDIB = StretchAndConvert( aSrcBuf, aTwoRect, nDstFormat,
346 const_cast<BitmapPalette*>(pDstPal), &aSrcBuf.maColorMask );
347 XDestroyImage( pImage );
351 return pDIB;
354 // -----------------------------------------------------------------------------
356 XImage* X11SalBitmap::ImplCreateXImage( SalDisplay *pSalDisp, int nScreen, long nDepth, const SalTwoRect& rTwoRect ) const
358 XImage* pImage = NULL;
360 if( !mpDIB && mpDDB )
362 const_cast<X11SalBitmap*>(this)->mpDIB =
363 ImplCreateDIB( mpDDB->ImplGetPixmap(),
364 mpDDB->ImplGetScreen(),
365 mpDDB->ImplGetDepth(),
366 0, 0,
367 mpDDB->ImplGetWidth(),
368 mpDDB->ImplGetHeight(),
369 mbGrey );
372 if( mpDIB && mpDIB->mnWidth && mpDIB->mnHeight )
374 Display* pXDisp = pSalDisp->GetDisplay();
375 long nWidth = rTwoRect.mnDestWidth;
376 long nHeight = rTwoRect.mnDestHeight;
378 if( 1 == GetBitCount() )
379 nDepth = 1;
381 pImage = XCreateImage( pXDisp, pSalDisp->GetVisual( nScreen ).GetVisual(),
382 nDepth, ( 1 == nDepth ) ? XYBitmap :ZPixmap, 0, NULL,
383 nWidth, nHeight, 32, 0 );
385 if( pImage )
387 BitmapBuffer* pDstBuf;
388 ULONG nDstFormat = BMP_FORMAT_TOP_DOWN;
389 BitmapPalette* pPal = NULL;
390 ColorMask* pMask = NULL;
392 switch( pImage->bits_per_pixel )
394 case( 1 ):
395 nDstFormat |= ( LSBFirst == pImage->bitmap_bit_order ? BMP_FORMAT_1BIT_LSB_PAL : BMP_FORMAT_1BIT_MSB_PAL );
396 break;
398 case( 4 ):
399 nDstFormat |= ( LSBFirst == pImage->bitmap_bit_order ? BMP_FORMAT_4BIT_LSN_PAL : BMP_FORMAT_4BIT_MSN_PAL );
400 break;
402 case( 8 ):
403 nDstFormat |= BMP_FORMAT_8BIT_PAL;
404 break;
406 case( 16 ):
408 #ifdef OSL_BIGENDIAN
410 if( MSBFirst == pImage->byte_order )
411 nDstFormat |= BMP_FORMAT_16BIT_TC_MSB_MASK;
412 else
413 nDstFormat |= BMP_FORMAT_16BIT_TC_LSB_MASK;
415 #else /* OSL_LITENDIAN */
417 nDstFormat |= BMP_FORMAT_16BIT_TC_LSB_MASK;
418 if( MSBFirst == pImage->byte_order )
419 pImage->byte_order = LSBFirst;
421 #endif
423 pMask = new ColorMask( pImage->red_mask, pImage->green_mask, pImage->blue_mask );
425 break;
427 case( 24 ):
429 if( ( LSBFirst == pImage->byte_order ) && ( pImage->red_mask == 0xFF ) )
430 nDstFormat |= BMP_FORMAT_24BIT_TC_RGB;
431 else
432 nDstFormat |= BMP_FORMAT_24BIT_TC_BGR;
434 break;
436 case( 32 ):
438 if( LSBFirst == pImage->byte_order )
439 nDstFormat |= ( pImage->red_mask == 0xFF ? BMP_FORMAT_32BIT_TC_RGBA : BMP_FORMAT_32BIT_TC_BGRA );
440 else
441 nDstFormat |= ( pImage->red_mask == 0xFF ? BMP_FORMAT_32BIT_TC_ABGR : BMP_FORMAT_32BIT_TC_ARGB );
443 break;
446 if( pImage->depth == 1 )
448 pPal = new BitmapPalette( 2 );
449 (*pPal)[ 0 ] = Color( COL_BLACK );
450 (*pPal)[ 1 ] = Color( COL_WHITE );
452 else if( pImage->depth == 8 && mbGrey )
454 pPal = new BitmapPalette( 256 );
456 for( USHORT i = 0; i < 256; i++ )
458 BitmapColor& rBmpCol = (*pPal)[ i ];
460 rBmpCol.SetRed( i );
461 rBmpCol.SetGreen( i );
462 rBmpCol.SetBlue( i );
466 else if( pImage->depth <= 8 )
468 const SalColormap& rColMap = pSalDisp->GetColormap( nScreen );
469 const USHORT nCols = Min( (ULONG)rColMap.GetUsed(), (ULONG)(1 << pImage->depth) );
471 pPal = new BitmapPalette( nCols );
473 for( USHORT i = 0; i < nCols; i++ )
475 const SalColor nColor( rColMap.GetColor( i ) );
476 BitmapColor& rBmpCol = (*pPal)[ i ];
478 rBmpCol.SetRed( SALCOLOR_RED( nColor ) );
479 rBmpCol.SetGreen( SALCOLOR_GREEN( nColor ) );
480 rBmpCol.SetBlue( SALCOLOR_BLUE( nColor ) );
484 pDstBuf = StretchAndConvert( *mpDIB, rTwoRect, nDstFormat, pPal, pMask );
485 delete pPal;
486 delete pMask;
488 if( pDstBuf && pDstBuf->mpBits )
490 // set data in buffer as data member in pImage
491 pImage->data = (char*) pDstBuf->mpBits;
493 // destroy buffer; don't destroy allocated data in buffer
494 delete pDstBuf;
496 else
498 XDestroyImage( pImage );
499 pImage = NULL;
504 return pImage;
507 // -----------------------------------------------------------------------------
508 bool X11SalBitmap::ImplCreateFromDrawable( Drawable aDrawable,
509 int nScreen, long nDrawableDepth,
510 long nX, long nY, long nWidth, long nHeight )
512 Destroy();
514 if( aDrawable && nWidth && nHeight && nDrawableDepth )
515 mpDDB = new ImplSalDDB( aDrawable, nScreen, nDrawableDepth, nX, nY, nWidth, nHeight );
517 return( mpDDB != NULL );
519 // -----------------------------------------------------------------------------
521 bool
522 X11SalBitmap::SnapShot (Display* pDisplay, XLIB_Window hWindow)
524 if (hWindow != None)
526 XWindowAttributes aAttribute;
527 XGetWindowAttributes (pDisplay, hWindow, &aAttribute);
528 if (aAttribute.map_state == IsViewable)
530 // get coordinates relative to root window
531 XLIB_Window hPetitFleur;
532 int nRootX, nRootY;
534 if (XTranslateCoordinates (pDisplay, hWindow, aAttribute.root,
535 0, 0, &nRootX, &nRootY, &hPetitFleur))
537 XWindowAttributes aRootAttribute;
538 XGetWindowAttributes (pDisplay, aAttribute.root, &aRootAttribute);
540 int width = aAttribute.width;
541 int height = aAttribute.height;
542 int x = nRootX;
543 int y = nRootY;
545 // horizontal range check
546 if (x < 0)
548 width = width + x;
549 x = 0;
551 else
552 if (x > aRootAttribute.width)
554 width = 0;
555 x = aRootAttribute.width;
557 else
558 if (x + width > aRootAttribute.width)
560 width = aRootAttribute.width - x;
563 // vertical range check
564 if (y < 0)
566 height = height + y;
567 y = 0;
569 else
570 if (y > aRootAttribute.height)
572 height = 0;
573 y = aRootAttribute.height;
575 else
576 if (y + height > aRootAttribute.height)
578 height = aRootAttribute.height - y;
581 if ((width > 0) && (height > 0))
583 XImage* pImage = XGetImage( pDisplay, aAttribute.root,
584 x, y, width, height, AllPlanes, ZPixmap );
585 bool bSnapShot = ImplCreateFromXImage( pDisplay,
586 aAttribute.root,
587 XScreenNumberOfScreen( aAttribute.screen ),
588 pImage );
589 XDestroyImage (pImage);
591 return bSnapShot;
597 return False;
600 bool
601 X11SalBitmap::ImplCreateFromXImage (Display* pDisplay, XLIB_Window hWindow, int nScreen, XImage* pImage)
603 Destroy();
605 if (pImage != NULL && pImage->width != 0 && pImage->height != 0 && pImage->depth != 0)
607 mpDDB = new ImplSalDDB (pDisplay, hWindow, nScreen, pImage);
608 return True;
610 return False;
613 ImplSalDDB* X11SalBitmap::ImplGetDDB( Drawable aDrawable,
614 int nScreen,
615 long nDrawableDepth,
616 const SalTwoRect& rTwoRect ) const
618 if( !mpDDB || !mpDDB->ImplMatches( nScreen, nDrawableDepth, rTwoRect ) )
620 if( mpDDB )
622 // do we already have a DIB? if not, create aDIB from current DDB first
623 if( !mpDIB )
625 const_cast<X11SalBitmap*>(this)->mpDIB = ImplCreateDIB( mpDDB->ImplGetPixmap(),
626 mpDDB->ImplGetScreen(),
627 mpDDB->ImplGetDepth(),
628 0, 0,
629 mpDDB->ImplGetWidth(),
630 mpDDB->ImplGetHeight(),
631 mbGrey );
634 delete mpDDB, const_cast<X11SalBitmap*>(this)->mpDDB = NULL;
637 if( mpCache )
638 mpCache->ImplRemove( const_cast<X11SalBitmap*>(this) );
640 SalTwoRect aTwoRect( rTwoRect );
641 if( aTwoRect.mnSrcX < 0 )
643 aTwoRect.mnSrcWidth += aTwoRect.mnSrcX;
644 aTwoRect.mnSrcX = 0;
646 if( aTwoRect.mnSrcY < 0 )
648 aTwoRect.mnSrcHeight += aTwoRect.mnSrcY;
649 aTwoRect.mnSrcY = 0;
652 // create new DDB from DIB
653 const Size aSize( GetSize() );
654 if( aTwoRect.mnSrcWidth == aTwoRect.mnDestWidth &&
655 aTwoRect.mnSrcHeight == aTwoRect.mnDestHeight )
657 aTwoRect.mnSrcX = aTwoRect.mnSrcY = aTwoRect.mnDestX = aTwoRect.mnDestY = 0;
658 aTwoRect.mnSrcWidth = aTwoRect.mnDestWidth = aSize.Width();
659 aTwoRect.mnSrcHeight = aTwoRect.mnDestHeight = aSize.Height();
661 else if( aTwoRect.mnSrcWidth+aTwoRect.mnSrcX > aSize.Width() ||
662 aTwoRect.mnSrcHeight+aTwoRect.mnSrcY > aSize.Height() )
664 // #i47823# this should not happen at all, but does nonetheless
665 // because BitmapEx allows for mask bitmaps of different size
666 // than image bitmap (broken)
667 if( aTwoRect.mnSrcX >= aSize.Width() ||
668 aTwoRect.mnSrcY >= aSize.Height() )
669 return NULL; // this would be a really mad case
671 if( aTwoRect.mnSrcWidth+aTwoRect.mnSrcX > aSize.Width() )
673 aTwoRect.mnSrcWidth = aSize.Width()-aTwoRect.mnSrcX;
674 if( aTwoRect.mnSrcWidth < 1 )
676 aTwoRect.mnSrcX = 0;
677 aTwoRect.mnSrcWidth = aSize.Width();
680 if( aTwoRect.mnSrcHeight+aTwoRect.mnSrcY > aSize.Height() )
682 aTwoRect.mnSrcHeight = aSize.Height() - aTwoRect.mnSrcY;
683 if( aTwoRect.mnSrcHeight < 1 )
685 aTwoRect.mnSrcY = 0;
686 aTwoRect.mnSrcHeight = aSize.Height();
691 XImage* pImage = ImplCreateXImage( GetX11SalData()->GetDisplay(), nScreen,
692 nDrawableDepth, aTwoRect );
694 if( pImage )
696 const_cast<X11SalBitmap*>(this)->mpDDB = new ImplSalDDB( pImage, aDrawable, nScreen, aTwoRect );
697 delete[] pImage->data, pImage->data = NULL;
698 XDestroyImage( pImage );
700 if( mpCache )
701 mpCache->ImplAdd( const_cast<X11SalBitmap*>(this), mpDDB->ImplGetMemSize() );
705 return mpDDB;
708 // -----------------------------------------------------------------------------
710 void X11SalBitmap::ImplDraw( Drawable aDrawable,
711 int nScreen,
712 long nDrawableDepth,
713 const SalTwoRect& rTwoRect,
714 const GC& rGC ) const
716 ImplGetDDB( aDrawable, nScreen, nDrawableDepth, rTwoRect );
717 if( mpDDB )
718 mpDDB->ImplDraw( aDrawable, nDrawableDepth, rTwoRect, rGC );
721 // -----------------------------------------------------------------------------
723 bool X11SalBitmap::Create( const Size& rSize, USHORT nBitCount, const BitmapPalette& rPal )
725 Destroy();
726 mpDIB = ImplCreateDIB( rSize, nBitCount, rPal );
728 return( mpDIB != NULL );
731 // -----------------------------------------------------------------------------
733 bool X11SalBitmap::Create( const SalBitmap& rSSalBmp )
735 Destroy();
737 const X11SalBitmap& rSalBmp = static_cast<const X11SalBitmap&>( rSSalBmp );
739 if( rSalBmp.mpDIB )
741 // TODO: reference counting...
742 mpDIB = new BitmapBuffer( *rSalBmp.mpDIB );
743 // TODO: get rid of this when BitmapBuffer gets copy constructor
746 mpDIB->mpBits = new BYTE[ mpDIB->mnScanlineSize * mpDIB->mnHeight ];
748 catch( std::bad_alloc& )
750 delete mpDIB;
751 mpDIB = NULL;
754 if( mpDIB )
755 memcpy( mpDIB->mpBits, rSalBmp.mpDIB->mpBits, mpDIB->mnScanlineSize * mpDIB->mnHeight );
757 else if( rSalBmp.mpDDB )
758 ImplCreateFromDrawable( rSalBmp.mpDDB->ImplGetPixmap(),
759 rSalBmp.mpDDB->ImplGetScreen(),
760 rSalBmp.mpDDB->ImplGetDepth(),
761 0, 0, rSalBmp.mpDDB->ImplGetWidth(), rSalBmp.mpDDB->ImplGetHeight() );
763 return( ( !rSalBmp.mpDIB && !rSalBmp.mpDDB ) ||
764 ( rSalBmp.mpDIB && ( mpDIB != NULL ) ) ||
765 ( rSalBmp.mpDDB && ( mpDDB != NULL ) ) );
768 // -----------------------------------------------------------------------------
770 bool X11SalBitmap::Create( const SalBitmap&, SalGraphics* )
772 return FALSE;
775 // -----------------------------------------------------------------------------
777 bool X11SalBitmap::Create( const SalBitmap&, USHORT )
779 return FALSE;
782 // -----------------------------------------------------------------------------
784 bool X11SalBitmap::Create( const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmapCanvas > xBitmapCanvas, Size& rSize, bool bMask )
786 ::com::sun::star::uno::Reference< ::com::sun::star::beans::XFastPropertySet > xFastPropertySet( xBitmapCanvas, ::com::sun::star::uno::UNO_QUERY );
787 if( xFastPropertySet.get() ) {
788 long pixmapHandle;
789 sal_Int32 depth;
790 ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > args;
792 if( xFastPropertySet->getFastPropertyValue(bMask ? 2 : 1) >>= args ) {
793 if( ( args[1] >>= pixmapHandle ) && ( args[2] >>= depth ) ) {
795 mbGrey = bMask;
796 bool bSuccess = ImplCreateFromDrawable( pixmapHandle, 0, depth, 0, 0, (long) rSize.Width(), (long) rSize.Height() );
797 bool bFreePixmap;
798 if( bSuccess && (args[0] >>= bFreePixmap) && bFreePixmap )
799 XFreePixmap( GetX11SalData()->GetDisplay()->GetDisplay(), pixmapHandle );
801 return bSuccess;
806 return false;
809 // -----------------------------------------------------------------------------
811 void X11SalBitmap::Destroy()
813 if( mpDIB )
815 delete[] mpDIB->mpBits;
816 delete mpDIB, mpDIB = NULL;
819 if( mpDDB )
820 delete mpDDB, mpDDB = NULL;
822 if( mpCache )
823 mpCache->ImplRemove( this );
826 // -----------------------------------------------------------------------------
828 Size X11SalBitmap::GetSize() const
830 Size aSize;
832 if( mpDIB )
833 aSize.Width() = mpDIB->mnWidth, aSize.Height() = mpDIB->mnHeight;
834 else if( mpDDB )
835 aSize.Width() = mpDDB->ImplGetWidth(), aSize.Height() = mpDDB->ImplGetHeight();
837 return aSize;
840 // -----------------------------------------------------------------------------
842 USHORT X11SalBitmap::GetBitCount() const
844 USHORT nBitCount;
846 if( mpDIB )
847 nBitCount = mpDIB->mnBitCount;
848 else if( mpDDB )
849 nBitCount = mpDDB->ImplGetDepth();
850 else
851 nBitCount = 0;
853 return nBitCount;
856 // -----------------------------------------------------------------------------
858 BitmapBuffer* X11SalBitmap::AcquireBuffer( bool )
860 if( !mpDIB && mpDDB )
862 mpDIB = ImplCreateDIB( mpDDB->ImplGetPixmap(),
863 mpDDB->ImplGetScreen(),
864 mpDDB->ImplGetDepth(),
865 0, 0, mpDDB->ImplGetWidth(), mpDDB->ImplGetHeight(), mbGrey );
868 return mpDIB;
871 // -----------------------------------------------------------------------------
873 void X11SalBitmap::ReleaseBuffer( BitmapBuffer*, bool bReadOnly )
875 if( !bReadOnly )
877 if( mpDDB )
878 delete mpDDB, mpDDB = NULL;
880 if( mpCache )
881 mpCache->ImplRemove( this );
885 // -----------------------------------------------------------------------------
887 bool X11SalBitmap::GetSystemData( BitmapSystemData& rData )
889 if( mpDDB )
891 // Rename/retype pDummy to your likings (though X11 Pixmap is
892 // prolly not a good idea, since it's accessed from
893 // non-platform aware code in vcl/bitmap.hxx)
894 rData.aPixmap = (void*)mpDDB->ImplGetPixmap();
895 rData.mnWidth = mpDDB->ImplGetWidth ();
896 rData.mnHeight = mpDDB->ImplGetHeight ();
897 return true;
900 return false;
903 // --------------
904 // - ImplSalDDB -
905 // --------------
907 ImplSalDDB::ImplSalDDB( XImage* pImage, Drawable aDrawable, int nScreen, const SalTwoRect& rTwoRect ) :
908 maPixmap ( 0 ),
909 maTwoRect ( rTwoRect ),
910 mnDepth ( pImage->depth ),
911 mnScreen ( nScreen )
913 SalDisplay* pSalDisp = GetX11SalData()->GetDisplay();
914 Display* pXDisp = pSalDisp->GetDisplay();
916 if( (maPixmap = XCreatePixmap( pXDisp, aDrawable, ImplGetWidth(), ImplGetHeight(), ImplGetDepth() )) )
918 XGCValues aValues;
919 GC aGC;
920 int nValues = GCFunction;
922 aValues.function = GXcopy;
924 if( 1 == mnDepth )
926 nValues |= ( GCForeground | GCBackground );
927 aValues.foreground = 1, aValues.background = 0;
930 aGC = XCreateGC( pXDisp, maPixmap, nValues, &aValues );
931 XPutImage( pXDisp, maPixmap, aGC, pImage, 0, 0, 0, 0, maTwoRect.mnDestWidth, maTwoRect.mnDestHeight );
932 XFreeGC( pXDisp, aGC );
936 // -----------------------------------------------------------------------------------------
937 // create from XImage
939 ImplSalDDB::ImplSalDDB (Display* pDisplay, XLIB_Window hWindow, int nScreen, XImage* pImage) :
940 mnScreen( nScreen )
942 maPixmap = XCreatePixmap (pDisplay, hWindow, pImage->width, pImage->height, pImage->depth);
943 if (maPixmap != 0)
945 XGCValues aValues;
946 GC aGC;
947 int nValues = GCFunction;
949 aValues.function = GXcopy;
951 if (pImage->depth == 1)
953 nValues |= ( GCForeground | GCBackground );
954 aValues.foreground = 1;
955 aValues.background = 0;
958 aGC = XCreateGC (pDisplay, maPixmap, nValues, &aValues);
959 XPutImage (pDisplay, maPixmap, aGC, pImage, 0, 0, 0, 0, pImage->width, pImage->height);
960 XFreeGC (pDisplay, aGC);
962 maTwoRect.mnSrcX = 0;
963 maTwoRect.mnSrcY = 0;
964 maTwoRect.mnDestX = 0;
965 maTwoRect.mnDestY = 0;
966 maTwoRect.mnSrcWidth = pImage->width;
967 maTwoRect.mnDestWidth = pImage->width;
968 maTwoRect.mnSrcHeight = pImage->height;
969 maTwoRect.mnDestHeight = pImage->height;
971 mnDepth = pImage->depth;
975 // -----------------------------------------------------------------------------
977 ImplSalDDB::ImplSalDDB( Drawable aDrawable, int nScreen, long nDrawableDepth, long nX, long nY, long nWidth, long nHeight ) :
978 mnDepth( nDrawableDepth ),
979 mnScreen( nScreen )
981 SalDisplay* pSalDisp = GetX11SalData()->GetDisplay();
982 Display* pXDisp = pSalDisp->GetDisplay();
984 if( (maPixmap = XCreatePixmap( pXDisp, aDrawable, nWidth, nHeight, nDrawableDepth )) )
986 XGCValues aValues;
987 GC aGC;
988 int nValues = GCFunction;
990 aValues.function = GXcopy;
992 if( 1 == mnDepth )
994 nValues |= ( GCForeground | GCBackground );
995 aValues.foreground = 1, aValues.background = 0;
998 aGC = XCreateGC( pXDisp, maPixmap, nValues, &aValues );
999 ImplDraw( aDrawable, nDrawableDepth, maPixmap, mnDepth,
1000 nX, nY, nWidth, nHeight, 0, 0, aGC );
1001 XFreeGC( pXDisp, aGC );
1003 maTwoRect.mnSrcX = maTwoRect.mnSrcY = maTwoRect.mnDestX = maTwoRect.mnDestY = 0;
1004 maTwoRect.mnSrcWidth = maTwoRect.mnDestWidth = nWidth;
1005 maTwoRect.mnSrcHeight = maTwoRect.mnDestHeight = nHeight;
1009 // -----------------------------------------------------------------------------
1011 ImplSalDDB::~ImplSalDDB()
1013 if( maPixmap && ImplGetSVData() )
1014 XFreePixmap( GetX11SalData()->GetDisplay()->GetDisplay(), maPixmap );
1017 // -----------------------------------------------------------------------------
1019 bool ImplSalDDB::ImplMatches( int nScreen, long nDepth, const SalTwoRect& rTwoRect ) const
1021 bool bRet = FALSE;
1023 if( ( maPixmap != 0 ) && ( ( mnDepth == nDepth ) || ( 1 == mnDepth ) ) && nScreen == mnScreen)
1025 if( rTwoRect.mnSrcX == maTwoRect.mnSrcX && rTwoRect.mnSrcY == maTwoRect.mnSrcY &&
1026 rTwoRect.mnSrcWidth == maTwoRect.mnSrcWidth && rTwoRect.mnSrcHeight == maTwoRect.mnSrcHeight &&
1027 rTwoRect.mnDestWidth == maTwoRect.mnDestWidth && rTwoRect.mnDestHeight == maTwoRect.mnDestHeight )
1029 // absolutely indentically
1030 bRet = TRUE;
1032 else if( rTwoRect.mnSrcWidth == rTwoRect.mnDestWidth && rTwoRect.mnSrcHeight == rTwoRect.mnDestHeight &&
1033 maTwoRect.mnSrcWidth == maTwoRect.mnDestWidth && maTwoRect.mnSrcHeight == maTwoRect.mnDestHeight &&
1034 rTwoRect.mnSrcX >= maTwoRect.mnSrcX && rTwoRect.mnSrcY >= maTwoRect.mnSrcY &&
1035 ( rTwoRect.mnSrcX + rTwoRect.mnSrcWidth ) <= ( maTwoRect.mnSrcX + maTwoRect.mnSrcWidth ) &&
1036 ( rTwoRect.mnSrcY + rTwoRect.mnSrcHeight ) <= ( maTwoRect.mnSrcY + maTwoRect.mnSrcHeight ) )
1038 bRet = TRUE;
1042 return bRet;
1045 // -----------------------------------------------------------------------------
1047 void ImplSalDDB::ImplDraw( Drawable aDrawable, long nDrawableDepth, const SalTwoRect& rTwoRect, const GC& rGC ) const
1049 ImplDraw( maPixmap, mnDepth, aDrawable, nDrawableDepth,
1050 rTwoRect.mnSrcX - maTwoRect.mnSrcX, rTwoRect.mnSrcY - maTwoRect.mnSrcY,
1051 rTwoRect.mnDestWidth, rTwoRect.mnDestHeight,
1052 rTwoRect.mnDestX, rTwoRect.mnDestY, rGC );
1055 // -----------------------------------------------------------------------------
1057 void ImplSalDDB::ImplDraw( Drawable aSrcDrawable, long nSrcDrawableDepth,
1058 Drawable aDstDrawable, long,
1059 long nSrcX, long nSrcY,
1060 long nDestWidth, long nDestHeight,
1061 long nDestX, long nDestY, const GC& rGC )
1063 SalDisplay* pSalDisp = GetX11SalData()->GetDisplay();
1064 Display* pXDisp = pSalDisp->GetDisplay();
1066 if( 1 == nSrcDrawableDepth )
1068 XCopyPlane( pXDisp, aSrcDrawable, aDstDrawable, rGC,
1069 nSrcX, nSrcY, nDestWidth, nDestHeight, nDestX, nDestY, 1 );
1071 else
1073 XCopyArea( pXDisp, aSrcDrawable, aDstDrawable, rGC,
1074 nSrcX, nSrcY, nDestWidth, nDestHeight, nDestX, nDestY );
1078 // ----------------------
1079 // - ImplSalBitmapCache -
1080 // ----------------------
1082 struct ImplBmpObj
1084 X11SalBitmap* mpBmp;
1085 ULONG mnMemSize;
1086 ULONG mnFlags;
1088 ImplBmpObj( X11SalBitmap* pBmp, ULONG nMemSize, ULONG nFlags ) :
1089 mpBmp( pBmp ), mnMemSize( nMemSize ), mnFlags( nFlags ) {}
1092 // -----------------------------------------------------------------------------
1094 ImplSalBitmapCache::ImplSalBitmapCache() :
1095 mnTotalSize( 0UL )
1099 // -----------------------------------------------------------------------------
1101 ImplSalBitmapCache::~ImplSalBitmapCache()
1103 ImplClear();
1106 // -----------------------------------------------------------------------------
1108 void ImplSalBitmapCache::ImplAdd( X11SalBitmap* pBmp, ULONG nMemSize, ULONG nFlags )
1110 ImplBmpObj* pObj;
1111 bool bFound = FALSE;
1113 for( pObj = (ImplBmpObj*) maBmpList.Last(); pObj && !bFound; pObj = (ImplBmpObj*) maBmpList.Prev() )
1114 if( pObj->mpBmp == pBmp )
1115 bFound = TRUE;
1117 mnTotalSize += nMemSize;
1119 if( bFound )
1121 mnTotalSize -= pObj->mnMemSize;
1122 pObj->mnMemSize = nMemSize, pObj->mnFlags = nFlags;
1124 else
1125 maBmpList.Insert( new ImplBmpObj( pBmp, nMemSize, nFlags ), LIST_APPEND );
1128 // -----------------------------------------------------------------------------
1130 void ImplSalBitmapCache::ImplRemove( X11SalBitmap* pBmp )
1132 for( ImplBmpObj* pObj = (ImplBmpObj*) maBmpList.Last(); pObj; pObj = (ImplBmpObj*) maBmpList.Prev() )
1134 if( pObj->mpBmp == pBmp )
1136 maBmpList.Remove( pObj );
1137 pObj->mpBmp->ImplRemovedFromCache();
1138 mnTotalSize -= pObj->mnMemSize;
1139 delete pObj;
1140 break;
1145 // -----------------------------------------------------------------------------
1147 void ImplSalBitmapCache::ImplClear()
1149 for( ImplBmpObj* pObj = (ImplBmpObj*) maBmpList.First(); pObj; pObj = (ImplBmpObj*) maBmpList.Next() )
1151 pObj->mpBmp->ImplRemovedFromCache();
1152 delete pObj;
1155 maBmpList.Clear();
1156 mnTotalSize = 0;