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