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