merge the formfield patch from ooo-build
[ooovba.git] / vcl / source / gdi / animate.cxx
blobdf734ecddfaeb994a12a73660f9c3f05881873d6
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: animate.cxx,v $
10 * $Revision: 1.11 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #define ENABLE_BYTESTRING_STREAM_OPERATORS
35 #include <vcl/animate.hxx>
36 #include <tools/debug.hxx>
37 #include <tools/stream.hxx>
38 #include <rtl/crc.h>
39 #include <vcl/virdev.hxx>
40 #include <vcl/window.hxx>
41 #include <impanmvw.hxx>
42 DBG_NAME( Animation )
44 // -----------
45 // - Defines -
46 // -----------
48 #define MIN_TIMEOUT 2L
49 #define INC_TIMEOUT 0L
51 // -----------
52 // - statics -
53 // -----------
55 ULONG Animation::mnAnimCount = 0UL;
57 // -------------------
58 // - AnimationBitmap -
59 // -------------------
61 ULONG AnimationBitmap::GetChecksum() const
63 sal_uInt32 nCrc = aBmpEx.GetChecksum();
64 SVBT32 aBT32;
66 UInt32ToSVBT32( aPosPix.X(), aBT32 );
67 nCrc = rtl_crc32( nCrc, aBT32, 4 );
69 UInt32ToSVBT32( aPosPix.Y(), aBT32 );
70 nCrc = rtl_crc32( nCrc, aBT32, 4 );
72 UInt32ToSVBT32( aSizePix.Width(), aBT32 );
73 nCrc = rtl_crc32( nCrc, aBT32, 4 );
75 UInt32ToSVBT32( aSizePix.Height(), aBT32 );
76 nCrc = rtl_crc32( nCrc, aBT32, 4 );
78 UInt32ToSVBT32( (long) nWait, aBT32 );
79 nCrc = rtl_crc32( nCrc, aBT32, 4 );
81 UInt32ToSVBT32( (long) eDisposal, aBT32 );
82 nCrc = rtl_crc32( nCrc, aBT32, 4 );
84 UInt32ToSVBT32( (long) bUserInput, aBT32 );
85 nCrc = rtl_crc32( nCrc, aBT32, 4 );
87 return nCrc;
90 // -------------
91 // - Animation -
92 // -------------
94 Animation::Animation() :
95 mnLoopCount ( 0 ),
96 mnLoops ( 0 ),
97 mnPos ( 0 ),
98 meCycleMode ( CYCLE_NORMAL ),
99 mbIsInAnimation ( FALSE ),
100 mbLoopTerminated ( FALSE ),
101 mbIsWaiting ( FALSE )
103 DBG_CTOR( Animation, NULL );
104 maTimer.SetTimeoutHdl( LINK( this, Animation, ImplTimeoutHdl ) );
105 mpViewList = new List;
108 // -----------------------------------------------------------------------
110 Animation::Animation( const Animation& rAnimation ) :
111 maBitmapEx ( rAnimation.maBitmapEx ),
112 maGlobalSize ( rAnimation.maGlobalSize ),
113 mnLoopCount ( rAnimation.mnLoopCount ),
114 mnPos ( rAnimation.mnPos ),
115 meCycleMode ( rAnimation.meCycleMode ),
116 mbIsInAnimation ( FALSE ),
117 mbLoopTerminated ( rAnimation.mbLoopTerminated ),
118 mbIsWaiting ( rAnimation.mbIsWaiting )
120 DBG_CTOR( Animation, NULL );
122 for( long i = 0, nCount = rAnimation.maList.Count(); i < nCount; i++ )
123 maList.Insert( new AnimationBitmap( *(AnimationBitmap*) rAnimation.maList.GetObject( i ) ), LIST_APPEND );
125 maTimer.SetTimeoutHdl( LINK( this, Animation, ImplTimeoutHdl ) );
126 mpViewList = new List;
127 mnLoops = mbLoopTerminated ? 0 : mnLoopCount;
130 // -----------------------------------------------------------------------
132 Animation::~Animation()
134 DBG_DTOR( Animation, NULL );
136 if( mbIsInAnimation )
137 Stop();
139 for( void* pStepBmp = maList.First(); pStepBmp; pStepBmp = maList.Next() )
140 delete (AnimationBitmap*) pStepBmp;
142 for( void* pView = mpViewList->First(); pView; pView = mpViewList->Next() )
143 delete (ImplAnimView*) pView;
145 delete mpViewList;
148 // -----------------------------------------------------------------------
150 Animation& Animation::operator=( const Animation& rAnimation )
152 Clear();
154 for( long i = 0, nCount = rAnimation.maList.Count(); i < nCount; i++ )
155 maList.Insert( new AnimationBitmap( *(AnimationBitmap*) rAnimation.maList.GetObject( i ) ), LIST_APPEND );
157 maGlobalSize = rAnimation.maGlobalSize;
158 maBitmapEx = rAnimation.maBitmapEx;
159 meCycleMode = rAnimation.meCycleMode;
160 mnLoopCount = rAnimation.mnLoopCount;
161 mnPos = rAnimation.mnPos;
162 mbLoopTerminated = rAnimation.mbLoopTerminated;
163 mbIsWaiting = rAnimation.mbIsWaiting;
164 mnLoops = mbLoopTerminated ? 0 : mnLoopCount;
166 return *this;
169 // -----------------------------------------------------------------------
171 BOOL Animation::operator==( const Animation& rAnimation ) const
173 const ULONG nCount = maList.Count();
174 BOOL bRet = FALSE;
176 if( rAnimation.maList.Count() == nCount &&
177 rAnimation.maBitmapEx == maBitmapEx &&
178 rAnimation.maGlobalSize == maGlobalSize &&
179 rAnimation.meCycleMode == meCycleMode )
181 bRet = TRUE;
183 for( ULONG n = 0; n < nCount; n++ )
185 if( ( *(AnimationBitmap*) maList.GetObject( n ) ) !=
186 ( *(AnimationBitmap*) rAnimation.maList.GetObject( n ) ) )
188 bRet = FALSE;
189 break;
194 return bRet;
197 // ------------------------------------------------------------------
199 BOOL Animation::IsEqual( const Animation& rAnimation ) const
201 const ULONG nCount = maList.Count();
202 BOOL bRet = FALSE;
204 if( rAnimation.maList.Count() == nCount &&
205 rAnimation.maBitmapEx.IsEqual( maBitmapEx ) &&
206 rAnimation.maGlobalSize == maGlobalSize &&
207 rAnimation.meCycleMode == meCycleMode )
209 for( ULONG n = 0; ( n < nCount ) && !bRet; n++ )
210 if( ( (AnimationBitmap*) maList.GetObject( n ) )->IsEqual( *(AnimationBitmap*) rAnimation.maList.GetObject( n ) ) )
211 bRet = TRUE;
214 return bRet;
217 // ------------------------------------------------------------------
219 BOOL Animation::IsEmpty() const
221 return( maBitmapEx.IsEmpty() && !maList.Count() );
224 // ------------------------------------------------------------------
226 void Animation::SetEmpty()
228 maTimer.Stop();
229 mbIsInAnimation = FALSE;
230 maGlobalSize = Size();
231 maBitmapEx.SetEmpty();
233 for( void* pStepBmp = maList.First(); pStepBmp; pStepBmp = maList.Next() )
234 delete (AnimationBitmap*) pStepBmp;
235 maList.Clear();
237 for( void* pView = mpViewList->First(); pView; pView = mpViewList->Next() )
238 delete (ImplAnimView*) pView;
239 mpViewList->Clear();
242 // -----------------------------------------------------------------------
244 void Animation::Clear()
246 SetEmpty();
249 // -----------------------------------------------------------------------
251 BOOL Animation::IsTransparent() const
253 Point aPoint;
254 Rectangle aRect( aPoint, maGlobalSize );
255 BOOL bRet = FALSE;
257 // Falls irgendein 'kleines' Bildchen durch den Hintergrund
258 // ersetzt werden soll, muessen wir 'transparent' sein, um
259 // richtig dargestellt zu werden, da die Appl. aus Optimierungsgruenden
260 // kein Invalidate auf nicht-transp. Grafiken ausfuehren
261 for( long i = 0, nCount = maList.Count(); i < nCount; i++ )
263 const AnimationBitmap* pAnimBmp = (AnimationBitmap*) maList.GetObject( i );
265 if( DISPOSE_BACK == pAnimBmp->eDisposal && Rectangle( pAnimBmp->aPosPix, pAnimBmp->aSizePix ) != aRect )
267 bRet = TRUE;
268 break;
272 if( !bRet )
273 bRet = maBitmapEx.IsTransparent();
275 return bRet;
278 // -----------------------------------------------------------------------
280 ULONG Animation::GetSizeBytes() const
282 ULONG nSizeBytes = GetBitmapEx().GetSizeBytes();
284 for( long i = 0, nCount = maList.Count(); i < nCount; i++ )
286 const AnimationBitmap* pAnimBmp = (AnimationBitmap*) maList.GetObject( i );
287 nSizeBytes += pAnimBmp->aBmpEx.GetSizeBytes();
290 return nSizeBytes;
293 // -----------------------------------------------------------------------
295 ULONG Animation::GetChecksum() const
297 SVBT32 aBT32;
298 sal_uInt32 nCrc = GetBitmapEx().GetChecksum();
300 UInt32ToSVBT32( maList.Count(), aBT32 );
301 nCrc = rtl_crc32( nCrc, aBT32, 4 );
303 UInt32ToSVBT32( maGlobalSize.Width(), aBT32 );
304 nCrc = rtl_crc32( nCrc, aBT32, 4 );
306 UInt32ToSVBT32( maGlobalSize.Height(), aBT32 );
307 nCrc = rtl_crc32( nCrc, aBT32, 4 );
309 UInt32ToSVBT32( (long) meCycleMode, aBT32 );
310 nCrc = rtl_crc32( nCrc, aBT32, 4 );
312 for( long i = 0, nCount = maList.Count(); i < nCount; i++ )
314 UInt32ToSVBT32( ( (AnimationBitmap*) maList.GetObject( i ) )->GetChecksum(), aBT32 );
315 nCrc = rtl_crc32( nCrc, aBT32, 4 );
318 return nCrc;
321 // -----------------------------------------------------------------------
323 BOOL Animation::Start( OutputDevice* pOut, const Point& rDestPt, long nExtraData,
324 OutputDevice* pFirstFrameOutDev )
326 return Start( pOut, rDestPt, pOut->PixelToLogic( maGlobalSize ), nExtraData, pFirstFrameOutDev );
329 // -----------------------------------------------------------------------
331 BOOL Animation::Start( OutputDevice* pOut, const Point& rDestPt, const Size& rDestSz, long nExtraData,
332 OutputDevice* pFirstFrameOutDev )
334 BOOL bRet = FALSE;
336 if( maList.Count() )
338 if( ( pOut->GetOutDevType() == OUTDEV_WINDOW ) && !mbLoopTerminated &&
339 ( ANIMATION_TIMEOUT_ON_CLICK != ( (AnimationBitmap*) maList.GetObject( mnPos ) )->nWait ) )
341 ImplAnimView* pView;
342 ImplAnimView* pMatch = NULL;
344 for( pView = (ImplAnimView*) mpViewList->First(); pView; pView = (ImplAnimView*) mpViewList->Next() )
346 if( pView->ImplMatches( pOut, nExtraData ) )
348 if( pView->ImplGetOutPos() == rDestPt &&
349 pView->ImplGetOutSizePix() == pOut->LogicToPixel( rDestSz ) )
351 pView->ImplRepaint();
352 pMatch = pView;
354 else
356 delete (ImplAnimView*) mpViewList->Remove( pView );
357 pView = NULL;
360 break;
364 if( !mpViewList->Count() )
366 maTimer.Stop();
367 mbIsInAnimation = FALSE;
368 mnPos = 0UL;
371 if( !pMatch )
372 mpViewList->Insert( new ImplAnimView( this, pOut, rDestPt, rDestSz, nExtraData, pFirstFrameOutDev ), LIST_APPEND );
374 if( !mbIsInAnimation )
376 ImplRestartTimer( ( (AnimationBitmap*) maList.GetObject( mnPos ) )->nWait );
377 mbIsInAnimation = TRUE;
380 else
381 Draw( pOut, rDestPt, rDestSz );
383 bRet = TRUE;
386 return bRet;
389 // -----------------------------------------------------------------------
391 void Animation::Stop( OutputDevice* pOut, long nExtraData )
393 ImplAnimView* pView = (ImplAnimView*) mpViewList->First();
395 while( pView )
397 if( pView->ImplMatches( pOut, nExtraData ) )
399 delete (ImplAnimView*) mpViewList->Remove( pView );
400 pView = (ImplAnimView*) mpViewList->GetCurObject();
402 else
403 pView = (ImplAnimView*) mpViewList->Next();
406 if( !mpViewList->Count() )
408 maTimer.Stop();
409 mbIsInAnimation = FALSE;
413 // -----------------------------------------------------------------------
415 void Animation::Draw( OutputDevice* pOut, const Point& rDestPt ) const
417 Draw( pOut, rDestPt, pOut->PixelToLogic( maGlobalSize ) );
420 // -----------------------------------------------------------------------
422 void Animation::Draw( OutputDevice* pOut, const Point& rDestPt, const Size& rDestSz ) const
424 const ULONG nCount = maList.Count();
426 if( nCount )
428 AnimationBitmap* pObj = (AnimationBitmap*) maList.GetObject( Min( mnPos, (long) nCount - 1L ) );
430 if( pOut->GetConnectMetaFile() || ( pOut->GetOutDevType() == OUTDEV_PRINTER ) )
431 ( (AnimationBitmap*) maList.GetObject( 0 ) )->aBmpEx.Draw( pOut, rDestPt, rDestSz );
432 else if( ANIMATION_TIMEOUT_ON_CLICK == pObj->nWait )
433 pObj->aBmpEx.Draw( pOut, rDestPt, rDestSz );
434 else
436 const ULONG nOldPos = mnPos;
437 ( (Animation*) this )->mnPos = mbLoopTerminated ? ( nCount - 1UL ) : mnPos;
438 delete new ImplAnimView( (Animation*) this, pOut, rDestPt, rDestSz, 0 );
439 ( (Animation*) this )->mnPos = nOldPos;
444 // -----------------------------------------------------------------------
446 void Animation::ImplRestartTimer( ULONG nTimeout )
448 maTimer.SetTimeout( Max( nTimeout, (ULONG)(MIN_TIMEOUT + ( mnAnimCount - 1 ) * INC_TIMEOUT) ) * 10L );
449 maTimer.Start();
452 // -----------------------------------------------------------------------
454 IMPL_LINK( Animation, ImplTimeoutHdl, Timer*, EMPTYARG )
456 const ULONG nAnimCount = maList.Count();
458 if( nAnimCount )
460 ImplAnimView* pView;
461 BOOL bGlobalPause = TRUE;
463 if( maNotifyLink.IsSet() )
465 AInfo* pAInfo;
467 // create AInfo-List
468 for( pView = (ImplAnimView*) mpViewList->First(); pView; pView = (ImplAnimView*) mpViewList->Next() )
469 maAInfoList.Insert( pView->ImplCreateAInfo() );
471 maNotifyLink.Call( this );
473 // set view state from AInfo structure
474 for( pAInfo = (AInfo*) maAInfoList.First(); pAInfo; pAInfo = (AInfo*) maAInfoList.Next() )
476 if( !pAInfo->pViewData )
478 pView = new ImplAnimView( this, pAInfo->pOutDev,
479 pAInfo->aStartOrg, pAInfo->aStartSize, pAInfo->nExtraData );
481 mpViewList->Insert( pView, LIST_APPEND );
483 else
484 pView = (ImplAnimView*) pAInfo->pViewData;
486 pView->ImplPause( pAInfo->bPause );
487 pView->ImplSetMarked( TRUE );
490 // delete AInfo structures
491 for( pAInfo = (AInfo*) maAInfoList.First(); pAInfo; pAInfo = (AInfo*) maAInfoList.Next() )
492 delete (AInfo*) pAInfo;
493 maAInfoList.Clear();
495 // delete all unmarked views and reset marked state
496 pView = (ImplAnimView*) mpViewList->First();
497 while( pView )
499 if( !pView->ImplIsMarked() )
501 delete (ImplAnimView*) mpViewList->Remove( pView );
502 pView = (ImplAnimView*) mpViewList->GetCurObject();
504 else
506 if( !pView->ImplIsPause() )
507 bGlobalPause = FALSE;
509 pView->ImplSetMarked( FALSE );
510 pView = (ImplAnimView*) mpViewList->Next();
514 else
515 bGlobalPause = FALSE;
517 if( !mpViewList->Count() )
518 Stop();
519 else if( bGlobalPause )
520 ImplRestartTimer( 10 );
521 else
523 AnimationBitmap* pStepBmp = (AnimationBitmap*) maList.GetObject( ++mnPos );
525 if( !pStepBmp )
527 if( mnLoops == 1 )
529 Stop();
530 mbLoopTerminated = TRUE;
531 mnPos = nAnimCount - 1UL;
532 maBitmapEx = ( (AnimationBitmap*) maList.GetObject( mnPos ) )->aBmpEx;
533 return 0L;
535 else
537 if( mnLoops )
538 mnLoops--;
540 mnPos = 0;
541 pStepBmp = (AnimationBitmap*) maList.GetObject( mnPos );
545 // Paint all views; after painting check, if view is
546 // marked; in this case remove view, because area of output
547 // lies out of display area of window; mark state is
548 // set from view itself
549 pView = (ImplAnimView*) mpViewList->First();
550 while( pView )
552 pView->ImplDraw( mnPos );
554 if( pView->ImplIsMarked() )
556 delete (ImplAnimView*) mpViewList->Remove( pView );
557 pView = (ImplAnimView*) mpViewList->GetCurObject();
559 else
560 pView = (ImplAnimView*) mpViewList->Next();
563 // stop or restart timer
564 if( !mpViewList->Count() )
565 Stop();
566 else
567 ImplRestartTimer( pStepBmp->nWait );
570 else
571 Stop();
573 return 0L;
576 // -----------------------------------------------------------------------
578 BOOL Animation::Insert( const AnimationBitmap& rStepBmp )
580 BOOL bRet = FALSE;
582 if( !IsInAnimation() )
584 Point aPoint;
585 Rectangle aGlobalRect( aPoint, maGlobalSize );
587 maGlobalSize = aGlobalRect.Union( Rectangle( rStepBmp.aPosPix, rStepBmp.aSizePix ) ).GetSize();
588 maList.Insert( new AnimationBitmap( rStepBmp ), LIST_APPEND );
590 // zunaechst nehmen wir die erste BitmapEx als Ersatz-BitmapEx
591 if( maList.Count() == 1 )
592 maBitmapEx = rStepBmp.aBmpEx;
594 bRet = TRUE;
597 return bRet;
600 // -----------------------------------------------------------------------
602 const AnimationBitmap& Animation::Get( USHORT nAnimation ) const
604 DBG_ASSERT( ( nAnimation < maList.Count() ), "No object at this position" );
605 return *(AnimationBitmap*) maList.GetObject( nAnimation );
608 // -----------------------------------------------------------------------
610 void Animation::Replace( const AnimationBitmap& rNewAnimationBitmap, USHORT nAnimation )
612 DBG_ASSERT( ( nAnimation < maList.Count() ), "No object at this position" );
614 delete (AnimationBitmap*) maList.Replace( new AnimationBitmap( rNewAnimationBitmap ), nAnimation );
616 // Falls wir an erster Stelle einfuegen,
617 // muessen wir natuerlich auch,
618 // auch die Ersatzdarstellungs-BitmapEx
619 // aktualisieren;
620 if ( ( !nAnimation && ( !mbLoopTerminated || ( maList.Count() == 1 ) ) ) ||
621 ( ( nAnimation == maList.Count() - 1 ) && mbLoopTerminated ) )
623 maBitmapEx = rNewAnimationBitmap.aBmpEx;
627 // -----------------------------------------------------------------------
629 void Animation::SetLoopCount( const ULONG nLoopCount )
631 mnLoopCount = nLoopCount;
632 ResetLoopCount();
635 // -----------------------------------------------------------------------
637 void Animation::ResetLoopCount()
639 mnLoops = mnLoopCount;
640 mbLoopTerminated = FALSE;
643 // -----------------------------------------------------------------------
645 BOOL Animation::Convert( BmpConversion eConversion )
647 DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
649 BOOL bRet;
651 if( !IsInAnimation() && maList.Count() )
653 bRet = TRUE;
655 for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() )
656 bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.Convert( eConversion );
658 maBitmapEx.Convert( eConversion );
660 else
661 bRet = FALSE;
663 return bRet;
666 // -----------------------------------------------------------------------
668 BOOL Animation::ReduceColors( USHORT nNewColorCount, BmpReduce eReduce )
670 DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
672 BOOL bRet;
674 if( !IsInAnimation() && maList.Count() )
676 bRet = TRUE;
678 for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() )
679 bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.ReduceColors( nNewColorCount, eReduce );
681 maBitmapEx.ReduceColors( nNewColorCount, eReduce );
683 else
684 bRet = FALSE;
686 return bRet;
689 // -----------------------------------------------------------------------
691 BOOL Animation::Invert()
693 DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
695 BOOL bRet;
697 if( !IsInAnimation() && maList.Count() )
699 bRet = TRUE;
701 for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() )
702 bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.Invert();
704 maBitmapEx.Invert();
706 else
707 bRet = FALSE;
709 return bRet;
712 // -----------------------------------------------------------------------
714 BOOL Animation::Mirror( ULONG nMirrorFlags )
716 DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
718 BOOL bRet;
720 if( !IsInAnimation() && maList.Count() )
722 bRet = TRUE;
724 if( nMirrorFlags )
726 for( AnimationBitmap* pStepBmp = (AnimationBitmap*) maList.First();
727 pStepBmp && bRet;
728 pStepBmp = (AnimationBitmap*) maList.Next() )
730 if( ( bRet = pStepBmp->aBmpEx.Mirror( nMirrorFlags ) ) == TRUE )
732 if( nMirrorFlags & BMP_MIRROR_HORZ )
733 pStepBmp->aPosPix.X() = maGlobalSize.Width() - pStepBmp->aPosPix.X() - pStepBmp->aSizePix.Width();
735 if( nMirrorFlags & BMP_MIRROR_VERT )
736 pStepBmp->aPosPix.Y() = maGlobalSize.Height() - pStepBmp->aPosPix.Y() - pStepBmp->aSizePix.Height();
740 maBitmapEx.Mirror( nMirrorFlags );
743 else
744 bRet = FALSE;
746 return bRet;
749 // -----------------------------------------------------------------------
751 BOOL Animation::Dither( ULONG nDitherFlags )
753 DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
755 BOOL bRet;
757 if( !IsInAnimation() && maList.Count() )
759 bRet = TRUE;
761 for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() )
762 bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.Dither( nDitherFlags );
764 maBitmapEx.Dither( nDitherFlags );
766 else
767 bRet = FALSE;
769 return bRet;
772 // -----------------------------------------------------------------------
774 BOOL Animation::Adjust( short nLuminancePercent, short nContrastPercent,
775 short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
776 double fGamma, BOOL bInvert )
778 DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
780 BOOL bRet;
782 if( !IsInAnimation() && maList.Count() )
784 bRet = TRUE;
786 for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() )
788 bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.Adjust( nLuminancePercent, nContrastPercent,
789 nChannelRPercent, nChannelGPercent, nChannelBPercent,
790 fGamma, bInvert );
793 maBitmapEx.Adjust( nLuminancePercent, nContrastPercent,
794 nChannelRPercent, nChannelGPercent, nChannelBPercent,
795 fGamma, bInvert );
797 else
798 bRet = FALSE;
800 return bRet;
803 // -----------------------------------------------------------------------
805 BOOL Animation::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam, const Link* pProgress )
807 DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
809 BOOL bRet;
811 if( !IsInAnimation() && maList.Count() )
813 bRet = TRUE;
815 for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() )
816 bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.Filter( eFilter, pFilterParam, pProgress );
818 maBitmapEx.Filter( eFilter, pFilterParam, pProgress );
820 else
821 bRet = FALSE;
823 return bRet;
826 // -----------------------------------------------------------------------
828 SvStream& operator<<( SvStream& rOStm, const Animation& rAnimation )
830 const USHORT nCount = rAnimation.Count();
832 if( nCount )
834 const ByteString aDummyStr;
835 const UINT32 nDummy32 = 0UL;
837 // Falls keine BitmapEx gesetzt wurde, schreiben wir
838 // einfach die erste Bitmap der Animation
839 if( !rAnimation.GetBitmapEx().GetBitmap() )
840 rOStm << rAnimation.Get( 0 ).aBmpEx;
841 else
842 rOStm << rAnimation.GetBitmapEx();
844 // Kennung schreiben ( SDANIMA1 )
845 rOStm << (UINT32) 0x5344414e << (UINT32) 0x494d4931;
847 for( USHORT i = 0; i < nCount; i++ )
849 const AnimationBitmap& rAnimBmp = rAnimation.Get( i );
850 const UINT16 nRest = nCount - i - 1;
852 // AnimationBitmap schreiben
853 rOStm << rAnimBmp.aBmpEx;
854 rOStm << rAnimBmp.aPosPix;
855 rOStm << rAnimBmp.aSizePix;
856 rOStm << rAnimation.maGlobalSize;
857 rOStm << (UINT16) ( ( ANIMATION_TIMEOUT_ON_CLICK == rAnimBmp.nWait ) ? 65535 : rAnimBmp.nWait );
858 rOStm << (UINT16) rAnimBmp.eDisposal;
859 rOStm << (BYTE) rAnimBmp.bUserInput;
860 rOStm << (UINT32) rAnimation.mnLoopCount;
861 rOStm << nDummy32; // unbenutzt
862 rOStm << nDummy32; // unbenutzt
863 rOStm << nDummy32; // unbenutzt
864 rOStm << aDummyStr; // unbenutzt
865 rOStm << nRest; // Anzahl der Strukturen, die noch _folgen_
869 return rOStm;
872 // -----------------------------------------------------------------------
874 SvStream& operator>>( SvStream& rIStm, Animation& rAnimation )
876 Bitmap aBmp;
877 ULONG nStmPos = rIStm.Tell();
878 UINT32 nAnimMagic1, nAnimMagic2;
879 USHORT nOldFormat = rIStm.GetNumberFormatInt();
880 BOOL bReadAnimations = FALSE;
882 rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
883 nStmPos = rIStm.Tell();
884 rIStm >> nAnimMagic1 >> nAnimMagic2;
886 rAnimation.Clear();
888 // Wenn die BitmapEx am Anfang schon gelesen
889 // wurde ( von Graphic ), koennen wir direkt die Animationsbitmaps einlesen
890 if( ( nAnimMagic1 == 0x5344414e ) && ( nAnimMagic2 == 0x494d4931 ) && !rIStm.GetError() )
891 bReadAnimations = TRUE;
892 // ansonsten versuchen wir erstmal die Bitmap(-Ex) zu lesen
893 else
895 rIStm.Seek( nStmPos );
896 rIStm >> rAnimation.maBitmapEx;
897 nStmPos = rIStm.Tell();
898 rIStm >> nAnimMagic1 >> nAnimMagic2;
900 if( ( nAnimMagic1 == 0x5344414e ) && ( nAnimMagic2 == 0x494d4931 ) && !rIStm.GetError() )
901 bReadAnimations = TRUE;
902 else
903 rIStm.Seek( nStmPos );
906 // ggf. Animationsbitmaps lesen
907 if( bReadAnimations )
909 AnimationBitmap aAnimBmp;
910 BitmapEx aBmpEx;
911 ByteString aDummyStr;
912 UINT32 nTmp32;
913 UINT16 nTmp16;
914 BYTE cTmp;
918 rIStm >> aAnimBmp.aBmpEx;
919 rIStm >> aAnimBmp.aPosPix;
920 rIStm >> aAnimBmp.aSizePix;
921 rIStm >> rAnimation.maGlobalSize;
922 rIStm >> nTmp16; aAnimBmp.nWait = ( ( 65535 == nTmp16 ) ? ANIMATION_TIMEOUT_ON_CLICK : nTmp16 );
923 rIStm >> nTmp16; aAnimBmp.eDisposal = ( Disposal) nTmp16;
924 rIStm >> cTmp; aAnimBmp.bUserInput = (BOOL) cTmp;
925 rIStm >> nTmp32; rAnimation.mnLoopCount = (USHORT) nTmp32;
926 rIStm >> nTmp32; // unbenutzt
927 rIStm >> nTmp32; // unbenutzt
928 rIStm >> nTmp32; // unbenutzt
929 rIStm >> aDummyStr; // unbenutzt
930 rIStm >> nTmp16; // Rest zu lesen
932 rAnimation.Insert( aAnimBmp );
934 while( nTmp16 && !rIStm.GetError() );
936 rAnimation.ResetLoopCount();
939 rIStm.SetNumberFormatInt( nOldFormat );
941 return rIStm;