/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #ifdef FREEBSD #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "xrender_peer.hxx" #if defined HAVE_VALGRIND_HEADERS #include #endif // ------------- // - SalBitmap - // ------------- SalBitmap* X11SalInstance::CreateSalBitmap() { return new X11SalBitmap(); } ImplSalBitmapCache* X11SalBitmap::mpCache = NULL; sal_uLong X11SalBitmap::mnCacheInstCount = 0; // ----------------------------------------------------------------------------- X11SalBitmap::X11SalBitmap() : mpDIB( NULL ) , mpDDB( NULL ) , mbGrey( false ) , mbHasAlpha( false ) { } // ----------------------------------------------------------------------------- X11SalBitmap::~X11SalBitmap() { Destroy(); } // ----------------------------------------------------------------------------- void X11SalBitmap::ImplCreateCache() { if( !mnCacheInstCount++ ) mpCache = new ImplSalBitmapCache; } // ----------------------------------------------------------------------------- void X11SalBitmap::ImplDestroyCache() { DBG_ASSERT( mnCacheInstCount, "X11SalBitmap::ImplDestroyCache(): underflow" ); if( mnCacheInstCount && !--mnCacheInstCount ) delete mpCache, mpCache = NULL; } // ----------------------------------------------------------------------------- void X11SalBitmap::ImplRemovedFromCache() { if( mpDDB ) delete mpDDB, mpDDB = NULL; } #if defined HAVE_VALGRIND_HEADERS namespace { void blankExtraSpace(BitmapBuffer* pDIB) { size_t nExtraSpaceInScanLine = pDIB->mnScanlineSize - pDIB->mnWidth * pDIB->mnBitCount / 8; if (nExtraSpaceInScanLine) { for (long i = 0; i < pDIB->mnHeight; ++i) { sal_uInt8 *pRow = pDIB->mpBits + (i * pDIB->mnScanlineSize); memset(pRow + (pDIB->mnScanlineSize - nExtraSpaceInScanLine), 0, nExtraSpaceInScanLine); } } } } #endif // ----------------------------------------------------------------------------- BitmapBuffer* X11SalBitmap::ImplCreateDIB( const Size& rSize, sal_uInt16 nBitCount, const BitmapPalette& rPal ) { DBG_ASSERT( nBitCount == 1 || nBitCount == 4 || nBitCount == 8 || nBitCount == 16 || nBitCount == 24 , "Unsupported BitCount!" ); BitmapBuffer* pDIB = NULL; if( rSize.Width() && rSize.Height() ) { try { pDIB = new BitmapBuffer; } catch (const std::bad_alloc&) { pDIB = NULL; } if( pDIB ) { const sal_uInt16 nColors = ( nBitCount <= 8 ) ? ( 1 << nBitCount ) : 0; pDIB->mnFormat = BMP_FORMAT_BOTTOM_UP; switch( nBitCount ) { case( 1 ): pDIB->mnFormat |= BMP_FORMAT_1BIT_MSB_PAL; break; case( 4 ): pDIB->mnFormat |= BMP_FORMAT_4BIT_MSN_PAL; break; case( 8 ): pDIB->mnFormat |= BMP_FORMAT_8BIT_PAL; break; #ifdef OSL_BIGENDIAN case(16 ): pDIB->mnFormat|= BMP_FORMAT_16BIT_TC_MSB_MASK; pDIB->maColorMask = ColorMask( 0xf800, 0x07e0, 0x001f ); break; #else case(16 ): pDIB->mnFormat|= BMP_FORMAT_16BIT_TC_LSB_MASK; pDIB->maColorMask = ColorMask( 0xf800, 0x07e0, 0x001f ); break; #endif default: nBitCount = 24; //fall through case 24: pDIB->mnFormat |= BMP_FORMAT_24BIT_TC_BGR; break; } pDIB->mnWidth = rSize.Width(); pDIB->mnHeight = rSize.Height(); pDIB->mnScanlineSize = AlignedWidth4Bytes( pDIB->mnWidth * nBitCount ); pDIB->mnBitCount = nBitCount; if( nColors ) { pDIB->maPalette = rPal; pDIB->maPalette.SetEntryCount( nColors ); } try { pDIB->mpBits = new sal_uInt8[ pDIB->mnScanlineSize * pDIB->mnHeight ]; #if defined HAVE_VALGRIND_HEADERS if (RUNNING_ON_VALGRIND) blankExtraSpace(pDIB); #endif } catch (const std::bad_alloc&) { delete pDIB; pDIB = NULL; } } } else pDIB = NULL; return pDIB; } // ----------------------------------------------------------------------------- BitmapBuffer* X11SalBitmap::ImplCreateDIB( Drawable aDrawable, SalX11Screen nScreen, long nDrawableDepth, long nX, long nY, long nWidth, long nHeight, bool bGrey ) { BitmapBuffer* pDIB = NULL; if( aDrawable && nWidth && nHeight && nDrawableDepth ) { SalDisplay* pSalDisp = GetGenericData()->GetSalDisplay(); Display* pXDisp = pSalDisp->GetDisplay(); // do not die on XError here // alternatively one could check the coordinates for being offscreen // but this call can actually work on servers with backing store // defaults even if the rectangle is offscreen // so better catch the XError GetGenericData()->ErrorTrapPush(); XImage* pImage = XGetImage( pXDisp, aDrawable, nX, nY, nWidth, nHeight, AllPlanes, ZPixmap ); bool bWasError = GetGenericData()->ErrorTrapPop( false ); if( ! bWasError && pImage && pImage->data ) { const SalTwoRect aTwoRect = { 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight }; BitmapBuffer aSrcBuf; sal_uLong nDstFormat = BMP_FORMAT_BOTTOM_UP; const BitmapPalette* pDstPal = NULL; aSrcBuf.mnFormat = BMP_FORMAT_TOP_DOWN; aSrcBuf.mnWidth = nWidth; aSrcBuf.mnHeight = nHeight; aSrcBuf.mnBitCount = pImage->bits_per_pixel; aSrcBuf.mnScanlineSize = pImage->bytes_per_line; aSrcBuf.mpBits = (sal_uInt8*) pImage->data; pImage->red_mask = pSalDisp->GetVisual( nScreen ).red_mask; pImage->green_mask = pSalDisp->GetVisual( nScreen ).green_mask; pImage->blue_mask = pSalDisp->GetVisual( nScreen ).blue_mask; switch( aSrcBuf.mnBitCount ) { case( 1 ): { aSrcBuf.mnFormat |= ( LSBFirst == pImage->bitmap_bit_order ? BMP_FORMAT_1BIT_LSB_PAL : BMP_FORMAT_1BIT_MSB_PAL ); nDstFormat |= BMP_FORMAT_1BIT_MSB_PAL; } break; case( 4 ): { aSrcBuf.mnFormat |= ( LSBFirst == pImage->bitmap_bit_order ? BMP_FORMAT_4BIT_LSN_PAL : BMP_FORMAT_4BIT_MSN_PAL ); nDstFormat |= BMP_FORMAT_4BIT_MSN_PAL; } break; case( 8 ): { aSrcBuf.mnFormat |= BMP_FORMAT_8BIT_PAL; nDstFormat |= BMP_FORMAT_8BIT_PAL; } break; case( 16 ): { nDstFormat |= BMP_FORMAT_24BIT_TC_BGR; aSrcBuf.maColorMask = ColorMask( pImage->red_mask, pImage->green_mask, pImage->blue_mask ); if( LSBFirst == pImage->byte_order ) { aSrcBuf.mnFormat |= BMP_FORMAT_16BIT_TC_LSB_MASK; } else { aSrcBuf.mnFormat |= BMP_FORMAT_16BIT_TC_MSB_MASK; } } break; case( 24 ): { if( ( LSBFirst == pImage->byte_order ) && ( pImage->red_mask == 0xFF ) ) aSrcBuf.mnFormat |= BMP_FORMAT_24BIT_TC_RGB; else aSrcBuf.mnFormat |= BMP_FORMAT_24BIT_TC_BGR; nDstFormat |= BMP_FORMAT_24BIT_TC_BGR; } break; case( 32 ): { if( LSBFirst == pImage->byte_order ) aSrcBuf.mnFormat |= ( pSalDisp->GetVisual(nScreen).red_mask == 0xFF ? BMP_FORMAT_32BIT_TC_RGBA : BMP_FORMAT_32BIT_TC_BGRA ); else aSrcBuf.mnFormat |= ( pSalDisp->GetVisual(nScreen).red_mask == 0xFF ? BMP_FORMAT_32BIT_TC_ABGR : BMP_FORMAT_32BIT_TC_ARGB ); nDstFormat |= BMP_FORMAT_24BIT_TC_BGR; } break; } BitmapPalette& rPal = aSrcBuf.maPalette; if( aSrcBuf.mnBitCount == 1 ) { rPal.SetEntryCount( 2 ); pDstPal = &rPal; rPal[ 0 ] = Color( COL_BLACK ); rPal[ 1 ] = Color( COL_WHITE ); } else if( pImage->depth == 8 && bGrey ) { rPal.SetEntryCount( 256 ); pDstPal = &rPal; for( sal_uInt16 i = 0; i < 256; i++ ) { BitmapColor& rBmpCol = rPal[ i ]; rBmpCol.SetRed( i ); rBmpCol.SetGreen( i ); rBmpCol.SetBlue( i ); } } else if( aSrcBuf.mnBitCount <= 8 ) { const SalColormap& rColMap = pSalDisp->GetColormap( nScreen ); const sal_uInt16 nCols = std::min( (sal_uLong)rColMap.GetUsed() , (sal_uLong)(1 << nDrawableDepth) ); rPal.SetEntryCount( nCols ); pDstPal = &rPal; for( sal_uInt16 i = 0; i < nCols; i++ ) { const SalColor nColor( rColMap.GetColor( i ) ); BitmapColor& rBmpCol = rPal[ i ]; rBmpCol.SetRed( SALCOLOR_RED( nColor ) ); rBmpCol.SetGreen( SALCOLOR_GREEN( nColor ) ); rBmpCol.SetBlue( SALCOLOR_BLUE( nColor ) ); } } nDstFormat = aSrcBuf.mnFormat; pDIB = StretchAndConvert( aSrcBuf, aTwoRect, nDstFormat, const_cast(pDstPal), &aSrcBuf.maColorMask ); XDestroyImage( pImage ); } } return pDIB; } // ----------------------------------------------------------------------------- XImage* X11SalBitmap::ImplCreateXImage( SalDisplay *pSalDisp, SalX11Screen nScreen, long nDepth, const SalTwoRect& rTwoRect ) const { XImage* pImage = NULL; if( !mpDIB && mpDDB ) { const_cast(this)->mpDIB = ImplCreateDIB( mpDDB->ImplGetPixmap(), mpDDB->ImplGetScreen(), mpDDB->ImplGetDepth(), 0, 0, mpDDB->ImplGetWidth(), mpDDB->ImplGetHeight(), mbGrey ); } if( mpDIB && mpDIB->mnWidth && mpDIB->mnHeight ) { Display* pXDisp = pSalDisp->GetDisplay(); long nWidth = rTwoRect.mnDestWidth; long nHeight = rTwoRect.mnDestHeight; if( 1 == GetBitCount() ) nDepth = 1; pImage = XCreateImage( pXDisp, pSalDisp->GetVisual( nScreen ).GetVisual(), nDepth, ( 1 == nDepth ) ? XYBitmap :ZPixmap, 0, NULL, nWidth, nHeight, 32, 0 ); if( pImage ) { BitmapBuffer* pDstBuf; sal_uLong nDstFormat = BMP_FORMAT_TOP_DOWN; BitmapPalette* pPal = NULL; ColorMask* pMask = NULL; switch( pImage->bits_per_pixel ) { case( 1 ): nDstFormat |= ( LSBFirst == pImage->bitmap_bit_order ? BMP_FORMAT_1BIT_LSB_PAL : BMP_FORMAT_1BIT_MSB_PAL ); break; case( 4 ): nDstFormat |= ( LSBFirst == pImage->bitmap_bit_order ? BMP_FORMAT_4BIT_LSN_PAL : BMP_FORMAT_4BIT_MSN_PAL ); break; case( 8 ): nDstFormat |= BMP_FORMAT_8BIT_PAL; break; case( 16 ): { #ifdef OSL_BIGENDIAN if( MSBFirst == pImage->byte_order ) nDstFormat |= BMP_FORMAT_16BIT_TC_MSB_MASK; else nDstFormat |= BMP_FORMAT_16BIT_TC_LSB_MASK; #else /* OSL_LITENDIAN */ nDstFormat |= BMP_FORMAT_16BIT_TC_LSB_MASK; if( MSBFirst == pImage->byte_order ) pImage->byte_order = LSBFirst; #endif pMask = new ColorMask( pImage->red_mask, pImage->green_mask, pImage->blue_mask ); } break; case( 24 ): { if( ( LSBFirst == pImage->byte_order ) && ( pImage->red_mask == 0xFF ) ) nDstFormat |= BMP_FORMAT_24BIT_TC_RGB; else nDstFormat |= BMP_FORMAT_24BIT_TC_BGR; } break; case( 32 ): { if( LSBFirst == pImage->byte_order ) nDstFormat |= ( pImage->red_mask == 0xFF ? BMP_FORMAT_32BIT_TC_RGBA : BMP_FORMAT_32BIT_TC_BGRA ); else nDstFormat |= ( pImage->red_mask == 0xFF ? BMP_FORMAT_32BIT_TC_ABGR : BMP_FORMAT_32BIT_TC_ARGB ); } break; } if( pImage->depth == 1 ) { pPal = new BitmapPalette( 2 ); (*pPal)[ 0 ] = Color( COL_BLACK ); (*pPal)[ 1 ] = Color( COL_WHITE ); } else if( pImage->depth == 8 && mbGrey ) { pPal = new BitmapPalette( 256 ); for( sal_uInt16 i = 0; i < 256; i++ ) { BitmapColor& rBmpCol = (*pPal)[ i ]; rBmpCol.SetRed( i ); rBmpCol.SetGreen( i ); rBmpCol.SetBlue( i ); } } else if( pImage->depth <= 8 ) { const SalColormap& rColMap = pSalDisp->GetColormap( nScreen ); const sal_uInt16 nCols = std::min( (sal_uLong)rColMap.GetUsed() , (sal_uLong)(1 << pImage->depth) ); pPal = new BitmapPalette( nCols ); for( sal_uInt16 i = 0; i < nCols; i++ ) { const SalColor nColor( rColMap.GetColor( i ) ); BitmapColor& rBmpCol = (*pPal)[ i ]; rBmpCol.SetRed( SALCOLOR_RED( nColor ) ); rBmpCol.SetGreen( SALCOLOR_GREEN( nColor ) ); rBmpCol.SetBlue( SALCOLOR_BLUE( nColor ) ); } } pDstBuf = StretchAndConvert( *mpDIB, rTwoRect, nDstFormat, pPal, pMask ); delete pPal; delete pMask; if( pDstBuf && pDstBuf->mpBits ) { #if defined HAVE_VALGRIND_HEADERS if (RUNNING_ON_VALGRIND) blankExtraSpace(pDstBuf); #endif // set data in buffer as data member in pImage pImage->data = (char*) pDstBuf->mpBits; // destroy buffer; don't destroy allocated data in buffer delete pDstBuf; } else { XDestroyImage( pImage ); pImage = NULL; } } } return pImage; } // ----------------------------------------------------------------------------- bool X11SalBitmap::ImplCreateFromDrawable( Drawable aDrawable, void *pVisual, SalX11Screen nScreen, long nDrawableDepth, long nX, long nY, long nWidth, long nHeight ) { Destroy(); if( aDrawable && nWidth && nHeight && nDrawableDepth ) mpDDB = new ImplSalDDB( aDrawable, pVisual, nScreen, nDrawableDepth, nX, nY, nWidth, nHeight ); return( mpDDB != NULL ); } // ----------------------------------------------------------------------------- ImplSalDDB* X11SalBitmap::ImplGetDDB( Drawable aDrawable, SalX11Screen nXScreen, long nDrawableDepth, const SalTwoRect& rTwoRect ) const { if( !mpDDB || !mpDDB->ImplMatches( nXScreen, nDrawableDepth, rTwoRect ) ) { if( mpDDB ) { // do we already have a DIB? if not, create aDIB from current DDB first if( !mpDIB ) { const_cast(this)->mpDIB = ImplCreateDIB( mpDDB->ImplGetPixmap(), mpDDB->ImplGetScreen(), mpDDB->ImplGetDepth(), 0, 0, mpDDB->ImplGetWidth(), mpDDB->ImplGetHeight(), mbGrey ); } delete mpDDB, const_cast(this)->mpDDB = NULL; } if( mpCache ) mpCache->ImplRemove( const_cast(this) ); SalTwoRect aTwoRect( rTwoRect ); if( aTwoRect.mnSrcX < 0 ) { aTwoRect.mnSrcWidth += aTwoRect.mnSrcX; aTwoRect.mnSrcX = 0; } if( aTwoRect.mnSrcY < 0 ) { aTwoRect.mnSrcHeight += aTwoRect.mnSrcY; aTwoRect.mnSrcY = 0; } // create new DDB from DIB const Size aSize( GetSize() ); if( aTwoRect.mnSrcWidth == aTwoRect.mnDestWidth && aTwoRect.mnSrcHeight == aTwoRect.mnDestHeight ) { aTwoRect.mnSrcX = aTwoRect.mnSrcY = aTwoRect.mnDestX = aTwoRect.mnDestY = 0; aTwoRect.mnSrcWidth = aTwoRect.mnDestWidth = aSize.Width(); aTwoRect.mnSrcHeight = aTwoRect.mnDestHeight = aSize.Height(); } else if( aTwoRect.mnSrcWidth+aTwoRect.mnSrcX > aSize.Width() || aTwoRect.mnSrcHeight+aTwoRect.mnSrcY > aSize.Height() ) { // #i47823# this should not happen at all, but does nonetheless // because BitmapEx allows for mask bitmaps of different size // than image bitmap (broken) if( aTwoRect.mnSrcX >= aSize.Width() || aTwoRect.mnSrcY >= aSize.Height() ) return NULL; // this would be a really mad case if( aTwoRect.mnSrcWidth+aTwoRect.mnSrcX > aSize.Width() ) { aTwoRect.mnSrcWidth = aSize.Width()-aTwoRect.mnSrcX; if( aTwoRect.mnSrcWidth < 1 ) { aTwoRect.mnSrcX = 0; aTwoRect.mnSrcWidth = aSize.Width(); } } if( aTwoRect.mnSrcHeight+aTwoRect.mnSrcY > aSize.Height() ) { aTwoRect.mnSrcHeight = aSize.Height() - aTwoRect.mnSrcY; if( aTwoRect.mnSrcHeight < 1 ) { aTwoRect.mnSrcY = 0; aTwoRect.mnSrcHeight = aSize.Height(); } } } XImage* pImage = ImplCreateXImage( GetGenericData()->GetSalDisplay(), nXScreen, nDrawableDepth, aTwoRect ); if( pImage ) { const_cast(this)->mpDDB = new ImplSalDDB( pImage, aDrawable, nXScreen, aTwoRect ); delete[] pImage->data, pImage->data = NULL; XDestroyImage( pImage ); if( mpCache ) mpCache->ImplAdd( const_cast(this), mpDDB->ImplGetMemSize() ); } } return mpDDB; } // ----------------------------------------------------------------------------- void X11SalBitmap::ImplDraw( Drawable aDrawable, SalX11Screen nXScreen, long nDrawableDepth, const SalTwoRect& rTwoRect, const GC& rGC ) const { ImplGetDDB( aDrawable, nXScreen, nDrawableDepth, rTwoRect ); if( mpDDB ) mpDDB->ImplDraw( aDrawable, nDrawableDepth, rTwoRect, rGC ); } // ----------------------------------------------------------------------------- bool X11SalBitmap::Create( const Size& rSize, sal_uInt16 nBitCount, const BitmapPalette& rPal ) { Destroy(); mpDIB = ImplCreateDIB( rSize, nBitCount, rPal ); return( mpDIB != NULL ); } // ----------------------------------------------------------------------------- bool X11SalBitmap::Create( const SalBitmap& rSSalBmp ) { Destroy(); const X11SalBitmap& rSalBmp = static_cast( rSSalBmp ); if( rSalBmp.mpDIB ) { // TODO: reference counting... mpDIB = new BitmapBuffer( *rSalBmp.mpDIB ); // TODO: get rid of this when BitmapBuffer gets copy constructor try { mpDIB->mpBits = new sal_uInt8[ mpDIB->mnScanlineSize * mpDIB->mnHeight ]; #if defined HAVE_VALGRIND_HEADERS if (RUNNING_ON_VALGRIND) blankExtraSpace(mpDIB); #endif } catch (const std::bad_alloc&) { delete mpDIB; mpDIB = NULL; } if( mpDIB ) memcpy( mpDIB->mpBits, rSalBmp.mpDIB->mpBits, mpDIB->mnScanlineSize * mpDIB->mnHeight ); } else if( rSalBmp.mpDDB ) ImplCreateFromDrawable( rSalBmp.mpDDB->ImplGetPixmap(), rSalBmp.mpDDB->ImplGetVisual(), rSalBmp.mpDDB->ImplGetScreen(), rSalBmp.mpDDB->ImplGetDepth(), 0, 0, rSalBmp.mpDDB->ImplGetWidth(), rSalBmp.mpDDB->ImplGetHeight() ); return( ( !rSalBmp.mpDIB && !rSalBmp.mpDDB ) || ( rSalBmp.mpDIB && ( mpDIB != NULL ) ) || ( rSalBmp.mpDDB && ( mpDDB != NULL ) ) ); } // ----------------------------------------------------------------------------- bool X11SalBitmap::Create( const SalBitmap&, SalGraphics* ) { return false; } // ----------------------------------------------------------------------------- bool X11SalBitmap::Create( const SalBitmap&, sal_uInt16 ) { return false; } // ----------------------------------------------------------------------------- bool X11SalBitmap::Create( const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmapCanvas > xBitmapCanvas, Size& rSize, bool bMask ) { ::com::sun::star::uno::Reference< ::com::sun::star::beans::XFastPropertySet > xFastPropertySet( xBitmapCanvas, ::com::sun::star::uno::UNO_QUERY ); if( xFastPropertySet.get() ) { sal_Int32 depth; ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > args; if( xFastPropertySet->getFastPropertyValue(bMask ? 2 : 1) >>= args ) { long pixmapHandle; sal_Int64 nVisualPtr; if( args.getLength() >= 4 && ( args[1] >>= pixmapHandle ) && ( args[2] >>= depth ) && ( args[3] >>= nVisualPtr ) ) { mbGrey = bMask; bool bSuccess = ImplCreateFromDrawable( pixmapHandle, reinterpret_cast(nVisualPtr), // FIXME: this seems multi-screen broken to me SalX11Screen( 0 ), depth, 0, 0, (long) rSize.Width(), (long) rSize.Height() ); bool bFreePixmap = false; if( bSuccess && (args[0] >>= bFreePixmap) && bFreePixmap ) XFreePixmap( GetGenericData()->GetSalDisplay()->GetDisplay(), pixmapHandle ); return bSuccess; } } } return false; } // ----------------------------------------------------------------------------- void X11SalBitmap::Destroy() { if( mpDIB ) { delete[] mpDIB->mpBits; delete mpDIB, mpDIB = NULL; } if( mpDDB ) delete mpDDB, mpDDB = NULL; if( mpCache ) mpCache->ImplRemove( this ); } // ----------------------------------------------------------------------------- Size X11SalBitmap::GetSize() const { Size aSize; if( mpDIB ) aSize.Width() = mpDIB->mnWidth, aSize.Height() = mpDIB->mnHeight; else if( mpDDB ) aSize.Width() = mpDDB->ImplGetWidth(), aSize.Height() = mpDDB->ImplGetHeight(); return aSize; } // ----------------------------------------------------------------------------- sal_uInt16 X11SalBitmap::GetBitCount() const { sal_uInt16 nBitCount; if( mpDIB ) nBitCount = mpDIB->mnBitCount; else if( mpDDB ) nBitCount = mpDDB->ImplGetDepth(); else nBitCount = 0; return nBitCount; } // ----------------------------------------------------------------------------- BitmapBuffer* X11SalBitmap::AcquireBuffer( bool ) { if( !mpDIB && mpDDB ) { mpDIB = ImplCreateDIB( mpDDB->ImplGetPixmap(), mpDDB->ImplGetScreen(), mpDDB->ImplGetDepth(), 0, 0, mpDDB->ImplGetWidth(), mpDDB->ImplGetHeight(), mbGrey ); } return mpDIB; } // ----------------------------------------------------------------------------- void X11SalBitmap::ReleaseBuffer( BitmapBuffer*, bool bReadOnly ) { if( !bReadOnly ) { if( mpDDB ) delete mpDDB, mpDDB = NULL; if( mpCache ) mpCache->ImplRemove( this ); } } // ----------------------------------------------------------------------------- bool X11SalBitmap::GetSystemData( BitmapSystemData& rData ) { if( mpDDB ) { // Rename/retype pDummy to your likings (though X11 Pixmap is // prolly not a good idea, since it's accessed from // non-platform aware code in vcl/bitmap.hxx) rData.aPixmap = (void*)mpDDB->ImplGetPixmap(); rData.aVisual = mpDDB->ImplGetVisual (); rData.mnWidth = mpDDB->ImplGetWidth (); rData.mnHeight = mpDDB->ImplGetHeight (); return true; } return false; } // -------------- // - ImplSalDDB - // -------------- ImplSalDDB::ImplSalDDB( XImage* pImage, Drawable aDrawable, SalX11Screen nXScreen, const SalTwoRect& rTwoRect ) : maPixmap ( 0 ) , mpVisual ( NULL ) , maTwoRect ( rTwoRect ) , mnDepth ( pImage->depth ) , mnXScreen ( nXScreen ) { SalDisplay* pSalDisp = GetGenericData()->GetSalDisplay(); Display* pXDisp = pSalDisp->GetDisplay(); if( (maPixmap = limitXCreatePixmap( pXDisp, aDrawable, ImplGetWidth(), ImplGetHeight(), ImplGetDepth() )) ) { XGCValues aValues; GC aGC; int nValues = GCFunction; aValues.function = GXcopy; if( 1 == mnDepth ) { nValues |= ( GCForeground | GCBackground ); aValues.foreground = 1, aValues.background = 0; } aGC = XCreateGC( pXDisp, maPixmap, nValues, &aValues ); XPutImage( pXDisp, maPixmap, aGC, pImage, 0, 0, 0, 0, maTwoRect.mnDestWidth, maTwoRect.mnDestHeight ); XFreeGC( pXDisp, aGC ); } } // ----------------------------------------------------------------------------- ImplSalDDB::ImplSalDDB( Drawable aDrawable, void *pVisual, SalX11Screen nXScreen, long nDrawableDepth, long nX, long nY, long nWidth, long nHeight ) : mpVisual ( pVisual ) , mnDepth( nDrawableDepth ) , mnXScreen( nXScreen ) { SalDisplay* pSalDisp = GetGenericData()->GetSalDisplay(); Display* pXDisp = pSalDisp->GetDisplay(); if( (maPixmap = limitXCreatePixmap( pXDisp, aDrawable, nWidth, nHeight, nDrawableDepth )) ) { XGCValues aValues; GC aGC; int nValues = GCFunction; aValues.function = GXcopy; if( 1 == mnDepth ) { nValues |= ( GCForeground | GCBackground ); aValues.foreground = 1, aValues.background = 0; } aGC = XCreateGC( pXDisp, maPixmap, nValues, &aValues ); ImplDraw( aDrawable, nDrawableDepth, maPixmap, mnDepth, nX, nY, nWidth, nHeight, 0, 0, aGC ); XFreeGC( pXDisp, aGC ); maTwoRect.mnSrcX = maTwoRect.mnSrcY = maTwoRect.mnDestX = maTwoRect.mnDestY = 0; maTwoRect.mnSrcWidth = maTwoRect.mnDestWidth = nWidth; maTwoRect.mnSrcHeight = maTwoRect.mnDestHeight = nHeight; } } // ----------------------------------------------------------------------------- ImplSalDDB::~ImplSalDDB() { if( maPixmap && ImplGetSVData() ) XFreePixmap( GetGenericData()->GetSalDisplay()->GetDisplay(), maPixmap ); } // ----------------------------------------------------------------------------- bool ImplSalDDB::ImplMatches( SalX11Screen nXScreen, long nDepth, const SalTwoRect& rTwoRect ) const { bool bRet = false; if( ( maPixmap != 0 ) && ( ( mnDepth == nDepth ) || ( 1 == mnDepth ) ) && nXScreen == mnXScreen) { if ( rTwoRect.mnSrcX == maTwoRect.mnSrcX && rTwoRect.mnSrcY == maTwoRect.mnSrcY && rTwoRect.mnSrcWidth == maTwoRect.mnSrcWidth && rTwoRect.mnSrcHeight == maTwoRect.mnSrcHeight && rTwoRect.mnDestWidth == maTwoRect.mnDestWidth && rTwoRect.mnDestHeight == maTwoRect.mnDestHeight ) { // absolutely indentically bRet = true; } else if( rTwoRect.mnSrcWidth == rTwoRect.mnDestWidth && rTwoRect.mnSrcHeight == rTwoRect.mnDestHeight && maTwoRect.mnSrcWidth == maTwoRect.mnDestWidth && maTwoRect.mnSrcHeight == maTwoRect.mnDestHeight && rTwoRect.mnSrcX >= maTwoRect.mnSrcX && rTwoRect.mnSrcY >= maTwoRect.mnSrcY && ( rTwoRect.mnSrcX + rTwoRect.mnSrcWidth ) <= ( maTwoRect.mnSrcX + maTwoRect.mnSrcWidth ) && ( rTwoRect.mnSrcY + rTwoRect.mnSrcHeight ) <= ( maTwoRect.mnSrcY + maTwoRect.mnSrcHeight ) ) { bRet = true; } } return bRet; } // ----------------------------------------------------------------------------- void ImplSalDDB::ImplDraw( Drawable aDrawable, long nDrawableDepth, const SalTwoRect& rTwoRect, const GC& rGC ) const { ImplDraw( maPixmap, mnDepth, aDrawable, nDrawableDepth, rTwoRect.mnSrcX - maTwoRect.mnSrcX, rTwoRect.mnSrcY - maTwoRect.mnSrcY, rTwoRect.mnDestWidth, rTwoRect.mnDestHeight, rTwoRect.mnDestX, rTwoRect.mnDestY, rGC ); } // ----------------------------------------------------------------------------- void ImplSalDDB::ImplDraw( Drawable aSrcDrawable, long nSrcDrawableDepth, Drawable aDstDrawable, long, long nSrcX, long nSrcY, long nDestWidth, long nDestHeight, long nDestX, long nDestY, const GC& rGC ) { SalDisplay* pSalDisp = GetGenericData()->GetSalDisplay(); Display* pXDisp = pSalDisp->GetDisplay(); if( 1 == nSrcDrawableDepth ) { XCopyPlane( pXDisp, aSrcDrawable, aDstDrawable, rGC, nSrcX, nSrcY, nDestWidth, nDestHeight, nDestX, nDestY, 1 ); } else { XCopyArea( pXDisp, aSrcDrawable, aDstDrawable, rGC, nSrcX, nSrcY, nDestWidth, nDestHeight, nDestX, nDestY ); } } // ---------------------- // - ImplSalBitmapCache - // ---------------------- struct ImplBmpObj { X11SalBitmap* mpBmp; sal_uLong mnMemSize; sal_uLong mnFlags; ImplBmpObj( X11SalBitmap* pBmp, sal_uLong nMemSize, sal_uLong nFlags ) : mpBmp( pBmp ), mnMemSize( nMemSize ), mnFlags( nFlags ) {} }; // ----------------------------------------------------------------------------- ImplSalBitmapCache::ImplSalBitmapCache() : mnTotalSize( 0UL ) { } // ----------------------------------------------------------------------------- ImplSalBitmapCache::~ImplSalBitmapCache() { ImplClear(); } // ----------------------------------------------------------------------------- void ImplSalBitmapCache::ImplAdd( X11SalBitmap* pBmp, sal_uLong nMemSize, sal_uLong nFlags ) { ImplBmpObj* pObj = NULL; bool bFound = false; for( BmpList_impl::iterator it = maBmpList.begin(); (it != maBmpList.end() ) && !bFound ; ++it ) { pObj = *it; if( pObj->mpBmp == pBmp ) bFound = true; } mnTotalSize += nMemSize; if( bFound ) { mnTotalSize -= pObj->mnMemSize; pObj->mnMemSize = nMemSize, pObj->mnFlags = nFlags; } else maBmpList.push_back( new ImplBmpObj( pBmp, nMemSize, nFlags ) ); } // ----------------------------------------------------------------------------- void ImplSalBitmapCache::ImplRemove( X11SalBitmap* pBmp ) { for( BmpList_impl::iterator it = maBmpList.begin(); it != maBmpList.end(); ++it ) { if( (*it)->mpBmp == pBmp ) { (*it)->mpBmp->ImplRemovedFromCache(); mnTotalSize -= (*it)->mnMemSize; delete *it; maBmpList.erase( it ); break; } } } // ----------------------------------------------------------------------------- void ImplSalBitmapCache::ImplClear() { for( BmpList_impl::iterator it = maBmpList.begin(); it != maBmpList.end(); ++it ) { (*it)->mpBmp->ImplRemovedFromCache(); delete *it; } maBmpList.clear(); mnTotalSize = 0; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */