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 31 #include <ctype.h> 32 33 #include <rtl/crc.h> 34 35 #include <tools/stream.hxx> 36 #include <tools/debug.hxx> 37 #include <tools/rc.h> 38 39 #include <vcl/salbtype.hxx> 40 #include <vcl/outdev.hxx> 41 #include <vcl/alpha.hxx> 42 #include <vcl/bitmapex.hxx> 43 #include <vcl/pngread.hxx> 44 #include <vcl/svapp.hxx> 45 #include <vcl/bmpacc.hxx> 46 47 #include <image.h> 48 #include <impimagetree.hxx> 49 50 // ------------ 51 // - BitmapEx - 52 // ------------ 53 54 BitmapEx::BitmapEx() : 55 eTransparent( TRANSPARENT_NONE ), 56 bAlpha ( sal_False ) 57 { 58 } 59 60 // ------------------------------------------------------------------ 61 62 BitmapEx::BitmapEx( const BitmapEx& rBitmapEx ) : 63 aBitmap ( rBitmapEx.aBitmap ), 64 aMask ( rBitmapEx.aMask ), 65 aBitmapSize ( rBitmapEx.aBitmapSize ), 66 aTransparentColor ( rBitmapEx.aTransparentColor ), 67 eTransparent ( rBitmapEx.eTransparent ), 68 bAlpha ( rBitmapEx.bAlpha ) 69 { 70 } 71 72 BitmapEx::BitmapEx( const BitmapEx& rBitmapEx, Point aSrc, Size aSize ) : 73 eTransparent( TRANSPARENT_NONE ), 74 bAlpha ( sal_False ) 75 { 76 if( rBitmapEx.IsEmpty() ) 77 return; 78 79 aBitmap = Bitmap( aSize, rBitmapEx.aBitmap.GetBitCount() ); 80 aBitmapSize = aSize; 81 if( rBitmapEx.IsAlpha() ) 82 { 83 bAlpha = sal_True; 84 aMask = AlphaMask( aSize ).ImplGetBitmap(); 85 } 86 else if( rBitmapEx.IsTransparent() ) 87 aMask = Bitmap( aSize, rBitmapEx.aMask.GetBitCount() ); 88 89 Rectangle aDestRect( Point( 0, 0 ), aSize ); 90 Rectangle aSrcRect( aSrc, aSize ); 91 CopyPixel( aDestRect, aSrcRect, &rBitmapEx ); 92 } 93 94 // ------------------------------------------------------------------ 95 96 BitmapEx::BitmapEx( const ResId& rResId ) : 97 eTransparent( TRANSPARENT_NONE ), 98 bAlpha ( sal_False ) 99 { 100 static ImplImageTreeSingletonRef aImageTree; 101 ResMgr* pResMgr = NULL; 102 103 ResMgr::GetResourceSkipHeader( rResId.SetRT( RSC_BITMAP ), &pResMgr ); 104 pResMgr->ReadLong(); 105 pResMgr->ReadLong(); 106 107 const String aFileName( pResMgr->ReadString() ); 108 ::rtl::OUString aCurrentSymbolsStyle = Application::GetSettings().GetStyleSettings().GetCurrentSymbolsStyleName(); 109 110 if( !aImageTree->loadImage( aFileName, aCurrentSymbolsStyle, *this ) ) 111 { 112 #ifdef DBG_UTIL 113 ByteString aErrorStr( "BitmapEx::BitmapEx( const ResId& rResId ): could not load image <" ); 114 DBG_ERROR( ( ( aErrorStr += ByteString( aFileName, RTL_TEXTENCODING_ASCII_US ) ) += '>' ).GetBuffer() ); 115 #endif 116 } 117 } 118 119 // ------------------------------------------------------------------ 120 121 BitmapEx::BitmapEx( const Bitmap& rBmp ) : 122 aBitmap ( rBmp ), 123 aBitmapSize ( aBitmap.GetSizePixel() ), 124 eTransparent( TRANSPARENT_NONE ), 125 bAlpha ( sal_False ) 126 { 127 } 128 129 // ------------------------------------------------------------------ 130 131 BitmapEx::BitmapEx( const Bitmap& rBmp, const Bitmap& rMask ) : 132 aBitmap ( rBmp ), 133 aMask ( rMask ), 134 aBitmapSize ( aBitmap.GetSizePixel() ), 135 eTransparent ( !rMask ? TRANSPARENT_NONE : TRANSPARENT_BITMAP ), 136 bAlpha ( sal_False ) 137 { 138 DBG_ASSERT( !rMask || rBmp.GetSizePixel() == rMask.GetSizePixel(), 139 "BitmapEx::BitmapEx(): size mismatch for bitmap and mask." ); 140 141 // #105489# Ensure a mask is exactly one bit deep 142 if( !!aMask && aMask.GetBitCount() != 1 ) 143 { 144 OSL_TRACE("BitmapEx: forced mask to monochrome"); 145 aMask.ImplMakeMono( 255 ); 146 } 147 } 148 149 // ------------------------------------------------------------------ 150 151 BitmapEx::BitmapEx( const Bitmap& rBmp, const AlphaMask& rAlphaMask ) : 152 aBitmap ( rBmp ), 153 aMask ( rAlphaMask.ImplGetBitmap() ), 154 aBitmapSize ( aBitmap.GetSizePixel() ), 155 eTransparent ( !rAlphaMask ? TRANSPARENT_NONE : TRANSPARENT_BITMAP ), 156 bAlpha ( !rAlphaMask ? sal_False : sal_True ) 157 { 158 DBG_ASSERT( !rAlphaMask || rBmp.GetSizePixel() == rAlphaMask.GetSizePixel(), 159 "BitmapEx::BitmapEx(): size mismatch for bitmap and alpha mask." ); 160 161 // #i75531# the workaround below can go when 162 // X11SalGraphics::drawAlphaBitmap()'s render acceleration 163 // can handle the bitmap depth mismatch directly 164 if( aBitmap.GetBitCount() < aMask.GetBitCount() ) 165 aBitmap.Convert( BMP_CONVERSION_24BIT ); 166 } 167 168 // ------------------------------------------------------------------ 169 170 BitmapEx::BitmapEx( const Bitmap& rBmp, const Color& rTransparentColor ) : 171 aBitmap ( rBmp ), 172 aBitmapSize ( aBitmap.GetSizePixel() ), 173 aTransparentColor ( rTransparentColor ), 174 eTransparent ( TRANSPARENT_BITMAP ), 175 bAlpha ( sal_False ) 176 { 177 aMask = aBitmap.CreateMask( aTransparentColor ); 178 179 DBG_ASSERT( rBmp.GetSizePixel() == aMask.GetSizePixel(), 180 "BitmapEx::BitmapEx(): size mismatch for bitmap and alpha mask." ); 181 } 182 183 // ------------------------------------------------------------------ 184 185 BitmapEx::~BitmapEx() 186 { 187 } 188 189 // ------------------------------------------------------------------ 190 191 // ------------------------------------------------------------------ 192 193 BitmapEx& BitmapEx::operator=( const BitmapEx& rBitmapEx ) 194 { 195 if( &rBitmapEx != this ) 196 { 197 aBitmap = rBitmapEx.aBitmap; 198 aMask = rBitmapEx.aMask; 199 aBitmapSize = rBitmapEx.aBitmapSize; 200 aTransparentColor = rBitmapEx.aTransparentColor; 201 eTransparent = rBitmapEx.eTransparent; 202 bAlpha = rBitmapEx.bAlpha; 203 } 204 205 return *this; 206 } 207 208 // ------------------------------------------------------------------ 209 210 sal_Bool BitmapEx::operator==( const BitmapEx& rBitmapEx ) const 211 { 212 if( eTransparent != rBitmapEx.eTransparent ) 213 return sal_False; 214 215 if( aBitmap != rBitmapEx.aBitmap ) 216 return sal_False; 217 218 if( aBitmapSize != rBitmapEx.aBitmapSize ) 219 return sal_False; 220 221 if( eTransparent == TRANSPARENT_NONE ) 222 return sal_True; 223 224 if( eTransparent == TRANSPARENT_COLOR ) 225 return aTransparentColor == rBitmapEx.aTransparentColor; 226 227 return( ( aMask == rBitmapEx.aMask ) && ( bAlpha == rBitmapEx.bAlpha ) ); 228 } 229 230 // ------------------------------------------------------------------ 231 232 sal_Bool BitmapEx::IsEqual( const BitmapEx& rBmpEx ) const 233 { 234 return( rBmpEx.eTransparent == eTransparent && 235 rBmpEx.bAlpha == bAlpha && 236 rBmpEx.aBitmap.IsEqual( aBitmap ) && 237 rBmpEx.aMask.IsEqual( aMask ) ); 238 } 239 240 // ------------------------------------------------------------------ 241 242 sal_Bool BitmapEx::IsEmpty() const 243 { 244 return( aBitmap.IsEmpty() && aMask.IsEmpty() ); 245 } 246 247 // ------------------------------------------------------------------ 248 249 void BitmapEx::SetEmpty() 250 { 251 aBitmap.SetEmpty(); 252 aMask.SetEmpty(); 253 eTransparent = TRANSPARENT_NONE; 254 bAlpha = sal_False; 255 } 256 257 // ------------------------------------------------------------------ 258 259 void BitmapEx::Clear() 260 { 261 SetEmpty(); 262 } 263 264 // ------------------------------------------------------------------ 265 266 sal_Bool BitmapEx::IsTransparent() const 267 { 268 return( eTransparent != TRANSPARENT_NONE ); 269 } 270 271 // ------------------------------------------------------------------ 272 273 sal_Bool BitmapEx::IsAlpha() const 274 { 275 return( IsTransparent() && bAlpha ); 276 } 277 278 // ------------------------------------------------------------------ 279 280 Bitmap BitmapEx::GetBitmap( const Color* pTransReplaceColor ) const 281 { 282 Bitmap aRetBmp( aBitmap ); 283 284 if( pTransReplaceColor && ( eTransparent != TRANSPARENT_NONE ) ) 285 { 286 Bitmap aTempMask; 287 288 if( eTransparent == TRANSPARENT_COLOR ) 289 aTempMask = aBitmap.CreateMask( aTransparentColor ); 290 else 291 aTempMask = aMask; 292 293 if( !IsAlpha() ) 294 aRetBmp.Replace( aTempMask, *pTransReplaceColor ); 295 else 296 aRetBmp.Replace( GetAlpha(), *pTransReplaceColor ); 297 } 298 299 return aRetBmp; 300 } 301 302 // ------------------------------------------------------------------ 303 304 BitmapEx BitmapEx::GetColorTransformedBitmapEx( BmpColorMode eColorMode ) const 305 { 306 BitmapEx aRet; 307 308 if( BMP_COLOR_HIGHCONTRAST == eColorMode ) 309 { 310 aRet = *this; 311 aRet.aBitmap = aBitmap.GetColorTransformedBitmap( eColorMode ); 312 } 313 else if( BMP_COLOR_MONOCHROME_BLACK == eColorMode || 314 BMP_COLOR_MONOCHROME_WHITE == eColorMode ) 315 { 316 aRet = *this; 317 aRet.aBitmap = aRet.aBitmap.GetColorTransformedBitmap( eColorMode ); 318 319 if( !aRet.aMask.IsEmpty() ) 320 { 321 aRet.aMask.CombineSimple( aRet.aBitmap, BMP_COMBINE_OR ); 322 aRet.aBitmap.Erase( ( BMP_COLOR_MONOCHROME_BLACK == eColorMode ) ? COL_BLACK : COL_WHITE ); 323 324 DBG_ASSERT( aRet.aBitmap.GetSizePixel() == aRet.aMask.GetSizePixel(), 325 "BitmapEx::GetColorTransformedBitmapEx(): size mismatch for bitmap and alpha mask." ); 326 } 327 } 328 329 return aRet; 330 } 331 332 // ------------------------------------------------------------------ 333 334 Bitmap BitmapEx::GetMask() const 335 { 336 Bitmap aRet( aMask ); 337 338 if( IsAlpha() ) 339 aRet.ImplMakeMono( 255 ); 340 341 return aRet; 342 } 343 344 // ------------------------------------------------------------------ 345 346 AlphaMask BitmapEx::GetAlpha() const 347 { 348 AlphaMask aAlpha; 349 350 if( IsAlpha() ) 351 aAlpha.ImplSetBitmap( aMask ); 352 else 353 aAlpha = aMask; 354 355 return aAlpha; 356 } 357 358 // ------------------------------------------------------------------ 359 360 sal_uLong BitmapEx::GetSizeBytes() const 361 { 362 sal_uLong nSizeBytes = aBitmap.GetSizeBytes(); 363 364 if( eTransparent == TRANSPARENT_BITMAP ) 365 nSizeBytes += aMask.GetSizeBytes(); 366 367 return nSizeBytes; 368 } 369 370 // ------------------------------------------------------------------ 371 372 sal_uLong BitmapEx::GetChecksum() const 373 { 374 sal_uInt32 nCrc = aBitmap.GetChecksum(); 375 SVBT32 aBT32; 376 377 UInt32ToSVBT32( (long) eTransparent, aBT32 ); 378 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 379 380 UInt32ToSVBT32( (long) bAlpha, aBT32 ); 381 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 382 383 if( ( TRANSPARENT_BITMAP == eTransparent ) && !aMask.IsEmpty() ) 384 { 385 UInt32ToSVBT32( aMask.GetChecksum(), aBT32 ); 386 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 387 } 388 389 return nCrc; 390 } 391 392 // ------------------------------------------------------------------ 393 394 void BitmapEx::SetSizePixel( const Size& rNewSize ) 395 { 396 Scale( rNewSize ); 397 } 398 399 // ------------------------------------------------------------------ 400 401 sal_Bool BitmapEx::Invert() 402 { 403 sal_Bool bRet = sal_False; 404 405 if( !!aBitmap ) 406 { 407 bRet = aBitmap.Invert(); 408 409 if( bRet && ( eTransparent == TRANSPARENT_COLOR ) ) 410 aTransparentColor = BitmapColor( aTransparentColor ).Invert(); 411 } 412 413 return bRet; 414 } 415 416 // ------------------------------------------------------------------ 417 418 sal_Bool BitmapEx::Mirror( sal_uLong nMirrorFlags ) 419 { 420 sal_Bool bRet = sal_False; 421 422 if( !!aBitmap ) 423 { 424 bRet = aBitmap.Mirror( nMirrorFlags ); 425 426 if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask ) 427 aMask.Mirror( nMirrorFlags ); 428 } 429 430 return bRet; 431 } 432 433 // ------------------------------------------------------------------ 434 435 sal_Bool BitmapEx::Scale( const double& rScaleX, const double& rScaleY, sal_uLong nScaleFlag ) 436 { 437 sal_Bool bRet = sal_False; 438 439 if( !!aBitmap ) 440 { 441 bRet = aBitmap.Scale( rScaleX, rScaleY, nScaleFlag ); 442 443 if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask ) 444 aMask.Scale( rScaleX, rScaleY, BMP_SCALE_FAST ); 445 446 aBitmapSize = aBitmap.GetSizePixel(); 447 448 DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(), 449 "BitmapEx::Scale(): size mismatch for bitmap and alpha mask." ); 450 } 451 452 return bRet; 453 } 454 455 // ------------------------------------------------------------------------ 456 457 sal_Bool BitmapEx::Scale( const Size& rNewSize, sal_uLong nScaleFlag ) 458 { 459 sal_Bool bRet; 460 461 if( aBitmapSize.Width() && aBitmapSize.Height() ) 462 { 463 bRet = Scale( (double) rNewSize.Width() / aBitmapSize.Width(), 464 (double) rNewSize.Height() / aBitmapSize.Height(), 465 nScaleFlag ); 466 } 467 else 468 bRet = sal_True; 469 470 return bRet; 471 } 472 473 // ------------------------------------------------------------------ 474 475 sal_Bool BitmapEx::Rotate( long nAngle10, const Color& rFillColor ) 476 { 477 sal_Bool bRet = sal_False; 478 479 if( !!aBitmap ) 480 { 481 const sal_Bool bTransRotate = ( Color( COL_TRANSPARENT ) == rFillColor ); 482 483 if( bTransRotate ) 484 { 485 if( eTransparent == TRANSPARENT_COLOR ) 486 bRet = aBitmap.Rotate( nAngle10, aTransparentColor ); 487 else 488 { 489 bRet = aBitmap.Rotate( nAngle10, COL_BLACK ); 490 491 if( eTransparent == TRANSPARENT_NONE ) 492 { 493 aMask = Bitmap( aBitmapSize, 1 ); 494 aMask.Erase( COL_BLACK ); 495 eTransparent = TRANSPARENT_BITMAP; 496 } 497 498 if( bRet && !!aMask ) 499 aMask.Rotate( nAngle10, COL_WHITE ); 500 } 501 } 502 else 503 { 504 bRet = aBitmap.Rotate( nAngle10, rFillColor ); 505 506 if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask ) 507 aMask.Rotate( nAngle10, COL_WHITE ); 508 } 509 510 aBitmapSize = aBitmap.GetSizePixel(); 511 512 DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(), 513 "BitmapEx::Rotate(): size mismatch for bitmap and alpha mask." ); 514 } 515 516 return bRet; 517 } 518 519 // ------------------------------------------------------------------ 520 521 sal_Bool BitmapEx::Crop( const Rectangle& rRectPixel ) 522 { 523 sal_Bool bRet = sal_False; 524 525 if( !!aBitmap ) 526 { 527 bRet = aBitmap.Crop( rRectPixel ); 528 529 if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask ) 530 aMask.Crop( rRectPixel ); 531 532 aBitmapSize = aBitmap.GetSizePixel(); 533 534 DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(), 535 "BitmapEx::Crop(): size mismatch for bitmap and alpha mask." ); 536 } 537 538 return bRet; 539 } 540 541 // ------------------------------------------------------------------ 542 543 sal_Bool BitmapEx::Convert( BmpConversion eConversion ) 544 { 545 return( !!aBitmap ? aBitmap.Convert( eConversion ) : sal_False ); 546 } 547 548 // ------------------------------------------------------------------ 549 550 sal_Bool BitmapEx::ReduceColors( sal_uInt16 nNewColorCount, BmpReduce eReduce ) 551 { 552 return( !!aBitmap ? aBitmap.ReduceColors( nNewColorCount, eReduce ) : sal_False ); 553 } 554 555 // ------------------------------------------------------------------ 556 557 sal_Bool BitmapEx::Expand( sal_uLong nDX, sal_uLong nDY, const Color* pInitColor, sal_Bool bExpandTransparent ) 558 { 559 sal_Bool bRet = sal_False; 560 561 if( !!aBitmap ) 562 { 563 bRet = aBitmap.Expand( nDX, nDY, pInitColor ); 564 565 if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask ) 566 { 567 Color aColor( bExpandTransparent ? COL_WHITE : COL_BLACK ); 568 aMask.Expand( nDX, nDY, &aColor ); 569 } 570 571 aBitmapSize = aBitmap.GetSizePixel(); 572 573 DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(), 574 "BitmapEx::Expand(): size mismatch for bitmap and alpha mask." ); 575 } 576 577 return bRet; 578 } 579 580 // ------------------------------------------------------------------ 581 582 sal_Bool BitmapEx::CopyPixel( const Rectangle& rRectDst, const Rectangle& rRectSrc, 583 const BitmapEx* pBmpExSrc ) 584 { 585 sal_Bool bRet = sal_False; 586 587 if( !pBmpExSrc || pBmpExSrc->IsEmpty() ) 588 { 589 if( !aBitmap.IsEmpty() ) 590 { 591 bRet = aBitmap.CopyPixel( rRectDst, rRectSrc ); 592 593 if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask ) 594 aMask.CopyPixel( rRectDst, rRectSrc ); 595 } 596 } 597 else 598 { 599 if( !aBitmap.IsEmpty() ) 600 { 601 bRet = aBitmap.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aBitmap ); 602 603 if( bRet ) 604 { 605 if( pBmpExSrc->IsAlpha() ) 606 { 607 if( IsAlpha() ) 608 // cast to use the optimized AlphaMask::CopyPixel 609 ((AlphaMask*) &aMask)->CopyPixel( rRectDst, rRectSrc, (AlphaMask*)&pBmpExSrc->aMask ); 610 else if( IsTransparent() ) 611 { 612 AlphaMask* pAlpha = new AlphaMask( aMask ); 613 614 aMask = pAlpha->ImplGetBitmap(); 615 delete pAlpha; 616 bAlpha = sal_True; 617 aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask ); 618 } 619 else 620 { 621 sal_uInt8 cBlack = 0; 622 AlphaMask* pAlpha = new AlphaMask( GetSizePixel(), &cBlack ); 623 624 aMask = pAlpha->ImplGetBitmap(); 625 delete pAlpha; 626 eTransparent = TRANSPARENT_BITMAP; 627 bAlpha = sal_True; 628 aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask ); 629 } 630 } 631 else if( pBmpExSrc->IsTransparent() ) 632 { 633 if( IsAlpha() ) 634 { 635 AlphaMask aAlpha( pBmpExSrc->aMask ); 636 aMask.CopyPixel( rRectDst, rRectSrc, &aAlpha.ImplGetBitmap() ); 637 } 638 else if( IsTransparent() ) 639 aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask ); 640 else 641 { 642 aMask = Bitmap( GetSizePixel(), 1 ); 643 aMask.Erase( Color( COL_BLACK ) ); 644 eTransparent = TRANSPARENT_BITMAP; 645 aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask ); 646 } 647 } 648 else if( IsAlpha() ) 649 { 650 sal_uInt8 cBlack = 0; 651 const AlphaMask aAlphaSrc( pBmpExSrc->GetSizePixel(), &cBlack ); 652 653 aMask.CopyPixel( rRectDst, rRectSrc, &aAlphaSrc.ImplGetBitmap() ); 654 } 655 else if( IsTransparent() ) 656 { 657 Bitmap aMaskSrc( pBmpExSrc->GetSizePixel(), 1 ); 658 659 aMaskSrc.Erase( Color( COL_BLACK ) ); 660 aMask.CopyPixel( rRectDst, rRectSrc, &aMaskSrc ); 661 } 662 } 663 } 664 } 665 666 return bRet; 667 } 668 669 // ------------------------------------------------------------------ 670 671 sal_Bool BitmapEx::Erase( const Color& rFillColor ) 672 { 673 sal_Bool bRet = sal_False; 674 675 if( !!aBitmap ) 676 { 677 bRet = aBitmap.Erase( rFillColor ); 678 679 if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask ) 680 { 681 // #104416# Respect transparency on fill color 682 if( rFillColor.GetTransparency() ) 683 { 684 const Color aFill( rFillColor.GetTransparency(), rFillColor.GetTransparency(), rFillColor.GetTransparency() ); 685 aMask.Erase( aFill ); 686 } 687 else 688 { 689 const Color aBlack( COL_BLACK ); 690 aMask.Erase( aBlack ); 691 } 692 } 693 } 694 695 return bRet; 696 } 697 698 // ------------------------------------------------------------------ 699 700 sal_Bool BitmapEx::Dither( sal_uLong nDitherFlags ) 701 { 702 return( !!aBitmap ? aBitmap.Dither( nDitherFlags ) : sal_False ); 703 } 704 705 // ------------------------------------------------------------------ 706 707 sal_Bool BitmapEx::Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uLong nTol ) 708 { 709 return( !!aBitmap ? aBitmap.Replace( rSearchColor, rReplaceColor, nTol ) : sal_False ); 710 } 711 712 // ------------------------------------------------------------------ 713 714 sal_Bool BitmapEx::Replace( const Color* pSearchColors, const Color* pReplaceColors, sal_uLong nColorCount, const sal_uLong* pTols ) 715 { 716 return( !!aBitmap ? aBitmap.Replace( pSearchColors, pReplaceColors, nColorCount, (sal_uLong*) pTols ) : sal_False ); 717 } 718 719 // ------------------------------------------------------------------ 720 721 sal_Bool BitmapEx::Adjust( short nLuminancePercent, short nContrastPercent, 722 short nChannelRPercent, short nChannelGPercent, short nChannelBPercent, 723 double fGamma, sal_Bool bInvert ) 724 { 725 return( !!aBitmap ? aBitmap.Adjust( nLuminancePercent, nContrastPercent, 726 nChannelRPercent, nChannelGPercent, nChannelBPercent, 727 fGamma, bInvert ) : sal_False ); 728 } 729 730 // ------------------------------------------------------------------ 731 732 sal_Bool BitmapEx::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam, const Link* pProgress ) 733 { 734 return( !!aBitmap ? aBitmap.Filter( eFilter, pFilterParam, pProgress ) : sal_False ); 735 } 736 737 // ------------------------------------------------------------------ 738 739 void BitmapEx::Draw( OutputDevice* pOutDev, const Point& rDestPt ) const 740 { 741 pOutDev->DrawBitmapEx( rDestPt, *this ); 742 } 743 744 // ------------------------------------------------------------------ 745 746 void BitmapEx::Draw( OutputDevice* pOutDev, 747 const Point& rDestPt, const Size& rDestSize ) const 748 { 749 pOutDev->DrawBitmapEx( rDestPt, rDestSize, *this ); 750 } 751 752 // ------------------------------------------------------------------ 753 754 void BitmapEx::Draw( OutputDevice* pOutDev, 755 const Point& rDestPt, const Size& rDestSize, 756 const Point& rSrcPtPixel, const Size& rSrcSizePixel ) const 757 { 758 pOutDev->DrawBitmapEx( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, *this ); 759 } 760 761 // ------------------------------------------------------------------ 762 763 sal_uInt8 BitmapEx::GetTransparency(sal_Int32 nX, sal_Int32 nY) const 764 { 765 sal_uInt8 nTransparency(0xff); 766 767 if(!aBitmap.IsEmpty()) 768 { 769 if(nX >= 0 && nX < aBitmapSize.Width() && nY >= 0 && nY < aBitmapSize.Height()) 770 { 771 switch(eTransparent) 772 { 773 case TRANSPARENT_NONE: 774 { 775 // not transparent, ergo all covered 776 nTransparency = 0x00; 777 break; 778 } 779 case TRANSPARENT_COLOR: 780 { 781 Bitmap aTestBitmap(aBitmap); 782 BitmapReadAccess* pRead = aTestBitmap.AcquireReadAccess(); 783 784 if(pRead) 785 { 786 const Color aColor = pRead->GetColor(nY, nX); 787 788 // if color is not equal to TransparentColor, we are not transparent 789 if(aColor != aTransparentColor) 790 { 791 nTransparency = 0x00; 792 } 793 794 aTestBitmap.ReleaseAccess(pRead); 795 } 796 break; 797 } 798 case TRANSPARENT_BITMAP: 799 { 800 if(!aMask.IsEmpty()) 801 { 802 Bitmap aTestBitmap(aMask); 803 BitmapReadAccess* pRead = aTestBitmap.AcquireReadAccess(); 804 805 if(pRead) 806 { 807 const BitmapColor aBitmapColor(pRead->GetPixel(nY, nX)); 808 809 if(bAlpha) 810 { 811 nTransparency = aBitmapColor.GetIndex(); 812 } 813 else 814 { 815 if(0x00 == aBitmapColor.GetIndex()) 816 { 817 nTransparency = 0x00; 818 } 819 } 820 821 aTestBitmap.ReleaseAccess(pRead); 822 } 823 } 824 break; 825 } 826 } 827 } 828 } 829 830 return nTransparency; 831 } 832 833 // ------------------------------------------------------------------ 834 835 SvStream& operator<<( SvStream& rOStm, const BitmapEx& rBitmapEx ) 836 { 837 rBitmapEx.aBitmap.Write( rOStm ); 838 839 rOStm << (sal_uInt32) 0x25091962; 840 rOStm << (sal_uInt32) 0xACB20201; 841 rOStm << (sal_uInt8) rBitmapEx.eTransparent; 842 843 if( rBitmapEx.eTransparent == TRANSPARENT_BITMAP ) 844 rBitmapEx.aMask.Write( rOStm ); 845 else if( rBitmapEx.eTransparent == TRANSPARENT_COLOR ) 846 rOStm << rBitmapEx.aTransparentColor; 847 848 return rOStm; 849 } 850 851 // ------------------------------------------------------------------ 852 853 SvStream& operator>>( SvStream& rIStm, BitmapEx& rBitmapEx ) 854 { 855 Bitmap aBmp; 856 857 rIStm >> aBmp; 858 859 if( !rIStm.GetError() ) 860 { 861 const sal_uLong nStmPos = rIStm.Tell(); 862 sal_uInt32 nMagic1 = 0; 863 sal_uInt32 nMagic2 = 0; 864 865 rIStm >> nMagic1 >> nMagic2; 866 867 if( ( nMagic1 != 0x25091962 ) || ( nMagic2 != 0xACB20201 ) || rIStm.GetError() ) 868 { 869 rIStm.ResetError(); 870 rIStm.Seek( nStmPos ); 871 rBitmapEx = aBmp; 872 } 873 else 874 { 875 sal_uInt8 bTransparent = false; 876 877 rIStm >> bTransparent; 878 879 if( bTransparent == (sal_uInt8) TRANSPARENT_BITMAP ) 880 { 881 Bitmap aMask; 882 883 rIStm >> aMask; 884 885 if( !!aMask) 886 { 887 // do we have an alpha mask? 888 if( ( 8 == aMask.GetBitCount() ) && aMask.HasGreyPalette() ) 889 { 890 AlphaMask aAlpha; 891 892 // create alpha mask quickly (without greyscale conversion) 893 aAlpha.ImplSetBitmap( aMask ); 894 rBitmapEx = BitmapEx( aBmp, aAlpha ); 895 } 896 else 897 rBitmapEx = BitmapEx( aBmp, aMask ); 898 } 899 else 900 rBitmapEx = aBmp; 901 } 902 else if( bTransparent == (sal_uInt8) TRANSPARENT_COLOR ) 903 { 904 Color aTransparentColor; 905 906 rIStm >> aTransparentColor; 907 rBitmapEx = BitmapEx( aBmp, aTransparentColor ); 908 } 909 else 910 rBitmapEx = aBmp; 911 } 912 } 913 914 return rIStm; 915 } 916