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