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 120 : Animation::Animation() :
64 : mnLoopCount ( 0 ),
65 : mnLoops ( 0 ),
66 : mnPos ( 0 ),
67 : meCycleMode ( CYCLE_NORMAL ),
68 : mbIsInAnimation ( false ),
69 : mbLoopTerminated ( false ),
70 120 : mbIsWaiting ( false )
71 : {
72 120 : maTimer.SetTimeoutHdl( LINK( this, Animation, ImplTimeoutHdl ) );
73 120 : }
74 :
75 24 : 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 24 : mbIsWaiting ( rAnimation.mbIsWaiting )
84 : {
85 :
86 140 : for( size_t i = 0, nCount = rAnimation.maList.size(); i < nCount; i++ )
87 116 : maList.push_back( new AnimationBitmap( *rAnimation.maList[ i ] ) );
88 :
89 24 : maTimer.SetTimeoutHdl( LINK( this, Animation, ImplTimeoutHdl ) );
90 24 : mnLoops = mbLoopTerminated ? 0 : mnLoopCount;
91 24 : }
92 :
93 284 : Animation::~Animation()
94 : {
95 :
96 142 : if( mbIsInAnimation )
97 0 : Stop();
98 :
99 298 : for( size_t i = 0, n = maList.size(); i < n; ++i )
100 156 : delete maList[ i ];
101 :
102 142 : for( size_t i = 0, n = maViewList.size(); i < n; ++i )
103 0 : delete maViewList[ i ];
104 142 : }
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 24 : void Animation::Clear()
152 : {
153 24 : maTimer.Stop();
154 24 : mbIsInAnimation = false;
155 24 : maGlobalSize = Size();
156 24 : maBitmapEx.SetEmpty();
157 :
158 140 : for( size_t i = 0, n = maList.size(); i < n; ++i )
159 116 : delete maList[ i ];
160 24 : maList.clear();
161 :
162 24 : for( size_t i = 0, n = maViewList.size(); i < n; ++i )
163 0 : delete maViewList[ i ];
164 24 : maViewList.clear();
165 24 : }
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->matches( pOut, nExtraData ) )
254 : {
255 0 : if( pView->getOutPos() == rDestPt &&
256 0 : pView->getOutSizePix() == pOut->LogicToPixel( rDestSz ) )
257 : {
258 0 : pView->repaint();
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->matches( 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 : const_cast<Animation*>(this)->mnPos = mbLoopTerminated ? ( nCount - 1UL ) : mnPos;
342 0 : delete new ImplAnimView( const_cast<Animation*>(this), pOut, rDestPt, rDestSz, 0 );
343 0 : const_cast<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_TYPED(Animation, ImplTimeoutHdl, Timer *, void)
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 : // create AInfo-List
369 0 : for( size_t i = 0, n = maViewList.size(); i < n; ++i )
370 0 : aAInfoList.push_back( maViewList[ i ]->createAInfo() );
371 :
372 0 : maNotifyLink.Call( this );
373 :
374 : // set view state from AInfo structure
375 0 : for( size_t i = 0, n = aAInfoList.size(); i < n; ++i )
376 : {
377 0 : AInfo* pAInfo = aAInfoList[ i ];
378 0 : if( !pAInfo->pViewData )
379 : {
380 : pView = new ImplAnimView( this, pAInfo->pOutDev,
381 0 : pAInfo->aStartOrg, pAInfo->aStartSize, pAInfo->nExtraData );
382 :
383 0 : maViewList.push_back( pView );
384 : }
385 : else
386 0 : pView = static_cast<ImplAnimView*>(pAInfo->pViewData);
387 :
388 0 : pView->pause( pAInfo->bPause );
389 0 : pView->setMarked( true );
390 : }
391 :
392 : // delete AInfo structures
393 0 : for( size_t i = 0, n = aAInfoList.size(); i < n; ++i )
394 0 : delete aAInfoList[ i ];
395 0 : aAInfoList.clear();
396 :
397 : // delete all unmarked views and reset marked state
398 0 : for( size_t i = 0; i < maViewList.size(); )
399 : {
400 0 : pView = maViewList[ i ];
401 0 : if( !pView->isMarked() )
402 : {
403 0 : delete pView;
404 0 : maViewList.erase( maViewList.begin() + i );
405 : }
406 : else
407 : {
408 0 : if( !pView->isPause() )
409 0 : bGlobalPause = false;
410 :
411 0 : pView->setMarked( false );
412 0 : i++;
413 : }
414 : }
415 : }
416 : else
417 0 : bGlobalPause = false;
418 :
419 0 : if( maViewList.empty() )
420 0 : Stop();
421 0 : else if( bGlobalPause )
422 0 : ImplRestartTimer( 10 );
423 : else
424 : {
425 0 : AnimationBitmap* pStepBmp = (++mnPos < maList.size()) ? maList[ mnPos ] : NULL;
426 :
427 0 : if( !pStepBmp )
428 : {
429 0 : if( mnLoops == 1 )
430 : {
431 0 : Stop();
432 0 : mbLoopTerminated = true;
433 0 : mnPos = nAnimCount - 1UL;
434 0 : maBitmapEx = maList[ mnPos ]->aBmpEx;
435 0 : return;
436 : }
437 : else
438 : {
439 0 : if( mnLoops )
440 0 : mnLoops--;
441 :
442 0 : mnPos = 0;
443 0 : pStepBmp = maList[ mnPos ];
444 : }
445 : }
446 :
447 : // Paint all views; after painting check, if view is
448 : // marked; in this case remove view, because area of output
449 : // lies out of display area of window; mark state is
450 : // set from view itself
451 0 : for( size_t i = 0; i < maViewList.size(); )
452 : {
453 0 : pView = maViewList[ i ];
454 0 : pView->draw( mnPos );
455 :
456 0 : if( pView->isMarked() )
457 : {
458 0 : delete pView;
459 0 : maViewList.erase( maViewList.begin() + i );
460 : }
461 : else
462 0 : i++;
463 : }
464 :
465 : // stop or restart timer
466 0 : if( maViewList.empty() )
467 0 : Stop();
468 : else
469 0 : ImplRestartTimer( pStepBmp->nWait );
470 : }
471 : }
472 : else
473 0 : Stop();
474 : }
475 :
476 156 : bool Animation::Insert( const AnimationBitmap& rStepBmp )
477 : {
478 156 : bool bRet = false;
479 :
480 156 : if( !IsInAnimation() )
481 : {
482 156 : Point aPoint;
483 156 : Rectangle aGlobalRect( aPoint, maGlobalSize );
484 :
485 156 : maGlobalSize = aGlobalRect.Union( Rectangle( rStepBmp.aPosPix, rStepBmp.aSizePix ) ).GetSize();
486 156 : maList.push_back( new AnimationBitmap( rStepBmp ) );
487 :
488 : // As a start, we make the first BitmapEx the replacement BitmapEx
489 156 : if( maList.size() == 1 )
490 102 : maBitmapEx = rStepBmp.aBmpEx;
491 :
492 156 : bRet = true;
493 : }
494 :
495 156 : return bRet;
496 : }
497 :
498 91 : const AnimationBitmap& Animation::Get( sal_uInt16 nAnimation ) const
499 : {
500 : DBG_ASSERT( ( nAnimation < maList.size() ), "No object at this position" );
501 91 : return *maList[ nAnimation ];
502 : }
503 :
504 0 : void Animation::Replace( const AnimationBitmap& rNewAnimationBitmap, sal_uInt16 nAnimation )
505 : {
506 : DBG_ASSERT( ( nAnimation < maList.size() ), "No object at this position" );
507 :
508 0 : delete maList[ nAnimation ];
509 0 : maList[ nAnimation ] = new AnimationBitmap( rNewAnimationBitmap );
510 :
511 : // If we insert at first position we also need to
512 : // update the replacement BitmapEx
513 0 : if ( ( !nAnimation
514 0 : && ( !mbLoopTerminated
515 0 : || ( maList.size() == 1 )
516 : )
517 : )
518 0 : ||
519 0 : ( ( nAnimation == maList.size() - 1 )
520 0 : && mbLoopTerminated
521 : )
522 : )
523 : {
524 0 : maBitmapEx = rNewAnimationBitmap.aBmpEx;
525 : }
526 0 : }
527 :
528 95 : void Animation::SetLoopCount( const sal_uLong nLoopCount )
529 : {
530 95 : mnLoopCount = nLoopCount;
531 95 : ResetLoopCount();
532 95 : }
533 :
534 95 : void Animation::ResetLoopCount()
535 : {
536 95 : mnLoops = mnLoopCount;
537 95 : mbLoopTerminated = false;
538 95 : }
539 :
540 0 : bool Animation::Convert( BmpConversion eConversion )
541 : {
542 : DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
543 :
544 : bool bRet;
545 :
546 0 : if( !IsInAnimation() && !maList.empty() )
547 : {
548 0 : bRet = true;
549 :
550 0 : for( size_t i = 0, n = maList.size(); ( i < n ) && bRet; ++i )
551 0 : bRet = maList[ i ]->aBmpEx.Convert( eConversion );
552 :
553 0 : maBitmapEx.Convert( eConversion );
554 : }
555 : else
556 0 : bRet = false;
557 :
558 0 : return bRet;
559 : }
560 :
561 0 : bool Animation::ReduceColors( sal_uInt16 nNewColorCount, BmpReduce eReduce )
562 : {
563 : DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
564 :
565 : bool bRet;
566 :
567 0 : if( !IsInAnimation() && !maList.empty() )
568 : {
569 0 : bRet = true;
570 :
571 0 : for( size_t i = 0, n = maList.size(); ( i < n ) && bRet; ++i )
572 0 : bRet = maList[ i ]->aBmpEx.ReduceColors( nNewColorCount, eReduce );
573 :
574 0 : maBitmapEx.ReduceColors( nNewColorCount, eReduce );
575 : }
576 : else
577 0 : bRet = false;
578 :
579 0 : return bRet;
580 : }
581 :
582 0 : bool Animation::Invert()
583 : {
584 : DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
585 :
586 : bool bRet;
587 :
588 0 : if( !IsInAnimation() && !maList.empty() )
589 : {
590 0 : bRet = true;
591 :
592 0 : for( size_t i = 0, n = maList.size(); ( i < n ) && bRet; ++i )
593 0 : bRet = maList[ i ]->aBmpEx.Invert();
594 :
595 0 : maBitmapEx.Invert();
596 : }
597 : else
598 0 : bRet = false;
599 :
600 0 : return bRet;
601 : }
602 :
603 0 : bool Animation::Mirror( BmpMirrorFlags nMirrorFlags )
604 : {
605 : DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
606 :
607 : bool bRet;
608 :
609 0 : if( !IsInAnimation() && !maList.empty() )
610 : {
611 0 : bRet = true;
612 :
613 0 : if( nMirrorFlags != BmpMirrorFlags::NONE )
614 : {
615 0 : for( size_t i = 0, n = maList.size(); ( i < n ) && bRet; ++i )
616 : {
617 0 : AnimationBitmap* pStepBmp = maList[ i ];
618 0 : if( ( bRet = pStepBmp->aBmpEx.Mirror( nMirrorFlags ) ) )
619 : {
620 0 : if( nMirrorFlags & BmpMirrorFlags::Horizontal )
621 0 : pStepBmp->aPosPix.X() = maGlobalSize.Width() - pStepBmp->aPosPix.X() - pStepBmp->aSizePix.Width();
622 :
623 0 : if( nMirrorFlags & BmpMirrorFlags::Vertical )
624 0 : pStepBmp->aPosPix.Y() = maGlobalSize.Height() - pStepBmp->aPosPix.Y() - pStepBmp->aSizePix.Height();
625 : }
626 : }
627 :
628 0 : maBitmapEx.Mirror( nMirrorFlags );
629 : }
630 : }
631 : else
632 0 : bRet = false;
633 :
634 0 : return bRet;
635 : }
636 :
637 0 : bool Animation::Adjust( short nLuminancePercent, short nContrastPercent,
638 : short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
639 : double fGamma, bool bInvert )
640 : {
641 : DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
642 :
643 : bool bRet;
644 :
645 0 : if( !IsInAnimation() && !maList.empty() )
646 : {
647 0 : bRet = true;
648 :
649 0 : for( size_t i = 0, n = maList.size(); ( i < n ) && bRet; ++i )
650 : {
651 0 : bRet = maList[ i ]->aBmpEx.Adjust( nLuminancePercent,
652 : nContrastPercent,
653 : nChannelRPercent,
654 : nChannelGPercent,
655 : nChannelBPercent,
656 : fGamma, bInvert
657 0 : );
658 : }
659 :
660 : maBitmapEx.Adjust( nLuminancePercent, nContrastPercent,
661 : nChannelRPercent, nChannelGPercent, nChannelBPercent,
662 0 : fGamma, bInvert );
663 : }
664 : else
665 0 : bRet = false;
666 :
667 0 : return bRet;
668 : }
669 :
670 0 : bool Animation::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam, const Link<>* pProgress )
671 : {
672 : DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
673 :
674 : bool bRet;
675 :
676 0 : if( !IsInAnimation() && !maList.empty() )
677 : {
678 0 : bRet = true;
679 :
680 0 : for( size_t i = 0, n = maList.size(); ( i < n ) && bRet; ++i )
681 0 : bRet = maList[ i ]->aBmpEx.Filter( eFilter, pFilterParam, pProgress );
682 :
683 0 : (void)maBitmapEx.Filter(eFilter, pFilterParam, pProgress);
684 : }
685 : else
686 0 : bRet = false;
687 :
688 0 : return bRet;
689 : }
690 :
691 0 : SvStream& WriteAnimation( SvStream& rOStm, const Animation& rAnimation )
692 : {
693 0 : const sal_uInt16 nCount = rAnimation.Count();
694 :
695 0 : if( nCount )
696 : {
697 0 : const sal_uInt32 nDummy32 = 0UL;
698 :
699 : // If no BitmapEx was set we write the first Bitmap of
700 : // the Animation
701 0 : if( !rAnimation.GetBitmapEx().GetBitmap() )
702 0 : WriteDIBBitmapEx(rAnimation.Get( 0 ).aBmpEx, rOStm);
703 : else
704 0 : WriteDIBBitmapEx(rAnimation.GetBitmapEx(), rOStm);
705 :
706 : // Write identifier ( SDANIMA1 )
707 0 : rOStm.WriteUInt32( 0x5344414e ).WriteUInt32( 0x494d4931 );
708 :
709 0 : for( sal_uInt16 i = 0; i < nCount; i++ )
710 : {
711 0 : const AnimationBitmap& rAnimBmp = rAnimation.Get( i );
712 0 : const sal_uInt16 nRest = nCount - i - 1;
713 :
714 : // Write AnimationBitmap
715 0 : WriteDIBBitmapEx(rAnimBmp.aBmpEx, rOStm);
716 0 : WritePair( rOStm, rAnimBmp.aPosPix );
717 0 : WritePair( rOStm, rAnimBmp.aSizePix );
718 0 : WritePair( rOStm, rAnimation.maGlobalSize );
719 0 : rOStm.WriteUInt16( ( ANIMATION_TIMEOUT_ON_CLICK == rAnimBmp.nWait ) ? 65535 : rAnimBmp.nWait );
720 0 : rOStm.WriteUInt16( rAnimBmp.eDisposal );
721 0 : rOStm.WriteBool( rAnimBmp.bUserInput );
722 0 : rOStm.WriteUInt32( rAnimation.mnLoopCount );
723 0 : rOStm.WriteUInt32( nDummy32 ); // Unused
724 0 : rOStm.WriteUInt32( nDummy32 ); // Unused
725 0 : rOStm.WriteUInt32( nDummy32 ); // Unused
726 0 : write_uInt16_lenPrefixed_uInt8s_FromOString(rOStm, OString()); // dummy
727 0 : rOStm.WriteUInt16( nRest ); // Count of remaining structures
728 : }
729 : }
730 :
731 0 : return rOStm;
732 : }
733 :
734 0 : SvStream& ReadAnimation( SvStream& rIStm, Animation& rAnimation )
735 : {
736 0 : Bitmap aBmp;
737 0 : sal_uLong nStmPos = rIStm.Tell();
738 : sal_uInt32 nAnimMagic1, nAnimMagic2;
739 0 : SvStreamEndian nOldFormat = rIStm.GetEndian();
740 0 : bool bReadAnimations = false;
741 :
742 0 : rIStm.SetEndian( SvStreamEndian::LITTLE );
743 0 : nStmPos = rIStm.Tell();
744 0 : rIStm.ReadUInt32( nAnimMagic1 ).ReadUInt32( nAnimMagic2 );
745 :
746 0 : rAnimation.Clear();
747 :
748 : // If the BitmapEx at the beginning have already been read (by Graphic)
749 : // we can start reading the AnimationBitmaps right away
750 0 : if( ( nAnimMagic1 == 0x5344414e ) && ( nAnimMagic2 == 0x494d4931 ) && !rIStm.GetError() )
751 0 : bReadAnimations = true;
752 : // Else, we try reading the Bitmap(-Ex)
753 : else
754 : {
755 0 : rIStm.Seek( nStmPos );
756 0 : ReadDIBBitmapEx(rAnimation.maBitmapEx, rIStm);
757 0 : nStmPos = rIStm.Tell();
758 0 : rIStm.ReadUInt32( nAnimMagic1 ).ReadUInt32( nAnimMagic2 );
759 :
760 0 : if( ( nAnimMagic1 == 0x5344414e ) && ( nAnimMagic2 == 0x494d4931 ) && !rIStm.GetError() )
761 0 : bReadAnimations = true;
762 : else
763 0 : rIStm.Seek( nStmPos );
764 : }
765 :
766 : // Read AnimationBitmaps
767 0 : if( bReadAnimations )
768 : {
769 0 : AnimationBitmap aAnimBmp;
770 0 : BitmapEx aBmpEx;
771 : sal_uInt32 nTmp32;
772 : sal_uInt16 nTmp16;
773 : bool cTmp;
774 :
775 0 : do
776 : {
777 0 : ReadDIBBitmapEx(aAnimBmp.aBmpEx, rIStm);
778 0 : ReadPair( rIStm, aAnimBmp.aPosPix );
779 0 : ReadPair( rIStm, aAnimBmp.aSizePix );
780 0 : ReadPair( rIStm, rAnimation.maGlobalSize );
781 0 : rIStm.ReadUInt16( nTmp16 ); aAnimBmp.nWait = ( ( 65535 == nTmp16 ) ? ANIMATION_TIMEOUT_ON_CLICK : nTmp16 );
782 0 : rIStm.ReadUInt16( nTmp16 ); aAnimBmp.eDisposal = ( Disposal) nTmp16;
783 0 : rIStm.ReadCharAsBool( cTmp ); aAnimBmp.bUserInput = cTmp;
784 0 : rIStm.ReadUInt32( nTmp32 ); rAnimation.mnLoopCount = (sal_uInt16) nTmp32;
785 0 : rIStm.ReadUInt32( nTmp32 ); // Unused
786 0 : rIStm.ReadUInt32( nTmp32 ); // Unused
787 0 : rIStm.ReadUInt32( nTmp32 ); // Unused
788 0 : read_uInt16_lenPrefixed_uInt8s_ToOString(rIStm); // Unused
789 0 : rIStm.ReadUInt16( nTmp16 ); // The rest to read
790 :
791 0 : rAnimation.Insert( aAnimBmp );
792 : }
793 0 : while( nTmp16 && !rIStm.GetError() );
794 :
795 0 : rAnimation.ResetLoopCount();
796 : }
797 :
798 0 : rIStm.SetEndian( nOldFormat );
799 :
800 0 : return rIStm;
801 : }
802 :
803 0 : AInfo::AInfo() : pOutDev( NULL ),
804 : pViewData( NULL ),
805 : nExtraData( 0L ),
806 : bWithSize( false ),
807 0 : bPause( false ) {}
808 :
809 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|