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 #define ENABLE_BYTESTRING_STREAM_OPERATORS 32 #include <vcl/animate.hxx> 33 #include <tools/debug.hxx> 34 #include <tools/stream.hxx> 35 #include <rtl/crc.h> 36 #include <vcl/virdev.hxx> 37 #include <vcl/window.hxx> 38 #include <impanmvw.hxx> 39 DBG_NAME( Animation ) 40 41 // ----------- 42 // - Defines - 43 // ----------- 44 45 #define MIN_TIMEOUT 2L 46 #define INC_TIMEOUT 0L 47 48 // ----------- 49 // - statics - 50 // ----------- 51 52 sal_uLong Animation::mnAnimCount = 0UL; 53 54 // ------------------- 55 // - AnimationBitmap - 56 // ------------------- 57 58 sal_uLong AnimationBitmap::GetChecksum() const 59 { 60 sal_uInt32 nCrc = aBmpEx.GetChecksum(); 61 SVBT32 aBT32; 62 63 UInt32ToSVBT32( aPosPix.X(), aBT32 ); 64 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 65 66 UInt32ToSVBT32( aPosPix.Y(), aBT32 ); 67 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 68 69 UInt32ToSVBT32( aSizePix.Width(), aBT32 ); 70 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 71 72 UInt32ToSVBT32( aSizePix.Height(), aBT32 ); 73 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 74 75 UInt32ToSVBT32( (long) nWait, aBT32 ); 76 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 77 78 UInt32ToSVBT32( (long) eDisposal, aBT32 ); 79 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 80 81 UInt32ToSVBT32( (long) bUserInput, aBT32 ); 82 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 83 84 return nCrc; 85 } 86 87 // ------------- 88 // - Animation - 89 // ------------- 90 91 Animation::Animation() : 92 mnLoopCount ( 0 ), 93 mnLoops ( 0 ), 94 mnPos ( 0 ), 95 meCycleMode ( CYCLE_NORMAL ), 96 mbIsInAnimation ( sal_False ), 97 mbLoopTerminated ( sal_False ), 98 mbIsWaiting ( sal_False ) 99 { 100 DBG_CTOR( Animation, NULL ); 101 maTimer.SetTimeoutHdl( LINK( this, Animation, ImplTimeoutHdl ) ); 102 mpViewList = new List; 103 } 104 105 // ----------------------------------------------------------------------- 106 107 Animation::Animation( const Animation& rAnimation ) : 108 maBitmapEx ( rAnimation.maBitmapEx ), 109 maGlobalSize ( rAnimation.maGlobalSize ), 110 mnLoopCount ( rAnimation.mnLoopCount ), 111 mnPos ( rAnimation.mnPos ), 112 meCycleMode ( rAnimation.meCycleMode ), 113 mbIsInAnimation ( sal_False ), 114 mbLoopTerminated ( rAnimation.mbLoopTerminated ), 115 mbIsWaiting ( rAnimation.mbIsWaiting ) 116 { 117 DBG_CTOR( Animation, NULL ); 118 119 for( long i = 0, nCount = rAnimation.maList.Count(); i < nCount; i++ ) 120 maList.Insert( new AnimationBitmap( *(AnimationBitmap*) rAnimation.maList.GetObject( i ) ), LIST_APPEND ); 121 122 maTimer.SetTimeoutHdl( LINK( this, Animation, ImplTimeoutHdl ) ); 123 mpViewList = new List; 124 mnLoops = mbLoopTerminated ? 0 : mnLoopCount; 125 } 126 127 // ----------------------------------------------------------------------- 128 129 Animation::~Animation() 130 { 131 DBG_DTOR( Animation, NULL ); 132 133 if( mbIsInAnimation ) 134 Stop(); 135 136 for( void* pStepBmp = maList.First(); pStepBmp; pStepBmp = maList.Next() ) 137 delete (AnimationBitmap*) pStepBmp; 138 139 for( void* pView = mpViewList->First(); pView; pView = mpViewList->Next() ) 140 delete (ImplAnimView*) pView; 141 142 delete mpViewList; 143 } 144 145 // ----------------------------------------------------------------------- 146 147 Animation& Animation::operator=( const Animation& rAnimation ) 148 { 149 Clear(); 150 151 for( long i = 0, nCount = rAnimation.maList.Count(); i < nCount; i++ ) 152 maList.Insert( new AnimationBitmap( *(AnimationBitmap*) rAnimation.maList.GetObject( i ) ), LIST_APPEND ); 153 154 maGlobalSize = rAnimation.maGlobalSize; 155 maBitmapEx = rAnimation.maBitmapEx; 156 meCycleMode = rAnimation.meCycleMode; 157 mnLoopCount = rAnimation.mnLoopCount; 158 mnPos = rAnimation.mnPos; 159 mbLoopTerminated = rAnimation.mbLoopTerminated; 160 mbIsWaiting = rAnimation.mbIsWaiting; 161 mnLoops = mbLoopTerminated ? 0 : mnLoopCount; 162 163 return *this; 164 } 165 166 // ----------------------------------------------------------------------- 167 168 sal_Bool Animation::operator==( const Animation& rAnimation ) const 169 { 170 const sal_uLong nCount = maList.Count(); 171 sal_Bool bRet = sal_False; 172 173 if( rAnimation.maList.Count() == nCount && 174 rAnimation.maBitmapEx == maBitmapEx && 175 rAnimation.maGlobalSize == maGlobalSize && 176 rAnimation.meCycleMode == meCycleMode ) 177 { 178 bRet = sal_True; 179 180 for( sal_uLong n = 0; n < nCount; n++ ) 181 { 182 if( ( *(AnimationBitmap*) maList.GetObject( n ) ) != 183 ( *(AnimationBitmap*) rAnimation.maList.GetObject( n ) ) ) 184 { 185 bRet = sal_False; 186 break; 187 } 188 } 189 } 190 191 return bRet; 192 } 193 194 // ------------------------------------------------------------------ 195 196 sal_Bool Animation::IsEqual( const Animation& rAnimation ) const 197 { 198 const sal_uLong nCount = maList.Count(); 199 sal_Bool bRet = sal_False; 200 201 if( rAnimation.maList.Count() == nCount && 202 rAnimation.maBitmapEx.IsEqual( maBitmapEx ) && 203 rAnimation.maGlobalSize == maGlobalSize && 204 rAnimation.meCycleMode == meCycleMode ) 205 { 206 for( sal_uLong n = 0; ( n < nCount ) && !bRet; n++ ) 207 if( ( (AnimationBitmap*) maList.GetObject( n ) )->IsEqual( *(AnimationBitmap*) rAnimation.maList.GetObject( n ) ) ) 208 bRet = sal_True; 209 } 210 211 return bRet; 212 } 213 214 // ------------------------------------------------------------------ 215 216 sal_Bool Animation::IsEmpty() const 217 { 218 return( maBitmapEx.IsEmpty() && !maList.Count() ); 219 } 220 221 // ------------------------------------------------------------------ 222 223 void Animation::SetEmpty() 224 { 225 maTimer.Stop(); 226 mbIsInAnimation = sal_False; 227 maGlobalSize = Size(); 228 maBitmapEx.SetEmpty(); 229 230 for( void* pStepBmp = maList.First(); pStepBmp; pStepBmp = maList.Next() ) 231 delete (AnimationBitmap*) pStepBmp; 232 maList.Clear(); 233 234 for( void* pView = mpViewList->First(); pView; pView = mpViewList->Next() ) 235 delete (ImplAnimView*) pView; 236 mpViewList->Clear(); 237 } 238 239 // ----------------------------------------------------------------------- 240 241 void Animation::Clear() 242 { 243 SetEmpty(); 244 } 245 246 // ----------------------------------------------------------------------- 247 248 sal_Bool Animation::IsTransparent() const 249 { 250 Point aPoint; 251 Rectangle aRect( aPoint, maGlobalSize ); 252 sal_Bool bRet = sal_False; 253 254 // Falls irgendein 'kleines' Bildchen durch den Hintergrund 255 // ersetzt werden soll, muessen wir 'transparent' sein, um 256 // richtig dargestellt zu werden, da die Appl. aus Optimierungsgruenden 257 // kein Invalidate auf nicht-transp. Grafiken ausfuehren 258 for( long i = 0, nCount = maList.Count(); i < nCount; i++ ) 259 { 260 const AnimationBitmap* pAnimBmp = (AnimationBitmap*) maList.GetObject( i ); 261 262 if( DISPOSE_BACK == pAnimBmp->eDisposal && Rectangle( pAnimBmp->aPosPix, pAnimBmp->aSizePix ) != aRect ) 263 { 264 bRet = sal_True; 265 break; 266 } 267 } 268 269 if( !bRet ) 270 bRet = maBitmapEx.IsTransparent(); 271 272 return bRet; 273 } 274 275 // ----------------------------------------------------------------------- 276 277 sal_uLong Animation::GetSizeBytes() const 278 { 279 sal_uLong nSizeBytes = GetBitmapEx().GetSizeBytes(); 280 281 for( long i = 0, nCount = maList.Count(); i < nCount; i++ ) 282 { 283 const AnimationBitmap* pAnimBmp = (AnimationBitmap*) maList.GetObject( i ); 284 nSizeBytes += pAnimBmp->aBmpEx.GetSizeBytes(); 285 } 286 287 return nSizeBytes; 288 } 289 290 // ----------------------------------------------------------------------- 291 292 sal_uLong Animation::GetChecksum() const 293 { 294 SVBT32 aBT32; 295 sal_uInt32 nCrc = GetBitmapEx().GetChecksum(); 296 297 UInt32ToSVBT32( maList.Count(), aBT32 ); 298 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 299 300 UInt32ToSVBT32( maGlobalSize.Width(), aBT32 ); 301 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 302 303 UInt32ToSVBT32( maGlobalSize.Height(), aBT32 ); 304 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 305 306 UInt32ToSVBT32( (long) meCycleMode, aBT32 ); 307 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 308 309 for( long i = 0, nCount = maList.Count(); i < nCount; i++ ) 310 { 311 UInt32ToSVBT32( ( (AnimationBitmap*) maList.GetObject( i ) )->GetChecksum(), aBT32 ); 312 nCrc = rtl_crc32( nCrc, aBT32, 4 ); 313 } 314 315 return nCrc; 316 } 317 318 // ----------------------------------------------------------------------- 319 320 sal_Bool Animation::Start( OutputDevice* pOut, const Point& rDestPt, long nExtraData, 321 OutputDevice* pFirstFrameOutDev ) 322 { 323 return Start( pOut, rDestPt, pOut->PixelToLogic( maGlobalSize ), nExtraData, pFirstFrameOutDev ); 324 } 325 326 // ----------------------------------------------------------------------- 327 328 sal_Bool Animation::Start( OutputDevice* pOut, const Point& rDestPt, const Size& rDestSz, long nExtraData, 329 OutputDevice* pFirstFrameOutDev ) 330 { 331 sal_Bool bRet = sal_False; 332 333 if( maList.Count() ) 334 { 335 if( ( pOut->GetOutDevType() == OUTDEV_WINDOW ) && !mbLoopTerminated && 336 ( ANIMATION_TIMEOUT_ON_CLICK != ( (AnimationBitmap*) maList.GetObject( mnPos ) )->nWait ) ) 337 { 338 ImplAnimView* pView; 339 ImplAnimView* pMatch = NULL; 340 341 for( pView = (ImplAnimView*) mpViewList->First(); pView; pView = (ImplAnimView*) mpViewList->Next() ) 342 { 343 if( pView->ImplMatches( pOut, nExtraData ) ) 344 { 345 if( pView->ImplGetOutPos() == rDestPt && 346 pView->ImplGetOutSizePix() == pOut->LogicToPixel( rDestSz ) ) 347 { 348 pView->ImplRepaint(); 349 pMatch = pView; 350 } 351 else 352 { 353 delete (ImplAnimView*) mpViewList->Remove( pView ); 354 pView = NULL; 355 } 356 357 break; 358 } 359 } 360 361 if( !mpViewList->Count() ) 362 { 363 maTimer.Stop(); 364 mbIsInAnimation = sal_False; 365 mnPos = 0UL; 366 } 367 368 if( !pMatch ) 369 mpViewList->Insert( new ImplAnimView( this, pOut, rDestPt, rDestSz, nExtraData, pFirstFrameOutDev ), LIST_APPEND ); 370 371 if( !mbIsInAnimation ) 372 { 373 ImplRestartTimer( ( (AnimationBitmap*) maList.GetObject( mnPos ) )->nWait ); 374 mbIsInAnimation = sal_True; 375 } 376 } 377 else 378 Draw( pOut, rDestPt, rDestSz ); 379 380 bRet = sal_True; 381 } 382 383 return bRet; 384 } 385 386 // ----------------------------------------------------------------------- 387 388 void Animation::Stop( OutputDevice* pOut, long nExtraData ) 389 { 390 ImplAnimView* pView = (ImplAnimView*) mpViewList->First(); 391 392 while( pView ) 393 { 394 if( pView->ImplMatches( pOut, nExtraData ) ) 395 { 396 delete (ImplAnimView*) mpViewList->Remove( pView ); 397 pView = (ImplAnimView*) mpViewList->GetCurObject(); 398 } 399 else 400 pView = (ImplAnimView*) mpViewList->Next(); 401 } 402 403 if( !mpViewList->Count() ) 404 { 405 maTimer.Stop(); 406 mbIsInAnimation = sal_False; 407 } 408 } 409 410 // ----------------------------------------------------------------------- 411 412 void Animation::Draw( OutputDevice* pOut, const Point& rDestPt ) const 413 { 414 Draw( pOut, rDestPt, pOut->PixelToLogic( maGlobalSize ) ); 415 } 416 417 // ----------------------------------------------------------------------- 418 419 void Animation::Draw( OutputDevice* pOut, const Point& rDestPt, const Size& rDestSz ) const 420 { 421 const sal_uLong nCount = maList.Count(); 422 423 if( nCount ) 424 { 425 AnimationBitmap* pObj = (AnimationBitmap*) maList.GetObject( Min( mnPos, (long) nCount - 1L ) ); 426 427 if( pOut->GetConnectMetaFile() || ( pOut->GetOutDevType() == OUTDEV_PRINTER ) ) 428 ( (AnimationBitmap*) maList.GetObject( 0 ) )->aBmpEx.Draw( pOut, rDestPt, rDestSz ); 429 else if( ANIMATION_TIMEOUT_ON_CLICK == pObj->nWait ) 430 pObj->aBmpEx.Draw( pOut, rDestPt, rDestSz ); 431 else 432 { 433 const sal_uLong nOldPos = mnPos; 434 ( (Animation*) this )->mnPos = mbLoopTerminated ? ( nCount - 1UL ) : mnPos; 435 delete new ImplAnimView( (Animation*) this, pOut, rDestPt, rDestSz, 0 ); 436 ( (Animation*) this )->mnPos = nOldPos; 437 } 438 } 439 } 440 441 // ----------------------------------------------------------------------- 442 443 void Animation::ImplRestartTimer( sal_uLong nTimeout ) 444 { 445 maTimer.SetTimeout( Max( nTimeout, (sal_uLong)(MIN_TIMEOUT + ( mnAnimCount - 1 ) * INC_TIMEOUT) ) * 10L ); 446 maTimer.Start(); 447 } 448 449 // ----------------------------------------------------------------------- 450 451 IMPL_LINK( Animation, ImplTimeoutHdl, Timer*, EMPTYARG ) 452 { 453 const sal_uLong nAnimCount = maList.Count(); 454 455 if( nAnimCount ) 456 { 457 ImplAnimView* pView; 458 sal_Bool bGlobalPause = sal_True; 459 460 if( maNotifyLink.IsSet() ) 461 { 462 AInfo* pAInfo; 463 464 // create AInfo-List 465 for( pView = (ImplAnimView*) mpViewList->First(); pView; pView = (ImplAnimView*) mpViewList->Next() ) 466 maAInfoList.Insert( pView->ImplCreateAInfo() ); 467 468 maNotifyLink.Call( this ); 469 470 // set view state from AInfo structure 471 for( pAInfo = (AInfo*) maAInfoList.First(); pAInfo; pAInfo = (AInfo*) maAInfoList.Next() ) 472 { 473 if( !pAInfo->pViewData ) 474 { 475 pView = new ImplAnimView( this, pAInfo->pOutDev, 476 pAInfo->aStartOrg, pAInfo->aStartSize, pAInfo->nExtraData ); 477 478 mpViewList->Insert( pView, LIST_APPEND ); 479 } 480 else 481 pView = (ImplAnimView*) pAInfo->pViewData; 482 483 pView->ImplPause( pAInfo->bPause ); 484 pView->ImplSetMarked( sal_True ); 485 } 486 487 // delete AInfo structures 488 for( pAInfo = (AInfo*) maAInfoList.First(); pAInfo; pAInfo = (AInfo*) maAInfoList.Next() ) 489 delete (AInfo*) pAInfo; 490 maAInfoList.Clear(); 491 492 // delete all unmarked views and reset marked state 493 pView = (ImplAnimView*) mpViewList->First(); 494 while( pView ) 495 { 496 if( !pView->ImplIsMarked() ) 497 { 498 delete (ImplAnimView*) mpViewList->Remove( pView ); 499 pView = (ImplAnimView*) mpViewList->GetCurObject(); 500 } 501 else 502 { 503 if( !pView->ImplIsPause() ) 504 bGlobalPause = sal_False; 505 506 pView->ImplSetMarked( sal_False ); 507 pView = (ImplAnimView*) mpViewList->Next(); 508 } 509 } 510 } 511 else 512 bGlobalPause = sal_False; 513 514 if( !mpViewList->Count() ) 515 Stop(); 516 else if( bGlobalPause ) 517 ImplRestartTimer( 10 ); 518 else 519 { 520 AnimationBitmap* pStepBmp = (AnimationBitmap*) maList.GetObject( ++mnPos ); 521 522 if( !pStepBmp ) 523 { 524 if( mnLoops == 1 ) 525 { 526 Stop(); 527 mbLoopTerminated = sal_True; 528 mnPos = nAnimCount - 1UL; 529 maBitmapEx = ( (AnimationBitmap*) maList.GetObject( mnPos ) )->aBmpEx; 530 return 0L; 531 } 532 else 533 { 534 if( mnLoops ) 535 mnLoops--; 536 537 mnPos = 0; 538 pStepBmp = (AnimationBitmap*) maList.GetObject( mnPos ); 539 } 540 } 541 542 // Paint all views; after painting check, if view is 543 // marked; in this case remove view, because area of output 544 // lies out of display area of window; mark state is 545 // set from view itself 546 pView = (ImplAnimView*) mpViewList->First(); 547 while( pView ) 548 { 549 pView->ImplDraw( mnPos ); 550 551 if( pView->ImplIsMarked() ) 552 { 553 delete (ImplAnimView*) mpViewList->Remove( pView ); 554 pView = (ImplAnimView*) mpViewList->GetCurObject(); 555 } 556 else 557 pView = (ImplAnimView*) mpViewList->Next(); 558 } 559 560 // stop or restart timer 561 if( !mpViewList->Count() ) 562 Stop(); 563 else 564 ImplRestartTimer( pStepBmp->nWait ); 565 } 566 } 567 else 568 Stop(); 569 570 return 0L; 571 } 572 573 // ----------------------------------------------------------------------- 574 575 sal_Bool Animation::Insert( const AnimationBitmap& rStepBmp ) 576 { 577 sal_Bool bRet = sal_False; 578 579 if( !IsInAnimation() ) 580 { 581 Point aPoint; 582 Rectangle aGlobalRect( aPoint, maGlobalSize ); 583 584 maGlobalSize = aGlobalRect.Union( Rectangle( rStepBmp.aPosPix, rStepBmp.aSizePix ) ).GetSize(); 585 maList.Insert( new AnimationBitmap( rStepBmp ), LIST_APPEND ); 586 587 // zunaechst nehmen wir die erste BitmapEx als Ersatz-BitmapEx 588 if( maList.Count() == 1 ) 589 maBitmapEx = rStepBmp.aBmpEx; 590 591 bRet = sal_True; 592 } 593 594 return bRet; 595 } 596 597 // ----------------------------------------------------------------------- 598 599 const AnimationBitmap& Animation::Get( sal_uInt16 nAnimation ) const 600 { 601 DBG_ASSERT( ( nAnimation < maList.Count() ), "No object at this position" ); 602 return *(AnimationBitmap*) maList.GetObject( nAnimation ); 603 } 604 605 // ----------------------------------------------------------------------- 606 607 void Animation::Replace( const AnimationBitmap& rNewAnimationBitmap, sal_uInt16 nAnimation ) 608 { 609 DBG_ASSERT( ( nAnimation < maList.Count() ), "No object at this position" ); 610 611 delete (AnimationBitmap*) maList.Replace( new AnimationBitmap( rNewAnimationBitmap ), nAnimation ); 612 613 // Falls wir an erster Stelle einfuegen, 614 // muessen wir natuerlich auch, 615 // auch die Ersatzdarstellungs-BitmapEx 616 // aktualisieren; 617 if ( ( !nAnimation && ( !mbLoopTerminated || ( maList.Count() == 1 ) ) ) || 618 ( ( nAnimation == maList.Count() - 1 ) && mbLoopTerminated ) ) 619 { 620 maBitmapEx = rNewAnimationBitmap.aBmpEx; 621 } 622 } 623 624 // ----------------------------------------------------------------------- 625 626 void Animation::SetLoopCount( const sal_uLong nLoopCount ) 627 { 628 mnLoopCount = nLoopCount; 629 ResetLoopCount(); 630 } 631 632 // ----------------------------------------------------------------------- 633 634 void Animation::ResetLoopCount() 635 { 636 mnLoops = mnLoopCount; 637 mbLoopTerminated = sal_False; 638 } 639 640 // ----------------------------------------------------------------------- 641 642 sal_Bool Animation::Convert( BmpConversion eConversion ) 643 { 644 DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" ); 645 646 sal_Bool bRet; 647 648 if( !IsInAnimation() && maList.Count() ) 649 { 650 bRet = sal_True; 651 652 for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() ) 653 bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.Convert( eConversion ); 654 655 maBitmapEx.Convert( eConversion ); 656 } 657 else 658 bRet = sal_False; 659 660 return bRet; 661 } 662 663 // ----------------------------------------------------------------------- 664 665 sal_Bool Animation::ReduceColors( sal_uInt16 nNewColorCount, BmpReduce eReduce ) 666 { 667 DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" ); 668 669 sal_Bool bRet; 670 671 if( !IsInAnimation() && maList.Count() ) 672 { 673 bRet = sal_True; 674 675 for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() ) 676 bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.ReduceColors( nNewColorCount, eReduce ); 677 678 maBitmapEx.ReduceColors( nNewColorCount, eReduce ); 679 } 680 else 681 bRet = sal_False; 682 683 return bRet; 684 } 685 686 // ----------------------------------------------------------------------- 687 688 sal_Bool Animation::Invert() 689 { 690 DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" ); 691 692 sal_Bool bRet; 693 694 if( !IsInAnimation() && maList.Count() ) 695 { 696 bRet = sal_True; 697 698 for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() ) 699 bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.Invert(); 700 701 maBitmapEx.Invert(); 702 } 703 else 704 bRet = sal_False; 705 706 return bRet; 707 } 708 709 // ----------------------------------------------------------------------- 710 711 sal_Bool Animation::Mirror( sal_uLong nMirrorFlags ) 712 { 713 DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" ); 714 715 sal_Bool bRet; 716 717 if( !IsInAnimation() && maList.Count() ) 718 { 719 bRet = sal_True; 720 721 if( nMirrorFlags ) 722 { 723 for( AnimationBitmap* pStepBmp = (AnimationBitmap*) maList.First(); 724 pStepBmp && bRet; 725 pStepBmp = (AnimationBitmap*) maList.Next() ) 726 { 727 if( ( bRet = pStepBmp->aBmpEx.Mirror( nMirrorFlags ) ) == sal_True ) 728 { 729 if( nMirrorFlags & BMP_MIRROR_HORZ ) 730 pStepBmp->aPosPix.X() = maGlobalSize.Width() - pStepBmp->aPosPix.X() - pStepBmp->aSizePix.Width(); 731 732 if( nMirrorFlags & BMP_MIRROR_VERT ) 733 pStepBmp->aPosPix.Y() = maGlobalSize.Height() - pStepBmp->aPosPix.Y() - pStepBmp->aSizePix.Height(); 734 } 735 } 736 737 maBitmapEx.Mirror( nMirrorFlags ); 738 } 739 } 740 else 741 bRet = sal_False; 742 743 return bRet; 744 } 745 746 // ----------------------------------------------------------------------- 747 748 sal_Bool Animation::Dither( sal_uLong nDitherFlags ) 749 { 750 DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" ); 751 752 sal_Bool bRet; 753 754 if( !IsInAnimation() && maList.Count() ) 755 { 756 bRet = sal_True; 757 758 for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() ) 759 bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.Dither( nDitherFlags ); 760 761 maBitmapEx.Dither( nDitherFlags ); 762 } 763 else 764 bRet = sal_False; 765 766 return bRet; 767 } 768 769 // ----------------------------------------------------------------------- 770 771 sal_Bool Animation::Adjust( short nLuminancePercent, short nContrastPercent, 772 short nChannelRPercent, short nChannelGPercent, short nChannelBPercent, 773 double fGamma, sal_Bool bInvert ) 774 { 775 DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" ); 776 777 sal_Bool bRet; 778 779 if( !IsInAnimation() && maList.Count() ) 780 { 781 bRet = sal_True; 782 783 for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() ) 784 { 785 bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.Adjust( nLuminancePercent, nContrastPercent, 786 nChannelRPercent, nChannelGPercent, nChannelBPercent, 787 fGamma, bInvert ); 788 } 789 790 maBitmapEx.Adjust( nLuminancePercent, nContrastPercent, 791 nChannelRPercent, nChannelGPercent, nChannelBPercent, 792 fGamma, bInvert ); 793 } 794 else 795 bRet = sal_False; 796 797 return bRet; 798 } 799 800 // ----------------------------------------------------------------------- 801 802 sal_Bool Animation::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam, const Link* pProgress ) 803 { 804 DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" ); 805 806 sal_Bool bRet; 807 808 if( !IsInAnimation() && maList.Count() ) 809 { 810 bRet = sal_True; 811 812 for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() ) 813 bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.Filter( eFilter, pFilterParam, pProgress ); 814 815 maBitmapEx.Filter( eFilter, pFilterParam, pProgress ); 816 } 817 else 818 bRet = sal_False; 819 820 return bRet; 821 } 822 823 // ----------------------------------------------------------------------- 824 825 SvStream& operator<<( SvStream& rOStm, const Animation& rAnimation ) 826 { 827 const sal_uInt16 nCount = rAnimation.Count(); 828 829 if( nCount ) 830 { 831 const ByteString aDummyStr; 832 const sal_uInt32 nDummy32 = 0UL; 833 834 // Falls keine BitmapEx gesetzt wurde, schreiben wir 835 // einfach die erste Bitmap der Animation 836 if( !rAnimation.GetBitmapEx().GetBitmap() ) 837 rOStm << rAnimation.Get( 0 ).aBmpEx; 838 else 839 rOStm << rAnimation.GetBitmapEx(); 840 841 // Kennung schreiben ( SDANIMA1 ) 842 rOStm << (sal_uInt32) 0x5344414e << (sal_uInt32) 0x494d4931; 843 844 for( sal_uInt16 i = 0; i < nCount; i++ ) 845 { 846 const AnimationBitmap& rAnimBmp = rAnimation.Get( i ); 847 const sal_uInt16 nRest = nCount - i - 1; 848 849 // AnimationBitmap schreiben 850 rOStm << rAnimBmp.aBmpEx; 851 rOStm << rAnimBmp.aPosPix; 852 rOStm << rAnimBmp.aSizePix; 853 rOStm << rAnimation.maGlobalSize; 854 rOStm << (sal_uInt16) ( ( ANIMATION_TIMEOUT_ON_CLICK == rAnimBmp.nWait ) ? 65535 : rAnimBmp.nWait ); 855 rOStm << (sal_uInt16) rAnimBmp.eDisposal; 856 rOStm << (sal_uInt8) rAnimBmp.bUserInput; 857 rOStm << (sal_uInt32) rAnimation.mnLoopCount; 858 rOStm << nDummy32; // unbenutzt 859 rOStm << nDummy32; // unbenutzt 860 rOStm << nDummy32; // unbenutzt 861 rOStm << aDummyStr; // unbenutzt 862 rOStm << nRest; // Anzahl der Strukturen, die noch _folgen_ 863 } 864 } 865 866 return rOStm; 867 } 868 869 // ----------------------------------------------------------------------- 870 871 SvStream& operator>>( SvStream& rIStm, Animation& rAnimation ) 872 { 873 Bitmap aBmp; 874 sal_uLong nStmPos = rIStm.Tell(); 875 sal_uInt32 nAnimMagic1, nAnimMagic2; 876 sal_uInt16 nOldFormat = rIStm.GetNumberFormatInt(); 877 sal_Bool bReadAnimations = sal_False; 878 879 rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); 880 nStmPos = rIStm.Tell(); 881 rIStm >> nAnimMagic1 >> nAnimMagic2; 882 883 rAnimation.Clear(); 884 885 // Wenn die BitmapEx am Anfang schon gelesen 886 // wurde ( von Graphic ), koennen wir direkt die Animationsbitmaps einlesen 887 if( ( nAnimMagic1 == 0x5344414e ) && ( nAnimMagic2 == 0x494d4931 ) && !rIStm.GetError() ) 888 bReadAnimations = sal_True; 889 // ansonsten versuchen wir erstmal die Bitmap(-Ex) zu lesen 890 else 891 { 892 rIStm.Seek( nStmPos ); 893 rIStm >> rAnimation.maBitmapEx; 894 nStmPos = rIStm.Tell(); 895 rIStm >> nAnimMagic1 >> nAnimMagic2; 896 897 if( ( nAnimMagic1 == 0x5344414e ) && ( nAnimMagic2 == 0x494d4931 ) && !rIStm.GetError() ) 898 bReadAnimations = sal_True; 899 else 900 rIStm.Seek( nStmPos ); 901 } 902 903 // ggf. Animationsbitmaps lesen 904 if( bReadAnimations ) 905 { 906 AnimationBitmap aAnimBmp; 907 BitmapEx aBmpEx; 908 ByteString aDummyStr; 909 sal_uInt32 nTmp32; 910 sal_uInt16 nTmp16; 911 sal_uInt8 cTmp; 912 913 do 914 { 915 rIStm >> aAnimBmp.aBmpEx; 916 rIStm >> aAnimBmp.aPosPix; 917 rIStm >> aAnimBmp.aSizePix; 918 rIStm >> rAnimation.maGlobalSize; 919 rIStm >> nTmp16; aAnimBmp.nWait = ( ( 65535 == nTmp16 ) ? ANIMATION_TIMEOUT_ON_CLICK : nTmp16 ); 920 rIStm >> nTmp16; aAnimBmp.eDisposal = ( Disposal) nTmp16; 921 rIStm >> cTmp; aAnimBmp.bUserInput = (sal_Bool) cTmp; 922 rIStm >> nTmp32; rAnimation.mnLoopCount = (sal_uInt16) nTmp32; 923 rIStm >> nTmp32; // unbenutzt 924 rIStm >> nTmp32; // unbenutzt 925 rIStm >> nTmp32; // unbenutzt 926 rIStm >> aDummyStr; // unbenutzt 927 rIStm >> nTmp16; // Rest zu lesen 928 929 rAnimation.Insert( aAnimBmp ); 930 } 931 while( nTmp16 && !rIStm.GetError() ); 932 933 rAnimation.ResetLoopCount(); 934 } 935 936 rIStm.SetNumberFormatInt( nOldFormat ); 937 938 return rIStm; 939 } 940