xref: /trunk/main/vcl/source/gdi/animate.cxx (revision 45fd3b9a)
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 
GetChecksum() const56 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 
Animation()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 
Animation(const Animation & rAnimation)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 
~Animation()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 
operator =(const Animation & rAnimation)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 
operator ==(const Animation & rAnimation) const166 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 
IsEqual(const Animation & rAnimation) const194 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 
IsEmpty() const214 sal_Bool Animation::IsEmpty() const
215 {
216 	return( maBitmapEx.IsEmpty() && !maList.Count() );
217 }
218 
219 // ------------------------------------------------------------------
220 
SetEmpty()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 
Clear()239 void Animation::Clear()
240 {
241 	SetEmpty();
242 }
243 
244 // -----------------------------------------------------------------------
245 
IsTransparent() const246 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 
GetSizeBytes() const275 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 
GetChecksum() const290 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 
Start(OutputDevice * pOut,const Point & rDestPt,long nExtraData,OutputDevice * pFirstFrameOutDev)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 
Start(OutputDevice * pOut,const Point & rDestPt,const Size & rDestSz,long nExtraData,OutputDevice * pFirstFrameOutDev)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 
Stop(OutputDevice * pOut,long nExtraData)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 
Draw(OutputDevice * pOut,const Point & rDestPt) const410 void Animation::Draw( OutputDevice* pOut, const Point& rDestPt ) const
411 {
412 	Draw( pOut, rDestPt, pOut->PixelToLogic( maGlobalSize ) );
413 }
414 
415 // -----------------------------------------------------------------------
416 
Draw(OutputDevice * pOut,const Point & rDestPt,const Size & rDestSz) const417 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 
ImplRestartTimer(sal_uLong nTimeout)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 
IMPL_LINK(Animation,ImplTimeoutHdl,Timer *,EMPTYARG)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 
Insert(const AnimationBitmap & rStepBmp)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 
Get(sal_uInt16 nAnimation) const597 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 
Replace(const AnimationBitmap & rNewAnimationBitmap,sal_uInt16 nAnimation)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 
SetLoopCount(const sal_uLong nLoopCount)624 void Animation::SetLoopCount( const sal_uLong nLoopCount )
625 {
626 	mnLoopCount = nLoopCount;
627 	ResetLoopCount();
628 }
629 
630 // -----------------------------------------------------------------------
631 
ResetLoopCount()632 void Animation::ResetLoopCount()
633 {
634 	mnLoops = mnLoopCount;
635 	mbLoopTerminated = sal_False;
636 }
637 
638 // -----------------------------------------------------------------------
639 
Convert(BmpConversion eConversion)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 
ReduceColors(sal_uInt16 nNewColorCount,BmpReduce eReduce)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 
Invert()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 
Mirror(sal_uLong nMirrorFlags)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 
Dither(sal_uLong nDitherFlags)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 
Adjust(short nLuminancePercent,short nContrastPercent,short nChannelRPercent,short nChannelGPercent,short nChannelBPercent,double fGamma,sal_Bool bInvert)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 
Filter(BmpFilter eFilter,const BmpFilterParam * pFilterParam,const Link * pProgress)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 
operator <<(SvStream & rOStm,const Animation & rAnimation)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 
operator >>(SvStream & rIStm,Animation & rAnimation)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