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 : #include <vcl/animate.hxx>
21 : #include <tools/debug.hxx>
22 : #include <tools/stream.hxx>
23 : #include <rtl/crc.h>
24 : #include <vcl/virdev.hxx>
25 : #include <vcl/window.hxx>
26 : #include <impanmvw.hxx>
27 : #include <vcl/dibtools.hxx>
28 :
29 : #define MIN_TIMEOUT 2L
30 : #define INC_TIMEOUT 0L
31 :
32 : sal_uLong Animation::mnAnimCount = 0UL;
33 :
34 0 : sal_uLong AnimationBitmap::GetChecksum() const
35 : {
36 0 : sal_uInt32 nCrc = aBmpEx.GetChecksum();
37 : SVBT32 aBT32;
38 :
39 0 : UInt32ToSVBT32( aPosPix.X(), aBT32 );
40 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
41 :
42 0 : UInt32ToSVBT32( aPosPix.Y(), aBT32 );
43 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
44 :
45 0 : UInt32ToSVBT32( aSizePix.Width(), aBT32 );
46 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
47 :
48 0 : UInt32ToSVBT32( aSizePix.Height(), aBT32 );
49 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
50 :
51 0 : UInt32ToSVBT32( (long) nWait, aBT32 );
52 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
53 :
54 0 : UInt32ToSVBT32( (long) eDisposal, aBT32 );
55 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
56 :
57 0 : UInt32ToSVBT32( (long) bUserInput, aBT32 );
58 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
59 :
60 0 : return nCrc;
61 : }
62 :
63 0 : Animation::Animation() :
64 : mnLoopCount ( 0 ),
65 : mnLoops ( 0 ),
66 : mnPos ( 0 ),
67 : meCycleMode ( CYCLE_NORMAL ),
68 : mbIsInAnimation ( false ),
69 : mbLoopTerminated ( false ),
70 0 : mbIsWaiting ( false )
71 : {
72 0 : maTimer.SetTimeoutHdl( LINK( this, Animation, ImplTimeoutHdl ) );
73 0 : }
74 :
75 0 : Animation::Animation( const Animation& rAnimation ) :
76 : maBitmapEx ( rAnimation.maBitmapEx ),
77 : maGlobalSize ( rAnimation.maGlobalSize ),
78 : mnLoopCount ( rAnimation.mnLoopCount ),
79 : mnPos ( rAnimation.mnPos ),
80 : meCycleMode ( rAnimation.meCycleMode ),
81 : mbIsInAnimation ( false ),
82 : mbLoopTerminated ( rAnimation.mbLoopTerminated ),
83 0 : mbIsWaiting ( rAnimation.mbIsWaiting )
84 : {
85 :
86 0 : for( size_t i = 0, nCount = rAnimation.maList.size(); i < nCount; i++ )
87 0 : maList.push_back( new AnimationBitmap( *rAnimation.maList[ i ] ) );
88 :
89 0 : maTimer.SetTimeoutHdl( LINK( this, Animation, ImplTimeoutHdl ) );
90 0 : mnLoops = mbLoopTerminated ? 0 : mnLoopCount;
91 0 : }
92 :
93 0 : Animation::~Animation()
94 : {
95 :
96 0 : if( mbIsInAnimation )
97 0 : Stop();
98 :
99 0 : for( size_t i = 0, n = maList.size(); i < n; ++i )
100 0 : delete maList[ i ];
101 :
102 0 : for( size_t i = 0, n = maViewList.size(); i < n; ++i )
103 0 : delete maViewList[ i ];
104 0 : }
105 :
106 0 : Animation& Animation::operator=( const Animation& rAnimation )
107 : {
108 0 : Clear();
109 :
110 0 : for( size_t i = 0, nCount = rAnimation.maList.size(); i < nCount; i++ )
111 0 : maList.push_back( new AnimationBitmap( *rAnimation.maList[ i ] ) );
112 :
113 0 : maGlobalSize = rAnimation.maGlobalSize;
114 0 : maBitmapEx = rAnimation.maBitmapEx;
115 0 : meCycleMode = rAnimation.meCycleMode;
116 0 : mnLoopCount = rAnimation.mnLoopCount;
117 0 : mnPos = rAnimation.mnPos;
118 0 : mbLoopTerminated = rAnimation.mbLoopTerminated;
119 0 : mbIsWaiting = rAnimation.mbIsWaiting;
120 0 : mnLoops = mbLoopTerminated ? 0 : mnLoopCount;
121 :
122 0 : return *this;
123 : }
124 :
125 0 : bool Animation::operator==( const Animation& rAnimation ) const
126 : {
127 0 : const size_t nCount = maList.size();
128 0 : bool bRet = false;
129 :
130 0 : if( rAnimation.maList.size() == nCount
131 0 : && rAnimation.maBitmapEx == maBitmapEx
132 0 : && rAnimation.maGlobalSize == maGlobalSize
133 0 : && rAnimation.meCycleMode == meCycleMode
134 : )
135 : {
136 0 : bRet = true;
137 :
138 0 : for( size_t n = 0; n < nCount; n++ )
139 : {
140 0 : if( ( *maList[ n ] ) != ( *rAnimation.maList[ n ] ) )
141 : {
142 0 : bRet = false;
143 0 : break;
144 : }
145 : }
146 : }
147 :
148 0 : return bRet;
149 : }
150 :
151 0 : void Animation::Clear()
152 : {
153 0 : maTimer.Stop();
154 0 : mbIsInAnimation = false;
155 0 : maGlobalSize = Size();
156 0 : maBitmapEx.SetEmpty();
157 :
158 0 : for( size_t i = 0, n = maList.size(); i < n; ++i )
159 0 : delete maList[ i ];
160 0 : maList.clear();
161 :
162 0 : for( size_t i = 0, n = maViewList.size(); i < n; ++i )
163 0 : delete maViewList[ i ];
164 0 : maViewList.clear();
165 0 : }
166 :
167 0 : bool Animation::IsTransparent() const
168 : {
169 0 : Point aPoint;
170 0 : Rectangle aRect( aPoint, maGlobalSize );
171 0 : bool bRet = false;
172 :
173 : // If some small bitmap needs to be replaced by the background,
174 : // we need to be transparent, in order to be displayed correctly
175 : // as the application (?) does not invalidate on non-transparent
176 : // graphics due to performance reasons.
177 0 : for( size_t i = 0, nCount = maList.size(); i < nCount; i++ )
178 : {
179 0 : const AnimationBitmap* pAnimBmp = maList[ i ];
180 :
181 0 : if( DISPOSE_BACK == pAnimBmp->eDisposal
182 0 : && Rectangle( pAnimBmp->aPosPix, pAnimBmp->aSizePix ) != aRect
183 : )
184 : {
185 0 : bRet = true;
186 0 : break;
187 : }
188 : }
189 :
190 0 : if( !bRet )
191 0 : bRet = maBitmapEx.IsTransparent();
192 :
193 0 : return bRet;
194 : }
195 :
196 0 : sal_uLong Animation::GetSizeBytes() const
197 : {
198 0 : sal_uLong nSizeBytes = GetBitmapEx().GetSizeBytes();
199 :
200 0 : for( size_t i = 0, nCount = maList.size(); i < nCount; i++ )
201 : {
202 0 : const AnimationBitmap* pAnimBmp = maList[ i ];
203 0 : nSizeBytes += pAnimBmp->aBmpEx.GetSizeBytes();
204 : }
205 :
206 0 : return nSizeBytes;
207 : }
208 :
209 0 : sal_uLong Animation::GetChecksum() const
210 : {
211 : SVBT32 aBT32;
212 0 : sal_uInt32 nCrc = GetBitmapEx().GetChecksum();
213 :
214 0 : UInt32ToSVBT32( maList.size(), aBT32 );
215 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
216 :
217 0 : UInt32ToSVBT32( maGlobalSize.Width(), aBT32 );
218 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
219 :
220 0 : UInt32ToSVBT32( maGlobalSize.Height(), aBT32 );
221 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
222 :
223 0 : UInt32ToSVBT32( (long) meCycleMode, aBT32 );
224 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
225 :
226 0 : for( size_t i = 0, nCount = maList.size(); i < nCount; i++ )
227 : {
228 0 : UInt32ToSVBT32( maList[ i ]->GetChecksum(), aBT32 );
229 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
230 : }
231 :
232 0 : return nCrc;
233 : }
234 :
235 0 : bool Animation::Start( OutputDevice* pOut, const Point& rDestPt, const Size& rDestSz, long nExtraData,
236 : OutputDevice* pFirstFrameOutDev )
237 : {
238 0 : bool bRet = false;
239 :
240 0 : if( !maList.empty() )
241 : {
242 0 : if( ( pOut->GetOutDevType() == OUTDEV_WINDOW )
243 0 : && !mbLoopTerminated
244 0 : && ( ANIMATION_TIMEOUT_ON_CLICK != maList[ mnPos ]->nWait )
245 : )
246 : {
247 : ImplAnimView* pView;
248 0 : ImplAnimView* pMatch = NULL;
249 :
250 0 : for( size_t i = 0; i < maViewList.size(); ++i )
251 : {
252 0 : pView = maViewList[ i ];
253 0 : if( pView->ImplMatches( pOut, nExtraData ) )
254 : {
255 0 : if( pView->ImplGetOutPos() == rDestPt &&
256 0 : pView->ImplGetOutSizePix() == pOut->LogicToPixel( rDestSz ) )
257 : {
258 0 : pView->ImplRepaint();
259 0 : pMatch = pView;
260 : }
261 : else
262 : {
263 0 : delete maViewList[ i ];
264 0 : maViewList.erase( maViewList.begin() + i );
265 0 : pView = NULL;
266 : }
267 :
268 0 : break;
269 : }
270 : }
271 :
272 0 : if( maViewList.empty() )
273 : {
274 0 : maTimer.Stop();
275 0 : mbIsInAnimation = false;
276 0 : mnPos = 0UL;
277 : }
278 :
279 0 : if( !pMatch )
280 0 : maViewList.push_back( new ImplAnimView( this, pOut, rDestPt, rDestSz, nExtraData, pFirstFrameOutDev ) );
281 :
282 0 : if( !mbIsInAnimation )
283 : {
284 0 : ImplRestartTimer( maList[ mnPos ]->nWait );
285 0 : mbIsInAnimation = true;
286 : }
287 : }
288 : else
289 0 : Draw( pOut, rDestPt, rDestSz );
290 :
291 0 : bRet = true;
292 : }
293 :
294 0 : return bRet;
295 : }
296 :
297 0 : void Animation::Stop( OutputDevice* pOut, long nExtraData )
298 : {
299 0 : for( size_t i = 0; i < maViewList.size(); )
300 : {
301 :
302 0 : ImplAnimView* pView = maViewList[ i ];
303 0 : if( pView->ImplMatches( pOut, nExtraData ) )
304 : {
305 0 : delete pView;
306 0 : maViewList.erase( maViewList.begin() + i );
307 : }
308 : else
309 0 : i++;
310 : }
311 :
312 0 : if( maViewList.empty() )
313 : {
314 0 : maTimer.Stop();
315 0 : mbIsInAnimation = false;
316 : }
317 0 : }
318 :
319 0 : void Animation::Draw( OutputDevice* pOut, const Point& rDestPt ) const
320 : {
321 0 : Draw( pOut, rDestPt, pOut->PixelToLogic( maGlobalSize ) );
322 0 : }
323 :
324 0 : void Animation::Draw( OutputDevice* pOut, const Point& rDestPt, const Size& rDestSz ) const
325 : {
326 0 : const size_t nCount = maList.size();
327 :
328 0 : if( nCount )
329 : {
330 0 : AnimationBitmap* pObj = maList[ std::min( mnPos, nCount - 1 ) ];
331 :
332 0 : if( pOut->GetConnectMetaFile()
333 0 : || ( pOut->GetOutDevType() == OUTDEV_PRINTER )
334 : )
335 0 : maList[ 0 ]->aBmpEx.Draw( pOut, rDestPt, rDestSz );
336 0 : else if( ANIMATION_TIMEOUT_ON_CLICK == pObj->nWait )
337 0 : pObj->aBmpEx.Draw( pOut, rDestPt, rDestSz );
338 : else
339 : {
340 0 : const size_t nOldPos = mnPos;
341 0 : ( (Animation*) this )->mnPos = mbLoopTerminated ? ( nCount - 1UL ) : mnPos;
342 0 : delete new ImplAnimView( (Animation*) this, pOut, rDestPt, rDestSz, 0 );
343 0 : ( (Animation*) this )->mnPos = nOldPos;
344 : }
345 : }
346 0 : }
347 :
348 0 : void Animation::ImplRestartTimer( sal_uLong nTimeout )
349 : {
350 0 : maTimer.SetTimeout( std::max( nTimeout, (sal_uLong)(MIN_TIMEOUT + ( mnAnimCount - 1 ) * INC_TIMEOUT) ) * 10L );
351 0 : maTimer.Start();
352 0 : }
353 :
354 : typedef ::std::vector< AInfo* > AInfoList_impl;
355 :
356 0 : IMPL_LINK_NOARG(Animation, ImplTimeoutHdl)
357 : {
358 0 : const size_t nAnimCount = maList.size();
359 0 : AInfoList_impl aAInfoList;
360 :
361 0 : if( nAnimCount )
362 : {
363 : ImplAnimView* pView;
364 0 : bool bGlobalPause = true;
365 :
366 0 : if( maNotifyLink.IsSet() )
367 : {
368 : AInfo* pAInfo;
369 :
370 : // create AInfo-List
371 0 : for( size_t i = 0, n = maViewList.size(); i < n; ++i )
372 0 : aAInfoList.push_back( maViewList[ i ]->ImplCreateAInfo() );
373 :
374 0 : maNotifyLink.Call( this );
375 :
376 : // set view state from AInfo structure
377 0 : for( size_t i = 0, n = aAInfoList.size(); i < n; ++i )
378 : {
379 0 : pAInfo = aAInfoList[ i ];
380 0 : if( !pAInfo->pViewData )
381 : {
382 : pView = new ImplAnimView( this, pAInfo->pOutDev,
383 0 : pAInfo->aStartOrg, pAInfo->aStartSize, pAInfo->nExtraData );
384 :
385 0 : maViewList.push_back( pView );
386 : }
387 : else
388 0 : pView = (ImplAnimView*) pAInfo->pViewData;
389 :
390 0 : pView->ImplPause( pAInfo->bPause );
391 0 : pView->ImplSetMarked( true );
392 : }
393 :
394 : // delete AInfo structures
395 0 : for( size_t i = 0, n = aAInfoList.size(); i < n; ++i )
396 0 : delete aAInfoList[ i ];
397 0 : aAInfoList.clear();
398 :
399 : // delete all unmarked views and reset marked state
400 0 : for( size_t i = 0; i < maViewList.size(); )
401 : {
402 0 : pView = maViewList[ i ];
403 0 : if( !pView->ImplIsMarked() )
404 : {
405 0 : delete pView;
406 0 : maViewList.erase( maViewList.begin() + i );
407 : }
408 : else
409 : {
410 0 : if( !pView->ImplIsPause() )
411 0 : bGlobalPause = false;
412 :
413 0 : pView->ImplSetMarked( false );
414 0 : i++;
415 : }
416 : }
417 : }
418 : else
419 0 : bGlobalPause = false;
420 :
421 0 : if( maViewList.empty() )
422 0 : Stop();
423 0 : else if( bGlobalPause )
424 0 : ImplRestartTimer( 10 );
425 : else
426 : {
427 0 : AnimationBitmap* pStepBmp = (++mnPos < maList.size()) ? maList[ mnPos ] : NULL;
428 :
429 0 : if( !pStepBmp )
430 : {
431 0 : if( mnLoops == 1 )
432 : {
433 0 : Stop();
434 0 : mbLoopTerminated = true;
435 0 : mnPos = nAnimCount - 1UL;
436 0 : maBitmapEx = maList[ mnPos ]->aBmpEx;
437 0 : return 0L;
438 : }
439 : else
440 : {
441 0 : if( mnLoops )
442 0 : mnLoops--;
443 :
444 0 : mnPos = 0;
445 0 : pStepBmp = maList[ mnPos ];
446 : }
447 : }
448 :
449 : // Paint all views; after painting check, if view is
450 : // marked; in this case remove view, because area of output
451 : // lies out of display area of window; mark state is
452 : // set from view itself
453 0 : for( size_t i = 0; i < maViewList.size(); )
454 : {
455 0 : pView = maViewList[ i ];
456 0 : pView->ImplDraw( mnPos );
457 :
458 0 : if( pView->ImplIsMarked() )
459 : {
460 0 : delete pView;
461 0 : maViewList.erase( maViewList.begin() + i );
462 : }
463 : else
464 0 : i++;
465 : }
466 :
467 : // stop or restart timer
468 0 : if( maViewList.empty() )
469 0 : Stop();
470 : else
471 0 : ImplRestartTimer( pStepBmp->nWait );
472 : }
473 : }
474 : else
475 0 : Stop();
476 :
477 0 : return 0L;
478 : }
479 :
480 0 : bool Animation::Insert( const AnimationBitmap& rStepBmp )
481 : {
482 0 : bool bRet = false;
483 :
484 0 : if( !IsInAnimation() )
485 : {
486 0 : Point aPoint;
487 0 : Rectangle aGlobalRect( aPoint, maGlobalSize );
488 :
489 0 : maGlobalSize = aGlobalRect.Union( Rectangle( rStepBmp.aPosPix, rStepBmp.aSizePix ) ).GetSize();
490 0 : maList.push_back( new AnimationBitmap( rStepBmp ) );
491 :
492 : // As a start, we make the first BitmapEx the replacement BitmapEx
493 0 : if( maList.size() == 1 )
494 0 : maBitmapEx = rStepBmp.aBmpEx;
495 :
496 0 : bRet = true;
497 : }
498 :
499 0 : return bRet;
500 : }
501 :
502 0 : const AnimationBitmap& Animation::Get( sal_uInt16 nAnimation ) const
503 : {
504 : DBG_ASSERT( ( nAnimation < maList.size() ), "No object at this position" );
505 0 : return *maList[ nAnimation ];
506 : }
507 :
508 0 : void Animation::Replace( const AnimationBitmap& rNewAnimationBitmap, sal_uInt16 nAnimation )
509 : {
510 : DBG_ASSERT( ( nAnimation < maList.size() ), "No object at this position" );
511 :
512 0 : delete maList[ nAnimation ];
513 0 : maList[ nAnimation ] = new AnimationBitmap( rNewAnimationBitmap );
514 :
515 : // If we insert at first position we also need to
516 : // update the replacement BitmapEx
517 0 : if ( ( !nAnimation
518 0 : && ( !mbLoopTerminated
519 0 : || ( maList.size() == 1 )
520 : )
521 : )
522 0 : ||
523 0 : ( ( nAnimation == maList.size() - 1 )
524 0 : && mbLoopTerminated
525 : )
526 : )
527 : {
528 0 : maBitmapEx = rNewAnimationBitmap.aBmpEx;
529 : }
530 0 : }
531 :
532 0 : void Animation::SetLoopCount( const sal_uLong nLoopCount )
533 : {
534 0 : mnLoopCount = nLoopCount;
535 0 : ResetLoopCount();
536 0 : }
537 :
538 0 : void Animation::ResetLoopCount()
539 : {
540 0 : mnLoops = mnLoopCount;
541 0 : mbLoopTerminated = false;
542 0 : }
543 :
544 0 : bool Animation::Convert( BmpConversion eConversion )
545 : {
546 : DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
547 :
548 : bool bRet;
549 :
550 0 : if( !IsInAnimation() && !maList.empty() )
551 : {
552 0 : bRet = true;
553 :
554 0 : for( size_t i = 0, n = maList.size(); ( i < n ) && bRet; ++i )
555 0 : bRet = maList[ i ]->aBmpEx.Convert( eConversion );
556 :
557 0 : maBitmapEx.Convert( eConversion );
558 : }
559 : else
560 0 : bRet = false;
561 :
562 0 : return bRet;
563 : }
564 :
565 0 : bool Animation::ReduceColors( sal_uInt16 nNewColorCount, BmpReduce eReduce )
566 : {
567 : DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
568 :
569 : bool bRet;
570 :
571 0 : if( !IsInAnimation() && !maList.empty() )
572 : {
573 0 : bRet = true;
574 :
575 0 : for( size_t i = 0, n = maList.size(); ( i < n ) && bRet; ++i )
576 0 : bRet = maList[ i ]->aBmpEx.ReduceColors( nNewColorCount, eReduce );
577 :
578 0 : maBitmapEx.ReduceColors( nNewColorCount, eReduce );
579 : }
580 : else
581 0 : bRet = false;
582 :
583 0 : return bRet;
584 : }
585 :
586 0 : bool Animation::Invert()
587 : {
588 : DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
589 :
590 : bool bRet;
591 :
592 0 : if( !IsInAnimation() && !maList.empty() )
593 : {
594 0 : bRet = true;
595 :
596 0 : for( size_t i = 0, n = maList.size(); ( i < n ) && bRet; ++i )
597 0 : bRet = maList[ i ]->aBmpEx.Invert();
598 :
599 0 : maBitmapEx.Invert();
600 : }
601 : else
602 0 : bRet = false;
603 :
604 0 : return bRet;
605 : }
606 :
607 0 : bool Animation::Mirror( sal_uLong nMirrorFlags )
608 : {
609 : DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
610 :
611 : bool bRet;
612 :
613 0 : if( !IsInAnimation() && !maList.empty() )
614 : {
615 0 : bRet = true;
616 :
617 0 : if( nMirrorFlags )
618 : {
619 0 : for( size_t i = 0, n = maList.size(); ( i < n ) && bRet; ++i )
620 : {
621 0 : AnimationBitmap* pStepBmp = maList[ i ];
622 0 : if( ( bRet = pStepBmp->aBmpEx.Mirror( nMirrorFlags ) ) )
623 : {
624 0 : if( nMirrorFlags & BMP_MIRROR_HORZ )
625 0 : pStepBmp->aPosPix.X() = maGlobalSize.Width() - pStepBmp->aPosPix.X() - pStepBmp->aSizePix.Width();
626 :
627 0 : if( nMirrorFlags & BMP_MIRROR_VERT )
628 0 : pStepBmp->aPosPix.Y() = maGlobalSize.Height() - pStepBmp->aPosPix.Y() - pStepBmp->aSizePix.Height();
629 : }
630 : }
631 :
632 0 : maBitmapEx.Mirror( nMirrorFlags );
633 : }
634 : }
635 : else
636 0 : bRet = false;
637 :
638 0 : return bRet;
639 : }
640 :
641 0 : bool Animation::Adjust( short nLuminancePercent, short nContrastPercent,
642 : short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
643 : double fGamma, bool bInvert )
644 : {
645 : DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
646 :
647 : bool bRet;
648 :
649 0 : if( !IsInAnimation() && !maList.empty() )
650 : {
651 0 : bRet = true;
652 :
653 0 : for( size_t i = 0, n = maList.size(); ( i < n ) && bRet; ++i )
654 : {
655 0 : bRet = maList[ i ]->aBmpEx.Adjust( nLuminancePercent,
656 : nContrastPercent,
657 : nChannelRPercent,
658 : nChannelGPercent,
659 : nChannelBPercent,
660 : fGamma, bInvert
661 0 : );
662 : }
663 :
664 : maBitmapEx.Adjust( nLuminancePercent, nContrastPercent,
665 : nChannelRPercent, nChannelGPercent, nChannelBPercent,
666 0 : fGamma, bInvert );
667 : }
668 : else
669 0 : bRet = false;
670 :
671 0 : return bRet;
672 : }
673 :
674 0 : bool Animation::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam, const Link* pProgress )
675 : {
676 : DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
677 :
678 : bool bRet;
679 :
680 0 : if( !IsInAnimation() && !maList.empty() )
681 : {
682 0 : bRet = true;
683 :
684 0 : for( size_t i = 0, n = maList.size(); ( i < n ) && bRet; ++i )
685 0 : bRet = maList[ i ]->aBmpEx.Filter( eFilter, pFilterParam, pProgress );
686 :
687 0 : maBitmapEx.Filter( eFilter, pFilterParam, pProgress );
688 : }
689 : else
690 0 : bRet = false;
691 :
692 0 : return bRet;
693 : }
694 :
695 0 : SvStream& WriteAnimation( SvStream& rOStm, const Animation& rAnimation )
696 : {
697 0 : const sal_uInt16 nCount = rAnimation.Count();
698 :
699 0 : if( nCount )
700 : {
701 0 : const sal_uInt32 nDummy32 = 0UL;
702 :
703 : // If no BitmapEx was set we write the first Bitmap of
704 : // the Animation
705 0 : if( !rAnimation.GetBitmapEx().GetBitmap() )
706 0 : WriteDIBBitmapEx(rAnimation.Get( 0 ).aBmpEx, rOStm);
707 : else
708 0 : WriteDIBBitmapEx(rAnimation.GetBitmapEx(), rOStm);
709 :
710 : // Write identifier ( SDANIMA1 )
711 0 : rOStm.WriteUInt32( (sal_uInt32) 0x5344414e ).WriteUInt32( (sal_uInt32) 0x494d4931 );
712 :
713 0 : for( sal_uInt16 i = 0; i < nCount; i++ )
714 : {
715 0 : const AnimationBitmap& rAnimBmp = rAnimation.Get( i );
716 0 : const sal_uInt16 nRest = nCount - i - 1;
717 :
718 : // Write AnimationBitmap
719 0 : WriteDIBBitmapEx(rAnimBmp.aBmpEx, rOStm);
720 0 : WritePair( rOStm, rAnimBmp.aPosPix );
721 0 : WritePair( rOStm, rAnimBmp.aSizePix );
722 0 : WritePair( rOStm, rAnimation.maGlobalSize );
723 0 : rOStm.WriteUInt16( (sal_uInt16) ( ( ANIMATION_TIMEOUT_ON_CLICK == rAnimBmp.nWait ) ? 65535 : rAnimBmp.nWait ) );
724 0 : rOStm.WriteUInt16( (sal_uInt16) rAnimBmp.eDisposal );
725 0 : rOStm.WriteUChar( (sal_uInt8) rAnimBmp.bUserInput );
726 0 : rOStm.WriteUInt32( (sal_uInt32) rAnimation.mnLoopCount );
727 0 : rOStm.WriteUInt32( nDummy32 ); // Unused
728 0 : rOStm.WriteUInt32( nDummy32 ); // Unused
729 0 : rOStm.WriteUInt32( nDummy32 ); // Unused
730 0 : write_uInt16_lenPrefixed_uInt8s_FromOString(rOStm, OString()); // dummy
731 0 : rOStm.WriteUInt16( nRest ); // Count of remaining structures
732 : }
733 : }
734 :
735 0 : return rOStm;
736 : }
737 :
738 0 : SvStream& ReadAnimation( SvStream& rIStm, Animation& rAnimation )
739 : {
740 0 : Bitmap aBmp;
741 0 : sal_uLong nStmPos = rIStm.Tell();
742 : sal_uInt32 nAnimMagic1, nAnimMagic2;
743 0 : sal_uInt16 nOldFormat = rIStm.GetNumberFormatInt();
744 0 : bool bReadAnimations = false;
745 :
746 0 : rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
747 0 : nStmPos = rIStm.Tell();
748 0 : rIStm.ReadUInt32( nAnimMagic1 ).ReadUInt32( nAnimMagic2 );
749 :
750 0 : rAnimation.Clear();
751 :
752 : // If the BitmapEx at the beginning have already been read (by Graphic)
753 : // we can start reading the AnimationBitmaps right away
754 0 : if( ( nAnimMagic1 == 0x5344414e ) && ( nAnimMagic2 == 0x494d4931 ) && !rIStm.GetError() )
755 0 : bReadAnimations = true;
756 : // Else, we try reading the Bitmap(-Ex)
757 : else
758 : {
759 0 : rIStm.Seek( nStmPos );
760 0 : ReadDIBBitmapEx(rAnimation.maBitmapEx, rIStm);
761 0 : nStmPos = rIStm.Tell();
762 0 : rIStm.ReadUInt32( nAnimMagic1 ).ReadUInt32( nAnimMagic2 );
763 :
764 0 : if( ( nAnimMagic1 == 0x5344414e ) && ( nAnimMagic2 == 0x494d4931 ) && !rIStm.GetError() )
765 0 : bReadAnimations = true;
766 : else
767 0 : rIStm.Seek( nStmPos );
768 : }
769 :
770 : // Read AnimationBitmaps
771 0 : if( bReadAnimations )
772 : {
773 0 : AnimationBitmap aAnimBmp;
774 0 : BitmapEx aBmpEx;
775 : sal_uInt32 nTmp32;
776 : sal_uInt16 nTmp16;
777 : bool cTmp;
778 :
779 0 : do
780 : {
781 0 : ReadDIBBitmapEx(aAnimBmp.aBmpEx, rIStm);
782 0 : ReadPair( rIStm, aAnimBmp.aPosPix );
783 0 : ReadPair( rIStm, aAnimBmp.aSizePix );
784 0 : ReadPair( rIStm, rAnimation.maGlobalSize );
785 0 : rIStm.ReadUInt16( nTmp16 ); aAnimBmp.nWait = ( ( 65535 == nTmp16 ) ? ANIMATION_TIMEOUT_ON_CLICK : nTmp16 );
786 0 : rIStm.ReadUInt16( nTmp16 ); aAnimBmp.eDisposal = ( Disposal) nTmp16;
787 0 : rIStm.ReadCharAsBool( cTmp ); aAnimBmp.bUserInput = cTmp;
788 0 : rIStm.ReadUInt32( nTmp32 ); rAnimation.mnLoopCount = (sal_uInt16) nTmp32;
789 0 : rIStm.ReadUInt32( nTmp32 ); // Unused
790 0 : rIStm.ReadUInt32( nTmp32 ); // Unused
791 0 : rIStm.ReadUInt32( nTmp32 ); // Unused
792 0 : read_uInt16_lenPrefixed_uInt8s_ToOString(rIStm); // Unused
793 0 : rIStm.ReadUInt16( nTmp16 ); // The rest to read
794 :
795 0 : rAnimation.Insert( aAnimBmp );
796 : }
797 0 : while( nTmp16 && !rIStm.GetError() );
798 :
799 0 : rAnimation.ResetLoopCount();
800 : }
801 :
802 0 : rIStm.SetNumberFormatInt( nOldFormat );
803 :
804 0 : return rIStm;
805 : }
806 :
807 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|