blob: 0cd2db5386ac683abd44cd50b166b749b04ff5ff [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"
#define ENABLE_BYTESTRING_STREAM_OPERATORS
#include <vcl/animate.hxx>
#include <tools/debug.hxx>
#include <tools/stream.hxx>
#include <rtl/crc.h>
#include <vcl/virdev.hxx>
#include <vcl/window.hxx>
#include <impanmvw.hxx>
#include <vcl/dibtools.hxx>
DBG_NAME( Animation )
// -----------
// - Defines -
// -----------
#define MIN_TIMEOUT 2L
#define INC_TIMEOUT 0L
// -----------
// - statics -
// -----------
sal_uLong Animation::mnAnimCount = 0UL;
// -------------------
// - AnimationBitmap -
// -------------------
sal_uLong AnimationBitmap::GetChecksum() const
{
sal_uInt32 nCrc = aBmpEx.GetChecksum();
SVBT32 aBT32;
UInt32ToSVBT32( aPosPix.X(), aBT32 );
nCrc = rtl_crc32( nCrc, aBT32, 4 );
UInt32ToSVBT32( aPosPix.Y(), aBT32 );
nCrc = rtl_crc32( nCrc, aBT32, 4 );
UInt32ToSVBT32( aSizePix.Width(), aBT32 );
nCrc = rtl_crc32( nCrc, aBT32, 4 );
UInt32ToSVBT32( aSizePix.Height(), aBT32 );
nCrc = rtl_crc32( nCrc, aBT32, 4 );
UInt32ToSVBT32( (long) nWait, aBT32 );
nCrc = rtl_crc32( nCrc, aBT32, 4 );
UInt32ToSVBT32( (long) eDisposal, aBT32 );
nCrc = rtl_crc32( nCrc, aBT32, 4 );
UInt32ToSVBT32( (long) bUserInput, aBT32 );
nCrc = rtl_crc32( nCrc, aBT32, 4 );
return nCrc;
}
// -------------
// - Animation -
// -------------
Animation::Animation() :
mnLoopCount ( 0 ),
mnLoops ( 0 ),
mnPos ( 0 ),
meCycleMode ( CYCLE_NORMAL ),
mbIsInAnimation ( sal_False ),
mbLoopTerminated ( sal_False ),
mbIsWaiting ( sal_False )
{
DBG_CTOR( Animation, NULL );
maTimer.SetTimeoutHdl( LINK( this, Animation, ImplTimeoutHdl ) );
mpViewList = new List;
}
// -----------------------------------------------------------------------
Animation::Animation( const Animation& rAnimation ) :
maBitmapEx ( rAnimation.maBitmapEx ),
maGlobalSize ( rAnimation.maGlobalSize ),
mnLoopCount ( rAnimation.mnLoopCount ),
mnPos ( rAnimation.mnPos ),
meCycleMode ( rAnimation.meCycleMode ),
mbIsInAnimation ( sal_False ),
mbLoopTerminated ( rAnimation.mbLoopTerminated ),
mbIsWaiting ( rAnimation.mbIsWaiting )
{
DBG_CTOR( Animation, NULL );
for( long i = 0, nCount = rAnimation.maList.Count(); i < nCount; i++ )
maList.Insert( new AnimationBitmap( *(AnimationBitmap*) rAnimation.maList.GetObject( i ) ), LIST_APPEND );
maTimer.SetTimeoutHdl( LINK( this, Animation, ImplTimeoutHdl ) );
mpViewList = new List;
mnLoops = mbLoopTerminated ? 0 : mnLoopCount;
}
// -----------------------------------------------------------------------
Animation::~Animation()
{
DBG_DTOR( Animation, NULL );
if( mbIsInAnimation )
Stop();
for( void* pStepBmp = maList.First(); pStepBmp; pStepBmp = maList.Next() )
delete (AnimationBitmap*) pStepBmp;
for( void* pView = mpViewList->First(); pView; pView = mpViewList->Next() )
delete (ImplAnimView*) pView;
delete mpViewList;
}
// -----------------------------------------------------------------------
Animation& Animation::operator=( const Animation& rAnimation )
{
Clear();
for( long i = 0, nCount = rAnimation.maList.Count(); i < nCount; i++ )
maList.Insert( new AnimationBitmap( *(AnimationBitmap*) rAnimation.maList.GetObject( i ) ), LIST_APPEND );
maGlobalSize = rAnimation.maGlobalSize;
maBitmapEx = rAnimation.maBitmapEx;
meCycleMode = rAnimation.meCycleMode;
mnLoopCount = rAnimation.mnLoopCount;
mnPos = rAnimation.mnPos;
mbLoopTerminated = rAnimation.mbLoopTerminated;
mbIsWaiting = rAnimation.mbIsWaiting;
mnLoops = mbLoopTerminated ? 0 : mnLoopCount;
return *this;
}
// -----------------------------------------------------------------------
sal_Bool Animation::operator==( const Animation& rAnimation ) const
{
const sal_uLong nCount = maList.Count();
sal_Bool bRet = sal_False;
if( rAnimation.maList.Count() == nCount &&
rAnimation.maBitmapEx == maBitmapEx &&
rAnimation.maGlobalSize == maGlobalSize &&
rAnimation.meCycleMode == meCycleMode )
{
bRet = sal_True;
for( sal_uLong n = 0; n < nCount; n++ )
{
if( ( *(AnimationBitmap*) maList.GetObject( n ) ) !=
( *(AnimationBitmap*) rAnimation.maList.GetObject( n ) ) )
{
bRet = sal_False;
break;
}
}
}
return bRet;
}
// ------------------------------------------------------------------
sal_Bool Animation::IsEqual( const Animation& rAnimation ) const
{
const sal_uLong nCount = maList.Count();
sal_Bool bRet = sal_False;
if( rAnimation.maList.Count() == nCount &&
rAnimation.maBitmapEx.IsEqual( maBitmapEx ) &&
rAnimation.maGlobalSize == maGlobalSize &&
rAnimation.meCycleMode == meCycleMode )
{
for( sal_uLong n = 0; ( n < nCount ) && !bRet; n++ )
if( ( (AnimationBitmap*) maList.GetObject( n ) )->IsEqual( *(AnimationBitmap*) rAnimation.maList.GetObject( n ) ) )
bRet = sal_True;
}
return bRet;
}
// ------------------------------------------------------------------
sal_Bool Animation::IsEmpty() const
{
return( maBitmapEx.IsEmpty() && !maList.Count() );
}
// ------------------------------------------------------------------
void Animation::SetEmpty()
{
maTimer.Stop();
mbIsInAnimation = sal_False;
maGlobalSize = Size();
maBitmapEx.SetEmpty();
for( void* pStepBmp = maList.First(); pStepBmp; pStepBmp = maList.Next() )
delete (AnimationBitmap*) pStepBmp;
maList.Clear();
for( void* pView = mpViewList->First(); pView; pView = mpViewList->Next() )
delete (ImplAnimView*) pView;
mpViewList->Clear();
}
// -----------------------------------------------------------------------
void Animation::Clear()
{
SetEmpty();
}
// -----------------------------------------------------------------------
sal_Bool Animation::IsTransparent() const
{
Point aPoint;
Rectangle aRect( aPoint, maGlobalSize );
sal_Bool bRet = sal_False;
// Falls irgendein 'kleines' Bildchen durch den Hintergrund
// ersetzt werden soll, muessen wir 'transparent' sein, um
// richtig dargestellt zu werden, da die Appl. aus Optimierungsgruenden
// kein Invalidate auf nicht-transp. Grafiken ausfuehren
for( long i = 0, nCount = maList.Count(); i < nCount; i++ )
{
const AnimationBitmap* pAnimBmp = (AnimationBitmap*) maList.GetObject( i );
if( DISPOSE_BACK == pAnimBmp->eDisposal && Rectangle( pAnimBmp->aPosPix, pAnimBmp->aSizePix ) != aRect )
{
bRet = sal_True;
break;
}
}
if( !bRet )
bRet = maBitmapEx.IsTransparent();
return bRet;
}
// -----------------------------------------------------------------------
sal_uLong Animation::GetSizeBytes() const
{
sal_uLong nSizeBytes = GetBitmapEx().GetSizeBytes();
for( long i = 0, nCount = maList.Count(); i < nCount; i++ )
{
const AnimationBitmap* pAnimBmp = (AnimationBitmap*) maList.GetObject( i );
nSizeBytes += pAnimBmp->aBmpEx.GetSizeBytes();
}
return nSizeBytes;
}
// -----------------------------------------------------------------------
sal_uLong Animation::GetChecksum() const
{
SVBT32 aBT32;
sal_uInt32 nCrc = GetBitmapEx().GetChecksum();
UInt32ToSVBT32( maList.Count(), aBT32 );
nCrc = rtl_crc32( nCrc, aBT32, 4 );
UInt32ToSVBT32( maGlobalSize.Width(), aBT32 );
nCrc = rtl_crc32( nCrc, aBT32, 4 );
UInt32ToSVBT32( maGlobalSize.Height(), aBT32 );
nCrc = rtl_crc32( nCrc, aBT32, 4 );
UInt32ToSVBT32( (long) meCycleMode, aBT32 );
nCrc = rtl_crc32( nCrc, aBT32, 4 );
for( long i = 0, nCount = maList.Count(); i < nCount; i++ )
{
UInt32ToSVBT32( ( (AnimationBitmap*) maList.GetObject( i ) )->GetChecksum(), aBT32 );
nCrc = rtl_crc32( nCrc, aBT32, 4 );
}
return nCrc;
}
// -----------------------------------------------------------------------
sal_Bool Animation::Start( OutputDevice* pOut, const Point& rDestPt, long nExtraData,
OutputDevice* pFirstFrameOutDev )
{
return Start( pOut, rDestPt, pOut->PixelToLogic( maGlobalSize ), nExtraData, pFirstFrameOutDev );
}
// -----------------------------------------------------------------------
sal_Bool Animation::Start( OutputDevice* pOut, const Point& rDestPt, const Size& rDestSz, long nExtraData,
OutputDevice* pFirstFrameOutDev )
{
sal_Bool bRet = sal_False;
if( maList.Count() )
{
if( ( pOut->GetOutDevType() == OUTDEV_WINDOW ) && !mbLoopTerminated &&
( ANIMATION_TIMEOUT_ON_CLICK != ( (AnimationBitmap*) maList.GetObject( mnPos ) )->nWait ) )
{
ImplAnimView* pView;
ImplAnimView* pMatch = NULL;
for( pView = (ImplAnimView*) mpViewList->First(); pView; pView = (ImplAnimView*) mpViewList->Next() )
{
if( pView->ImplMatches( pOut, nExtraData ) )
{
if( pView->ImplGetOutPos() == rDestPt &&
pView->ImplGetOutSizePix() == pOut->LogicToPixel( rDestSz ) )
{
pView->ImplRepaint();
pMatch = pView;
}
else
{
delete (ImplAnimView*) mpViewList->Remove( pView );
pView = NULL;
}
break;
}
}
if( !mpViewList->Count() )
{
maTimer.Stop();
mbIsInAnimation = sal_False;
mnPos = 0UL;
}
if( !pMatch )
mpViewList->Insert( new ImplAnimView( this, pOut, rDestPt, rDestSz, nExtraData, pFirstFrameOutDev ), LIST_APPEND );
if( !mbIsInAnimation )
{
ImplRestartTimer( ( (AnimationBitmap*) maList.GetObject( mnPos ) )->nWait );
mbIsInAnimation = sal_True;
}
}
else
Draw( pOut, rDestPt, rDestSz );
bRet = sal_True;
}
return bRet;
}
// -----------------------------------------------------------------------
void Animation::Stop( OutputDevice* pOut, long nExtraData )
{
ImplAnimView* pView = (ImplAnimView*) mpViewList->First();
while( pView )
{
if( pView->ImplMatches( pOut, nExtraData ) )
{
delete (ImplAnimView*) mpViewList->Remove( pView );
pView = (ImplAnimView*) mpViewList->GetCurObject();
}
else
pView = (ImplAnimView*) mpViewList->Next();
}
if( !mpViewList->Count() )
{
maTimer.Stop();
mbIsInAnimation = sal_False;
}
}
// -----------------------------------------------------------------------
void Animation::Draw( OutputDevice* pOut, const Point& rDestPt ) const
{
Draw( pOut, rDestPt, pOut->PixelToLogic( maGlobalSize ) );
}
// -----------------------------------------------------------------------
void Animation::Draw( OutputDevice* pOut, const Point& rDestPt, const Size& rDestSz ) const
{
const sal_uLong nCount = maList.Count();
if( nCount )
{
AnimationBitmap* pObj = (AnimationBitmap*) maList.GetObject( Min( mnPos, (long) nCount - 1L ) );
if( pOut->GetConnectMetaFile() || ( pOut->GetOutDevType() == OUTDEV_PRINTER ) )
( (AnimationBitmap*) maList.GetObject( 0 ) )->aBmpEx.Draw( pOut, rDestPt, rDestSz );
else if( ANIMATION_TIMEOUT_ON_CLICK == pObj->nWait )
pObj->aBmpEx.Draw( pOut, rDestPt, rDestSz );
else
{
const sal_uLong nOldPos = mnPos;
( (Animation*) this )->mnPos = mbLoopTerminated ? ( nCount - 1UL ) : mnPos;
delete new ImplAnimView( (Animation*) this, pOut, rDestPt, rDestSz, 0 );
( (Animation*) this )->mnPos = nOldPos;
}
}
}
// -----------------------------------------------------------------------
void Animation::ImplRestartTimer( sal_uLong nTimeout )
{
maTimer.SetTimeout( Max( nTimeout, (sal_uLong)(MIN_TIMEOUT + ( mnAnimCount - 1 ) * INC_TIMEOUT) ) * 10L );
maTimer.Start();
}
// -----------------------------------------------------------------------
IMPL_LINK( Animation, ImplTimeoutHdl, Timer*, EMPTYARG )
{
const sal_uLong nAnimCount = maList.Count();
if( nAnimCount )
{
ImplAnimView* pView;
sal_Bool bGlobalPause = sal_True;
if( maNotifyLink.IsSet() )
{
AInfo* pAInfo;
// create AInfo-List
for( pView = (ImplAnimView*) mpViewList->First(); pView; pView = (ImplAnimView*) mpViewList->Next() )
maAInfoList.Insert( pView->ImplCreateAInfo() );
maNotifyLink.Call( this );
// set view state from AInfo structure
for( pAInfo = (AInfo*) maAInfoList.First(); pAInfo; pAInfo = (AInfo*) maAInfoList.Next() )
{
if( !pAInfo->pViewData )
{
pView = new ImplAnimView( this, pAInfo->pOutDev,
pAInfo->aStartOrg, pAInfo->aStartSize, pAInfo->nExtraData );
mpViewList->Insert( pView, LIST_APPEND );
}
else
pView = (ImplAnimView*) pAInfo->pViewData;
pView->ImplPause( pAInfo->bPause );
pView->ImplSetMarked( sal_True );
}
// delete AInfo structures
for( pAInfo = (AInfo*) maAInfoList.First(); pAInfo; pAInfo = (AInfo*) maAInfoList.Next() )
delete (AInfo*) pAInfo;
maAInfoList.Clear();
// delete all unmarked views and reset marked state
pView = (ImplAnimView*) mpViewList->First();
while( pView )
{
if( !pView->ImplIsMarked() )
{
delete (ImplAnimView*) mpViewList->Remove( pView );
pView = (ImplAnimView*) mpViewList->GetCurObject();
}
else
{
if( !pView->ImplIsPause() )
bGlobalPause = sal_False;
pView->ImplSetMarked( sal_False );
pView = (ImplAnimView*) mpViewList->Next();
}
}
}
else
bGlobalPause = sal_False;
if( !mpViewList->Count() )
Stop();
else if( bGlobalPause )
ImplRestartTimer( 10 );
else
{
AnimationBitmap* pStepBmp = (AnimationBitmap*) maList.GetObject( ++mnPos );
if( !pStepBmp )
{
if( mnLoops == 1 )
{
Stop();
mbLoopTerminated = sal_True;
mnPos = nAnimCount - 1UL;
maBitmapEx = ( (AnimationBitmap*) maList.GetObject( mnPos ) )->aBmpEx;
return 0L;
}
else
{
if( mnLoops )
mnLoops--;
mnPos = 0;
pStepBmp = (AnimationBitmap*) maList.GetObject( mnPos );
}
}
// Paint all views; after painting check, if view is
// marked; in this case remove view, because area of output
// lies out of display area of window; mark state is
// set from view itself
pView = (ImplAnimView*) mpViewList->First();
while( pView )
{
pView->ImplDraw( mnPos );
if( pView->ImplIsMarked() )
{
delete (ImplAnimView*) mpViewList->Remove( pView );
pView = (ImplAnimView*) mpViewList->GetCurObject();
}
else
pView = (ImplAnimView*) mpViewList->Next();
}
// stop or restart timer
if( !mpViewList->Count() )
Stop();
else
ImplRestartTimer( pStepBmp->nWait );
}
}
else
Stop();
return 0L;
}
// -----------------------------------------------------------------------
sal_Bool Animation::Insert( const AnimationBitmap& rStepBmp )
{
sal_Bool bRet = sal_False;
if( !IsInAnimation() )
{
Point aPoint;
Rectangle aGlobalRect( aPoint, maGlobalSize );
maGlobalSize = aGlobalRect.Union( Rectangle( rStepBmp.aPosPix, rStepBmp.aSizePix ) ).GetSize();
maList.Insert( new AnimationBitmap( rStepBmp ), LIST_APPEND );
// zunaechst nehmen wir die erste BitmapEx als Ersatz-BitmapEx
if( maList.Count() == 1 )
maBitmapEx = rStepBmp.aBmpEx;
bRet = sal_True;
}
return bRet;
}
// -----------------------------------------------------------------------
const AnimationBitmap& Animation::Get( sal_uInt16 nAnimation ) const
{
DBG_ASSERT( ( nAnimation < maList.Count() ), "No object at this position" );
return *(AnimationBitmap*) maList.GetObject( nAnimation );
}
// -----------------------------------------------------------------------
void Animation::Replace( const AnimationBitmap& rNewAnimationBitmap, sal_uInt16 nAnimation )
{
DBG_ASSERT( ( nAnimation < maList.Count() ), "No object at this position" );
delete (AnimationBitmap*) maList.Replace( new AnimationBitmap( rNewAnimationBitmap ), nAnimation );
// Falls wir an erster Stelle einfuegen,
// muessen wir natuerlich auch,
// auch die Ersatzdarstellungs-BitmapEx
// aktualisieren;
if ( ( !nAnimation && ( !mbLoopTerminated || ( maList.Count() == 1 ) ) ) ||
( ( nAnimation == maList.Count() - 1 ) && mbLoopTerminated ) )
{
maBitmapEx = rNewAnimationBitmap.aBmpEx;
}
}
// -----------------------------------------------------------------------
void Animation::SetLoopCount( const sal_uLong nLoopCount )
{
mnLoopCount = nLoopCount;
ResetLoopCount();
}
// -----------------------------------------------------------------------
void Animation::ResetLoopCount()
{
mnLoops = mnLoopCount;
mbLoopTerminated = sal_False;
}
// -----------------------------------------------------------------------
sal_Bool Animation::Convert( BmpConversion eConversion )
{
DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
sal_Bool bRet;
if( !IsInAnimation() && maList.Count() )
{
bRet = sal_True;
for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() )
bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.Convert( eConversion );
maBitmapEx.Convert( eConversion );
}
else
bRet = sal_False;
return bRet;
}
// -----------------------------------------------------------------------
sal_Bool Animation::ReduceColors( sal_uInt16 nNewColorCount, BmpReduce eReduce )
{
DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
sal_Bool bRet;
if( !IsInAnimation() && maList.Count() )
{
bRet = sal_True;
for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() )
bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.ReduceColors( nNewColorCount, eReduce );
maBitmapEx.ReduceColors( nNewColorCount, eReduce );
}
else
bRet = sal_False;
return bRet;
}
// -----------------------------------------------------------------------
sal_Bool Animation::Invert()
{
DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
sal_Bool bRet;
if( !IsInAnimation() && maList.Count() )
{
bRet = sal_True;
for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() )
bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.Invert();
maBitmapEx.Invert();
}
else
bRet = sal_False;
return bRet;
}
// -----------------------------------------------------------------------
sal_Bool Animation::Mirror( sal_uLong nMirrorFlags )
{
DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
sal_Bool bRet;
if( !IsInAnimation() && maList.Count() )
{
bRet = sal_True;
if( nMirrorFlags )
{
for( AnimationBitmap* pStepBmp = (AnimationBitmap*) maList.First();
pStepBmp && bRet;
pStepBmp = (AnimationBitmap*) maList.Next() )
{
if( ( bRet = pStepBmp->aBmpEx.Mirror( nMirrorFlags ) ) == sal_True )
{
if( nMirrorFlags & BMP_MIRROR_HORZ )
pStepBmp->aPosPix.X() = maGlobalSize.Width() - pStepBmp->aPosPix.X() - pStepBmp->aSizePix.Width();
if( nMirrorFlags & BMP_MIRROR_VERT )
pStepBmp->aPosPix.Y() = maGlobalSize.Height() - pStepBmp->aPosPix.Y() - pStepBmp->aSizePix.Height();
}
}
maBitmapEx.Mirror( nMirrorFlags );
}
}
else
bRet = sal_False;
return bRet;
}
// -----------------------------------------------------------------------
sal_Bool Animation::Dither( sal_uLong nDitherFlags )
{
DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
sal_Bool bRet;
if( !IsInAnimation() && maList.Count() )
{
bRet = sal_True;
for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() )
bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.Dither( nDitherFlags );
maBitmapEx.Dither( nDitherFlags );
}
else
bRet = sal_False;
return bRet;
}
// -----------------------------------------------------------------------
sal_Bool Animation::Adjust( short nLuminancePercent, short nContrastPercent,
short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
double fGamma, sal_Bool bInvert )
{
DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
sal_Bool bRet;
if( !IsInAnimation() && maList.Count() )
{
bRet = sal_True;
for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() )
{
bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.Adjust( nLuminancePercent, nContrastPercent,
nChannelRPercent, nChannelGPercent, nChannelBPercent,
fGamma, bInvert );
}
maBitmapEx.Adjust( nLuminancePercent, nContrastPercent,
nChannelRPercent, nChannelGPercent, nChannelBPercent,
fGamma, bInvert );
}
else
bRet = sal_False;
return bRet;
}
// -----------------------------------------------------------------------
sal_Bool Animation::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam, const Link* pProgress )
{
DBG_ASSERT( !IsInAnimation(), "Animation modified while it is animated" );
sal_Bool bRet;
if( !IsInAnimation() && maList.Count() )
{
bRet = sal_True;
for( void* pStepBmp = maList.First(); pStepBmp && bRet; pStepBmp = maList.Next() )
bRet = ( ( AnimationBitmap*) pStepBmp )->aBmpEx.Filter( eFilter, pFilterParam, pProgress );
maBitmapEx.Filter( eFilter, pFilterParam, pProgress );
}
else
bRet = sal_False;
return bRet;
}
// -----------------------------------------------------------------------
SvStream& operator<<( SvStream& rOStm, const Animation& rAnimation )
{
const sal_uInt16 nCount = rAnimation.Count();
if( nCount )
{
const ByteString aDummyStr;
const sal_uInt32 nDummy32 = 0UL;
// Falls keine BitmapEx gesetzt wurde, schreiben wir
// einfach die erste Bitmap der Animation
if( !rAnimation.GetBitmapEx().GetBitmap() )
WriteDIBBitmapEx(rAnimation.Get( 0 ).aBmpEx, rOStm);
else
WriteDIBBitmapEx(rAnimation.GetBitmapEx(), rOStm);
// Kennung schreiben ( SDANIMA1 )
rOStm << (sal_uInt32) 0x5344414e << (sal_uInt32) 0x494d4931;
for( sal_uInt16 i = 0; i < nCount; i++ )
{
const AnimationBitmap& rAnimBmp = rAnimation.Get( i );
const sal_uInt16 nRest = nCount - i - 1;
// AnimationBitmap schreiben
WriteDIBBitmapEx(rAnimBmp.aBmpEx, rOStm);
rOStm << rAnimBmp.aPosPix;
rOStm << rAnimBmp.aSizePix;
rOStm << rAnimation.maGlobalSize;
rOStm << (sal_uInt16) ( ( ANIMATION_TIMEOUT_ON_CLICK == rAnimBmp.nWait ) ? 65535 : rAnimBmp.nWait );
rOStm << (sal_uInt16) rAnimBmp.eDisposal;
rOStm << (sal_uInt8) rAnimBmp.bUserInput;
rOStm << (sal_uInt32) rAnimation.mnLoopCount;
rOStm << nDummy32; // unbenutzt
rOStm << nDummy32; // unbenutzt
rOStm << nDummy32; // unbenutzt
rOStm << aDummyStr; // unbenutzt
rOStm << nRest; // Anzahl der Strukturen, die noch _folgen_
}
}
return rOStm;
}
// -----------------------------------------------------------------------
SvStream& operator>>( SvStream& rIStm, Animation& rAnimation )
{
Bitmap aBmp;
sal_uLong nStmPos = rIStm.Tell();
sal_uInt32 nAnimMagic1, nAnimMagic2;
sal_uInt16 nOldFormat = rIStm.GetNumberFormatInt();
sal_Bool bReadAnimations = sal_False;
rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
nStmPos = rIStm.Tell();
rIStm >> nAnimMagic1 >> nAnimMagic2;
rAnimation.Clear();
// Wenn die BitmapEx am Anfang schon gelesen
// wurde ( von Graphic ), koennen wir direkt die Animationsbitmaps einlesen
if( ( nAnimMagic1 == 0x5344414e ) && ( nAnimMagic2 == 0x494d4931 ) && !rIStm.GetError() )
bReadAnimations = sal_True;
// ansonsten versuchen wir erstmal die Bitmap(-Ex) zu lesen
else
{
rIStm.Seek( nStmPos );
ReadDIBBitmapEx(rAnimation.maBitmapEx, rIStm);
nStmPos = rIStm.Tell();
rIStm >> nAnimMagic1 >> nAnimMagic2;
if( ( nAnimMagic1 == 0x5344414e ) && ( nAnimMagic2 == 0x494d4931 ) && !rIStm.GetError() )
bReadAnimations = sal_True;
else
rIStm.Seek( nStmPos );
}
// ggf. Animationsbitmaps lesen
if( bReadAnimations )
{
AnimationBitmap aAnimBmp;
BitmapEx aBmpEx;
ByteString aDummyStr;
sal_uInt32 nTmp32;
sal_uInt16 nTmp16;
sal_uInt8 cTmp;
do
{
ReadDIBBitmapEx(aAnimBmp.aBmpEx, rIStm);
rIStm >> aAnimBmp.aPosPix;
rIStm >> aAnimBmp.aSizePix;
rIStm >> rAnimation.maGlobalSize;
rIStm >> nTmp16; aAnimBmp.nWait = ( ( 65535 == nTmp16 ) ? ANIMATION_TIMEOUT_ON_CLICK : nTmp16 );
rIStm >> nTmp16; aAnimBmp.eDisposal = ( Disposal) nTmp16;
rIStm >> cTmp; aAnimBmp.bUserInput = (sal_Bool) cTmp;
rIStm >> nTmp32; rAnimation.mnLoopCount = (sal_uInt16) nTmp32;
rIStm >> nTmp32; // unbenutzt
rIStm >> nTmp32; // unbenutzt
rIStm >> nTmp32; // unbenutzt
rIStm >> aDummyStr; // unbenutzt
rIStm >> nTmp16; // Rest zu lesen
rAnimation.Insert( aAnimBmp );
}
while( nTmp16 && !rIStm.GetError() );
rAnimation.ResetLoopCount();
}
rIStm.SetNumberFormatInt( nOldFormat );
return rIStm;
}