/************************************************************** * * 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 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_vcl.hxx" #include #include #include #include // ------------- // - AlphaMask - // ------------- AlphaMask::AlphaMask() { } // ----------------------------------------------------------------------------- AlphaMask::AlphaMask( const Bitmap& rBitmap ) : Bitmap( rBitmap ) { if( !!rBitmap ) Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS ); } // ----------------------------------------------------------------------------- AlphaMask::AlphaMask( const AlphaMask& rAlphaMask ) : Bitmap( rAlphaMask ) { } // ----------------------------------------------------------------------------- AlphaMask::AlphaMask( const Size& rSizePixel, sal_uInt8* pEraseTransparency ) : Bitmap( rSizePixel, 8, &Bitmap::GetGreyPalette( 256 ) ) { if( pEraseTransparency ) Bitmap::Erase( Color( *pEraseTransparency, *pEraseTransparency, *pEraseTransparency ) ); } // ----------------------------------------------------------------------------- AlphaMask::~AlphaMask() { } // ----------------------------------------------------------------------------- AlphaMask& AlphaMask::operator=( const Bitmap& rBitmap ) { *(Bitmap*) this = rBitmap; if( !!rBitmap ) Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS ); return *this; } // ----------------------------------------------------------------------------- const Bitmap& AlphaMask::ImplGetBitmap() const { return( (const Bitmap&) *this ); } // ----------------------------------------------------------------------------- void AlphaMask::ImplSetBitmap( const Bitmap& rBitmap ) { DBG_ASSERT( ( 8 == rBitmap.GetBitCount() ) && rBitmap.HasGreyPalette(), "AlphaMask::ImplSetBitmap: invalid bitmap" ); *(Bitmap*) this = rBitmap; } // ----------------------------------------------------------------------------- Bitmap AlphaMask::GetBitmap() const { return ImplGetBitmap(); } // ----------------------------------------------------------------------------- sal_Bool AlphaMask::Crop( const Rectangle& rRectPixel ) { return Bitmap::Crop( rRectPixel ); } // ----------------------------------------------------------------------------- sal_Bool AlphaMask::Expand( sal_uLong nDX, sal_uLong nDY, sal_uInt8* pInitTransparency ) { Color aColor; if( pInitTransparency ) aColor = Color( *pInitTransparency, *pInitTransparency, *pInitTransparency ); return Bitmap::Expand( nDX, nDY, pInitTransparency ? &aColor : NULL ); } // ----------------------------------------------------------------------------- sal_Bool AlphaMask::CopyPixel( const Rectangle& rRectDst, const Rectangle& rRectSrc, const AlphaMask* pAlphaSrc ) { // Note: this code is copied from Bitmap::CopyPixel but avoids any palette lookups // this optimization is possible because the palettes of AlphaMasks are always identical (8bit GreyPalette, see ctor) const Size aSizePix( GetSizePixel() ); Rectangle aRectDst( rRectDst ); sal_Bool bRet = sal_False; aRectDst.Intersection( Rectangle( Point(), aSizePix ) ); if( !aRectDst.IsEmpty() ) { if( pAlphaSrc && ( *pAlphaSrc != *this ) ) { Bitmap* pSrc = (Bitmap*) pAlphaSrc; const Size aCopySizePix( pSrc->GetSizePixel() ); Rectangle aRectSrc( rRectSrc ); 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(); 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 = sal_True; } } } } return bRet; } // ----------------------------------------------------------------------------- sal_Bool AlphaMask::Erase( sal_uInt8 cTransparency ) { return Bitmap::Erase( Color( cTransparency, cTransparency, cTransparency ) ); } // ----------------------------------------------------------------------------- sal_Bool AlphaMask::Invert() { BitmapWriteAccess* pAcc = AcquireWriteAccess(); sal_Bool bRet = sal_False; if( pAcc && pAcc->GetBitCount() == 8 ) { BitmapColor aCol( 0 ); const long nWidth = pAcc->Width(), nHeight = pAcc->Height(); sal_uInt8* pMap = new sal_uInt8[ 256 ]; for( long i = 0; i < 256; i++ ) pMap[ i ] = ~(sal_uInt8) i; for( long nY = 0L; nY < nHeight; nY++ ) { for( long nX = 0L; nX < nWidth; nX++ ) { aCol.SetIndex( pMap[ pAcc->GetPixel( nY, nX ).GetIndex() ] ); pAcc->SetPixel( nY, nX, aCol ); } } delete[] pMap; bRet = sal_True; } if( pAcc ) ReleaseAccess( pAcc ); return bRet; } // ----------------------------------------------------------------------------- sal_Bool AlphaMask::Mirror( sal_uLong nMirrorFlags ) { return Bitmap::Mirror( nMirrorFlags ); } // ----------------------------------------------------------------------------- sal_Bool AlphaMask::Scale( const Size& rNewSize, sal_uLong nScaleFlag ) { sal_Bool bRet = Bitmap::Scale( rNewSize, nScaleFlag ); if( bRet && ( nScaleFlag == BMP_SCALE_INTERPOLATE ) ) Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS ); return bRet; } // ----------------------------------------------------------------------------- sal_Bool AlphaMask::Scale( const double& rScaleX, const double& rScaleY, sal_uLong nScaleFlag ) { sal_Bool bRet = Bitmap::Scale( rScaleX, rScaleY, nScaleFlag ); if( bRet && ( nScaleFlag == BMP_SCALE_INTERPOLATE ) ) Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS ); return bRet; } // ----------------------------------------------------------------------------- sal_Bool AlphaMask::Rotate( long nAngle10, sal_uInt8 cFillTransparency ) { return Bitmap::Rotate( nAngle10, Color( cFillTransparency, cFillTransparency, cFillTransparency ) ); } // ----------------------------------------------------------------------------- sal_Bool AlphaMask::Replace( const Bitmap& rMask, sal_uInt8 cReplaceTransparency ) { BitmapReadAccess* pMaskAcc = ( (Bitmap&) rMask ).AcquireReadAccess(); BitmapWriteAccess* pAcc = AcquireWriteAccess(); sal_Bool bRet = sal_False; if( pMaskAcc && pAcc ) { const BitmapColor aReplace( cReplaceTransparency ); const long nWidth = Min( pMaskAcc->Width(), pAcc->Width() ); const long nHeight = Min( pMaskAcc->Height(), pAcc->Height() ); const BitmapColor aMaskWhite( pMaskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) ); 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; } // ----------------------------------------------------------------------------- sal_Bool AlphaMask::Replace( sal_uInt8 cSearchTransparency, sal_uInt8 cReplaceTransparency, sal_uLong #ifdef DBG_UTIL nTol #endif ) { BitmapWriteAccess* pAcc = AcquireWriteAccess(); sal_Bool bRet = sal_False; DBG_ASSERT( !nTol, "AlphaMask::Replace: nTol not used yet" ); if( pAcc && pAcc->GetBitCount() == 8 ) { const long nWidth = pAcc->Width(), nHeight = pAcc->Height(); if( pAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ) { for( long nY = 0L; nY < nHeight; nY++ ) { Scanline pScan = pAcc->GetScanline( nY ); for( long nX = 0L; nX < nWidth; nX++, pScan++ ) { if( *pScan == cSearchTransparency ) *pScan = cReplaceTransparency; } } } else { BitmapColor aReplace( cReplaceTransparency ); for( long nY = 0L; nY < nHeight; nY++ ) { for( long nX = 0L; nX < nWidth; nX++ ) { if( pAcc->GetPixel( nY, nX ).GetIndex() == cSearchTransparency ) pAcc->SetPixel( nY, nX, aReplace ); } } } bRet = sal_True; } if( pAcc ) ReleaseAccess( pAcc ); return bRet; } // ----------------------------------------------------------------------------- sal_Bool AlphaMask::Replace( sal_uInt8* pSearchTransparencies, sal_uInt8* pReplaceTransparencies, sal_uLong nColorCount, sal_uLong* pTols ) { Color* pSearchColors = new Color[ nColorCount ]; Color* pReplaceColors = new Color[ nColorCount ]; sal_Bool bRet; for( sal_uLong i = 0; i < nColorCount; i++ ) { const sal_uInt8 cSearchTransparency = pSearchTransparencies[ i ]; const sal_uInt8 cReplaceTransparency = pReplaceTransparencies[ i ]; pSearchColors[ i ] = Color( cSearchTransparency, cSearchTransparency, cSearchTransparency ); pReplaceColors[ i ] = Color( cReplaceTransparency, cReplaceTransparency, cReplaceTransparency ); } bRet = Bitmap::Replace( pSearchColors, pReplaceColors, nColorCount, pTols ) && Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS ); delete[] pSearchColors; delete[] pReplaceColors; return bRet; } // ----------------------------------------------------------------------------- void AlphaMask::ReleaseAccess( BitmapReadAccess* pAccess ) { if( pAccess ) { Bitmap::ReleaseAccess( pAccess ); Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS ); } }