xref: /AOO41X/main/vcl/source/gdi/animate.cxx (revision 47148b3bc50811ceb41802e4cc50a5db21535900)
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