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