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