/************************************************************************* * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: image.cxx,v $ * * $Revision: 1.26 $ * * last change: $Author: obo $ $Date: 2006-09-17 12:02:02 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. * * * GNU Lesser General Public License Version 2.1 * ============================================= * Copyright 2005 by Sun Microsystems, Inc. * 901 San Antonio Road, Palo Alto, CA 94303, USA * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_vcl.hxx" #include #include #ifndef _RTL_LOGFILE_HXX_ #include #endif #ifndef _DEBUG_HXX #include #endif #ifndef _STREAM_HXX #include #endif #ifndef _SV_RC_H #include #endif #ifndef _TOOLS_RC_HXX #include #endif #ifndef _SV_RESMGR_HXX #include #endif #ifndef _SV_SETTINGS_HXX #include #endif #ifndef _SV_OUTDEV_HXX #include #endif #ifndef _SV_GRAPH_HXX #include #endif #ifndef _SV_SVAPP_HXX #include #endif #ifndef _SV_IMPIMAGETREE_H #include #endif #ifndef _SV_IMAGE_H #include #endif #ifndef _SV_IMAGE_HXX #include #endif DBG_NAME( Image ) DBG_NAME( ImageList ) #define IMAGE_FILE_VERSION 100 using namespace ::com::sun::star; // --------- // - Image - // --------- Image::Image() : mpImplData( NULL ) { DBG_CTOR( Image, NULL ); } // ----------------------------------------------------------------------- Image::Image( const ResId& rResId ) : mpImplData( NULL ) { DBG_CTOR( Image, NULL ); rResId.SetRT( RSC_IMAGE ); ResMgr* pResMgr = rResId.GetResMgr(); if( !pResMgr ) pResMgr = Resource::GetResManager(); if( pResMgr->GetResource( rResId ) ) { pResMgr->Increment( sizeof( RSHEADER_TYPE ) ); BitmapEx aBmpEx; ULONG nObjMask = pResMgr->ReadLong(); if( nObjMask & RSC_IMAGE_IMAGEBITMAP ) { aBmpEx = BitmapEx( ResId( (RSHEADER_TYPE*)pResMgr->GetClass() ) ); pResMgr->Increment( pResMgr->GetObjSize( (RSHEADER_TYPE*)pResMgr->GetClass() ) ); } if( nObjMask & RSC_IMAGE_MASKBITMAP ) { if( !aBmpEx.IsEmpty() ) { if( aBmpEx.GetTransparentType() == TRANSPARENT_NONE ) { const Bitmap aMaskBitmap( ResId( (RSHEADER_TYPE*)pResMgr->GetClass() ) ); aBmpEx = BitmapEx( aBmpEx.GetBitmap(), aMaskBitmap ); } } pResMgr->Increment( pResMgr->GetObjSize( (RSHEADER_TYPE*)pResMgr->GetClass() ) ); } if( nObjMask & RSC_IMAGE_MASKCOLOR ) { if( ! aBmpEx.IsEmpty() ) { if( aBmpEx.GetTransparentType() == TRANSPARENT_NONE ) { const Color aMaskColor( ResId( (RSHEADER_TYPE*)pResMgr->GetClass() ) ); aBmpEx = BitmapEx( aBmpEx.GetBitmap(), aMaskColor ); } } pResMgr->Increment( pResMgr->GetObjSize( (RSHEADER_TYPE*)pResMgr->GetClass() ) ); } if( !aBmpEx.IsEmpty() ) ImplInit( aBmpEx ); } } // ----------------------------------------------------------------------- Image::Image( const Image& rImage ) : mpImplData( rImage.mpImplData ) { DBG_CTOR( Image, NULL ); if( mpImplData ) ++mpImplData->mnRefCount; } // ----------------------------------------------------------------------- Image::Image( const BitmapEx& rBitmapEx ) : mpImplData( NULL ) { DBG_CTOR( Image, NULL ); ImplInit( rBitmapEx ); } // ----------------------------------------------------------------------- Image::Image( const Bitmap& rBitmap ) : mpImplData( NULL ) { DBG_CTOR( Image, NULL ); ImplInit( rBitmap ); } // ----------------------------------------------------------------------- Image::Image( const Bitmap& rBitmap, const Bitmap& rMaskBitmap ) : mpImplData( NULL ) { DBG_CTOR( Image, NULL ); const BitmapEx aBmpEx( rBitmap, rMaskBitmap ); ImplInit( aBmpEx ); } // ----------------------------------------------------------------------- Image::Image( const Bitmap& rBitmap, const Color& rColor ) : mpImplData( NULL ) { DBG_CTOR( Image, NULL ); const BitmapEx aBmpEx( rBitmap, rColor ); ImplInit( aBmpEx ); } // ----------------------------------------------------------------------- Image::Image( const uno::Reference< graphic::XGraphic >& rxGraphic ) : mpImplData( NULL ) { DBG_CTOR( Image, NULL ); const Graphic aGraphic( rxGraphic ); ImplInit( aGraphic.GetBitmapEx() ); } // ----------------------------------------------------------------------- Image::~Image() { DBG_DTOR( Image, NULL ); if( mpImplData && ( 0 == --mpImplData->mnRefCount ) ) delete mpImplData; } // ----------------------------------------------------------------------- void Image::ImplInit( const BitmapEx& rBmpEx ) { if( !rBmpEx.IsEmpty() ) { mpImplData = new ImplImage; mpImplData->mnRefCount = 1; if( rBmpEx.GetTransparentType() == TRANSPARENT_NONE ) { mpImplData->meType = IMAGETYPE_BITMAP; mpImplData->mpData = new Bitmap( rBmpEx.GetBitmap() ); } else { mpImplData->meType = IMAGETYPE_IMAGE; mpImplData->mpData = new ImplImageData( rBmpEx ); } } } // ----------------------------------------------------------------------- Size Image::GetSizePixel() const { DBG_CHKTHIS( Image, NULL ); Size aRet; if( mpImplData ) { switch( mpImplData->meType ) { case IMAGETYPE_BITMAP: aRet = static_cast< Bitmap* >( mpImplData->mpData )->GetSizePixel(); break; case IMAGETYPE_IMAGE: aRet = static_cast< ImplImageData* >( mpImplData->mpData )->maBmpEx.GetSizePixel(); break; case IMAGETYPE_IMAGEREF: aRet = static_cast< ImplImageRefData* >( mpImplData->mpData )->mpImplData->maImageSize; break; } } return aRet; } // ----------------------------------------------------------------------- BitmapEx Image::GetBitmapEx() const { DBG_CHKTHIS( Image, NULL ); BitmapEx aRet; if( mpImplData ) { switch( mpImplData->meType ) { case IMAGETYPE_BITMAP: aRet = *static_cast< Bitmap* >( mpImplData->mpData ); break; case IMAGETYPE_IMAGE: aRet = static_cast< ImplImageData* >( mpImplData->mpData )->maBmpEx; break; case IMAGETYPE_IMAGEREF: { ImplImageRefData* pData = static_cast< ImplImageRefData* >( mpImplData->mpData ); aRet = pData->mpImplData->mpImageBitmap->GetBitmapEx( 1, &pData->mnIndex ); } break; } } return aRet; } // ----------------------------------------------------------------------- uno::Reference< graphic::XGraphic > Image::GetXGraphic() const { const Graphic aGraphic( GetBitmapEx() ); return aGraphic.GetXGraphic(); } // ----------------------------------------------------------------------- Image Image::GetColorTransformedImage( ImageColorTransform eColorTransform ) const { DBG_CHKTHIS( Image, NULL ); Image aRet; if( IMAGECOLORTRANSFORM_HIGHCONTRAST == eColorTransform ) { BitmapEx aBmpEx( GetBitmapEx() ); if( !aBmpEx.IsEmpty() ) { Color* pSrcColors = NULL; Color* pDstColors = NULL; ULONG nColorCount = 0; Image::GetColorTransformArrays( eColorTransform, pSrcColors, pDstColors, nColorCount ); if( nColorCount && pSrcColors && pDstColors ) { aBmpEx.Replace( pSrcColors, pDstColors, nColorCount ); aRet = Image( aBmpEx ); } delete[] pSrcColors; delete[] pDstColors; } } else if( IMAGECOLORTRANSFORM_MONOCHROME_BLACK == eColorTransform || IMAGECOLORTRANSFORM_MONOCHROME_WHITE == eColorTransform ) { BitmapEx aBmpEx( GetBitmapEx() ); if( !aBmpEx.IsEmpty() ) aRet = Image( aBmpEx.GetColorTransformedBitmapEx( ( BmpColorMode )( eColorTransform ) ) ); } if( !aRet ) aRet = *this; return aRet; } // ----------------------------------------------------------------------- void Image::Invert() { BitmapEx aInvertedBmp( GetBitmapEx() ); aInvertedBmp.Invert(); *this = aInvertedBmp; } // ----------------------------------------------------------------------- void Image::GetColorTransformArrays( ImageColorTransform eColorTransform, Color*& rpSrcColor, Color*& rpDstColor, ULONG& rColorCount ) { if( IMAGECOLORTRANSFORM_HIGHCONTRAST == eColorTransform ) { rpSrcColor = new Color[ 4 ]; rpDstColor = new Color[ 4 ]; rColorCount = 4; rpSrcColor[ 0 ] = Color( COL_BLACK ); rpDstColor[ 0 ] = Color( COL_WHITE ); rpSrcColor[ 1 ] = Color( COL_WHITE ); rpDstColor[ 1 ] = Color( COL_BLACK ); rpSrcColor[ 2 ] = Color( COL_BLUE ); rpDstColor[ 2 ] = Color( COL_WHITE ); rpSrcColor[ 3 ] = Color( COL_LIGHTBLUE ); rpDstColor[ 3 ] = Color( COL_WHITE ); } else { rpSrcColor = rpDstColor = NULL; rColorCount = 0; } } // ----------------------------------------------------------------------- Image& Image::operator=( const Image& rImage ) { DBG_CHKTHIS( Image, NULL ); DBG_CHKOBJ( &rImage, Image, NULL ); if( rImage.mpImplData ) ++rImage.mpImplData->mnRefCount; if( mpImplData && ( 0 == --mpImplData->mnRefCount ) ) delete mpImplData; mpImplData = rImage.mpImplData; return *this; } // ----------------------------------------------------------------------- BOOL Image::operator==( const Image& rImage ) const { DBG_CHKTHIS( Image, NULL ); DBG_CHKOBJ( &rImage, Image, NULL ); bool bRet = false; if( rImage.mpImplData == mpImplData ) bRet = true; else if( !rImage.mpImplData || !mpImplData ) bRet = false; else if( rImage.mpImplData->mpData == mpImplData->mpData ) bRet = true; else if( rImage.mpImplData->meType == mpImplData->meType ) { switch( mpImplData->meType ) { case IMAGETYPE_BITMAP: bRet = ( *static_cast< Bitmap* >( rImage.mpImplData->mpData ) == *static_cast< Bitmap* >( mpImplData->mpData ) ); break; case IMAGETYPE_IMAGE: bRet = static_cast< ImplImageData* >( rImage.mpImplData->mpData )->IsEqual( *static_cast< ImplImageData* >( mpImplData->mpData ) ); break; case IMAGETYPE_IMAGEREF: bRet = static_cast< ImplImageRefData* >( rImage.mpImplData->mpData )->IsEqual( *static_cast< ImplImageRefData* >( mpImplData->mpData ) ); break; default: bRet = false; break; } } return bRet; } // ------------- // - ImageList - // ------------- ImageList::ImageList( USHORT nInit, USHORT nGrow ) : mpImplData( NULL ), mnInitSize( nInit ), mnGrowSize( nGrow ) { DBG_CTOR( ImageList, NULL ); } // ----------------------------------------------------------------------- ImageList::ImageList( const ResId& rResId ) : mpImplData( NULL ), mnInitSize( 1 ), mnGrowSize( 4 ) { RTL_LOGFILE_CONTEXT( aLog, "vcl: ImageList::ImageList( const ResId& rResId )" ); DBG_CTOR( ImageList, NULL ); rResId.SetRT( RSC_IMAGELIST ); ResMgr* pResMgr = rResId.GetResMgr(); if( !pResMgr ) pResMgr = Resource::GetResManager(); if( pResMgr->GetResource( rResId ) ) { pResMgr->Increment( sizeof( RSHEADER_TYPE ) ); ULONG nObjMask = pResMgr->ReadLong(); const String aPrefix( pResMgr->ReadString() ); ::boost::scoped_ptr< Color > spMaskColor; if( nObjMask & RSC_IMAGE_MASKCOLOR ) spMaskColor.reset( new Color( ResId( (RSHEADER_TYPE*)pResMgr->GetClass() ) ) ); pResMgr->Increment( pResMgr->GetObjSize( (RSHEADER_TYPE*)pResMgr->GetClass() ) ); if( nObjMask & RSC_IMAGELIST_IDLIST ) { for( sal_Int32 i = 0, nCount = pResMgr->ReadLong(); i < nCount; ++i ) pResMgr->ReadLong(); } BitmapEx aBmpEx; sal_Int32 nCount = pResMgr->ReadLong(); ::boost::scoped_array< USHORT > aIdArray( new USHORT[ nCount ] ); ::std::vector< ::rtl::OUString > aImageNames( nCount ); ::rtl::OUString aResMgrName( pResMgr->GetFileName() ); ::rtl::OUString aUserImageName; sal_Int32 nPos = aResMgrName.lastIndexOf( '\\' ); // load file entry list for( sal_Int32 i = 0; i < nCount; ++i ) { aImageNames[ i ] = pResMgr->ReadString(); aIdArray[ i ] = static_cast< USHORT >( pResMgr->ReadLong() ); } if( -1 == nPos ) nPos = aResMgrName.lastIndexOf( '/' ); if( -1 != nPos++ ) { const sal_Int32 nSecondPos = aResMgrName.lastIndexOf( '.' ); aUserImageName = aResMgrName.copy( nPos, ( ( -1 != nSecondPos ) ? nSecondPos : aResMgrName.getLength() ) - nPos ); } aUserImageName += ::rtl::OUString::valueOf( static_cast< sal_Int32 >( rResId.GetId() ) ); aUserImageName += ::rtl::OUString::valueOf( nCount ); ::rtl::OUString aCurrentSymbolsStyle = Application::GetSettings().GetStyleSettings().GetCurrentSymbolsStyleName(); aUserImageName += aCurrentSymbolsStyle; ImplInitBitmapEx( aUserImageName, aImageNames, aCurrentSymbolsStyle, aBmpEx, spMaskColor.get() ); if( nObjMask & RSC_IMAGELIST_IDCOUNT ) pResMgr->ReadShort(); ImplInit( aBmpEx, sal::static_int_cast(nCount), aIdArray.get(), NULL, 4 ); } } // ----------------------------------------------------------------------- ImageList::ImageList( const ::std::vector< ::rtl::OUString >& rNameVector, const ::rtl::OUString& rPrefix, const Color* pMaskColor ) : mpImplData( NULL ), mnInitSize( 1 ), mnGrowSize( 4 ) { RTL_LOGFILE_CONTEXT( aLog, "vcl: ImageList::ImageList(const vector< OUString >& ..." ); DBG_CTOR( ImageList, NULL ); BitmapEx aBmpEx; ::rtl::OUString aUserImageName( rPrefix ); ::std::vector< ::rtl::OUString > aImageNames( rNameVector.size() ); const lang::Locale& rLocale = Application::GetSettings().GetUILocale(); for( sal_Int32 i = 0, nCount = rNameVector.size(); i < nCount; ++i ) ( aImageNames[ i ] = rPrefix ) += rNameVector[ i ]; aUserImageName = ( ( aUserImageName += rLocale.Language ) += rLocale.Country ).replace( '/', '_' ); aUserImageName += ::rtl::OUString::valueOf( static_cast< sal_Int32 >( rNameVector.size() ) ); ::rtl::OUString aCurrentSymbolsStyle = Application::GetSettings().GetStyleSettings().GetCurrentSymbolsStyleName(); aUserImageName += aCurrentSymbolsStyle; ImplInitBitmapEx( aUserImageName, aImageNames, aCurrentSymbolsStyle, aBmpEx, pMaskColor ); ImplInit( aBmpEx, static_cast< USHORT >( rNameVector.size() ), NULL, &rNameVector, 4 ); } // ----------------------------------------------------------------------- ImageList::ImageList( const ImageList& rImageList ) : mpImplData( rImageList.mpImplData ), mnInitSize( rImageList.mnInitSize ), mnGrowSize( rImageList.mnGrowSize ) { DBG_CTOR( ImageList, NULL ); if( mpImplData ) ++mpImplData->mnRefCount; } // ----------------------------------------------------------------------- ImageList::ImageList( const BitmapEx& rBitmapEx, USHORT nInit, USHORT* pIdAry, USHORT nGrow ) : mpImplData( NULL ), mnInitSize( nInit ), mnGrowSize( nGrow ) { DBG_CTOR( ImageList, NULL ); ImplInit( rBitmapEx, nInit, pIdAry, NULL, nGrow ); } // ----------------------------------------------------------------------- ImageList::ImageList( const BitmapEx& rBitmapEx, const ::std::vector< ::rtl::OUString >& rNameVector, USHORT nGrow ) : mpImplData( NULL ), mnInitSize( static_cast< USHORT >( rNameVector.size() ) ), mnGrowSize( nGrow ) { RTL_LOGFILE_CONTEXT( aLog, "vcl: ImageList::ImageList( const BitmapEx& ..." ); DBG_CTOR( ImageList, NULL ); ImplInit( rBitmapEx, static_cast< USHORT >( rNameVector.size() ), NULL, &rNameVector, nGrow ); } // ----------------------------------------------------------------------- ImageList::ImageList( const Bitmap& rBitmap, USHORT nInit, USHORT* pIdAry, USHORT nGrow ) : mpImplData( NULL ), mnInitSize( nInit ), mnGrowSize( nGrow ) { DBG_CTOR( ImageList, NULL ); ImplInit( rBitmap, nInit, pIdAry, NULL, nGrow ); } // ----------------------------------------------------------------------- ImageList::ImageList( const Bitmap& rBitmap, const Bitmap& rMaskBmp, USHORT nInit, USHORT* pIdAry, USHORT nGrow ) : mpImplData( NULL ), mnInitSize( nInit ), mnGrowSize( nGrow ) { DBG_CTOR( ImageList, NULL ); const BitmapEx aBmpEx( rBitmap, rMaskBmp ); ImplInit( aBmpEx, nInit, pIdAry, NULL, nGrow ); } // ----------------------------------------------------------------------- ImageList::ImageList( const Bitmap& rBitmap, const Color& rColor, USHORT nInit, USHORT* pIdAry, USHORT nGrow ) { DBG_CTOR( ImageList, NULL ); const BitmapEx aBmpEx( rBitmap, rColor ); ImplInit( aBmpEx, nInit, pIdAry, NULL, nGrow ); } // ----------------------------------------------------------------------- ImageList::~ImageList() { DBG_DTOR( ImageList, NULL ); if( mpImplData && ( 0 == --mpImplData->mnRefCount ) && ( 0 == mpImplData->mnIRefCount ) ) delete mpImplData; } // ----------------------------------------------------------------------- void ImageList::ImplInitBitmapEx( const ::rtl::OUString& rUserImageName, const ::std::vector< ::rtl::OUString >& rImageNames, const ::rtl::OUString& rSymbolsStyle, BitmapEx& rBmpEx, const Color* pMaskColor ) const { static ImplImageTreeSingletonRef aImageTree; if( !aImageTree->loadImage( rUserImageName, rSymbolsStyle, rBmpEx ) ) { BitmapEx aCurBmpEx; Size aItemSizePixel; bool bInit = false; for( sal_Int32 i = 0, nCount = rImageNames.size(); i < nCount; ++i ) { if( aImageTree->loadImage( rImageNames[ i ], rSymbolsStyle, aCurBmpEx, true ) ) { const Size aCurSizePixel( aCurBmpEx.GetSizePixel() ); if( !bInit ) { const Size aTotalSize( aCurSizePixel.Width() * nCount, aCurSizePixel.Height() ); BYTE cTransparent = 255; const Bitmap aBmp( aTotalSize, 24 ); const AlphaMask aAlphaMask( aTotalSize, &cTransparent ); aItemSizePixel = aCurSizePixel; rBmpEx = BitmapEx( aBmp, aAlphaMask ); bInit = true; } #ifdef DBG_UTIL if( ( aItemSizePixel.Width() < aCurSizePixel.Width() ) || ( aItemSizePixel.Height() < aCurSizePixel.Height() ) ) { ByteString aStr( "Differerent dimensions in ItemList images: " ); aStr += ByteString( String( rImageNames[ i ] ), RTL_TEXTENCODING_ASCII_US ); aStr += " is "; aStr += ByteString::CreateFromInt32( aCurSizePixel.Width() ); aStr += "x"; aStr += ByteString::CreateFromInt32( aCurSizePixel.Height() ); aStr += " but needs to be "; aStr += ByteString::CreateFromInt32( aItemSizePixel.Width() ); aStr += "x"; aStr += ByteString::CreateFromInt32( aItemSizePixel.Height() ); DBG_ERROR( aStr.GetBuffer() ); } #endif const Rectangle aRectDst( Point( aItemSizePixel.Width() * i, 0 ), aItemSizePixel ); const Rectangle aRectSrc( Point( 0, 0 ), aCurSizePixel ); rBmpEx.CopyPixel( aRectDst, aRectSrc, &aCurBmpEx ); } #ifdef DBG_UTIL else { ByteString aErrorStr( "ImageList::ImplInitBitmapEx(...): could not load image <" ); DBG_ERROR( ( ( aErrorStr += ByteString( String( rImageNames[ i ] ), RTL_TEXTENCODING_ASCII_US ) ) += '>' ).GetBuffer() ); } #endif } if( !rBmpEx.IsEmpty() ) { if( !rBmpEx.IsTransparent() && pMaskColor ) rBmpEx = BitmapEx( rBmpEx.GetBitmap(), *pMaskColor ); aImageTree->addUserImage( rUserImageName, rBmpEx ); } } } // ----------------------------------------------------------------------- void ImageList::ImplInit( const BitmapEx& rBitmapEx, USHORT nInit, const USHORT* pIdAry, const ::std::vector< ::rtl::OUString >* pNames, USHORT nGrow ) { RTL_LOGFILE_CONTEXT( aLog, "vcl: ImageList::ImplInit" ); if( !nInit ) { mpImplData = NULL; mnInitSize = 1; mnGrowSize = nGrow; } else { DBG_ASSERT( !nInit || rBitmapEx.GetSizePixel().Width(), "ImageList::ImageList(): nInitSize != 0 and BmpSize.Width() == 0" ); DBG_ASSERT( (rBitmapEx.GetSizePixel().Width() % nInit) == 0, "ImageList::ImageList(): BmpSize % nInitSize != 0" ); Size aBmpSize( rBitmapEx.GetSizePixel() ); mpImplData = new ImplImageList; mnInitSize = nInit; mnGrowSize = nGrow; mpImplData->mnRefCount = 1; mpImplData->mnIRefCount = 0; mpImplData->mnCount = nInit; mpImplData->mnRealCount = nInit; mpImplData->mnArySize = nInit; mpImplData->mpAry = new ImageAryData[nInit]; mpImplData->maImageSize = Size( aBmpSize.Width() / nInit, aBmpSize.Height() ); for( USHORT i = 0; i < nInit; i++ ) { mpImplData->mpAry[ i ].mnId = pIdAry ? pIdAry[ i ] : ( i + 1 ); mpImplData->mpAry[ i ].mnRefCount = 1; if( pNames && ( i < pNames->size() ) ) mpImplData->mpAry[ i ].maName = (*pNames)[ i ]; } mpImplData->mpImageBitmap = new ImplImageBmp; mpImplData->mpImageBitmap->Create( rBitmapEx, mpImplData->maImageSize.Width(), mpImplData->maImageSize.Height(), nInit ); } } // ----------------------------------------------------------------------- void ImageList::ImplMakeUnique() { if( mpImplData && mpImplData->mnRefCount > 1 ) { ImplImageList* pNewData = new ImplImageList; USHORT i = 0, n = 0; --mpImplData->mnRefCount; pNewData->mnRefCount = 1; pNewData->mnIRefCount = 0; pNewData->mnCount = mpImplData->mnCount; pNewData->mnRealCount = mpImplData->mnRealCount; pNewData->mnArySize = mpImplData->mnArySize; pNewData->mpAry = new ImageAryData[ pNewData->mnArySize ]; pNewData->maImageSize = mpImplData->maImageSize; pNewData->mpImageBitmap = new ImplImageBmp; pNewData->mpImageBitmap->Create( pNewData->maImageSize.Width(), pNewData->maImageSize.Height(), pNewData->mnArySize ); while( i < mpImplData->mnArySize ) { if( mpImplData->mpAry[i].mnId ) { pNewData->mpAry[n].maName = mpImplData->mpAry[i].maName; pNewData->mpAry[n].mnId = mpImplData->mpAry[i].mnId; pNewData->mpAry[n].mnRefCount = 1; pNewData->mpImageBitmap->Replace( n, *mpImplData->mpImageBitmap, i ); ++n; } ++i; } mpImplData = pNewData; } } // ----------------------------------------------------------------------- USHORT ImageList::ImplGetImageId( const ::rtl::OUString& rImageName ) const { DBG_CHKTHIS( ImageList, NULL ); if( mpImplData && rImageName.getLength() ) { USHORT nPos = 0, i = 0; while( i < mpImplData->mnArySize ) { if( mpImplData->mpAry[i].maName == rImageName ) return mpImplData->mpAry[i].mnId; if ( mpImplData->mpAry[i].mnId ) ++nPos; ++i; } } return 0; } // ----------------------------------------------------------------------- void ImageList::AddImage( USHORT nId, const Image& rImage ) { DBG_CHKTHIS( ImageList, NULL ); DBG_CHKOBJ( &rImage, Image, NULL ); DBG_ASSERT( nId, "ImageList::AddImage(): ImageId == 0" ); DBG_ASSERT( GetImagePos( nId ) == IMAGELIST_IMAGE_NOTFOUND, "ImageList::AddImage() - ImageId already exists" ); DBG_ASSERT( rImage.mpImplData, "ImageList::AddImage(): Wrong Size" ); DBG_ASSERT( !mpImplData || (rImage.GetSizePixel() == mpImplData->maImageSize), "ImageList::AddImage(): Wrong Size" ); bool bHasImage = ( rImage.mpImplData != 0 ); ImageType eImageType = IMAGETYPE_BITMAP; Size aImageSize; USHORT nIndex; if( bHasImage ) { eImageType = rImage.mpImplData->meType; aImageSize = rImage.GetSizePixel(); } else { if( mpImplData ) { eImageType = IMAGETYPE_BITMAP; aImageSize = mpImplData->maImageSize; } else return; } if( !mpImplData ) { mpImplData = new ImplImageList; mpImplData->mnRefCount = 1; mpImplData->mnIRefCount = 0; mpImplData->mnCount = 0; mpImplData->mnRealCount = 0; mpImplData->mnArySize = mnInitSize; mpImplData->mpAry = new ImageAryData[mnInitSize]; mpImplData->maImageSize = aImageSize; mpImplData->mpImageBitmap = new ImplImageBmp; mpImplData->mpImageBitmap->Create( aImageSize.Width(), aImageSize.Height(), mnInitSize ); } else ImplMakeUnique(); if( mpImplData->mnRealCount == mpImplData->mnArySize ) { ImageAryData* pOldAry = mpImplData->mpAry; USHORT nOldSize = mpImplData->mnArySize; mpImplData->mnArySize = sal::static_int_cast(mpImplData->mnArySize + mnGrowSize); mpImplData->mpAry = new ImageAryData[mpImplData->mnArySize]; for( USHORT i = 0; i < nOldSize; ++i ) mpImplData->mpAry[ i ] = pOldAry[ i ]; mpImplData->mpImageBitmap->Expand( mnGrowSize ); delete[] pOldAry; nIndex = mpImplData->mnRealCount; } else { nIndex = 0; while( mpImplData->mpAry[nIndex].mnRefCount ) ++nIndex; } switch( eImageType ) { case IMAGETYPE_BITMAP: { if( !bHasImage ) { const Bitmap aBmp( aImageSize, 1 ); const BitmapEx aBmpEx( aBmp, Color( COL_BLACK ) ); mpImplData->mpImageBitmap->Replace( nIndex, aBmpEx ); } else mpImplData->mpImageBitmap->Replace( nIndex, *static_cast< Bitmap* >( rImage.mpImplData->mpData ) ); } break; case IMAGETYPE_IMAGE: { ImplImageData* pData = static_cast< ImplImageData* >( rImage.mpImplData->mpData ); if( pData->mpImageBitmap ) mpImplData->mpImageBitmap->Replace( nIndex, *pData->mpImageBitmap, 0 ); else mpImplData->mpImageBitmap->Replace( nIndex, pData->maBmpEx ); } break; case IMAGETYPE_IMAGEREF: { ImplImageRefData* pData = static_cast< ImplImageRefData* >( rImage.mpImplData->mpData ); mpImplData->mpImageBitmap->Replace( nIndex, *pData->mpImplData->mpImageBitmap, pData->mnIndex ); } break; } ++mpImplData->mnCount; ++mpImplData->mnRealCount; mpImplData->mpAry[nIndex].mnId = nId; mpImplData->mpAry[nIndex].mnRefCount = 1; } // ----------------------------------------------------------------------- void ImageList::AddImage( const ::rtl::OUString& rImageName, const Image& rImage ) { DBG_ASSERT( GetImagePos( rImageName ) == IMAGELIST_IMAGE_NOTFOUND, "ImageList::AddImage() - ImageName already exists" ); USHORT i, nMax = 0; if( mpImplData ) { for( i = 0; i < mpImplData->mnArySize; ++i ) { if( mpImplData->mpAry[ i ].mnId > nMax ) { nMax = mpImplData->mpAry[ i ].mnId; } } } if( nMax < USHRT_MAX ) { AddImage( ++nMax, rImage ); for( i = 0; i < mpImplData->mnArySize; ++i ) { if( mpImplData->mpAry[ i ].mnId == nMax ) { mpImplData->mpAry[ i ].maName = rImageName; break; } } } else { DBG_ERROR( "No free image id left" ); } } // ----------------------------------------------------------------------- void ImageList::CopyImage( USHORT nId, USHORT nCopyId ) { DBG_CHKTHIS( ImageList, NULL ); DBG_ASSERT( nId, "ImageList::CopyImage(): ImageId == 0" ); DBG_ASSERT( GetImagePos( nId ) == IMAGELIST_IMAGE_NOTFOUND, "ImageList::CopyImage(): ImageId already exists" ); DBG_ASSERT( GetImagePos( nCopyId ) != IMAGELIST_IMAGE_NOTFOUND, "ImageList::CopyImage(): Unknown nCopyId" ); USHORT nIndex, nCopyIndex = 0; while( nCopyIndex < mpImplData->mnArySize ) { if ( mpImplData->mpAry[nCopyIndex].mnId == nCopyId ) break; ++nCopyIndex; } if( nCopyIndex < mpImplData->mnArySize ) { ImplMakeUnique(); if( mpImplData->mnRealCount == mpImplData->mnArySize ) { ImageAryData* pOldAry = mpImplData->mpAry; USHORT nOldSize = mpImplData->mnArySize; mpImplData->mnArySize = sal::static_int_cast(mpImplData->mnArySize + mnGrowSize); mpImplData->mpAry = new ImageAryData[mpImplData->mnArySize]; for( USHORT i = 0; i < nOldSize; ++i ) mpImplData->mpAry[ i ] = pOldAry[ i ]; mpImplData->mpImageBitmap->Expand( mnGrowSize ); delete[] pOldAry; nIndex = mpImplData->mnRealCount; } else { nIndex = 0; while( mpImplData->mpAry[nIndex].mnRefCount ) nIndex++; } mpImplData->mpImageBitmap->Replace( nIndex, *mpImplData->mpImageBitmap, nCopyIndex ); ++mpImplData->mnCount; ++mpImplData->mnRealCount; mpImplData->mpAry[nIndex].mnId = nId; mpImplData->mpAry[nIndex].mnRefCount = 1; } } // ----------------------------------------------------------------------- void ImageList::CopyImage( const ::rtl::OUString& rImageName, const ::rtl::OUString& rCopyName ) { const USHORT nId1 = ImplGetImageId( rImageName ), nId2 = ImplGetImageId( rCopyName ); if( nId1 && nId2 ) CopyImage( nId1, nId2 ); } // ----------------------------------------------------------------------- void ImageList::ReplaceImage( USHORT nId, const Image& rImage ) { DBG_CHKTHIS( ImageList, NULL ); DBG_CHKOBJ( &rImage, Image, NULL ); DBG_ASSERT( GetImagePos( nId ) != IMAGELIST_IMAGE_NOTFOUND, "ImageList::ReplaceImage(): Unknown nId" ); RemoveImage( nId ); AddImage( nId, rImage ); } // ----------------------------------------------------------------------- void ImageList::ReplaceImage( const ::rtl::OUString& rImageName, const Image& rImage ) { const USHORT nId = ImplGetImageId( rImageName ); if( nId ) ReplaceImage( nId, rImage ); } // ----------------------------------------------------------------------- void ImageList::ReplaceImage( USHORT nId, USHORT nReplaceId ) { DBG_CHKTHIS( ImageList, NULL ); DBG_ASSERT( GetImagePos( nId ) != IMAGELIST_IMAGE_NOTFOUND, "ImageList::ReplaceImage(): Unknown nId" ); DBG_ASSERT( GetImagePos( nReplaceId ) != IMAGELIST_IMAGE_NOTFOUND, "ImageList::ReplaceImage(): Unknown nReplaceId" ); USHORT nPos1 = 0, nPos2 = 0; while( nPos1 < mpImplData->mnArySize ) { if ( mpImplData->mpAry[nPos1].mnId == nId ) break; ++nPos1; } if( nPos1 < mpImplData->mnArySize ) { while( nPos2 < mpImplData->mnArySize ) { if( mpImplData->mpAry[nPos2].mnId == nReplaceId ) break; ++nPos2; } if( nPos2 < mpImplData->mnArySize ) { ImplMakeUnique(); mpImplData->mpImageBitmap->Replace( nPos1, nPos2 ); } } } // ----------------------------------------------------------------------- void ImageList::ReplaceImage( const ::rtl::OUString& rImageName, const ::rtl::OUString& rReplaceName ) { const USHORT nId1 = ImplGetImageId( rImageName ), nId2 = ImplGetImageId( rReplaceName ); if( nId1 && nId2 ) ReplaceImage( nId1, nId2 ); } // ----------------------------------------------------------------------- void ImageList::RemoveImage( USHORT nId ) { DBG_CHKTHIS( ImageList, NULL ); if( mpImplData ) { USHORT i = 0; ImplMakeUnique(); while( i < mpImplData->mnArySize ) { if( mpImplData->mpAry[i].mnId == nId ) break; ++i; } if( i < mpImplData->mnArySize ) { --mpImplData->mpAry[i].mnRefCount; mpImplData->mpAry[i].mnId = 0; if( !mpImplData->mpAry[i].mnRefCount ) --mpImplData->mnRealCount; --mpImplData->mnCount; } } } // ----------------------------------------------------------------------- void ImageList::RemoveImage( const ::rtl::OUString& rImageName ) { const USHORT nId = ImplGetImageId( rImageName ); if( nId ) RemoveImage( nId ); } // ----------------------------------------------------------------------- Image ImageList::GetImage( USHORT nId ) const { DBG_CHKTHIS( ImageList, NULL ); Image aImage; if( mpImplData ) { USHORT i = 0; while( i < mpImplData->mnArySize ) { if( mpImplData->mpAry[i].mnId == nId ) break; ++i; } if( i < mpImplData->mnArySize ) { ImplImageRefData* mpData = new ImplImageRefData; ++mpImplData->mnIRefCount; ++mpImplData->mpAry[i].mnRefCount; mpData->mpImplData = mpImplData; mpData->mnIndex = i; aImage.mpImplData = new ImplImage; aImage.mpImplData->mnRefCount = 1; aImage.mpImplData->meType = IMAGETYPE_IMAGEREF; aImage.mpImplData->mpData = mpData; } } return aImage; } // ----------------------------------------------------------------------- Image ImageList::GetImage( const ::rtl::OUString& rImageName ) const { const USHORT nId = ImplGetImageId( rImageName ); if( nId ) return GetImage( nId ); else return Image(); } // ----------------------------------------------------------------------- void ImageList::Clear() { DBG_CHKTHIS( ImageList, NULL ); if( mpImplData && ( 0 == --mpImplData->mnRefCount ) ) delete mpImplData; mpImplData = NULL; } // ----------------------------------------------------------------------- USHORT ImageList::GetImageCount() const { DBG_CHKTHIS( ImageList, NULL ); return( mpImplData ? mpImplData->mnCount : 0 ); } // ----------------------------------------------------------------------- USHORT ImageList::GetImagePos( USHORT nId ) const { DBG_CHKTHIS( ImageList, NULL ); if( mpImplData && nId ) { USHORT nPos = 0, i = 0; while( i < mpImplData->mnArySize ) { if( mpImplData->mpAry[i].mnId == nId ) return nPos; if ( mpImplData->mpAry[i].mnId ) ++nPos; ++i; } } return IMAGELIST_IMAGE_NOTFOUND; } // ----------------------------------------------------------------------- USHORT ImageList::GetImagePos( const ::rtl::OUString& rImageName ) const { DBG_CHKTHIS( ImageList, NULL ); if( mpImplData && rImageName.getLength() ) { USHORT nPos = 0, i = 0; while( i < mpImplData->mnArySize ) { if( mpImplData->mpAry[i].maName == rImageName ) return nPos; if ( mpImplData->mpAry[i].mnId ) ++nPos; ++i; } } return IMAGELIST_IMAGE_NOTFOUND; } // ----------------------------------------------------------------------- USHORT ImageList::GetImageId( USHORT nPos ) const { DBG_CHKTHIS( ImageList, NULL ); if( mpImplData ) { USHORT nRealPos = 0, i = 0; while( i < mpImplData->mnArySize ) { if( (nPos == nRealPos) && (mpImplData->mpAry[i].mnId) ) return mpImplData->mpAry[i].mnId; if ( mpImplData->mpAry[i].mnId ) ++nRealPos; ++i; } } return 0; } // ----------------------------------------------------------------------- void ImageList::GetImageIds( ::std::vector< USHORT >& rIds ) const { RTL_LOGFILE_CONTEXT( aLog, "vcl: ImageList::GetImageIds" ); DBG_CHKTHIS( ImageList, NULL ); rIds = ::std::vector< USHORT >(); if( mpImplData ) { for( USHORT i = 0; i < mpImplData->mnArySize; ++i ) { if( mpImplData->mpAry[ i ].mnId ) rIds.push_back( mpImplData->mpAry[ i ].mnId ); } } } // ----------------------------------------------------------------------- ::rtl::OUString ImageList::GetImageName( USHORT nPos ) const { DBG_CHKTHIS( ImageList, NULL ); if( mpImplData ) { USHORT nRealPos = 0, i = 0; while( i < mpImplData->mnArySize ) { if( (nPos == nRealPos) && (mpImplData->mpAry[i].mnId) ) return mpImplData->mpAry[i].maName; if ( mpImplData->mpAry[i].mnId ) ++nRealPos; ++i; } } return ::rtl::OUString(); } // ----------------------------------------------------------------------- void ImageList::GetImageNames( ::std::vector< ::rtl::OUString >& rNames ) const { RTL_LOGFILE_CONTEXT( aLog, "vcl: ImageList::GetImageNames" ); DBG_CHKTHIS( ImageList, NULL ); rNames = ::std::vector< ::rtl::OUString >(); if( mpImplData ) { for( USHORT i = 0; i < mpImplData->mnArySize; ++i ) { if( mpImplData->mpAry[ i ].mnId ) rNames.push_back( mpImplData->mpAry[ i ].maName ); } } } // ----------------------------------------------------------------------- Size ImageList::GetImageSize() const { DBG_CHKTHIS( ImageList, NULL ); Size aRet; if( mpImplData ) aRet = mpImplData->maImageSize; return aRet; } // ----------------------------------------------------------------------- BitmapEx ImageList::GetBitmapEx() const { DBG_CHKTHIS( ImageList, NULL ); BitmapEx aRet; if( mpImplData ) { USHORT* pPosAry = new USHORT[ mpImplData->mnCount ]; USHORT nPosCount = 0; for( USHORT i = 0; i < mpImplData->mnArySize; i++ ) { if( mpImplData->mpAry[i].mnId ) { pPosAry[ nPosCount ] = i; ++nPosCount; } } aRet = mpImplData->mpImageBitmap->GetBitmapEx( nPosCount, pPosAry ); delete[] pPosAry; } return aRet; } // ----------------------------------------------------------------------- ImageList ImageList::GetColorTransformedImageList( ImageColorTransform eColorTransform ) const { DBG_CHKTHIS( ImageList, NULL ); ImageList aRet; if( IMAGECOLORTRANSFORM_HIGHCONTRAST == eColorTransform ) { Color* pSrcColors = NULL; Color* pDstColors = NULL; ULONG nColorCount = 0; aRet = *this; aRet.ImplMakeUnique(); Image::GetColorTransformArrays( eColorTransform, pSrcColors, pDstColors, nColorCount ); if( nColorCount && pSrcColors && pDstColors && mpImplData ) aRet.mpImplData->mpImageBitmap->ReplaceColors( pSrcColors, pDstColors, nColorCount ); delete[] pSrcColors; delete[] pDstColors; } else if( IMAGECOLORTRANSFORM_MONOCHROME_BLACK == eColorTransform || IMAGECOLORTRANSFORM_MONOCHROME_WHITE == eColorTransform ) { aRet = *this; aRet.ImplMakeUnique(); aRet.mpImplData->mpImageBitmap->ColorTransform( ( BmpColorMode )( eColorTransform ) ); } if( !aRet.GetImageCount() ) aRet = *this; return aRet; } // ----------------------------------------------------------------------- void ImageList::Invert() { ImageList aNew( *this ); aNew.ImplMakeUnique(); aNew.mpImplData->mpImageBitmap->Invert(); *this = aNew; } // ----------------------------------------------------------------------- ImageList& ImageList::operator=( const ImageList& rImageList ) { DBG_CHKTHIS( ImageList, NULL ); DBG_CHKOBJ( &rImageList, ImageList, NULL ); if( rImageList.mpImplData ) ++rImageList.mpImplData->mnRefCount; if( mpImplData && ( 0 == --mpImplData->mnRefCount ) && ( 0 == mpImplData->mnIRefCount ) ) delete mpImplData; mpImplData = rImageList.mpImplData; mnInitSize = rImageList.mnInitSize; mnGrowSize = rImageList.mnGrowSize; return *this; } // ----------------------------------------------------------------------- BOOL ImageList::operator==( const ImageList& rImageList ) const { DBG_CHKTHIS( ImageList, NULL ); DBG_CHKOBJ( &rImageList, ImageList, NULL ); bool bRet = false; if( rImageList.mpImplData == mpImplData ) bRet = true; else if( !rImageList.mpImplData || !mpImplData ) bRet = false; else if( ( rImageList.mpImplData->mnCount == mpImplData->mnCount ) && ( rImageList.mpImplData->maImageSize == mpImplData->maImageSize ) ) { bRet = true; } return bRet; } // ----------------------------------------------------------------------- SvStream& operator>>( SvStream& rIStream, ImageList& rImageList ) { DBG_CHKOBJ( &rImageList, ImageList, NULL ); if( rImageList.mpImplData ) { --rImageList.mpImplData->mnRefCount; if( ( 0 == rImageList.mpImplData->mnRefCount ) && ( 0 == rImageList.mpImplData->mnIRefCount ) ) delete rImageList.mpImplData; } rImageList.mpImplData = NULL; USHORT nVersion; Size aImageSize; BOOL bImageList; rIStream >> nVersion >> rImageList.mnInitSize >> rImageList.mnGrowSize >> bImageList; if( bImageList ) { BitmapEx aBmpEx; Bitmap aBmp; BYTE bMaskOrAlpha, bMaskColor; rIStream >> aImageSize.Width() >> aImageSize.Height(); rImageList.mpImplData = new ImplImageList; rImageList.mpImplData->mnRefCount = 1; rImageList.mpImplData->mnIRefCount= 0; rImageList.mpImplData->mnCount = rImageList.mnInitSize; rImageList.mpImplData->mnRealCount = rImageList.mnInitSize; rImageList.mpImplData->mnArySize = rImageList.mnInitSize; rImageList.mpImplData->mpAry = new ImageAryData[ rImageList.mnInitSize ]; rImageList.mpImplData->maImageSize = aImageSize; for( USHORT i = 0; i < rImageList.mnInitSize; ++i ) { rIStream >> rImageList.mpImplData->mpAry[i].mnId; rImageList.mpImplData->mpAry[i].mnRefCount = 1; } rIStream >> aBmp >> bMaskOrAlpha; if( bMaskOrAlpha ) { Bitmap aMaskOrAlpha; rIStream >> aMaskOrAlpha; if( aMaskOrAlpha.GetBitCount() == 8 && aMaskOrAlpha.HasGreyPalette() ) aBmpEx = BitmapEx( aBmp, AlphaMask( aMaskOrAlpha ) ); else aBmpEx = BitmapEx( aBmp, aMaskOrAlpha ); } rIStream >> bMaskColor; if( bMaskColor ) { Color aMaskColor; rIStream >> aMaskColor; if( !aBmpEx.IsAlpha() && !aBmpEx.IsTransparent() ) aBmpEx = BitmapEx( aBmp, aMaskColor ); } rImageList.mpImplData->mpImageBitmap = new ImplImageBmp; rImageList.mpImplData->mpImageBitmap->Create( aBmpEx, aImageSize.Width(), aImageSize.Height(), rImageList.mnInitSize ); } return rIStream; } // ----------------------------------------------------------------------- SvStream& operator<<( SvStream& rOStream, const ImageList& rImageList ) { DBG_CHKOBJ( &rImageList, ImageList, NULL ); USHORT nVersion = IMAGE_FILE_VERSION; BOOL bImageList = rImageList.mpImplData ? true : false; rOStream << nVersion; if ( !bImageList || !rImageList.mpImplData->mnCount ) rOStream << rImageList.mnInitSize << rImageList.mnGrowSize << ( bImageList = FALSE ); else { rOStream << rImageList.mpImplData->mnCount; rOStream << rImageList.mnGrowSize; rOStream << bImageList; rOStream << rImageList.mpImplData->maImageSize.Width(); rOStream << rImageList.mpImplData->maImageSize.Height(); USHORT* mpPosAry = new USHORT[rImageList.mpImplData->mnCount]; USHORT nPosCount = 0; for( USHORT i = 0; i < rImageList.mpImplData->mnArySize; ++i ) { if( rImageList.mpImplData->mpAry[i].mnId ) { rOStream << rImageList.mpImplData->mpAry[i].mnId; mpPosAry[ nPosCount++ ] = i; } } BitmapEx aBmpEx( rImageList.mpImplData->mpImageBitmap->GetBitmapEx( nPosCount, mpPosAry ) ); const BOOL bMaskOrAlpha = aBmpEx.IsAlpha() || aBmpEx.IsTransparent(); const BOOL bMaskColor = false; rOStream << aBmpEx.GetBitmap() << bMaskOrAlpha; if( bMaskOrAlpha ) rOStream << ( aBmpEx.IsAlpha() ? aBmpEx.GetAlpha().ImplGetBitmap() : aBmpEx.GetMask() ); // BitmapEx doesn't have internal mask colors anymore rOStream << bMaskColor; delete[] mpPosAry; } return rOStream; }