nss: upgrade to release 3.73
[LibreOffice.git] / vcl / unx / generic / gdi / salbmp.cxx
blobaa3cd0ac034d8823a6500d648f287455b2af7b16
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <string.h>
22 #ifdef FREEBSD
23 #include <sys/types.h>
24 #endif
26 #include <X11/Xlib.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>
47 #if HAVE_FEATURE_SKIA
48 #include <vcl/skia/SkiaHelper.hxx>
49 #include <skia/salbmp.hxx>
50 #endif
52 #if defined HAVE_VALGRIND_HEADERS
53 #include <valgrind/valgrind.h>
54 #endif
56 #include <memory>
59 std::shared_ptr<SalBitmap> X11SalInstance::CreateSalBitmap()
61 #if HAVE_FEATURE_SKIA
62 if (SkiaHelper::isVCLSkiaEnabled())
63 return std::make_shared<SkiaSalBitmap>();
64 else
65 #endif
66 if (OpenGLHelper::isVCLOpenGLEnabled())
67 return std::make_shared<OpenGLSalBitmap>();
68 else
69 return std::make_shared<X11SalBitmap>();
72 ImplSalBitmapCache* X11SalBitmap::mpCache = nullptr;
73 unsigned int X11SalBitmap::mnCacheInstCount = 0;
75 X11SalBitmap::X11SalBitmap()
76 : mbGrey( false )
80 X11SalBitmap::~X11SalBitmap()
82 Destroy();
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 )
97 delete mpCache;
98 mpCache = nullptr;
102 void X11SalBitmap::ImplRemovedFromCache()
104 mpDDB.reset();
107 #if defined HAVE_VALGRIND_HEADERS
108 namespace
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);
123 #endif
125 std::unique_ptr<BitmapBuffer> X11SalBitmap::ImplCreateDIB(
126 const Size& rSize,
127 sal_uInt16 nBitCount,
128 const BitmapPalette& rPal)
130 DBG_ASSERT(
131 nBitCount == 1
132 || nBitCount == 4
133 || nBitCount == 8
134 || nBitCount == 24
135 , "Unsupported BitCount!"
138 std::unique_ptr<BitmapBuffer> pDIB;
140 if( !rSize.Width() || !rSize.Height() )
141 return nullptr;
145 pDIB.reset(new BitmapBuffer);
147 catch (const std::bad_alloc&)
149 return nullptr;
152 const sal_uInt16 nColors = ( nBitCount <= 8 ) ? ( 1 << nBitCount ) : 0;
154 pDIB->mnFormat = ScanlineFormat::NONE;
156 switch( nBitCount )
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;
162 default:
163 SAL_WARN("vcl.gdi", "32-bit images not supported, converting to 24-bit");
164 nBitCount = 24;
165 pDIB->mnFormat |= ScanlineFormat::N24BitTcBgr;
166 break;
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);
173 if (bFail)
175 SAL_WARN("vcl.gdi", "checked multiply failed");
176 return nullptr;
178 pDIB->mnScanlineSize = AlignedWidth4Bytes(nScanlineBase);
179 if (pDIB->mnScanlineSize < nScanlineBase/8)
181 SAL_WARN("vcl.gdi", "scanline calculation wraparound");
182 return nullptr;
184 pDIB->mnBitCount = nBitCount;
186 if( nColors )
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());
198 #endif
200 catch (const std::bad_alloc&)
202 return nullptr;
205 return pDIB;
208 std::unique_ptr<BitmapBuffer> X11SalBitmap::ImplCreateDIB(
209 Drawable aDrawable,
210 SalX11Screen nScreen,
211 tools::Long nDrawableDepth,
212 tools::Long nX,
213 tools::Long nY,
214 tools::Long nWidth,
215 tools::Long nHeight,
216 bool bGrey
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 )
253 case 1:
255 aSrcBuf.mnFormat |= ( LSBFirst == pImage->bitmap_bit_order
256 ? ScanlineFormat::N1BitLsbPal
257 : ScanlineFormat::N1BitMsbPal
260 break;
262 case 4:
264 aSrcBuf.mnFormat |= ( LSBFirst == pImage->bitmap_bit_order
265 ? ScanlineFormat::N4BitLsnPal
266 : ScanlineFormat::N4BitMsnPal
269 break;
271 case 8:
273 aSrcBuf.mnFormat |= ScanlineFormat::N8BitPal;
275 break;
277 case 24:
279 if( ( LSBFirst == pImage->byte_order ) && ( pImage->red_mask == 0xFF ) )
280 aSrcBuf.mnFormat |= ScanlineFormat::N24BitTcRgb;
281 else
282 aSrcBuf.mnFormat |= ScanlineFormat::N24BitTcBgr;
284 break;
286 case 32:
288 if( LSBFirst == pImage->byte_order )
289 aSrcBuf.mnFormat |= ( pSalDisp->GetVisual(nScreen).red_mask == 0xFF
290 ? ScanlineFormat::N32BitTcRgba
291 : ScanlineFormat::N32BitTcBgra
293 else
294 aSrcBuf.mnFormat |= ( pSalDisp->GetVisual(nScreen).red_mask == 0xFF
295 ? ScanlineFormat::N32BitTcAbgr
296 : ScanlineFormat::N32BitTcArgb
299 break;
301 default: assert(false);
304 BitmapPalette& rPal = aSrcBuf.maPalette;
306 if( aSrcBuf.mnBitCount == 1 )
308 rPal.SetEntryCount( 2 );
309 pDstPal = &rPal;
311 rPal[ 0 ] = COL_BLACK;
312 rPal[ 1 ] = COL_WHITE;
314 else if( pImage->depth == 8 && bGrey )
316 rPal.SetEntryCount( 256 );
317 pDstPal = &rPal;
319 for( sal_uInt16 i = 0; i < 256; i++ )
321 BitmapColor& rBmpCol = rPal[ i ];
323 rBmpCol.SetRed( 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 );
336 pDstPal = &rPal;
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 );
355 return pDIB;
358 XImage* X11SalBitmap::ImplCreateXImage(
359 SalDisplay const *pSalDisp,
360 SalX11Screen nScreen,
361 tools::Long nDepth,
362 const SalTwoRect& rTwoRect
363 ) const
365 XImage* pImage = nullptr;
367 if( !mpDIB && mpDDB )
369 const_cast<X11SalBitmap*>(this)->mpDIB =
370 ImplCreateDIB( mpDDB->ImplGetPixmap(),
371 mpDDB->ImplGetScreen(),
372 mpDDB->ImplGetDepth(),
373 0, 0,
374 mpDDB->ImplGetWidth(),
375 mpDDB->ImplGetHeight(),
376 mbGrey );
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() )
386 nDepth = 1;
388 pImage = XCreateImage( pXDisp, pSalDisp->GetVisual( nScreen ).GetVisual(),
389 nDepth, ( 1 == nDepth ) ? XYBitmap :ZPixmap, 0, nullptr,
390 nWidth, nHeight, 32, 0 );
392 if( pImage )
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 )
401 case 1:
402 nDstFormat |= ( LSBFirst == pImage->bitmap_bit_order
403 ? ScanlineFormat::N1BitLsbPal
404 : ScanlineFormat::N1BitMsbPal
406 break;
408 case 4:
409 nDstFormat |= ( LSBFirst == pImage->bitmap_bit_order
410 ? ScanlineFormat::N4BitLsnPal
411 : ScanlineFormat::N4BitMsnPal
413 break;
415 case 8:
416 nDstFormat |= ScanlineFormat::N8BitPal;
417 break;
419 case 24:
421 if( ( LSBFirst == pImage->byte_order ) && ( pImage->red_mask == 0xFF ) )
422 nDstFormat |= ScanlineFormat::N24BitTcRgb;
423 else
424 nDstFormat |= ScanlineFormat::N24BitTcBgr;
426 break;
428 case 32:
430 if( LSBFirst == pImage->byte_order )
431 nDstFormat |= ( pImage->red_mask == 0xFF
432 ? ScanlineFormat::N32BitTcRgba
433 : ScanlineFormat::N32BitTcBgra
435 else
436 nDstFormat |= ( pImage->red_mask == 0xFF
437 ? ScanlineFormat::N32BitTcAbgr
438 : ScanlineFormat::N32BitTcArgb
441 break;
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 ];
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 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() );
487 xPal.reset();
488 xMask.reset();
490 if( pDstBuf && pDstBuf->mpBits )
492 #if defined HAVE_VALGRIND_HEADERS
493 if (RUNNING_ON_VALGRIND)
494 blankExtraSpace(pDstBuf.get());
495 #endif
496 // set data in buffer as data member in pImage
497 pImage->data = reinterpret_cast<char*>(pDstBuf->mpBits);
499 else
501 XDestroyImage( pImage );
502 pImage = nullptr;
505 // note that pDstBuf it deleted here, but that doesn't destroy allocated data in buffer
509 return pImage;
512 bool X11SalBitmap::ImplCreateFromDrawable(
513 Drawable aDrawable,
514 SalX11Screen nScreen,
515 tools::Long nDrawableDepth,
516 tools::Long nX,
517 tools::Long nY,
518 tools::Long nWidth,
519 tools::Long nHeight
521 Destroy();
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(
530 Drawable aDrawable,
531 SalX11Screen nXScreen,
532 tools::Long nDrawableDepth,
533 const SalTwoRect& rTwoRect
534 ) const
536 if( !mpDDB || !mpDDB->ImplMatches( nXScreen, nDrawableDepth, rTwoRect ) )
538 if( mpDDB )
540 // do we already have a DIB? if not, create aDIB from current DDB first
541 if( !mpDIB )
543 const_cast<X11SalBitmap*>(this)->mpDIB = ImplCreateDIB( mpDDB->ImplGetPixmap(),
544 mpDDB->ImplGetScreen(),
545 mpDDB->ImplGetDepth(),
546 0, 0,
547 mpDDB->ImplGetWidth(),
548 mpDDB->ImplGetHeight(),
549 mbGrey );
552 mpDDB.reset();
555 if( mpCache )
556 mpCache->ImplRemove( this );
558 SalTwoRect aTwoRect( rTwoRect );
559 if( aTwoRect.mnSrcX < 0 )
561 aTwoRect.mnSrcWidth += aTwoRect.mnSrcX;
562 aTwoRect.mnSrcX = 0;
564 if( aTwoRect.mnSrcY < 0 )
566 aTwoRect.mnSrcHeight += aTwoRect.mnSrcY;
567 aTwoRect.mnSrcY = 0;
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 )
594 aTwoRect.mnSrcX = 0;
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 )
603 aTwoRect.mnSrcY = 0;
604 aTwoRect.mnSrcHeight = aSize.Height();
609 XImage* pImage = ImplCreateXImage( vcl_sal::getSalDisplay(GetGenericUnixSalData()), nXScreen,
610 nDrawableDepth, aTwoRect );
612 if( pImage )
614 mpDDB.reset(new ImplSalDDB( pImage, aDrawable, nXScreen, aTwoRect ));
615 delete[] pImage->data;
616 pImage->data = nullptr;
617 XDestroyImage( pImage );
619 if( mpCache )
620 mpCache->ImplAdd( const_cast<X11SalBitmap*>(this) );
624 return mpDDB.get();
627 void X11SalBitmap::ImplDraw(
628 Drawable aDrawable,
629 SalX11Screen nXScreen,
630 tools::Long nDrawableDepth,
631 const SalTwoRect& rTwoRect,
632 const GC& rGC
633 ) const
635 ImplGetDDB( aDrawable, nXScreen, nDrawableDepth, rTwoRect );
636 if( mpDDB )
637 mpDDB->ImplDraw( aDrawable, rTwoRect, rGC );
640 bool X11SalBitmap::Create( const Size& rSize, sal_uInt16 nBitCount, const BitmapPalette& rPal )
642 Destroy();
643 mpDIB = ImplCreateDIB( rSize, nBitCount, rPal );
645 return( mpDIB != nullptr );
648 bool X11SalBitmap::Create( const SalBitmap& rSSalBmp )
650 Destroy();
652 if( dynamic_cast<const X11SalBitmap*>( &rSSalBmp ) == nullptr )
653 return false;
655 const X11SalBitmap& rSalBmp = static_cast<const X11SalBitmap&>( rSSalBmp );
657 if( rSalBmp.mpDIB )
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());
668 #endif
670 catch (const std::bad_alloc&)
672 mpDIB.reset();
675 if( mpDIB )
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* )
691 return false;
694 bool X11SalBitmap::Create( const SalBitmap&, sal_uInt16 )
696 return false;
699 bool X11SalBitmap::Create(
700 const css::uno::Reference< css::rendering::XBitmapCanvas >& rBitmapCanvas,
701 Size& rSize,
702 bool bMask
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
711 sal_Int32 depth;
712 if( ( args[1] >>= pixmapHandle ) && ( args[2] >>= depth ) ) {
714 mbGrey = bMask;
715 bool bSuccess = ImplCreateFromDrawable(
716 pixmapHandle,
717 // FIXME: this seems multi-screen broken to me
718 SalX11Screen( 0 ),
719 depth,
722 rSize.Width(),
723 rSize.Height()
725 bool bFreePixmap = false;
726 if( bSuccess && (args[0] >>= bFreePixmap) && bFreePixmap )
727 XFreePixmap( vcl_sal::getSalDisplay(GetGenericUnixSalData())->GetDisplay(), pixmapHandle );
729 return bSuccess;
734 return false;
737 void X11SalBitmap::Destroy()
739 if( mpDIB )
741 delete[] mpDIB->mpBits;
742 mpDIB.reset();
745 mpDDB.reset();
747 if( mpCache )
748 mpCache->ImplRemove( this );
751 Size X11SalBitmap::GetSize() const
753 Size aSize;
755 if( mpDIB )
757 aSize.setWidth( mpDIB->mnWidth );
758 aSize.setHeight( mpDIB->mnHeight );
760 else if( mpDDB )
762 aSize.setWidth( mpDDB->ImplGetWidth() );
763 aSize.setHeight( mpDDB->ImplGetHeight() );
766 return aSize;
769 sal_uInt16 X11SalBitmap::GetBitCount() const
771 sal_uInt16 nBitCount;
773 if( mpDIB )
774 nBitCount = mpDIB->mnBitCount;
775 else if( mpDDB )
776 nBitCount = mpDDB->ImplGetDepth();
777 else
778 nBitCount = 0;
780 return nBitCount;
783 BitmapBuffer* X11SalBitmap::AcquireBuffer( BitmapAccessMode /*nMode*/ )
785 if( !mpDIB && mpDDB )
787 mpDIB = ImplCreateDIB(
788 mpDDB->ImplGetPixmap(),
789 mpDDB->ImplGetScreen(),
790 mpDDB->ImplGetDepth(),
791 0, 0,
792 mpDDB->ImplGetWidth(),
793 mpDDB->ImplGetHeight(),
794 mbGrey
798 return mpDIB.get();
801 void X11SalBitmap::ReleaseBuffer( BitmapBuffer*, BitmapAccessMode nMode )
803 if( nMode == BitmapAccessMode::Write )
805 mpDDB.reset();
807 if( mpCache )
808 mpCache->ImplRemove( this );
809 InvalidateChecksum();
813 bool X11SalBitmap::GetSystemData( BitmapSystemData& rData )
815 if( mpDDB )
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 ();
823 return true;
826 return false;
829 bool X11SalBitmap::ScalingSupported() const
831 return false;
834 bool X11SalBitmap::Scale( const double& /*rScaleX*/, const double& /*rScaleY*/, BmpScaleFlag /*nScaleFlag*/ )
836 return false;
839 bool X11SalBitmap::Replace( const Color& /*rSearchColor*/, const Color& /*rReplaceColor*/, sal_uInt8 /*nTol*/ )
841 return false;
845 ImplSalDDB::ImplSalDDB( XImage* pImage, Drawable aDrawable,
846 SalX11Screen nXScreen, const SalTwoRect& rTwoRect )
847 : maPixmap ( 0 )
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() );
856 if (!maPixmap)
857 return;
859 XGCValues aValues;
860 GC aGC;
861 int nValues = GCFunction;
863 aValues.function = GXcopy;
865 if( 1 == mnDepth )
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(
878 Drawable aDrawable,
879 SalX11Screen nXScreen,
880 tools::Long nDrawableDepth,
881 tools::Long nX,
882 tools::Long nY,
883 tools::Long nWidth,
884 tools::Long nHeight
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 )) )
894 XGCValues aValues;
895 GC aGC;
896 int nValues = GCFunction;
898 aValues.function = GXcopy;
900 if( 1 == mnDepth )
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 );
912 else
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
927 bool bRet = false;
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
940 bRet = true;
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 )
952 bRet = true;
956 return bRet;
959 void ImplSalDDB::ImplDraw(
960 Drawable aDrawable,
961 const SalTwoRect& rTwoRect,
962 const GC& rGC
963 ) const
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,
975 tools::Long nSrcX,
976 tools::Long nSrcY,
977 tools::Long nDestWidth,
978 tools::Long nDestHeight,
979 tools::Long nDestX,
980 tools::Long nDestY,
981 const GC& rGC
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 );
991 else
993 XCopyArea( pXDisp, aSrcDrawable, aDstDrawable, rGC,
994 nSrcX, nSrcY, nDestWidth, nDestHeight, nDestX, nDestY );
999 ImplSalBitmapCache::ImplSalBitmapCache()
1003 ImplSalBitmapCache::~ImplSalBitmapCache()
1005 ImplClear();
1008 void ImplSalBitmapCache::ImplAdd( X11SalBitmap* pBmp )
1010 for(auto pObj : maBmpList)
1012 if( pObj == pBmp )
1013 return;
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();
1034 maBmpList.clear();
1037 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */