1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
23 #include <sys/types.h>
27 #include <X11/Xutil.h>
29 #include <osl/endian.h>
30 #include <sal/log.hxx>
32 #include <tools/helpers.hxx>
33 #include <tools/debug.hxx>
34 #include <vcl/bitmap.hxx>
35 #include <com/sun/star/beans/XFastPropertySet.hpp>
37 #include <unx/saldisp.hxx>
38 #include <unx/salbmp.h>
39 #include <unx/salinst.h>
40 #include <unx/x11/xlimits.hxx>
42 #include <o3tl/safeint.hxx>
43 #include <opengl/salbmp.hxx>
44 #include <vcl/opengl/OpenGLHelper.hxx>
46 #include <config_features.h>
48 #include <vcl/skia/SkiaHelper.hxx>
49 #include <skia/salbmp.hxx>
52 #if defined HAVE_VALGRIND_HEADERS
53 #include <valgrind/valgrind.h>
59 std::shared_ptr
<SalBitmap
> X11SalInstance::CreateSalBitmap()
62 if (SkiaHelper::isVCLSkiaEnabled())
63 return std::make_shared
<SkiaSalBitmap
>();
66 if (OpenGLHelper::isVCLOpenGLEnabled())
67 return std::make_shared
<OpenGLSalBitmap
>();
69 return std::make_shared
<X11SalBitmap
>();
72 ImplSalBitmapCache
* X11SalBitmap::mpCache
= nullptr;
73 unsigned int X11SalBitmap::mnCacheInstCount
= 0;
75 X11SalBitmap::X11SalBitmap()
80 X11SalBitmap::~X11SalBitmap()
85 void X11SalBitmap::ImplCreateCache()
87 if( !mnCacheInstCount
++ )
88 mpCache
= new ImplSalBitmapCache
;
91 void X11SalBitmap::ImplDestroyCache()
93 SAL_WARN_IF( !mnCacheInstCount
, "vcl", "X11SalBitmap::ImplDestroyCache(): underflow" );
95 if( mnCacheInstCount
&& !--mnCacheInstCount
)
102 void X11SalBitmap::ImplRemovedFromCache()
107 #if defined HAVE_VALGRIND_HEADERS
110 void blankExtraSpace(BitmapBuffer
* pDIB
)
112 size_t nExtraSpaceInScanLine
= pDIB
->mnScanlineSize
- pDIB
->mnWidth
* pDIB
->mnBitCount
/ 8;
113 if (nExtraSpaceInScanLine
)
115 for (tools::Long i
= 0; i
< pDIB
->mnHeight
; ++i
)
117 sal_uInt8
*pRow
= pDIB
->mpBits
+ (i
* pDIB
->mnScanlineSize
);
118 memset(pRow
+ (pDIB
->mnScanlineSize
- nExtraSpaceInScanLine
), 0, nExtraSpaceInScanLine
);
125 std::unique_ptr
<BitmapBuffer
> X11SalBitmap::ImplCreateDIB(
127 sal_uInt16 nBitCount
,
128 const BitmapPalette
& rPal
)
135 , "Unsupported BitCount!"
138 std::unique_ptr
<BitmapBuffer
> pDIB
;
140 if( !rSize
.Width() || !rSize
.Height() )
145 pDIB
.reset(new BitmapBuffer
);
147 catch (const std::bad_alloc
&)
152 const sal_uInt16 nColors
= ( nBitCount
<= 8 ) ? ( 1 << nBitCount
) : 0;
154 pDIB
->mnFormat
= ScanlineFormat::NONE
;
158 case 1: pDIB
->mnFormat
|= ScanlineFormat::N1BitMsbPal
; break;
159 case 4: pDIB
->mnFormat
|= ScanlineFormat::N4BitMsnPal
; break;
160 case 8: pDIB
->mnFormat
|= ScanlineFormat::N8BitPal
; break;
161 case 24: pDIB
->mnFormat
|= ScanlineFormat::N24BitTcBgr
; break;
163 SAL_WARN("vcl.gdi", "32-bit images not supported, converting to 24-bit");
165 pDIB
->mnFormat
|= ScanlineFormat::N24BitTcBgr
;
169 pDIB
->mnWidth
= rSize
.Width();
170 pDIB
->mnHeight
= rSize
.Height();
171 tools::Long nScanlineBase
;
172 bool bFail
= o3tl::checked_multiply
<tools::Long
>(pDIB
->mnWidth
, nBitCount
, nScanlineBase
);
175 SAL_WARN("vcl.gdi", "checked multiply failed");
178 pDIB
->mnScanlineSize
= AlignedWidth4Bytes(nScanlineBase
);
179 if (pDIB
->mnScanlineSize
< nScanlineBase
/8)
181 SAL_WARN("vcl.gdi", "scanline calculation wraparound");
184 pDIB
->mnBitCount
= nBitCount
;
188 pDIB
->maPalette
= rPal
;
189 pDIB
->maPalette
.SetEntryCount( nColors
);
194 pDIB
->mpBits
= new sal_uInt8
[ pDIB
->mnScanlineSize
* pDIB
->mnHeight
];
195 #if defined HAVE_VALGRIND_HEADERS
196 if (RUNNING_ON_VALGRIND
)
197 blankExtraSpace(pDIB
.get());
200 catch (const std::bad_alloc
&)
208 std::unique_ptr
<BitmapBuffer
> X11SalBitmap::ImplCreateDIB(
210 SalX11Screen nScreen
,
211 tools::Long nDrawableDepth
,
218 std::unique_ptr
<BitmapBuffer
> pDIB
;
220 if( aDrawable
&& nWidth
&& nHeight
&& nDrawableDepth
)
222 SalDisplay
* pSalDisp
= vcl_sal::getSalDisplay(GetGenericUnixSalData());
223 Display
* pXDisp
= pSalDisp
->GetDisplay();
225 // do not die on XError here
226 // alternatively one could check the coordinates for being offscreen
227 // but this call can actually work on servers with backing store
228 // defaults even if the rectangle is offscreen
229 // so better catch the XError
230 GetGenericUnixSalData()->ErrorTrapPush();
231 XImage
* pImage
= XGetImage( pXDisp
, aDrawable
, nX
, nY
, nWidth
, nHeight
, AllPlanes
, ZPixmap
);
232 bool bWasError
= GetGenericUnixSalData()->ErrorTrapPop( false );
234 if( ! bWasError
&& pImage
&& pImage
->data
)
236 const SalTwoRect aTwoRect
= { 0, 0, nWidth
, nHeight
, 0, 0, nWidth
, nHeight
};
237 BitmapBuffer aSrcBuf
;
238 const BitmapPalette
* pDstPal
= nullptr;
240 aSrcBuf
.mnFormat
= ScanlineFormat::TopDown
;
241 aSrcBuf
.mnWidth
= nWidth
;
242 aSrcBuf
.mnHeight
= nHeight
;
243 aSrcBuf
.mnBitCount
= pImage
->bits_per_pixel
;
244 aSrcBuf
.mnScanlineSize
= pImage
->bytes_per_line
;
245 aSrcBuf
.mpBits
= reinterpret_cast<sal_uInt8
*>(pImage
->data
);
247 pImage
->red_mask
= pSalDisp
->GetVisual( nScreen
).red_mask
;
248 pImage
->green_mask
= pSalDisp
->GetVisual( nScreen
).green_mask
;
249 pImage
->blue_mask
= pSalDisp
->GetVisual( nScreen
).blue_mask
;
251 switch( aSrcBuf
.mnBitCount
)
255 aSrcBuf
.mnFormat
|= ( LSBFirst
== pImage
->bitmap_bit_order
256 ? ScanlineFormat::N1BitLsbPal
257 : ScanlineFormat::N1BitMsbPal
264 aSrcBuf
.mnFormat
|= ( LSBFirst
== pImage
->bitmap_bit_order
265 ? ScanlineFormat::N4BitLsnPal
266 : ScanlineFormat::N4BitMsnPal
273 aSrcBuf
.mnFormat
|= ScanlineFormat::N8BitPal
;
279 if( ( LSBFirst
== pImage
->byte_order
) && ( pImage
->red_mask
== 0xFF ) )
280 aSrcBuf
.mnFormat
|= ScanlineFormat::N24BitTcRgb
;
282 aSrcBuf
.mnFormat
|= ScanlineFormat::N24BitTcBgr
;
288 if( LSBFirst
== pImage
->byte_order
)
289 aSrcBuf
.mnFormat
|= ( pSalDisp
->GetVisual(nScreen
).red_mask
== 0xFF
290 ? ScanlineFormat::N32BitTcRgba
291 : ScanlineFormat::N32BitTcBgra
294 aSrcBuf
.mnFormat
|= ( pSalDisp
->GetVisual(nScreen
).red_mask
== 0xFF
295 ? ScanlineFormat::N32BitTcAbgr
296 : ScanlineFormat::N32BitTcArgb
301 default: assert(false);
304 BitmapPalette
& rPal
= aSrcBuf
.maPalette
;
306 if( aSrcBuf
.mnBitCount
== 1 )
308 rPal
.SetEntryCount( 2 );
311 rPal
[ 0 ] = COL_BLACK
;
312 rPal
[ 1 ] = COL_WHITE
;
314 else if( pImage
->depth
== 8 && bGrey
)
316 rPal
.SetEntryCount( 256 );
319 for( sal_uInt16 i
= 0; i
< 256; i
++ )
321 BitmapColor
& rBmpCol
= rPal
[ i
];
324 rBmpCol
.SetGreen( i
);
325 rBmpCol
.SetBlue( i
);
329 else if( aSrcBuf
.mnBitCount
<= 8 )
331 const SalColormap
& rColMap
= pSalDisp
->GetColormap( nScreen
);
332 const sal_uInt16 nCols
= std::min(static_cast<sal_uLong
>(rColMap
.GetUsed()),
333 sal_uLong(1) << nDrawableDepth
);
335 rPal
.SetEntryCount( nCols
);
338 for( sal_uInt16 i
= 0; i
< nCols
; i
++ )
340 const Color
nColor( rColMap
.GetColor( i
) );
341 BitmapColor
& rBmpCol
= rPal
[ i
];
343 rBmpCol
.SetRed( nColor
.GetRed() );
344 rBmpCol
.SetGreen( nColor
.GetGreen() );
345 rBmpCol
.SetBlue( nColor
.GetBlue() );
349 pDIB
= StretchAndConvert( aSrcBuf
, aTwoRect
, aSrcBuf
.mnFormat
,
350 pDstPal
, &aSrcBuf
.maColorMask
);
351 XDestroyImage( pImage
);
358 XImage
* X11SalBitmap::ImplCreateXImage(
359 SalDisplay
const *pSalDisp
,
360 SalX11Screen nScreen
,
362 const SalTwoRect
& rTwoRect
365 XImage
* pImage
= nullptr;
367 if( !mpDIB
&& mpDDB
)
369 const_cast<X11SalBitmap
*>(this)->mpDIB
=
370 ImplCreateDIB( mpDDB
->ImplGetPixmap(),
371 mpDDB
->ImplGetScreen(),
372 mpDDB
->ImplGetDepth(),
374 mpDDB
->ImplGetWidth(),
375 mpDDB
->ImplGetHeight(),
379 if( mpDIB
&& mpDIB
->mnWidth
&& mpDIB
->mnHeight
)
381 Display
* pXDisp
= pSalDisp
->GetDisplay();
382 tools::Long nWidth
= rTwoRect
.mnDestWidth
;
383 tools::Long nHeight
= rTwoRect
.mnDestHeight
;
385 if( 1 == GetBitCount() )
388 pImage
= XCreateImage( pXDisp
, pSalDisp
->GetVisual( nScreen
).GetVisual(),
389 nDepth
, ( 1 == nDepth
) ? XYBitmap
:ZPixmap
, 0, nullptr,
390 nWidth
, nHeight
, 32, 0 );
394 std::unique_ptr
<BitmapBuffer
> pDstBuf
;
395 ScanlineFormat nDstFormat
= ScanlineFormat::TopDown
;
396 std::unique_ptr
<BitmapPalette
> xPal
;
397 std::unique_ptr
<ColorMask
> xMask
;
399 switch( pImage
->bits_per_pixel
)
402 nDstFormat
|= ( LSBFirst
== pImage
->bitmap_bit_order
403 ? ScanlineFormat::N1BitLsbPal
404 : ScanlineFormat::N1BitMsbPal
409 nDstFormat
|= ( LSBFirst
== pImage
->bitmap_bit_order
410 ? ScanlineFormat::N4BitLsnPal
411 : ScanlineFormat::N4BitMsnPal
416 nDstFormat
|= ScanlineFormat::N8BitPal
;
421 if( ( LSBFirst
== pImage
->byte_order
) && ( pImage
->red_mask
== 0xFF ) )
422 nDstFormat
|= ScanlineFormat::N24BitTcRgb
;
424 nDstFormat
|= ScanlineFormat::N24BitTcBgr
;
430 if( LSBFirst
== pImage
->byte_order
)
431 nDstFormat
|= ( pImage
->red_mask
== 0xFF
432 ? ScanlineFormat::N32BitTcRgba
433 : ScanlineFormat::N32BitTcBgra
436 nDstFormat
|= ( pImage
->red_mask
== 0xFF
437 ? ScanlineFormat::N32BitTcAbgr
438 : ScanlineFormat::N32BitTcArgb
443 default: assert(false);
446 if( pImage
->depth
== 1 )
448 xPal
.reset(new BitmapPalette( 2 ));
449 (*xPal
)[ 0 ] = COL_BLACK
;
450 (*xPal
)[ 1 ] = COL_WHITE
;
452 else if( pImage
->depth
== 8 && mbGrey
)
454 xPal
.reset(new BitmapPalette( 256 ));
456 for( sal_uInt16 i
= 0; i
< 256; i
++ )
458 BitmapColor
& rBmpCol
= (*xPal
)[ i
];
461 rBmpCol
.SetGreen( i
);
462 rBmpCol
.SetBlue( i
);
466 else if( pImage
->depth
<= 8 )
468 const SalColormap
& rColMap
= pSalDisp
->GetColormap( nScreen
);
469 const sal_uInt16 nCols
= std::min( static_cast<sal_uLong
>(rColMap
.GetUsed())
470 , static_cast<sal_uLong
>(1 << pImage
->depth
)
473 xPal
.reset(new BitmapPalette( nCols
));
475 for( sal_uInt16 i
= 0; i
< nCols
; i
++ )
477 const Color
nColor( rColMap
.GetColor( i
) );
478 BitmapColor
& rBmpCol
= (*xPal
)[ i
];
480 rBmpCol
.SetRed( nColor
.GetRed() );
481 rBmpCol
.SetGreen( nColor
.GetGreen() );
482 rBmpCol
.SetBlue( nColor
.GetBlue() );
486 pDstBuf
= StretchAndConvert( *mpDIB
, rTwoRect
, nDstFormat
, xPal
.get(), xMask
.get() );
490 if( pDstBuf
&& pDstBuf
->mpBits
)
492 #if defined HAVE_VALGRIND_HEADERS
493 if (RUNNING_ON_VALGRIND
)
494 blankExtraSpace(pDstBuf
.get());
496 // set data in buffer as data member in pImage
497 pImage
->data
= reinterpret_cast<char*>(pDstBuf
->mpBits
);
501 XDestroyImage( pImage
);
505 // note that pDstBuf it deleted here, but that doesn't destroy allocated data in buffer
512 bool X11SalBitmap::ImplCreateFromDrawable(
514 SalX11Screen nScreen
,
515 tools::Long nDrawableDepth
,
523 if( aDrawable
&& nWidth
&& nHeight
&& nDrawableDepth
)
524 mpDDB
.reset(new ImplSalDDB( aDrawable
, nScreen
, nDrawableDepth
, nX
, nY
, nWidth
, nHeight
));
526 return( mpDDB
!= nullptr );
529 ImplSalDDB
* X11SalBitmap::ImplGetDDB(
531 SalX11Screen nXScreen
,
532 tools::Long nDrawableDepth
,
533 const SalTwoRect
& rTwoRect
536 if( !mpDDB
|| !mpDDB
->ImplMatches( nXScreen
, nDrawableDepth
, rTwoRect
) )
540 // do we already have a DIB? if not, create aDIB from current DDB first
543 const_cast<X11SalBitmap
*>(this)->mpDIB
= ImplCreateDIB( mpDDB
->ImplGetPixmap(),
544 mpDDB
->ImplGetScreen(),
545 mpDDB
->ImplGetDepth(),
547 mpDDB
->ImplGetWidth(),
548 mpDDB
->ImplGetHeight(),
556 mpCache
->ImplRemove( this );
558 SalTwoRect
aTwoRect( rTwoRect
);
559 if( aTwoRect
.mnSrcX
< 0 )
561 aTwoRect
.mnSrcWidth
+= aTwoRect
.mnSrcX
;
564 if( aTwoRect
.mnSrcY
< 0 )
566 aTwoRect
.mnSrcHeight
+= aTwoRect
.mnSrcY
;
570 // create new DDB from DIB
571 const Size
aSize( GetSize() );
572 if( aTwoRect
.mnSrcWidth
== aTwoRect
.mnDestWidth
&&
573 aTwoRect
.mnSrcHeight
== aTwoRect
.mnDestHeight
)
575 aTwoRect
.mnSrcX
= aTwoRect
.mnSrcY
= aTwoRect
.mnDestX
= aTwoRect
.mnDestY
= 0;
576 aTwoRect
.mnSrcWidth
= aTwoRect
.mnDestWidth
= aSize
.Width();
577 aTwoRect
.mnSrcHeight
= aTwoRect
.mnDestHeight
= aSize
.Height();
579 else if( aTwoRect
.mnSrcWidth
+aTwoRect
.mnSrcX
> aSize
.Width() ||
580 aTwoRect
.mnSrcHeight
+aTwoRect
.mnSrcY
> aSize
.Height() )
582 // #i47823# this should not happen at all, but does nonetheless
583 // because BitmapEx allows for mask bitmaps of different size
584 // than image bitmap (broken)
585 if( aTwoRect
.mnSrcX
>= aSize
.Width() ||
586 aTwoRect
.mnSrcY
>= aSize
.Height() )
587 return nullptr; // this would be a really mad case
589 if( aTwoRect
.mnSrcWidth
+aTwoRect
.mnSrcX
> aSize
.Width() )
591 aTwoRect
.mnSrcWidth
= aSize
.Width()-aTwoRect
.mnSrcX
;
592 if( aTwoRect
.mnSrcWidth
< 1 )
595 aTwoRect
.mnSrcWidth
= aSize
.Width();
598 if( aTwoRect
.mnSrcHeight
+aTwoRect
.mnSrcY
> aSize
.Height() )
600 aTwoRect
.mnSrcHeight
= aSize
.Height() - aTwoRect
.mnSrcY
;
601 if( aTwoRect
.mnSrcHeight
< 1 )
604 aTwoRect
.mnSrcHeight
= aSize
.Height();
609 XImage
* pImage
= ImplCreateXImage( vcl_sal::getSalDisplay(GetGenericUnixSalData()), nXScreen
,
610 nDrawableDepth
, aTwoRect
);
614 mpDDB
.reset(new ImplSalDDB( pImage
, aDrawable
, nXScreen
, aTwoRect
));
615 delete[] pImage
->data
;
616 pImage
->data
= nullptr;
617 XDestroyImage( pImage
);
620 mpCache
->ImplAdd( const_cast<X11SalBitmap
*>(this) );
627 void X11SalBitmap::ImplDraw(
629 SalX11Screen nXScreen
,
630 tools::Long nDrawableDepth
,
631 const SalTwoRect
& rTwoRect
,
635 ImplGetDDB( aDrawable
, nXScreen
, nDrawableDepth
, rTwoRect
);
637 mpDDB
->ImplDraw( aDrawable
, rTwoRect
, rGC
);
640 bool X11SalBitmap::Create( const Size
& rSize
, sal_uInt16 nBitCount
, const BitmapPalette
& rPal
)
643 mpDIB
= ImplCreateDIB( rSize
, nBitCount
, rPal
);
645 return( mpDIB
!= nullptr );
648 bool X11SalBitmap::Create( const SalBitmap
& rSSalBmp
)
652 if( dynamic_cast<const X11SalBitmap
*>( &rSSalBmp
) == nullptr )
655 const X11SalBitmap
& rSalBmp
= static_cast<const X11SalBitmap
&>( rSSalBmp
);
659 // TODO: reference counting...
660 mpDIB
.reset(new BitmapBuffer( *rSalBmp
.mpDIB
));
661 // TODO: get rid of this when BitmapBuffer gets copy constructor
664 mpDIB
->mpBits
= new sal_uInt8
[ mpDIB
->mnScanlineSize
* mpDIB
->mnHeight
];
665 #if defined HAVE_VALGRIND_HEADERS
666 if (RUNNING_ON_VALGRIND
)
667 blankExtraSpace(mpDIB
.get());
670 catch (const std::bad_alloc
&)
676 memcpy( mpDIB
->mpBits
, rSalBmp
.mpDIB
->mpBits
, mpDIB
->mnScanlineSize
* mpDIB
->mnHeight
);
678 else if( rSalBmp
.mpDDB
)
679 ImplCreateFromDrawable( rSalBmp
.mpDDB
->ImplGetPixmap(),
680 rSalBmp
.mpDDB
->ImplGetScreen(),
681 rSalBmp
.mpDDB
->ImplGetDepth(),
682 0, 0, rSalBmp
.mpDDB
->ImplGetWidth(), rSalBmp
.mpDDB
->ImplGetHeight() );
684 return( ( !rSalBmp
.mpDIB
&& !rSalBmp
.mpDDB
) ||
685 ( rSalBmp
.mpDIB
&& ( mpDIB
!= nullptr ) ) ||
686 ( rSalBmp
.mpDDB
&& ( mpDDB
!= nullptr ) ) );
689 bool X11SalBitmap::Create( const SalBitmap
&, SalGraphics
* )
694 bool X11SalBitmap::Create( const SalBitmap
&, sal_uInt16
)
699 bool X11SalBitmap::Create(
700 const css::uno::Reference
< css::rendering::XBitmapCanvas
>& rBitmapCanvas
,
704 css::uno::Reference
< css::beans::XFastPropertySet
> xFastPropertySet( rBitmapCanvas
, css::uno::UNO_QUERY
);
706 if( xFastPropertySet
) {
707 css::uno::Sequence
< css::uno::Any
> args
;
709 if( xFastPropertySet
->getFastPropertyValue(bMask
? 2 : 1) >>= args
) {
710 sal_Int64 pixmapHandle
= {}; // spurious -Werror=maybe-uninitialized
712 if( ( args
[1] >>= pixmapHandle
) && ( args
[2] >>= depth
) ) {
715 bool bSuccess
= ImplCreateFromDrawable(
717 // FIXME: this seems multi-screen broken to me
725 bool bFreePixmap
= false;
726 if( bSuccess
&& (args
[0] >>= bFreePixmap
) && bFreePixmap
)
727 XFreePixmap( vcl_sal::getSalDisplay(GetGenericUnixSalData())->GetDisplay(), pixmapHandle
);
737 void X11SalBitmap::Destroy()
741 delete[] mpDIB
->mpBits
;
748 mpCache
->ImplRemove( this );
751 Size
X11SalBitmap::GetSize() const
757 aSize
.setWidth( mpDIB
->mnWidth
);
758 aSize
.setHeight( mpDIB
->mnHeight
);
762 aSize
.setWidth( mpDDB
->ImplGetWidth() );
763 aSize
.setHeight( mpDDB
->ImplGetHeight() );
769 sal_uInt16
X11SalBitmap::GetBitCount() const
771 sal_uInt16 nBitCount
;
774 nBitCount
= mpDIB
->mnBitCount
;
776 nBitCount
= mpDDB
->ImplGetDepth();
783 BitmapBuffer
* X11SalBitmap::AcquireBuffer( BitmapAccessMode
/*nMode*/ )
785 if( !mpDIB
&& mpDDB
)
787 mpDIB
= ImplCreateDIB(
788 mpDDB
->ImplGetPixmap(),
789 mpDDB
->ImplGetScreen(),
790 mpDDB
->ImplGetDepth(),
792 mpDDB
->ImplGetWidth(),
793 mpDDB
->ImplGetHeight(),
801 void X11SalBitmap::ReleaseBuffer( BitmapBuffer
*, BitmapAccessMode nMode
)
803 if( nMode
== BitmapAccessMode::Write
)
808 mpCache
->ImplRemove( this );
809 InvalidateChecksum();
813 bool X11SalBitmap::GetSystemData( BitmapSystemData
& rData
)
817 // Rename/retype pDummy to your likings (though X11 Pixmap is
818 // prolly not a good idea, since it's accessed from
819 // non-platform aware code in vcl/bitmap.hxx)
820 rData
.aPixmap
= reinterpret_cast<void*>(mpDDB
->ImplGetPixmap());
821 rData
.mnWidth
= mpDDB
->ImplGetWidth ();
822 rData
.mnHeight
= mpDDB
->ImplGetHeight ();
829 bool X11SalBitmap::ScalingSupported() const
834 bool X11SalBitmap::Scale( const double& /*rScaleX*/, const double& /*rScaleY*/, BmpScaleFlag
/*nScaleFlag*/ )
839 bool X11SalBitmap::Replace( const Color
& /*rSearchColor*/, const Color
& /*rReplaceColor*/, sal_uInt8
/*nTol*/ )
845 ImplSalDDB::ImplSalDDB( XImage
* pImage
, Drawable aDrawable
,
846 SalX11Screen nXScreen
, const SalTwoRect
& rTwoRect
)
848 , maTwoRect ( rTwoRect
)
849 , mnDepth ( pImage
->depth
)
850 , mnXScreen ( nXScreen
)
852 SalDisplay
* pSalDisp
= vcl_sal::getSalDisplay(GetGenericUnixSalData());
853 Display
* pXDisp
= pSalDisp
->GetDisplay();
855 maPixmap
= limitXCreatePixmap( pXDisp
, aDrawable
, ImplGetWidth(), ImplGetHeight(), ImplGetDepth() );
861 int nValues
= GCFunction
;
863 aValues
.function
= GXcopy
;
867 nValues
|= ( GCForeground
| GCBackground
);
868 aValues
.foreground
= 1;
869 aValues
.background
= 0;
872 aGC
= XCreateGC( pXDisp
, maPixmap
, nValues
, &aValues
);
873 XPutImage( pXDisp
, maPixmap
, aGC
, pImage
, 0, 0, 0, 0, maTwoRect
.mnDestWidth
, maTwoRect
.mnDestHeight
);
874 XFreeGC( pXDisp
, aGC
);
877 ImplSalDDB::ImplSalDDB(
879 SalX11Screen nXScreen
,
880 tools::Long nDrawableDepth
,
885 ) : maTwoRect(0, 0, nWidth
, nHeight
, 0, 0, nWidth
, nHeight
)
886 , mnDepth( nDrawableDepth
)
887 , mnXScreen( nXScreen
)
889 SalDisplay
* pSalDisp
= vcl_sal::getSalDisplay(GetGenericUnixSalData());
890 Display
* pXDisp
= pSalDisp
->GetDisplay();
892 if( (maPixmap
= limitXCreatePixmap( pXDisp
, aDrawable
, nWidth
, nHeight
, nDrawableDepth
)) )
896 int nValues
= GCFunction
;
898 aValues
.function
= GXcopy
;
902 nValues
|= ( GCForeground
| GCBackground
);
903 aValues
.foreground
= 1;
904 aValues
.background
= 0;
907 aGC
= XCreateGC( pXDisp
, maPixmap
, nValues
, &aValues
);
908 ImplDraw( aDrawable
, nDrawableDepth
, maPixmap
,
909 nX
, nY
, nWidth
, nHeight
, 0, 0, aGC
);
910 XFreeGC( pXDisp
, aGC
);
914 maTwoRect
.mnSrcWidth
= maTwoRect
.mnDestWidth
= 0;
915 maTwoRect
.mnSrcHeight
= maTwoRect
.mnDestHeight
= 0;
919 ImplSalDDB::~ImplSalDDB()
921 if( maPixmap
&& ImplGetSVData() )
922 XFreePixmap( vcl_sal::getSalDisplay(GetGenericUnixSalData())->GetDisplay(), maPixmap
);
925 bool ImplSalDDB::ImplMatches( SalX11Screen nXScreen
, tools::Long nDepth
, const SalTwoRect
& rTwoRect
) const
929 if( ( maPixmap
!= 0 ) && ( ( mnDepth
== nDepth
) || ( 1 == mnDepth
) ) && nXScreen
== mnXScreen
)
931 if ( rTwoRect
.mnSrcX
== maTwoRect
.mnSrcX
932 && rTwoRect
.mnSrcY
== maTwoRect
.mnSrcY
933 && rTwoRect
.mnSrcWidth
== maTwoRect
.mnSrcWidth
934 && rTwoRect
.mnSrcHeight
== maTwoRect
.mnSrcHeight
935 && rTwoRect
.mnDestWidth
== maTwoRect
.mnDestWidth
936 && rTwoRect
.mnDestHeight
== maTwoRect
.mnDestHeight
939 // absolutely identically
942 else if( rTwoRect
.mnSrcWidth
== rTwoRect
.mnDestWidth
943 && rTwoRect
.mnSrcHeight
== rTwoRect
.mnDestHeight
944 && maTwoRect
.mnSrcWidth
== maTwoRect
.mnDestWidth
945 && maTwoRect
.mnSrcHeight
== maTwoRect
.mnDestHeight
946 && rTwoRect
.mnSrcX
>= maTwoRect
.mnSrcX
947 && rTwoRect
.mnSrcY
>= maTwoRect
.mnSrcY
948 && ( rTwoRect
.mnSrcX
+ rTwoRect
.mnSrcWidth
) <= ( maTwoRect
.mnSrcX
+ maTwoRect
.mnSrcWidth
)
949 && ( rTwoRect
.mnSrcY
+ rTwoRect
.mnSrcHeight
) <= ( maTwoRect
.mnSrcY
+ maTwoRect
.mnSrcHeight
)
959 void ImplSalDDB::ImplDraw(
961 const SalTwoRect
& rTwoRect
,
965 ImplDraw( maPixmap
, mnDepth
, aDrawable
,
966 rTwoRect
.mnSrcX
- maTwoRect
.mnSrcX
, rTwoRect
.mnSrcY
- maTwoRect
.mnSrcY
,
967 rTwoRect
.mnDestWidth
, rTwoRect
.mnDestHeight
,
968 rTwoRect
.mnDestX
, rTwoRect
.mnDestY
, rGC
);
971 void ImplSalDDB::ImplDraw(
972 Drawable aSrcDrawable
,
973 tools::Long nSrcDrawableDepth
,
974 Drawable aDstDrawable
,
977 tools::Long nDestWidth
,
978 tools::Long nDestHeight
,
983 SalDisplay
* pSalDisp
= vcl_sal::getSalDisplay(GetGenericUnixSalData());
984 Display
* pXDisp
= pSalDisp
->GetDisplay();
986 if( 1 == nSrcDrawableDepth
)
988 XCopyPlane( pXDisp
, aSrcDrawable
, aDstDrawable
, rGC
,
989 nSrcX
, nSrcY
, nDestWidth
, nDestHeight
, nDestX
, nDestY
, 1 );
993 XCopyArea( pXDisp
, aSrcDrawable
, aDstDrawable
, rGC
,
994 nSrcX
, nSrcY
, nDestWidth
, nDestHeight
, nDestX
, nDestY
);
999 ImplSalBitmapCache::ImplSalBitmapCache()
1003 ImplSalBitmapCache::~ImplSalBitmapCache()
1008 void ImplSalBitmapCache::ImplAdd( X11SalBitmap
* pBmp
)
1010 for(auto pObj
: maBmpList
)
1015 maBmpList
.push_back( pBmp
);
1018 void ImplSalBitmapCache::ImplRemove( X11SalBitmap
const * pBmp
)
1020 auto it
= std::find(maBmpList
.begin(), maBmpList
.end(), pBmp
);
1021 if( it
!= maBmpList
.end() )
1023 (*it
)->ImplRemovedFromCache();
1024 maBmpList
.erase( it
);
1028 void ImplSalBitmapCache::ImplClear()
1030 for(auto pObj
: maBmpList
)
1032 pObj
->ImplRemovedFromCache();
1037 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */