1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_vcl.hxx" 30 #include <tools/debug.hxx> 31 #include <vcl/bmpacc.hxx> 32 #include <tools/color.hxx> 33 #include <vcl/alpha.hxx> 34 35 // ------------- 36 // - AlphaMask - 37 // ------------- 38 39 AlphaMask::AlphaMask() 40 { 41 } 42 43 // ----------------------------------------------------------------------------- 44 45 AlphaMask::AlphaMask( const Bitmap& rBitmap ) : 46 Bitmap( rBitmap ) 47 { 48 if( !!rBitmap ) 49 Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS ); 50 } 51 52 // ----------------------------------------------------------------------------- 53 54 AlphaMask::AlphaMask( const AlphaMask& rAlphaMask ) : 55 Bitmap( rAlphaMask ) 56 { 57 } 58 59 // ----------------------------------------------------------------------------- 60 61 AlphaMask::AlphaMask( const Size& rSizePixel, sal_uInt8* pEraseTransparency ) : 62 Bitmap( rSizePixel, 8, &Bitmap::GetGreyPalette( 256 ) ) 63 { 64 if( pEraseTransparency ) 65 Bitmap::Erase( Color( *pEraseTransparency, *pEraseTransparency, *pEraseTransparency ) ); 66 } 67 68 // ----------------------------------------------------------------------------- 69 70 AlphaMask::~AlphaMask() 71 { 72 } 73 74 // ----------------------------------------------------------------------------- 75 76 AlphaMask& AlphaMask::operator=( const Bitmap& rBitmap ) 77 { 78 *(Bitmap*) this = rBitmap; 79 80 if( !!rBitmap ) 81 Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS ); 82 83 return *this; 84 } 85 86 // ----------------------------------------------------------------------------- 87 88 const Bitmap& AlphaMask::ImplGetBitmap() const 89 { 90 return( (const Bitmap&) *this ); 91 } 92 93 // ----------------------------------------------------------------------------- 94 95 void AlphaMask::ImplSetBitmap( const Bitmap& rBitmap ) 96 { 97 DBG_ASSERT( ( 8 == rBitmap.GetBitCount() ) && rBitmap.HasGreyPalette(), "AlphaMask::ImplSetBitmap: invalid bitmap" ); 98 *(Bitmap*) this = rBitmap; 99 } 100 101 // ----------------------------------------------------------------------------- 102 103 Bitmap AlphaMask::GetBitmap() const 104 { 105 return ImplGetBitmap(); 106 } 107 108 // ----------------------------------------------------------------------------- 109 110 sal_Bool AlphaMask::Crop( const Rectangle& rRectPixel ) 111 { 112 return Bitmap::Crop( rRectPixel ); 113 } 114 115 // ----------------------------------------------------------------------------- 116 117 sal_Bool AlphaMask::Expand( sal_uLong nDX, sal_uLong nDY, sal_uInt8* pInitTransparency ) 118 { 119 Color aColor; 120 121 if( pInitTransparency ) 122 aColor = Color( *pInitTransparency, *pInitTransparency, *pInitTransparency ); 123 124 return Bitmap::Expand( nDX, nDY, pInitTransparency ? &aColor : NULL ); 125 } 126 127 // ----------------------------------------------------------------------------- 128 129 sal_Bool AlphaMask::CopyPixel( const Rectangle& rRectDst, const Rectangle& rRectSrc, 130 const AlphaMask* pAlphaSrc ) 131 { 132 // Note: this code is copied from Bitmap::CopyPixel but avoids any palette lookups 133 // this optimization is possible because the palettes of AlphaMasks are always identical (8bit GreyPalette, see ctor) 134 135 const Size aSizePix( GetSizePixel() ); 136 Rectangle aRectDst( rRectDst ); 137 sal_Bool bRet = sal_False; 138 139 aRectDst.Intersection( Rectangle( Point(), aSizePix ) ); 140 141 if( !aRectDst.IsEmpty() ) 142 { 143 if( pAlphaSrc && ( *pAlphaSrc != *this ) ) 144 { 145 Bitmap* pSrc = (Bitmap*) pAlphaSrc; 146 const Size aCopySizePix( pSrc->GetSizePixel() ); 147 Rectangle aRectSrc( rRectSrc ); 148 149 aRectSrc.Intersection( Rectangle( Point(), aCopySizePix ) ); 150 151 if( !aRectSrc.IsEmpty() ) 152 { 153 BitmapReadAccess* pReadAcc = pSrc->AcquireReadAccess(); 154 155 if( pReadAcc ) 156 { 157 BitmapWriteAccess* pWriteAcc = AcquireWriteAccess(); 158 159 if( pWriteAcc ) 160 { 161 const long nWidth = Min( aRectSrc.GetWidth(), aRectDst.GetWidth() ); 162 const long nHeight = Min( aRectSrc.GetHeight(), aRectDst.GetHeight() ); 163 const long nSrcEndX = aRectSrc.Left() + nWidth; 164 const long nSrcEndY = aRectSrc.Top() + nHeight; 165 long nDstY = aRectDst.Top(); 166 167 for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ ) 168 for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ ) 169 pWriteAcc->SetPixel( nDstY, nDstX, pReadAcc->GetPixel( nSrcY, nSrcX ) ); 170 171 ReleaseAccess( pWriteAcc ); 172 bRet = ( nWidth > 0L ) && ( nHeight > 0L ); 173 } 174 175 pSrc->ReleaseAccess( pReadAcc ); 176 } 177 } 178 } 179 else 180 { 181 Rectangle aRectSrc( rRectSrc ); 182 183 aRectSrc.Intersection( Rectangle( Point(), aSizePix ) ); 184 185 if( !aRectSrc.IsEmpty() && ( aRectSrc != aRectDst ) ) 186 { 187 BitmapWriteAccess* pWriteAcc = AcquireWriteAccess(); 188 189 if( pWriteAcc ) 190 { 191 const long nWidth = Min( aRectSrc.GetWidth(), aRectDst.GetWidth() ); 192 const long nHeight = Min( aRectSrc.GetHeight(), aRectDst.GetHeight() ); 193 const long nSrcX = aRectSrc.Left(); 194 const long nSrcY = aRectSrc.Top(); 195 const long nSrcEndX1 = nSrcX + nWidth - 1L; 196 const long nSrcEndY1 = nSrcY + nHeight - 1L; 197 const long nDstX = aRectDst.Left(); 198 const long nDstY = aRectDst.Top(); 199 const long nDstEndX1 = nDstX + nWidth - 1L; 200 const long nDstEndY1 = nDstY + nHeight - 1L; 201 202 if( ( nDstX <= nSrcX ) && ( nDstY <= nSrcY ) ) 203 { 204 for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ ) 205 for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ ) 206 pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) ); 207 } 208 else if( ( nDstX <= nSrcX ) && ( nDstY >= nSrcY ) ) 209 { 210 for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- ) 211 for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ ) 212 pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) ); 213 } 214 else if( ( nDstX >= nSrcX ) && ( nDstY <= nSrcY ) ) 215 { 216 for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ ) 217 for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- ) 218 pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) ); 219 } 220 else 221 { 222 for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- ) 223 for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- ) 224 pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) ); 225 } 226 227 ReleaseAccess( pWriteAcc ); 228 bRet = sal_True; 229 } 230 } 231 } 232 } 233 234 return bRet; 235 236 } 237 238 // ----------------------------------------------------------------------------- 239 240 sal_Bool AlphaMask::Erase( sal_uInt8 cTransparency ) 241 { 242 return Bitmap::Erase( Color( cTransparency, cTransparency, cTransparency ) ); 243 } 244 245 // ----------------------------------------------------------------------------- 246 247 sal_Bool AlphaMask::Invert() 248 { 249 BitmapWriteAccess* pAcc = AcquireWriteAccess(); 250 sal_Bool bRet = sal_False; 251 252 if( pAcc && pAcc->GetBitCount() == 8 ) 253 { 254 BitmapColor aCol( 0 ); 255 const long nWidth = pAcc->Width(), nHeight = pAcc->Height(); 256 sal_uInt8* pMap = new sal_uInt8[ 256 ]; 257 258 for( long i = 0; i < 256; i++ ) 259 pMap[ i ] = ~(sal_uInt8) i; 260 261 for( long nY = 0L; nY < nHeight; nY++ ) 262 { 263 for( long nX = 0L; nX < nWidth; nX++ ) 264 { 265 aCol.SetIndex( pMap[ pAcc->GetPixel( nY, nX ).GetIndex() ] ); 266 pAcc->SetPixel( nY, nX, aCol ); 267 } 268 } 269 270 delete[] pMap; 271 bRet = sal_True; 272 } 273 274 if( pAcc ) 275 ReleaseAccess( pAcc ); 276 277 return bRet; 278 } 279 280 // ----------------------------------------------------------------------------- 281 282 sal_Bool AlphaMask::Mirror( sal_uLong nMirrorFlags ) 283 { 284 return Bitmap::Mirror( nMirrorFlags ); 285 } 286 287 // ----------------------------------------------------------------------------- 288 289 sal_Bool AlphaMask::Scale( const Size& rNewSize, sal_uLong nScaleFlag ) 290 { 291 sal_Bool bRet = Bitmap::Scale( rNewSize, nScaleFlag ); 292 293 if( bRet && ( nScaleFlag == BMP_SCALE_INTERPOLATE ) ) 294 Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS ); 295 296 return bRet; 297 } 298 299 // ----------------------------------------------------------------------------- 300 301 sal_Bool AlphaMask::Scale( const double& rScaleX, const double& rScaleY, sal_uLong nScaleFlag ) 302 { 303 sal_Bool bRet = Bitmap::Scale( rScaleX, rScaleY, nScaleFlag ); 304 305 if( bRet && ( nScaleFlag == BMP_SCALE_INTERPOLATE ) ) 306 Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS ); 307 308 return bRet; 309 } 310 311 // ----------------------------------------------------------------------------- 312 313 sal_Bool AlphaMask::Rotate( long nAngle10, sal_uInt8 cFillTransparency ) 314 { 315 return Bitmap::Rotate( nAngle10, Color( cFillTransparency, cFillTransparency, cFillTransparency ) ); 316 } 317 318 // ----------------------------------------------------------------------------- 319 320 sal_Bool AlphaMask::Replace( const Bitmap& rMask, sal_uInt8 cReplaceTransparency ) 321 { 322 BitmapReadAccess* pMaskAcc = ( (Bitmap&) rMask ).AcquireReadAccess(); 323 BitmapWriteAccess* pAcc = AcquireWriteAccess(); 324 sal_Bool bRet = sal_False; 325 326 if( pMaskAcc && pAcc ) 327 { 328 const BitmapColor aReplace( cReplaceTransparency ); 329 const long nWidth = Min( pMaskAcc->Width(), pAcc->Width() ); 330 const long nHeight = Min( pMaskAcc->Height(), pAcc->Height() ); 331 const BitmapColor aMaskWhite( pMaskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) ); 332 333 for( long nY = 0L; nY < nHeight; nY++ ) 334 for( long nX = 0L; nX < nWidth; nX++ ) 335 if( pMaskAcc->GetPixel( nY, nX ) == aMaskWhite ) 336 pAcc->SetPixel( nY, nX, aReplace ); 337 } 338 339 ( (Bitmap&) rMask ).ReleaseAccess( pMaskAcc ); 340 ReleaseAccess( pAcc ); 341 342 return bRet; 343 } 344 345 // ----------------------------------------------------------------------------- 346 347 sal_Bool AlphaMask::Replace( sal_uInt8 cSearchTransparency, sal_uInt8 cReplaceTransparency, sal_uLong 348 #ifdef DBG_UTIL 349 nTol 350 #endif 351 ) 352 { 353 BitmapWriteAccess* pAcc = AcquireWriteAccess(); 354 sal_Bool bRet = sal_False; 355 356 DBG_ASSERT( !nTol, "AlphaMask::Replace: nTol not used yet" ); 357 358 if( pAcc && pAcc->GetBitCount() == 8 ) 359 { 360 const long nWidth = pAcc->Width(), nHeight = pAcc->Height(); 361 362 if( pAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ) 363 { 364 for( long nY = 0L; nY < nHeight; nY++ ) 365 { 366 Scanline pScan = pAcc->GetScanline( nY ); 367 368 for( long nX = 0L; nX < nWidth; nX++, pScan++ ) 369 { 370 if( *pScan == cSearchTransparency ) 371 *pScan = cReplaceTransparency; 372 } 373 } 374 } 375 else 376 { 377 BitmapColor aReplace( cReplaceTransparency ); 378 379 for( long nY = 0L; nY < nHeight; nY++ ) 380 { 381 for( long nX = 0L; nX < nWidth; nX++ ) 382 { 383 if( pAcc->GetPixel( nY, nX ).GetIndex() == cSearchTransparency ) 384 pAcc->SetPixel( nY, nX, aReplace ); 385 } 386 } 387 } 388 389 bRet = sal_True; 390 } 391 392 if( pAcc ) 393 ReleaseAccess( pAcc ); 394 395 return bRet; 396 } 397 398 // ----------------------------------------------------------------------------- 399 400 sal_Bool AlphaMask::Replace( sal_uInt8* pSearchTransparencies, sal_uInt8* pReplaceTransparencies, 401 sal_uLong nColorCount, sal_uLong* pTols ) 402 { 403 Color* pSearchColors = new Color[ nColorCount ]; 404 Color* pReplaceColors = new Color[ nColorCount ]; 405 sal_Bool bRet; 406 407 for( sal_uLong i = 0; i < nColorCount; i++ ) 408 { 409 const sal_uInt8 cSearchTransparency = pSearchTransparencies[ i ]; 410 const sal_uInt8 cReplaceTransparency = pReplaceTransparencies[ i ]; 411 412 pSearchColors[ i ] = Color( cSearchTransparency, cSearchTransparency, cSearchTransparency ); 413 pReplaceColors[ i ] = Color( cReplaceTransparency, cReplaceTransparency, cReplaceTransparency ); 414 } 415 416 bRet = Bitmap::Replace( pSearchColors, pReplaceColors, nColorCount, pTols ) && 417 Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS ); 418 419 delete[] pSearchColors; 420 delete[] pReplaceColors; 421 422 return bRet; 423 } 424 425 // ----------------------------------------------------------------------------- 426 427 void AlphaMask::ReleaseAccess( BitmapReadAccess* pAccess ) 428 { 429 if( pAccess ) 430 { 431 Bitmap::ReleaseAccess( pAccess ); 432 Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS ); 433 } 434 } 435