summaryrefslogtreecommitdiff
path: root/vcl/source/gdi/bitmap.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/gdi/bitmap.cxx')
-rw-r--r--vcl/source/gdi/bitmap.cxx1980
1 files changed, 1980 insertions, 0 deletions
diff --git a/vcl/source/gdi/bitmap.cxx b/vcl/source/gdi/bitmap.cxx
new file mode 100644
index 000000000000..d5016647cfca
--- /dev/null
+++ b/vcl/source/gdi/bitmap.cxx
@@ -0,0 +1,1980 @@
+/*************************************************************************
+ *
+ * $RCSfile: bitmap.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 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
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (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.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_BITMAP_CXX
+
+#ifndef _RTL_CRC_H_
+#include <rtl/crc.h>
+#endif
+#ifndef _SV_SALBTYPE_HXX
+#include <salbtype.hxx>
+#endif
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _SV_BMPACC_HXX
+#include <bmpacc.hxx>
+#endif
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_OUTDEV_HXX
+#include <outdev.hxx>
+#endif
+#ifndef _SV_IMPBMP_HXX
+#include <impbmp.hxx>
+#endif
+#ifndef _SV_RC_H
+#include <rc.h>
+#endif
+#ifndef _SV_BITMAP_HXX
+#include <bitmap.hxx>
+#endif
+#ifndef _SV_ALPHA_HXX
+#include <alpha.hxx>
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <svapp.hxx>
+#endif
+
+// ------------------------------------------------------------------
+
+Bitmap::Bitmap() :
+ mpImpBmp( NULL )
+{
+}
+
+// ------------------------------------------------------------------
+
+Bitmap::Bitmap( const ResId& rResId ) :
+ mpImpBmp( NULL )
+{
+ ResMgr * pResMgr = NULL;
+
+ ResMgr::GetResourceSkipHeader( rResId.SetRT( RSC_BITMAP ), &pResMgr );
+
+ USHORT nBitmapType;
+ USHORT nBitmapId;
+ nBitmapType = pResMgr->ReadShort();
+ nBitmapId = pResMgr->ReadShort();
+
+ SvStream* pBmpStream = pResMgr->pImpRes->GetBitmapStream( nBitmapId );
+ if( pBmpStream )
+ *pBmpStream >> *this;
+ // pop filename
+ String aDummy = pResMgr->ReadString();
+}
+
+// ------------------------------------------------------------------
+
+Bitmap::Bitmap( const Bitmap& rBitmap ) :
+ maPrefMapMode ( rBitmap.maPrefMapMode ),
+ maPrefSize ( rBitmap.maPrefSize )
+{
+ mpImpBmp = rBitmap.mpImpBmp;
+
+ if ( mpImpBmp )
+ mpImpBmp->ImplIncRefCount();
+}
+
+// ------------------------------------------------------------------
+
+Bitmap::Bitmap( const Size& rSizePixel, USHORT nBitCount, const BitmapPalette* pPal )
+{
+ if( rSizePixel.Width() && rSizePixel.Height() )
+ {
+ BitmapPalette aPal;
+ BitmapPalette* pRealPal = NULL;
+
+ if( nBitCount <= 8 )
+ {
+ if( !pPal )
+ {
+ if( 1 == nBitCount )
+ {
+ aPal.SetEntryCount( 2 );
+ aPal[ 0 ] = Color( COL_BLACK );
+ aPal[ 1 ] = Color( COL_WHITE );
+ }
+ else if( ( 4 == nBitCount ) || ( 8 == nBitCount ) )
+ {
+ aPal.SetEntryCount( 1 << nBitCount );
+ aPal[ 0 ] = Color( COL_BLACK );
+ aPal[ 1 ] = Color( COL_BLUE );
+ aPal[ 2 ] = Color( COL_GREEN );
+ aPal[ 3 ] = Color( COL_CYAN );
+ aPal[ 4 ] = Color( COL_RED );
+ aPal[ 5 ] = Color( COL_MAGENTA );
+ aPal[ 6 ] = Color( COL_BROWN );
+ aPal[ 7 ] = Color( COL_GRAY );
+ aPal[ 8 ] = Color( COL_LIGHTGRAY );
+ aPal[ 9 ] = Color( COL_LIGHTBLUE );
+ aPal[ 10 ] = Color( COL_LIGHTGREEN );
+ aPal[ 11 ] = Color( COL_LIGHTCYAN );
+ aPal[ 12 ] = Color( COL_LIGHTRED );
+ aPal[ 13 ] = Color( COL_LIGHTMAGENTA );
+ aPal[ 14 ] = Color( COL_YELLOW );
+ aPal[ 15 ] = Color( COL_WHITE );
+
+ // Dither-Palette erzeugen
+ if( 8 == nBitCount )
+ {
+ USHORT nActCol = 16;
+
+ for( USHORT nB = 0; nB < 256; nB += 51 )
+ for( USHORT nG = 0; nG < 256; nG += 51 )
+ for( USHORT nR = 0; nR < 256; nR += 51 )
+ aPal[ nActCol++ ] = BitmapColor( (BYTE) nR, (BYTE) nG, (BYTE) nB );
+
+ // Standard-Office-Farbe setzen
+ aPal[ nActCol++ ] = BitmapColor( 0, 184, 255 );
+ }
+ }
+ }
+ else
+ pRealPal = (BitmapPalette*) pPal;
+ }
+
+ mpImpBmp = new ImpBitmap;
+ mpImpBmp->ImplCreate( rSizePixel, nBitCount, pRealPal ? *pRealPal : aPal );
+ }
+ else
+ mpImpBmp = NULL;
+}
+
+// ------------------------------------------------------------------
+
+Bitmap::~Bitmap()
+{
+ ImplReleaseRef();
+}
+
+// ------------------------------------------------------------------
+
+const BitmapPalette& Bitmap::GetGreyPalette( USHORT nEntries )
+{
+ static BitmapPalette aGreyPalette2;
+ static BitmapPalette aGreyPalette4;
+ static BitmapPalette aGreyPalette16;
+ static BitmapPalette aGreyPalette256;
+
+ // create greyscale palette with 2, 4, 16 or 256 entries
+ if( 2 == nEntries || 4 == nEntries || 16 == nEntries || 256 == nEntries )
+ {
+ if( 2 == nEntries )
+ {
+ if( !aGreyPalette2.GetEntryCount() )
+ {
+ aGreyPalette2.SetEntryCount( 2 );
+ aGreyPalette2[ 0 ] = BitmapColor( 0, 0, 0 );
+ aGreyPalette2[ 1 ] = BitmapColor( 255, 255, 255 );
+ }
+
+ return aGreyPalette2;
+ }
+ else if( 4 == nEntries )
+ {
+ if( !aGreyPalette4.GetEntryCount() )
+ {
+ aGreyPalette4.SetEntryCount( 4 );
+ aGreyPalette4[ 0 ] = BitmapColor( 0, 0, 0 );
+ aGreyPalette4[ 1 ] = BitmapColor( 85, 85, 85 );
+ aGreyPalette4[ 2 ] = BitmapColor( 170, 170, 170 );
+ aGreyPalette4[ 3 ] = BitmapColor( 255, 255, 255 );
+ }
+
+ return aGreyPalette4;
+ }
+ else if( 16 == nEntries )
+ {
+ if( !aGreyPalette16.GetEntryCount() )
+ {
+ BYTE cGrey = 0, cGreyInc = 17;
+
+ aGreyPalette16.SetEntryCount( 16 );
+
+ for( USHORT i = 0; i < 16; i++, cGrey += cGreyInc )
+ aGreyPalette16[ i ] = BitmapColor( cGrey, cGrey, cGrey );
+ }
+
+ return aGreyPalette16;
+ }
+ else
+ {
+ if( !aGreyPalette256.GetEntryCount() )
+ {
+ aGreyPalette256.SetEntryCount( 256 );
+
+ for( USHORT i = 0; i < 256; i++ )
+ aGreyPalette256[ i ] = BitmapColor( (BYTE) i, (BYTE) i, (BYTE) i );
+ }
+
+ return aGreyPalette256;
+ }
+ }
+ else
+ {
+ DBG_ERROR( "Bitmap::GetGreyPalette: invalid entry count (2/4/16/256 allowed)" );
+ return aGreyPalette2;
+ }
+}
+
+// ------------------------------------------------------------------
+
+Bitmap& Bitmap::operator=( const Bitmap& rBitmap )
+{
+ maPrefSize = rBitmap.maPrefSize;
+ maPrefMapMode = rBitmap.maPrefMapMode;
+
+ if ( rBitmap.mpImpBmp )
+ rBitmap.mpImpBmp->ImplIncRefCount();
+
+ ImplReleaseRef();
+ mpImpBmp = rBitmap.mpImpBmp;
+
+ return *this;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::IsEqual( const Bitmap& rBmp ) const
+{
+ return( IsSameInstance( rBmp ) ||
+ ( rBmp.GetSizePixel() == GetSizePixel() &&
+ rBmp.GetBitCount() == GetBitCount() &&
+ rBmp.GetChecksum() == GetChecksum() ) );
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::SetEmpty()
+{
+ maPrefMapMode = MapMode();
+ maPrefSize = Size();
+
+ ImplReleaseRef();
+ mpImpBmp = NULL;
+}
+
+// ------------------------------------------------------------------
+
+Size Bitmap::GetSizePixel() const
+{
+ return( mpImpBmp ? mpImpBmp->ImplGetSize() : Size() );
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::SetSizePixel( const Size& rNewSize )
+{
+ Scale( rNewSize );
+}
+
+// ------------------------------------------------------------------
+
+USHORT Bitmap::GetBitCount() const
+{
+ return( mpImpBmp ? mpImpBmp->ImplGetBitCount() : 0 );
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::HasGreyPalette() const
+{
+ const USHORT nBitCount = GetBitCount();
+ BOOL bRet = FALSE;
+
+ if( 1 == nBitCount )
+ bRet = TRUE;
+ else if( 4 == nBitCount || 8 == nBitCount )
+ {
+ BitmapReadAccess* pRAcc = ( (Bitmap*) this )->AcquireReadAccess();
+
+ if( pRAcc )
+ {
+ if( pRAcc->HasPalette() && ( (BitmapPalette&) pRAcc->GetPalette() == GetGreyPalette( 1 << nBitCount ) ) )
+ bRet = TRUE;
+
+ ( (Bitmap*) this )->ReleaseAccess( pRAcc );
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+ULONG Bitmap::GetChecksum() const
+{
+ ULONG nRet = 0UL;
+
+ if( mpImpBmp )
+ {
+ nRet = mpImpBmp->ImplGetChecksum();
+
+ if( !nRet )
+ {
+ BitmapReadAccess* pRAcc = ( (Bitmap*) this )->AcquireReadAccess();
+
+ if( pRAcc && pRAcc->Width() && pRAcc->Height() )
+ {
+ sal_uInt32 nCrc = 0;
+ SVBT32 aBT32;
+
+ pRAcc->ImplZeroInitUnusedBits();
+
+ LongToSVBT32( pRAcc->Width(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pRAcc->Height(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pRAcc->GetBitCount(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pRAcc->GetColorMask().GetRedMask(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pRAcc->GetColorMask().GetGreenMask(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ LongToSVBT32( pRAcc->GetColorMask().GetBlueMask(), aBT32 );
+ nCrc = rtl_crc32( nCrc, aBT32, 4 );
+
+ if( pRAcc->HasPalette() )
+ {
+ nCrc = rtl_crc32( nCrc, pRAcc->GetPalette().ImplGetColorBuffer(),
+ pRAcc->GetPaletteEntryCount() * sizeof( BitmapColor ) );
+ }
+
+ nCrc = rtl_crc32( nCrc, pRAcc->GetBuffer(), pRAcc->GetScanlineSize() * pRAcc->Height() );
+
+ ( (Bitmap*) this )->ReleaseAccess( pRAcc );
+
+ mpImpBmp->ImplSetChecksum( nRet = nCrc );
+ }
+ }
+ }
+
+ return nRet;
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplReleaseRef()
+{
+ if( mpImpBmp )
+ {
+ if( mpImpBmp->ImplGetRefCount() > 1UL )
+ mpImpBmp->ImplDecRefCount();
+ else
+ {
+ delete mpImpBmp;
+ mpImpBmp = NULL;
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplMakeUnique()
+{
+ if( mpImpBmp && mpImpBmp->ImplGetRefCount() > 1UL )
+ {
+ ImpBitmap* pOldImpBmp = mpImpBmp;
+
+ pOldImpBmp->ImplDecRefCount();
+
+ mpImpBmp = new ImpBitmap;
+ mpImpBmp->ImplCreate( *pOldImpBmp );
+ }
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplAssignWithSize( const Bitmap& rBitmap )
+{
+ const Size aOldSizePix( GetSizePixel() );
+ const Size aNewSizePix( rBitmap.GetSizePixel() );
+ const MapMode aOldMapMode( maPrefMapMode );
+ Size aNewPrefSize;
+
+ if( ( aOldSizePix != aNewSizePix ) && aOldSizePix.Width() && aOldSizePix.Height() )
+ {
+ aNewPrefSize.Width() = FRound( maPrefSize.Width() * aNewSizePix.Width() / aOldSizePix.Width() );
+ aNewPrefSize.Height() = FRound( maPrefSize.Height() * aNewSizePix.Height() / aOldSizePix.Height() );
+ }
+ else
+ aNewPrefSize = maPrefSize;
+
+ *this = rBitmap;
+
+ maPrefSize = aNewPrefSize;
+ maPrefMapMode = aOldMapMode;
+}
+
+// ------------------------------------------------------------------
+
+ImpBitmap* Bitmap::ImplGetImpBitmap() const
+{
+ return mpImpBmp;
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplSetImpBitmap( ImpBitmap* pImpBmp )
+{
+ if( pImpBmp != mpImpBmp )
+ {
+ ImplReleaseRef();
+ mpImpBmp = pImpBmp;
+ }
+}
+
+// ------------------------------------------------------------------
+
+BitmapReadAccess* Bitmap::AcquireReadAccess()
+{
+#ifdef REMOTE_APPSERVER
+ BOOL bGottenFromServer = FALSE;
+ if( mpImpBmp && mpImpBmp->ImplIsGetPrepared() )
+ mpImpBmp->ImplResolveGet(), bGottenFromServer = TRUE;
+#endif
+
+ BitmapReadAccess* pReadAccess = new BitmapReadAccess( *this );
+
+ if( !*pReadAccess )
+ {
+ delete pReadAccess;
+ pReadAccess = NULL;
+ }
+
+#ifdef REMOTE_APPSERVER
+ if( pReadAccess && mpImpBmp && bGottenFromServer )
+ mpImpBmp->ImplReleaseRemoteBmp();
+#endif
+
+ return pReadAccess;
+}
+
+// ------------------------------------------------------------------
+
+BitmapWriteAccess* Bitmap::AcquireWriteAccess()
+{
+#ifdef REMOTE_APPSERVER
+ if( mpImpBmp && mpImpBmp->ImplIsGetPrepared() )
+ mpImpBmp->ImplResolveGet();
+#endif
+
+ BitmapWriteAccess* pWriteAccess = new BitmapWriteAccess( *this );
+
+ if( !*pWriteAccess )
+ {
+ delete pWriteAccess;
+ pWriteAccess = NULL;
+ }
+
+#ifdef REMOTE_APPSERVER
+ if( pWriteAccess && mpImpBmp )
+ mpImpBmp->ImplReleaseRemoteBmp();
+#endif
+
+ return pWriteAccess;
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ReleaseAccess( BitmapReadAccess* pBitmapAccess )
+{
+ delete pBitmapAccess;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Erase( const Color& rFillColor )
+{
+ BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pWriteAcc )
+ {
+ const ULONG nFormat = pWriteAcc->GetScanlineFormat();
+ BYTE cIndex;
+ BOOL bFast;
+
+ switch( nFormat )
+ {
+ case( BMP_FORMAT_1BIT_MSB_PAL ):
+ case( BMP_FORMAT_1BIT_LSB_PAL ):
+ {
+ cIndex = (BYTE) pWriteAcc->GetBestPaletteIndex( rFillColor );
+ cIndex = ( cIndex ? 255 : 0 );
+ bFast = TRUE;
+ }
+ break;
+
+ case( BMP_FORMAT_4BIT_MSN_PAL ):
+ case( BMP_FORMAT_4BIT_LSN_PAL ):
+ {
+ cIndex = (BYTE) pWriteAcc->GetBestPaletteIndex( rFillColor );
+ cIndex = cIndex | ( cIndex << 4 );
+ bFast = TRUE;
+ }
+ break;
+
+ case( BMP_FORMAT_8BIT_PAL ):
+ {
+ cIndex = (BYTE) pWriteAcc->GetBestPaletteIndex( rFillColor );
+ bFast = TRUE;
+ }
+ break;
+
+ case( BMP_FORMAT_24BIT_TC_BGR ):
+ case( BMP_FORMAT_24BIT_TC_RGB ):
+ {
+ if( ( rFillColor.GetRed() == rFillColor.GetGreen() ) &&
+ ( rFillColor.GetRed() == rFillColor.GetBlue() ) )
+ {
+ cIndex = rFillColor.GetRed();
+ bFast = TRUE;
+ }
+ else
+ bFast = FALSE;
+ }
+ break;
+
+ default:
+ bFast = FALSE;
+ break;
+ }
+
+ if( bFast )
+ {
+ const ULONG nBufSize = pWriteAcc->GetScanlineSize() * pWriteAcc->Height();
+ HMEMSET( pWriteAcc->GetBuffer(), cIndex, nBufSize );
+ }
+ else
+ {
+ Point aTmpPoint;
+ const Rectangle aRect( aTmpPoint, Size( pWriteAcc->Width(), pWriteAcc->Height() ) );
+ pWriteAcc->SetFillColor( rFillColor );
+ pWriteAcc->FillRect( aRect );
+ }
+
+ ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Invert()
+{
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pAcc )
+ {
+ if( pAcc->HasPalette() )
+ {
+ BitmapPalette aBmpPal( pAcc->GetPalette() );
+ const USHORT nCount = aBmpPal.GetEntryCount();
+
+ for( USHORT i = 0; i < nCount; i++ )
+ aBmpPal[ i ].Invert();
+
+ pAcc->SetPalette( aBmpPal );
+ }
+ else
+ {
+ const long nWidth = pAcc->Width();
+ const long nHeight = pAcc->Height();
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ for( long nY = 0L; nY < nHeight; nY++ )
+ pAcc->SetPixel( nY, nX, pAcc->GetPixel( nY, nX ).Invert() );
+ }
+
+ ReleaseAccess( pAcc );
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Mirror( ULONG nMirrorFlags )
+{
+ BOOL bHorz = ( ( nMirrorFlags & BMP_MIRROR_HORZ ) == BMP_MIRROR_HORZ );
+ BOOL bVert = ( ( nMirrorFlags & BMP_MIRROR_VERT ) == BMP_MIRROR_VERT );
+ BOOL bRet = FALSE;
+
+ if( bHorz && !bVert )
+ {
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+
+ if( pAcc )
+ {
+ const long nWidth = pAcc->Width();
+ const long nHeight = pAcc->Height();
+ const long nWidth1 = nWidth - 1L;
+ const long nWidth_2 = nWidth >> 1L;
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L, nOther = nWidth1; nX < nWidth_2; nX++, nOther-- )
+ {
+ const BitmapColor aTemp( pAcc->GetPixel( nY, nX ) );
+
+ pAcc->SetPixel( nY, nX, pAcc->GetPixel( nY, nOther ) );
+ pAcc->SetPixel( nY, nOther, aTemp );
+ }
+ }
+
+ ReleaseAccess( pAcc );
+ bRet = TRUE;
+ }
+ }
+ else if( bVert && !bHorz )
+ {
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+
+ if( pAcc )
+ {
+ const long nScanSize = pAcc->GetScanlineSize();
+ BYTE* pBuffer = new BYTE[ nScanSize ];
+ const long nHeight = pAcc->Height();
+ const long nHeight1 = nHeight - 1L;
+ const long nHeight_2 = nHeight >> 1L;
+
+ for( long nY = 0L, nOther = nHeight1; nY < nHeight_2; nY++, nOther-- )
+ {
+ HMEMCPY( pBuffer, pAcc->GetScanline( nY ), nScanSize );
+ HMEMCPY( pAcc->GetScanline( nY ), pAcc->GetScanline( nOther ), nScanSize );
+ HMEMCPY( pAcc->GetScanline( nOther ), pBuffer, nScanSize );
+ }
+
+ delete[] pBuffer;
+ ReleaseAccess( pAcc );
+ bRet = TRUE;
+ }
+ }
+ else if( bHorz && bVert )
+ {
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+
+ if( pAcc )
+ {
+ const long nWidth = pAcc->Width();
+ const long nWidth1 = nWidth - 1L;
+ const long nHeight = pAcc->Height();
+ long nHeight_2 = nHeight >> 1;
+
+ for( long nY = 0L, nOtherY = nHeight - 1L; nY < nHeight_2; nY++, nOtherY-- )
+ {
+ for( long nX = 0L, nOtherX = nWidth1; nX < nWidth; nX++, nOtherX-- )
+ {
+ const BitmapColor aTemp( pAcc->GetPixel( nY, nX ) );
+
+ pAcc->SetPixel( nY, nX, pAcc->GetPixel( nOtherY, nOtherX ) );
+ pAcc->SetPixel( nOtherY, nOtherX, aTemp );
+ }
+ }
+
+ // ggf. noch mittlere Zeile horizontal spiegeln
+ if( nHeight & 1 )
+ {
+ for( long nX = 0L, nOtherX = nWidth1, nWidth_2 = nWidth >> 1; nX < nWidth_2; nX++, nOtherX-- )
+ {
+ const BitmapColor aTemp( pAcc->GetPixel( nHeight_2, nX ) );
+ pAcc->SetPixel( nHeight_2, nX, pAcc->GetPixel( nHeight_2, nOtherX ) );
+ pAcc->SetPixel( nHeight_2, nOtherX, aTemp );
+ }
+ }
+
+ ReleaseAccess( pAcc );
+ bRet = TRUE;
+ }
+ }
+ else
+ bRet = TRUE;
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Rotate( long nAngle10, const Color& rFillColor )
+{
+ BOOL bRet = FALSE;
+
+ nAngle10 %= 3600L;
+ nAngle10 = ( nAngle10 < 0L ) ? ( 3599L + nAngle10 ) : nAngle10;
+
+ if( !nAngle10 )
+ bRet = TRUE;
+ else if( 1800L == nAngle10 )
+ bRet = Mirror( BMP_MIRROR_HORZ | BMP_MIRROR_VERT );
+ else
+ {
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+ Bitmap aRotatedBmp;
+
+ if( pReadAcc )
+ {
+ const Size aSizePix( GetSizePixel() );
+
+ if( ( 900L == nAngle10 ) || ( 2700L == nAngle10 ) )
+ {
+ const Size aNewSizePix( aSizePix.Height(), aSizePix.Width() );
+ Bitmap aNewBmp( aNewSizePix, GetBitCount(), &pReadAcc->GetPalette() );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const long nWidth = aSizePix.Width();
+ const long nWidth1 = nWidth - 1L;
+ const long nHeight = aSizePix.Height();
+ const long nHeight1 = nHeight - 1L;
+ const long nNewWidth = aNewSizePix.Width();
+ const long nNewHeight = aNewSizePix.Height();
+
+ if( 900L == nAngle10 )
+ {
+ for( long nY = 0L, nOtherX = nWidth1; nY < nNewHeight; nY++, nOtherX-- )
+ for( long nX = 0L, nOtherY = 0L; nX < nNewWidth; nX++ )
+ pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nOtherY++, nOtherX ) );
+ }
+ else if( 2700L == nAngle10 )
+ {
+ for( long nY = 0L, nOtherX = 0L; nY < nNewHeight; nY++, nOtherX++ )
+ for( long nX = 0L, nOtherY = nHeight1; nX < nNewWidth; nX++ )
+ pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nOtherY--, nOtherX ) );
+ }
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ }
+
+ aRotatedBmp = aNewBmp;
+ }
+ else
+ {
+ Point aTmpPoint;
+ Rectangle aTmpRectangle( aTmpPoint, aSizePix );
+ Polygon aPoly( aTmpRectangle );
+ aPoly.Rotate( aTmpPoint, (USHORT) nAngle10 );
+
+ Rectangle aNewBound( aPoly.GetBoundRect() );
+ const Size aNewSizePix( aNewBound.GetSize() );
+ Bitmap aNewBmp( aNewSizePix, GetBitCount(), &pReadAcc->GetPalette() );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const BitmapColor aFillColor( pWriteAcc->GetBestMatchingColor( rFillColor ) );
+ const double fCosAngle = cos( nAngle10 * F_PI1800 );
+ const double fSinAngle = sin( nAngle10 * F_PI1800 );
+ const double fXMin = aNewBound.Left();
+ const double fYMin = aNewBound.Top();
+ const long nWidth = aSizePix.Width();
+ const long nHeight = aSizePix.Height();
+ const long nNewWidth = aNewSizePix.Width();
+ const long nNewHeight = aNewSizePix.Height();
+ long nX;
+ long nY;
+ long nRotX;
+ long nRotY;
+ long nSinY;
+ long nCosY;
+ long* pCosX = new long[ nNewWidth ];
+ long* pSinX = new long[ nNewWidth ];
+ long* pCosY = new long[ nNewHeight ];
+ long* pSinY = new long[ nNewHeight ];
+
+ for ( nX = 0; nX < nNewWidth; nX++ )
+ {
+ const double fTmp = ( fXMin + nX ) * 64.;
+
+ pCosX[ nX ] = FRound( fCosAngle * fTmp );
+ pSinX[ nX ] = FRound( fSinAngle * fTmp );
+ }
+
+ for ( nY = 0; nY < nNewHeight; nY++ )
+ {
+ const double fTmp = ( fYMin + nY ) * 64.;
+
+ pCosY[ nY ] = FRound( fCosAngle * fTmp );
+ pSinY[ nY ] = FRound( fSinAngle * fTmp );
+ }
+
+ for( nY = 0L; nY < nNewHeight; nY++ )
+ {
+ nSinY = pSinY[ nY ];
+ nCosY = pCosY[ nY ];
+
+ for( nX = 0L; nX < nNewWidth; nX++ )
+ {
+ nRotX = ( pCosX[ nX ] - nSinY ) >> 6;
+ nRotY = ( pSinX[ nX ] + nCosY ) >> 6;
+
+ if ( ( nRotX > -1L ) && ( nRotX < nWidth ) && ( nRotY > -1L ) && ( nRotY < nHeight ) )
+ pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nRotY, nRotX ) );
+ else
+ pWriteAcc->SetPixel( nY, nX, aFillColor );
+ }
+ }
+
+ delete[] pSinX;
+ delete[] pCosX;
+ delete[] pSinY;
+ delete[] pCosY;
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ }
+
+ aRotatedBmp = aNewBmp;
+ }
+
+ ReleaseAccess( pReadAcc );
+ }
+
+ if( ( bRet = !!aRotatedBmp ) == TRUE )
+ ImplAssignWithSize( aRotatedBmp );
+ }
+
+ return bRet;
+};
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Crop( const Rectangle& rRectPixel )
+{
+ const Size aSizePix( GetSizePixel() );
+ Rectangle aRect( rRectPixel );
+ BOOL bRet = FALSE;
+
+ aRect.Intersection( Rectangle( Point(), aSizePix ) );
+
+ if( !aRect.IsEmpty() )
+ {
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+
+ if( pReadAcc )
+ {
+ Point aTmpPoint;
+ const Rectangle aNewRect( aTmpPoint, aRect.GetSize() );
+ Bitmap aNewBmp( aNewRect.GetSize(), GetBitCount(), &pReadAcc->GetPalette() );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const long nOldX = aRect.Left();
+ const long nOldY = aRect.Top();
+ const long nNewWidth = aNewRect.GetWidth();
+ const long nNewHeight = aNewRect.GetHeight();
+
+ for( long nY = 0, nY2 = nOldY; nY < nNewHeight; nY++, nY2++ )
+ for( long nX = 0, nX2 = nOldX; nX < nNewWidth; nX++, nX2++ )
+ pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nY2, nX2 ) );
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ ImplAssignWithSize( aNewBmp );
+ }
+ }
+
+ return bRet;
+};
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::CopyPixel( const Rectangle& rRectDst,
+ const Rectangle& rRectSrc, const Bitmap* pBmpSrc )
+{
+ const Size aSizePix( GetSizePixel() );
+ Rectangle aRectDst( rRectDst );
+ BOOL bRet = FALSE;
+
+ aRectDst.Intersection( Rectangle( Point(), aSizePix ) );
+
+ if( !aRectDst.IsEmpty() )
+ {
+ if( pBmpSrc && ( *pBmpSrc != *this ) )
+ {
+ Bitmap* pSrc = (Bitmap*) pBmpSrc;
+ const Size aCopySizePix( pSrc->GetSizePixel() );
+ Rectangle aRectSrc( rRectSrc );
+ const USHORT nSrcBitCount = pBmpSrc->GetBitCount();
+ const USHORT nDstBitCount = GetBitCount();
+
+ if( nSrcBitCount > nDstBitCount )
+ {
+ long nNextIndex = 0L;
+
+ if( ( nSrcBitCount == 24 ) && ( nDstBitCount < 24 ) )
+ Convert( BMP_CONVERSION_24BIT );
+ else if( ( nSrcBitCount == 8 ) && ( nDstBitCount < 8 ) )
+ {
+ Convert( BMP_CONVERSION_8BIT_COLORS );
+ nNextIndex = 16;
+ }
+ else if( ( nSrcBitCount == 4 ) && ( nDstBitCount < 4 ) )
+ {
+ Convert( BMP_CONVERSION_4BIT_COLORS );
+ nNextIndex = 2;
+ }
+
+ if( nNextIndex )
+ {
+ BitmapReadAccess* pSrcAcc = pSrc->AcquireReadAccess();
+ BitmapWriteAccess* pDstAcc = AcquireWriteAccess();
+
+ if( pSrcAcc && pDstAcc )
+ {
+ const long nSrcCount = pDstAcc->GetPaletteEntryCount();
+ const long nDstCount = 1 << nDstBitCount;
+ BOOL bFound;
+
+ for( long i = 0L; ( i < nSrcCount ) && ( nNextIndex < nSrcCount ); i++ )
+ {
+ const BitmapColor& rSrcCol = pSrcAcc->GetPaletteColor( (USHORT) i );
+
+ bFound = FALSE;
+
+ for( long j = 0L; j < nDstCount; j++ )
+ {
+ if( rSrcCol == pDstAcc->GetPaletteColor( (USHORT) j ) )
+ {
+ bFound = TRUE;
+ break;
+ }
+ }
+
+ if( !bFound )
+ pDstAcc->SetPaletteColor( (USHORT) nNextIndex++, rSrcCol );
+ }
+ }
+
+ if( pSrcAcc )
+ pSrc->ReleaseAccess( pSrcAcc );
+
+ if( pDstAcc )
+ ReleaseAccess( pDstAcc );
+ }
+ }
+
+ aRectSrc.Intersection( Rectangle( Point(), aCopySizePix ) );
+
+ if( !aRectSrc.IsEmpty() )
+ {
+ BitmapReadAccess* pReadAcc = pSrc->AcquireReadAccess();
+
+ if( pReadAcc )
+ {
+ BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const long nWidth = Min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
+ const long nHeight = Min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
+ const long nSrcEndX = aRectSrc.Left() + nWidth;
+ const long nSrcEndY = aRectSrc.Top() + nHeight;
+ long nDstY = aRectDst.Top();
+
+ if( pReadAcc->HasPalette() && pWriteAcc->HasPalette() )
+ {
+ const USHORT nCount = pReadAcc->GetPaletteEntryCount();
+ BYTE* pMap = new BYTE[ nCount ];
+
+ // Index-Map fuer Farbtabelle
+ // aufbauen, da das Bild ja (relativ) farbgenau
+ // kopiert werden soll
+ for( USHORT i = 0; i < nCount; i++ )
+ pMap[ i ] = (BYTE) pWriteAcc->GetBestPaletteIndex( pReadAcc->GetPaletteColor( i ) );
+
+ for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
+ for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
+ pWriteAcc->SetPixel( nDstY, nDstX, pMap[ pReadAcc->GetPixel( nSrcY, nSrcX ).GetIndex() ] );
+
+ delete[] pMap;
+ }
+ else if( pReadAcc->HasPalette() )
+ {
+ }
+ else
+ for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
+ for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
+ pWriteAcc->SetPixel( nDstY, nDstX, pReadAcc->GetPixel( nSrcY, nSrcX ) );
+
+ ReleaseAccess( pWriteAcc );
+ bRet = ( nWidth > 0L ) && ( nHeight > 0L );
+ }
+
+ pSrc->ReleaseAccess( pReadAcc );
+ }
+ }
+ }
+ else
+ {
+ Rectangle aRectSrc( rRectSrc );
+
+ aRectSrc.Intersection( Rectangle( Point(), aSizePix ) );
+
+ if( !aRectSrc.IsEmpty() && ( aRectSrc != aRectDst ) )
+ {
+ BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ const long nWidth = Min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
+ const long nHeight = Min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
+ const long nSrcX = aRectSrc.Left();
+ const long nSrcY = aRectSrc.Top();
+ const long nSrcEndX1 = nSrcX + nWidth - 1L;
+ const long nSrcEndY1 = nSrcY + nHeight - 1L;
+ const long nDstX = aRectDst.Left();
+ const long nDstY = aRectDst.Top();
+ const long nDstEndX1 = nDstX + nWidth - 1L;
+ const long nDstEndY1 = nDstY + nHeight - 1L;
+
+ if( ( nDstX <= nSrcX ) && ( nDstY <= nSrcY ) )
+ {
+ for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
+ for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
+ pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
+ }
+ else if( ( nDstX <= nSrcX ) && ( nDstY >= nSrcY ) )
+ {
+ for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
+ for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
+ pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
+ }
+ else if( ( nDstX >= nSrcX ) && ( nDstY <= nSrcY ) )
+ {
+ for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
+ for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
+ pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
+ }
+ else
+ {
+ for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
+ for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
+ pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
+ }
+
+ ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+ }
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Expand( ULONG nDX, ULONG nDY, const Color* pInitColor )
+{
+ BOOL bRet = FALSE;
+
+ if( nDX || nDY )
+ {
+ const Size aSizePixel( GetSizePixel() );
+ const long nWidth = aSizePixel.Width();
+ const long nHeight = aSizePixel.Height();
+ const Size aNewSize( nWidth + nDX, nHeight + nDY );
+ BitmapReadAccess* pReadAcc = AcquireReadAccess();
+
+ if( pReadAcc )
+ {
+// Was soll den das ?
+// BitmapPalette aBmpPal( pReadAcc ? pReadAcc->GetPalette() : BitmapPalette() );
+ BitmapPalette aBmpPal( pReadAcc->GetPalette() );
+ Bitmap aNewBmp( aNewSize, GetBitCount(), &aBmpPal );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+
+ if( pWriteAcc )
+ {
+ BitmapColor aColor;
+ const ULONG nScanlineSize = pReadAcc->GetScanlineSize();
+ const long nNewX = nWidth;
+ const long nNewY = nHeight;
+ const long nNewWidth = pWriteAcc->Width();
+ const long nNewHeight = pWriteAcc->Height();
+ long nX;
+ long nY;
+
+ if( pInitColor )
+ aColor = pWriteAcc->GetBestMatchingColor( *pInitColor );
+
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ pWriteAcc->CopyScanline( nY, *pReadAcc );
+
+ if( pInitColor && nDX )
+ for( nX = nNewX; nX < nNewWidth; nX++ )
+ pWriteAcc->SetPixel( nY, nX, aColor );
+ }
+
+ if( pInitColor && nDY )
+ for( nY = nNewY; nY < nNewHeight; nY++ )
+ for( nX = nNewX; nX < nNewWidth; nX++ )
+ pWriteAcc->SetPixel( nY, nX, aColor );
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pReadAcc );
+
+ if( bRet )
+ ImplAssignWithSize( aNewBmp );
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+Bitmap Bitmap::CreateMask( const Color& rTransColor, ULONG nTol ) const
+{
+ Bitmap aNewBmp( GetSizePixel(), 1 );
+ BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pWriteAcc )
+ {
+ BitmapReadAccess* pReadAcc = ( (Bitmap*) this )->AcquireReadAccess();
+
+ if( pReadAcc )
+ {
+ const long nWidth = pReadAcc->Width();
+ const long nHeight = pReadAcc->Height();
+ const BitmapColor aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
+ const BitmapColor aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+
+ if( !nTol )
+ {
+ const BitmapColor aTest( pReadAcc->GetBestMatchingColor( rTransColor ) );
+ long nX, nY, nShift;
+
+ if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_MSN_PAL ||
+ pReadAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_LSN_PAL )
+ {
+ // optimized for 4Bit-MSN/LSN source palette
+ const BYTE cTest = aTest.GetIndex();
+ const long nShiftInit = ( ( pReadAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_MSN_PAL ) ? 4 : 0 );
+
+ if( pWriteAcc->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
+ aWhite.GetIndex() == 1 )
+ {
+ // optimized for 1Bit-MSB destination palette
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ Scanline pSrc = pReadAcc->GetScanline( nY );
+ Scanline pDst = pWriteAcc->GetScanline( nY );
+ for( nX = 0L, nShift = nShiftInit; nX < nWidth; nX++, nShift ^= 4 )
+ {
+ if( cTest == ( ( pSrc[ nX >> 1 ] >> nShift ) & 0x0f ) )
+ pDst[ nX >> 3 ] |= 1 << ( 7 - ( nX & 7 ) );
+ else
+ pDst[ nX >> 3 ] &= ~( 1 << ( 7 - ( nX & 7 ) ) );
+ }
+ }
+ }
+ else
+ {
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ Scanline pSrc = pReadAcc->GetScanline( nY );
+ for( nX = 0L, nShift = nShiftInit; nX < nWidth; nX++, nShift ^= 4 )
+ {
+ if( cTest == ( ( pSrc[ nX >> 1 ] >> nShift ) & 0x0f ) )
+ pWriteAcc->SetPixel( nY, nX, aWhite );
+ else
+ pWriteAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ }
+ }
+ else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
+ {
+ // optimized for 8Bit source palette
+ const BYTE cTest = aTest.GetIndex();
+
+ if( pWriteAcc->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
+ aWhite.GetIndex() == 1 )
+ {
+ // optimized for 1Bit-MSB destination palette
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ Scanline pSrc = pReadAcc->GetScanline( nY );
+ Scanline pDst = pWriteAcc->GetScanline( nY );
+ for( nX = 0L; nX < nWidth; nX++ )
+ {
+ if( cTest == pSrc[ nX ] )
+ pDst[ nX >> 3 ] |= 1 << ( 7 - ( nX & 7 ) );
+ else
+ pDst[ nX >> 3 ] &= ~( 1 << ( 7 - ( nX & 7 ) ) );
+ }
+ }
+ }
+ else
+ {
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ Scanline pSrc = pReadAcc->GetScanline( nY );
+ for( nX = 0L; nX < nWidth; nX++ )
+ {
+ if( cTest == pSrc[ nX ] )
+ pWriteAcc->SetPixel( nY, nX, aWhite );
+ else
+ pWriteAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ }
+ }
+ else
+ {
+ // not optimized
+ for( nY = 0L; nY < nHeight; nY++ )
+ {
+ for( nX = 0L; nX < nWidth; nX++ )
+ {
+ if( aTest == pReadAcc->GetPixel( nY, nX ) )
+ pWriteAcc->SetPixel( nY, nX, aWhite );
+ else
+ pWriteAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ }
+ }
+ else
+ {
+ BitmapColor aCol;
+ long nR, nG, nB;
+ const long nMinR = MinMax( (long) rTransColor.GetRed() - nTol, 0, 255 );
+ const long nMaxR = MinMax( (long) rTransColor.GetRed() + nTol, 0, 255 );
+ const long nMinG = MinMax( (long) rTransColor.GetGreen() - nTol, 0, 255 );
+ const long nMaxG = MinMax( (long) rTransColor.GetGreen() + nTol, 0, 255 );
+ const long nMinB = MinMax( (long) rTransColor.GetBlue() - nTol, 0, 255 );
+ const long nMaxB = MinMax( (long) rTransColor.GetBlue() + nTol, 0, 255 );
+
+ if( pReadAcc->HasPalette() )
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aCol = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nX ) );
+ nR = aCol.GetRed();
+ nG = aCol.GetGreen();
+ nB = aCol.GetBlue();
+
+ if( nMinR <= nR && nMaxR >= nR &&
+ nMinG <= nG && nMaxG >= nG &&
+ nMinB <= nB && nMaxB >= nB )
+ {
+ pWriteAcc->SetPixel( nY, nX, aWhite );
+ }
+ else
+ pWriteAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ }
+ else
+ {
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aCol = pReadAcc->GetPixel( nY, nX );
+ nR = aCol.GetRed();
+ nG = aCol.GetGreen();
+ nB = aCol.GetBlue();
+
+ if( nMinR <= nR && nMaxR >= nR &&
+ nMinG <= nG && nMaxG >= nG &&
+ nMinB <= nB && nMaxB >= nB )
+ {
+ pWriteAcc->SetPixel( nY, nX, aWhite );
+ }
+ else
+ pWriteAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ }
+ }
+
+ ( (Bitmap*) this )->ReleaseAccess( pReadAcc );
+ bRet = TRUE;
+ }
+
+ aNewBmp.ReleaseAccess( pWriteAcc );
+ }
+
+ if( bRet )
+ {
+ aNewBmp.maPrefSize = maPrefSize;
+ aNewBmp.maPrefMapMode = maPrefMapMode;
+ }
+ else
+ aNewBmp = Bitmap();
+
+ return aNewBmp;
+}
+
+// ------------------------------------------------------------------
+
+Region Bitmap::CreateRegion( const Color& rColor, const Rectangle& rRect ) const
+{
+ Region aRegion;
+ Rectangle aRect( rRect );
+ BitmapReadAccess* pReadAcc = ( (Bitmap*) this )->AcquireReadAccess();
+
+ aRect.Intersection( Rectangle( Point(), GetSizePixel() ) );
+ aRect.Justify();
+
+ if( pReadAcc )
+ {
+ Rectangle aSubRect;
+ const long nLeft = aRect.Left();
+ const long nTop = aRect.Top();
+ const long nRight = aRect.Right();
+ const long nBottom = aRect.Bottom();
+ const BitmapColor aMatch( pReadAcc->GetBestMatchingColor( rColor ) );
+
+ aRegion.ImplBeginAddRect();
+
+ for( long nY = nTop; nY <= nBottom; nY++ )
+ {
+ aSubRect.Top() = aSubRect.Bottom() = nY;
+
+ for( long nX = nLeft; nX <= nRight; )
+ {
+ while( ( nX <= nRight ) && ( aMatch != pReadAcc->GetPixel( nY, nX ) ) )
+ nX++;
+
+ if( nX <= nRight )
+ {
+ aSubRect.Left() = nX;
+
+ while( ( nX <= nRight ) && ( aMatch == pReadAcc->GetPixel( nY, nX ) ) )
+ nX++;
+
+ aSubRect.Right() = nX - 1L;
+ aRegion.ImplAddRect( aSubRect );
+ }
+ }
+ }
+
+ aRegion.ImplEndAddRect();
+ ( (Bitmap*) this )->ReleaseAccess( pReadAcc );
+ }
+ else
+ aRegion = aRect;
+
+ return aRegion;
+}
+
+//fuer WIN16 Borland
+#ifdef WIN
+#pragma codeseg BITMAP_SEG1
+#endif
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Replace( const Bitmap& rMask, const Color& rReplaceColor )
+{
+ BitmapReadAccess* pMaskAcc = ( (Bitmap&) rMask ).AcquireReadAccess();
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pMaskAcc && pAcc )
+ {
+ const long nWidth = Min( pMaskAcc->Width(), pAcc->Width() );
+ const long nHeight = Min( pMaskAcc->Height(), pAcc->Height() );
+ const BitmapColor aMaskWhite( pMaskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+ BitmapColor aReplace;
+
+ if( pAcc->HasPalette() )
+ {
+ const USHORT nActColors = pAcc->GetPaletteEntryCount();
+ const USHORT nMaxColors = 1 << pAcc->GetBitCount();
+
+ // erst einmal naechste Farbe nehmen
+ aReplace = pAcc->GetBestMatchingColor( rReplaceColor );
+
+ // falls Palettenbild, und die zu setzende Farbe ist nicht
+ // in der Palette, suchen wir nach freien Eintraegen (teuer)
+ if( pAcc->GetPaletteColor( (BYTE) aReplace ) != BitmapColor( rReplaceColor ) )
+ {
+ // erst einmal nachsehen, ob wir unsere ReplaceColor
+ // nicht auf einen freien Platz am Ende der Palette
+ // setzen koennen
+ if( nActColors < nMaxColors )
+ {
+ pAcc->SetPaletteEntryCount( nActColors + 1 );
+ pAcc->SetPaletteColor( nActColors, rReplaceColor );
+ aReplace = BitmapColor( (BYTE) nActColors );
+ }
+ else
+ {
+ BOOL* pFlags = new BOOL[ nMaxColors ];
+
+ // alle Eintraege auf 0 setzen
+ memset( pFlags, 0, nMaxColors );
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ for( long nX = 0L; nX < nWidth; nX++ )
+ pFlags[ (BYTE) pAcc->GetPixel( nY, nX ) ] = TRUE;
+
+ for( USHORT i = 0UL; i < nMaxColors; i++ )
+ {
+ // Hurra, wir haben einen unbenutzten Eintrag
+ if( !pFlags[ i ] )
+ {
+ pAcc->SetPaletteColor( (USHORT) i, rReplaceColor );
+ aReplace = BitmapColor( (BYTE) i );
+ }
+ }
+
+ delete[] pFlags;
+ }
+ }
+ }
+ else
+ aReplace = rReplaceColor;
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ for( long nX = 0L; nX < nWidth; nX++ )
+ if( pMaskAcc->GetPixel( nY, nX ) == aMaskWhite )
+ pAcc->SetPixel( nY, nX, aReplace );
+ }
+
+ ( (Bitmap&) rMask ).ReleaseAccess( pMaskAcc );
+ ReleaseAccess( pAcc );
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Replace( const AlphaMask& rAlpha, const Color& rMergeColor )
+{
+ Bitmap aNewBmp( GetSizePixel(), 24 );
+ BitmapReadAccess* pAcc = AcquireReadAccess();
+ BitmapReadAccess* pAlphaAcc = ( (AlphaMask&) rAlpha ).AcquireReadAccess();
+ BitmapWriteAccess* pNewAcc = aNewBmp.AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pAcc && pAlphaAcc && pNewAcc )
+ {
+ BitmapColor aCol;
+ const long nWidth = Min( pAlphaAcc->Width(), pAcc->Width() );
+ const long nHeight = Min( pAlphaAcc->Height(), pAcc->Height() );
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aCol = pAcc->GetColor( nY, nX );
+ pNewAcc->SetPixel( nY, nX, aCol.Merge( rMergeColor, 255 - (BYTE) pAlphaAcc->GetPixel( nY, nX ) ) );
+ }
+ }
+
+ bRet = TRUE;
+ }
+
+ ReleaseAccess( pAcc );
+ ( (AlphaMask&) rAlpha ).ReleaseAccess( pAlphaAcc );
+ aNewBmp.ReleaseAccess( pNewAcc );
+
+ if( bRet )
+ {
+ const MapMode aMap( maPrefMapMode );
+ const Size aSize( maPrefSize );
+
+ *this = aNewBmp;
+
+ maPrefMapMode = aMap;
+ maPrefSize = aSize;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Replace( const Color& rSearchColor, const Color& rReplaceColor, ULONG nTol )
+{
+ // Bitmaps with 1 bit color depth can cause problems
+ // if they have other entries than black/white in their palette
+ if( 1 == GetBitCount() )
+ Convert( BMP_CONVERSION_4BIT_COLORS );
+
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pAcc )
+ {
+ const long nMinR = MinMax( (long) rSearchColor.GetRed() - nTol, 0, 255 );
+ const long nMaxR = MinMax( (long) rSearchColor.GetRed() + nTol, 0, 255 );
+ const long nMinG = MinMax( (long) rSearchColor.GetGreen() - nTol, 0, 255 );
+ const long nMaxG = MinMax( (long) rSearchColor.GetGreen() + nTol, 0, 255 );
+ const long nMinB = MinMax( (long) rSearchColor.GetBlue() - nTol, 0, 255 );
+ const long nMaxB = MinMax( (long) rSearchColor.GetBlue() + nTol, 0, 255 );
+
+ if( pAcc->HasPalette() )
+ {
+ for( USHORT i = 0, nPalCount = pAcc->GetPaletteEntryCount(); i < nPalCount; i++ )
+ {
+ const BitmapColor& rCol = pAcc->GetPaletteColor( i );
+
+ if( nMinR <= rCol.GetRed() && nMaxR >= rCol.GetRed() &&
+ nMinG <= rCol.GetGreen() && nMaxG >= rCol.GetGreen() &&
+ nMinB <= rCol.GetBlue() && nMaxB >= rCol.GetBlue() )
+ {
+ pAcc->SetPaletteColor( i, rReplaceColor );
+ }
+ }
+ }
+ else
+ {
+ BitmapColor aCol;
+ const BitmapColor aReplace( pAcc->GetBestMatchingColor( rReplaceColor ) );
+
+ for( long nY = 0L, nHeight = pAcc->Height(); nY < nHeight; nY++ )
+ {
+ for( long nX = 0L, nWidth = pAcc->Width(); nX < nWidth; nX++ )
+ {
+ aCol = pAcc->GetPixel( nY, nX );
+
+ if( nMinR <= aCol.GetRed() && nMaxR >= aCol.GetRed() &&
+ nMinG <= aCol.GetGreen() && nMaxG >= aCol.GetGreen() &&
+ nMinB <= aCol.GetBlue() && nMaxB >= aCol.GetBlue() )
+ {
+ pAcc->SetPixel( nY, nX, aReplace );
+ }
+ }
+ }
+ }
+
+ ReleaseAccess( pAcc );
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::Replace( const Color* pSearchColors, const Color* pReplaceColors,
+ ULONG nColorCount, ULONG* _pTols )
+{
+ // Bitmaps with 1 bit color depth can cause problems
+ // if they have other entries than black/white in their palette
+ if( 1 == GetBitCount() )
+ Convert( BMP_CONVERSION_4BIT_COLORS );
+
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pAcc )
+ {
+ long* pMinR = new long[ nColorCount ];
+ long* pMaxR = new long[ nColorCount ];
+ long* pMinG = new long[ nColorCount ];
+ long* pMaxG = new long[ nColorCount ];
+ long* pMinB = new long[ nColorCount ];
+ long* pMaxB = new long[ nColorCount ];
+ long* pTols;
+ ULONG i;
+
+ if( !_pTols )
+ {
+ pTols = new long[ nColorCount ];
+ memset( pTols, 0, nColorCount * sizeof( long ) );
+ }
+ else
+ pTols = (long*) _pTols;
+
+ for( i = 0UL; i < nColorCount; i++ )
+ {
+ const Color& rCol = pSearchColors[ i ];
+ const long nTol = pTols[ i ];
+
+ pMinR[ i ] = MinMax( (long) rCol.GetRed() - nTol, 0, 255 );
+ pMaxR[ i ] = MinMax( (long) rCol.GetRed() + nTol, 0, 255 );
+ pMinG[ i ] = MinMax( (long) rCol.GetGreen() - nTol, 0, 255 );
+ pMaxG[ i ] = MinMax( (long) rCol.GetGreen() + nTol, 0, 255 );
+ pMinB[ i ] = MinMax( (long) rCol.GetBlue() - nTol, 0, 255 );
+ pMaxB[ i ] = MinMax( (long) rCol.GetBlue() + nTol, 0, 255 );
+ }
+
+ if( pAcc->HasPalette() )
+ {
+ for( USHORT nEntry = 0, nPalCount = pAcc->GetPaletteEntryCount(); nEntry < nPalCount; nEntry++ )
+ {
+ const BitmapColor& rCol = pAcc->GetPaletteColor( nEntry );
+
+ for( i = 0UL; i < nColorCount; i++ )
+ {
+ if( pMinR[ i ] <= rCol.GetRed() && pMaxR[ i ] >= rCol.GetRed() &&
+ pMinG[ i ] <= rCol.GetGreen() && pMaxG[ i ] >= rCol.GetGreen() &&
+ pMinB[ i ] <= rCol.GetBlue() && pMaxB[ i ] >= rCol.GetBlue() )
+ {
+ pAcc->SetPaletteColor( (USHORT)nEntry, pReplaceColors[ i ] );
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ BitmapColor aCol;
+ BitmapColor* pReplaces = new BitmapColor[ nColorCount ];
+
+ for( i = 0UL; i < nColorCount; i++ )
+ pReplaces[ i ] = pAcc->GetBestMatchingColor( pReplaceColors[ i ] );
+
+ for( long nY = 0L, nHeight = pAcc->Height(); nY < nHeight; nY++ )
+ {
+ for( long nX = 0L, nWidth = pAcc->Width(); nX < nWidth; nX++ )
+ {
+ aCol = pAcc->GetPixel( nY, nX );
+
+ for( i = 0UL; i < nColorCount; i++ )
+ {
+ if( pMinR[ i ] <= aCol.GetRed() && pMaxR[ i ] >= aCol.GetRed() &&
+ pMinG[ i ] <= aCol.GetGreen() && pMaxG[ i ] >= aCol.GetGreen() &&
+ pMinB[ i ] <= aCol.GetBlue() && pMaxB[ i ] >= aCol.GetBlue() )
+ {
+ pAcc->SetPixel( nY, nX, pReplaces[ i ] );
+ break;
+ }
+ }
+ }
+ }
+
+ delete[] pReplaces;
+ }
+
+ if( !_pTols )
+ delete[] pTols;
+
+ delete[] pMinR;
+ delete[] pMaxR;
+ delete[] pMinG;
+ delete[] pMaxG;
+ delete[] pMinB;
+ delete[] pMaxB;
+ ReleaseAccess( pAcc );
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+Bitmap Bitmap::CreateDisplayBitmap( OutputDevice* pDisplay )
+{
+ Bitmap aDispBmp( *this );
+
+#ifndef REMOTE_APPSERVER
+ if( mpImpBmp && ( pDisplay->mpGraphics || pDisplay->ImplGetGraphics() ) )
+ {
+ ImpBitmap* pImpDispBmp = new ImpBitmap;
+
+ if( pImpDispBmp->ImplCreate( *mpImpBmp, pDisplay->mpGraphics ) )
+ aDispBmp.ImplSetImpBitmap( pImpDispBmp );
+ else
+ delete pImpDispBmp;
+ }
+#endif
+
+ return aDispBmp;
+}
+
+// ------------------------------------------------------------------
+
+BOOL Bitmap::CombineSimple( const Bitmap& rMask, BmpCombine eCombine )
+{
+ BitmapReadAccess* pMaskAcc = ( (Bitmap&) rMask ).AcquireReadAccess();
+ BitmapWriteAccess* pAcc = AcquireWriteAccess();
+ BOOL bRet = FALSE;
+
+ if( pMaskAcc && pAcc )
+ {
+ const long nWidth = Min( pMaskAcc->Width(), pAcc->Width() );
+ const long nHeight = Min( pMaskAcc->Height(), pAcc->Height() );
+ const Color aColBlack( COL_BLACK );
+ BitmapColor aPixel;
+ BitmapColor aMaskPixel;
+ const BitmapColor aWhite( pAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
+ const BitmapColor aBlack( pAcc->GetBestMatchingColor( aColBlack ) );
+ const BitmapColor aMaskBlack( pMaskAcc->GetBestMatchingColor( aColBlack ) );
+
+ switch( eCombine )
+ {
+ case( BMP_COMBINE_COPY ):
+ {
+ for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pMaskAcc->GetPixel( nY, nX ) == aMaskBlack )
+ pAcc->SetPixel( nY, nX, aBlack );
+ else
+ pAcc->SetPixel( nY, nX, aWhite );
+ }
+ }
+ break;
+
+ case( BMP_COMBINE_INVERT ):
+ {
+ for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pAcc->GetPixel( nY, nX ) == aBlack )
+ pAcc->SetPixel( nY, nX, aWhite );
+ else
+ pAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ break;
+
+ case( BMP_COMBINE_AND ):
+ {
+ for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack && pAcc->GetPixel( nY, nX ) != aBlack )
+ pAcc->SetPixel( nY, nX, aWhite );
+ else
+ pAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ break;
+
+ case( BMP_COMBINE_NAND ):
+ {
+ for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack && pAcc->GetPixel( nY, nX ) != aBlack )
+ pAcc->SetPixel( nY, nX, aBlack );
+ else
+ pAcc->SetPixel( nY, nX, aWhite );
+ }
+ }
+ break;
+
+ case( BMP_COMBINE_OR ):
+ {
+ for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack || pAcc->GetPixel( nY, nX ) != aBlack )
+ pAcc->SetPixel( nY, nX, aWhite );
+ else
+ pAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ break;
+
+ case( BMP_COMBINE_NOR ):
+ {
+ for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack || pAcc->GetPixel( nY, nX ) != aBlack )
+ pAcc->SetPixel( nY, nX, aBlack );
+ else
+ pAcc->SetPixel( nY, nX, aWhite );
+ }
+ }
+ break;
+
+ case( BMP_COMBINE_XOR ):
+ {
+ for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aPixel = pAcc->GetPixel( nY, nX );
+ aMaskPixel = pMaskAcc->GetPixel( nY, nX );
+
+ if( ( aMaskPixel != aMaskBlack && aPixel == aBlack ) ||
+ ( aMaskPixel == aMaskBlack && aPixel != aBlack ) )
+ {
+ pAcc->SetPixel( nY, nX, aWhite );
+ }
+ else
+ pAcc->SetPixel( nY, nX, aBlack );
+ }
+ }
+ break;
+
+ case( BMP_COMBINE_NXOR ):
+ {
+ for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aPixel = pAcc->GetPixel( nY, nX );
+ aMaskPixel = pMaskAcc->GetPixel( nY, nX );
+
+ if( ( aMaskPixel != aMaskBlack && aPixel == aBlack ) ||
+ ( aMaskPixel == aMaskBlack && aPixel != aBlack ) )
+ {
+ pAcc->SetPixel( nY, nX, aBlack );
+ }
+ else
+ pAcc->SetPixel( nY, nX, aWhite );
+ }
+ }
+ break;
+ }
+ }
+
+ ( (Bitmap&) rMask ).ReleaseAccess( pMaskAcc );
+ ReleaseAccess( pAcc );
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------
+
+#ifdef REMOTE_APPSERVER
+
+void Bitmap::ImplDrawRemote( OutputDevice* pOut,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Point& rDestPt, const Size& rDestSz ) const
+{
+ if( mpImpBmp )
+ {
+ if( !mpImpBmp->ImplGetRemoteBmp() )
+ mpImpBmp->ImplCreateRemoteBmp( *this );
+
+ mpImpBmp->ImplDrawRemoteBmp( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz );
+ }
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplDrawRemoteEx( OutputDevice* pOut,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Point& rDestPt, const Size& rDestSz,
+ const Bitmap& rMask ) const
+{
+ if( mpImpBmp )
+ {
+ if( !mpImpBmp->ImplGetRemoteBmp() )
+ mpImpBmp->ImplCreateRemoteBmp( *this );
+
+ mpImpBmp->ImplDrawRemoteBmpEx( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz, rMask );
+ }
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplDrawRemoteAlpha( OutputDevice* pOut,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Point& rDestPt, const Size& rDestSz,
+ const AlphaMask& rAlpha ) const
+{
+ if( mpImpBmp )
+ {
+ if( !mpImpBmp->ImplGetRemoteBmp() )
+ mpImpBmp->ImplCreateRemoteBmp( *this );
+
+ mpImpBmp->ImplDrawRemoteBmpAlpha( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz, rAlpha );
+ }
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplDrawRemoteMask( OutputDevice* pOut,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const Point& rDestPt, const Size& rDestSz,
+ const Color& rColor ) const
+{
+ if( mpImpBmp )
+ {
+ if( !mpImpBmp->ImplGetRemoteBmp() )
+ mpImpBmp->ImplCreateRemoteBmp( *this );
+
+ mpImpBmp->ImplDrawRemoteBmpMask( pOut, rSrcPt, rSrcSz, rDestPt, rDestSz, rColor );
+ }
+}
+
+// ------------------------------------------------------------------
+
+void Bitmap::ImplGetRemoteBmp( OutputDevice* pOut, const Point& rPt, const Size& rSz )
+{
+ DBG_ASSERT( !mpImpBmp, "Bitmap::ImplGetRemoteBmp???" );
+
+ mpImpBmp = new ImpBitmap;
+ mpImpBmp->ImplCreateRemoteBmp( *this, pOut, rPt, rSz );
+}
+
+#endif