diff -r 000000000000 -r 2e3d3ce01487 startupservices/startupanimation/sanimsvgplugin/src/sanimmifplugin.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/startupservices/startupanimation/sanimsvgplugin/src/sanimmifplugin.cpp Tue Feb 02 10:12:00 2010 +0200 @@ -0,0 +1,428 @@ +/* +* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Implementation of CSAnimMifPlugin class +* +*/ + + +#include + +#include "sanimmifplugin.h" +#include "assert.h" +#include "trace.h" + +/** MIF header contents. */ +class TMifHeader + { +public: + TInt32 iUID; + TInt32 iVersion; + TInt32 iArrayOffset; + TInt32 iArrayLength; + }; + +typedef TPckgBuf TMifHeaderPckg; + +/** Icon offset element from MIF file. */ +class TIconOffsetElement + { +public: + TInt32 iOffset; + TInt32 iLength; + }; + +typedef TPckgBuf TIconOffsetElementPckg; + +/** Icon header contents. */ +class TIconHeader + { +public: + TInt32 iUID; + TInt32 iVersion; + TInt32 iDataOffset; + TInt32 iDataLength; + TInt32 iType; + TInt32 iDepth; + TInt32 iAnimated; + TInt32 iMaskDepth; + }; + +typedef TPckgBuf TIconHeaderPckg; + +/** Type identifier for SVG. */ +const TInt KSvgType = 1; + +/** Number of array elements one frame occupies (bitmap & mask = 2). */ +const TInt KArrElementsPerFrame = 2; + +/** Step through icon array with this granularity. */ +const TInt KIconArrStep = 2; + +// ======== LOCAL FUNCTIONS ======== + +static TInt TimerCallBack( TAny* aPtr ) + { + FUNC_LOG; + + static_cast( aPtr )->TimerExpired(); + return KErrNone; + } + + +// ======== MEMBER FUNCTIONS ======== + +// --------------------------------------------------------------------------- +// CSAnimMifPlugin::NewL +// +// --------------------------------------------------------------------------- +// +CSAnimMifPlugin* CSAnimMifPlugin::NewL( TAny* aConstructionParameters ) + { + FUNC_LOG; + + CSAnimMifPlugin* self = + new( ELeave ) CSAnimMifPlugin( aConstructionParameters ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + + +// --------------------------------------------------------------------------- +// CSAnimMifPlugin::~CSAnimMifPlugin +// +// --------------------------------------------------------------------------- +// +CSAnimMifPlugin::~CSAnimMifPlugin() + { + FUNC_LOG; + + delete iDummy; + delete iTimer; + iFrames.ResetAndDestroy(); + } + + +// --------------------------------------------------------------------------- +// CSAnimMifPlugin::TimerExpired +// +// --------------------------------------------------------------------------- +// +void CSAnimMifPlugin::TimerExpired() + { + FUNC_LOG; + + if ( iCurrentFrame < iFrames.Count() - KArrElementsPerFrame ) + { + iCurrentFrame += KArrElementsPerFrame; // Each other array element is a mask + RefreshView(); + } + else + { + iTimer->Cancel(); + CompleteClientRequest( KErrNone ); + } + } + + +// --------------------------------------------------------------------------- +// CSAnimMifPlugin::Load +// +// --------------------------------------------------------------------------- +// +void CSAnimMifPlugin::Load( + RFs& aFs, + const TDesC& aFileName, + TRequestStatus& aStatus ) + { + FUNC_LOG; + INFO_1( "File name: %S", &aFileName ); + + iTimer->Cancel(); + iFrames.ResetAndDestroy(); + iCurrentFrame = -1; + + TRAPD( errorCode, LoadL( aFs, aFileName ) ); + ERROR( errorCode, "Failed to load image file" ); + SetClientRequest( aStatus ); + CompleteClientRequest( errorCode ); + } + + +// --------------------------------------------------------------------------- +// CSAnimMifPlugin::Start +// +// --------------------------------------------------------------------------- +// +void CSAnimMifPlugin::Start( TRequestStatus& aStatus ) + { + FUNC_LOG; + ASSERT_TRACE( iEngine, SAnimPanic::ENotInitialized ); + ASSERT_TRACE( !( iTimer->IsActive() ), SAnimPanic::EInternalError ); + + SetClientRequest( aStatus ); + + iCurrentFrame = 0; + if ( iCurrentFrame < iFrames.Count() - 1 ) // Last one is a mask + { + RefreshView(); + iTimer->Start( + iFrameDelay, iFrameDelay, TCallBack( TimerCallBack, this ) ); + } + else + { + CompleteClientRequest( KErrNone ); + } + } + + +// --------------------------------------------------------------------------- +// CSAnimMifPlugin::Cancel +// +// --------------------------------------------------------------------------- +// +void CSAnimMifPlugin::Cancel() + { + FUNC_LOG; + + CompleteClientRequest( KErrCancel ); + + iTimer->Cancel(); + } + + +// --------------------------------------------------------------------------- +// CSAnimMifPlugin::BackroundColour +// +// --------------------------------------------------------------------------- +// +TRgb CSAnimMifPlugin::BackroundColour() const + { + FUNC_LOG; + + return KRgbWhite; + } + + +// --------------------------------------------------------------------------- +// CSAnimMifPlugin::UpdateScreen +// +// --------------------------------------------------------------------------- +// +void CSAnimMifPlugin::UpdateScreen() + { + FUNC_LOG; + } + + +// --------------------------------------------------------------------------- +// CSAnimMifPlugin::CSAnimMifPlugin +// +// --------------------------------------------------------------------------- +// +CSAnimMifPlugin::CSAnimMifPlugin( TAny* aConstructionParameters ) + : CSAnimSvgPluginBase( aConstructionParameters ), + iCurrentFrame( -1 ) + { + FUNC_LOG; + } + + +// --------------------------------------------------------------------------- +// CSAnimMifPlugin::ConstructL +// +// --------------------------------------------------------------------------- +// +void CSAnimMifPlugin::ConstructL() + { + FUNC_LOG; + + iTimer = CPeriodic::NewL( CActive::EPriorityHigh ); + iDummy = new ( ELeave ) CFbsBitmap(); + User::LeaveIfError( iDummy->Create( TSize( 0, 0 ), EGray256 ) ); + } + + +// --------------------------------------------------------------------------- +// CSAnimMifPlugin::LoadL +// +// --------------------------------------------------------------------------- +// +void CSAnimMifPlugin::LoadL( RFs& aFs, const TDesC& aFileName ) + { + FUNC_LOG; + + delete iEngine; + iEngine = NULL; + iEngine = CSvgEngineInterfaceImpl::NewL( iDummy, this, iFontSpec ); + iEngine->SetBackgroundColor( KRgbWhite.Internal() ); + iEngine->SetDRMMode( EFalse ); + + RFile file; + CleanupClosePushL( file ); + User::LeaveIfError( file.Open( + aFs, aFileName, EFileRead | EFileShareReadersOnly ) ); + + TMifHeaderPckg header; + TInt errorCode = file.Read( header ); + ERROR( errorCode, "CSAnimMifPlugin::LoadL: failed to read file" ); + INFO_2( "CSAnimMifPlugin::LoadL: arr pos %d, arr length %d", + header().iArrayOffset, header().iArrayLength ); + User::LeaveIfError( errorCode ); + TInt fileSize( 0 ); + errorCode = file.Size( fileSize ); + ERROR( errorCode, "CSAnimMifPlugin::LoadL: failed to read file size" ); + User::LeaveIfError( errorCode ); + + if ( header().iArrayOffset < 0 || header().iArrayLength <= 0 || + header().iArrayOffset + header().iArrayLength <= 0 || + header().iArrayOffset + header().iArrayLength > fileSize ) + { + User::Leave( KErrCorrupt ); + } + + ReadIconArrayL( file, header().iArrayOffset, header().iArrayLength ); + + CleanupStack::PopAndDestroy( &file ); + } + + +// --------------------------------------------------------------------------- +// CSAnimMifPlugin::ReadIconArrayL +// +// --------------------------------------------------------------------------- +// +void CSAnimMifPlugin::ReadIconArrayL( + RFile& aFile, + const TInt32 aPosition, + const TInt32 aLength ) + { + FUNC_LOG; + + const TInt elementSize = sizeof( TIconOffsetElementPckg ) / 2; + INFO_1( "Reserving %d bytes", aLength * elementSize ); + + HBufC8* iconArray = HBufC8::NewLC( aLength * elementSize ); + TPtr8 iconArrayPtr = iconArray->Des(); + TInt errorCode = aFile.Read( aPosition, iconArrayPtr, aLength * elementSize ); + ERROR( errorCode, "CSAnimMifPlugin::ReadIconArrayL failed to read from file" ); + User::LeaveIfError( errorCode ); + + INFO_1( "Read %d bytes", iconArrayPtr.Length() ); + + for ( TInt i = 0; i < ( iconArrayPtr.Length() / elementSize ); i += KIconArrStep ) + { + INFO_1( "Read icon %d", i ); + + ReadIconOffsetElementL( + aFile, iconArrayPtr.MidTPtr( i * elementSize, elementSize ) ); + } + + CleanupStack::PopAndDestroy( iconArray ); + } + + +// --------------------------------------------------------------------------- +// CSAnimMifPlugin::ReadIconOffsetElementL +// +// --------------------------------------------------------------------------- +// +void CSAnimMifPlugin::ReadIconOffsetElementL( + RFile& aFile, + const TDesC8& aData ) + { + FUNC_LOG; + + TIconOffsetElementPckg element; + element.Copy( aData ); + INFO_2( "Offset %d, length %d", element().iOffset, element().iLength ); + + TIconHeaderPckg header; + TInt errorCode = aFile.Read( element().iOffset, header ); + ERROR( errorCode, "CSAnimMifPlugin::ReadIconOffsetElementL failed to read from file" ); + User::LeaveIfError( errorCode ); + + INFO_2( "Data pos %d, data length %d", header().iDataOffset, header().iDataLength ); + INFO_3( "Type %d, depth %d, mask depth %d", header().iType, header().iDepth, header().iMaskDepth ); + + if ( header().iType != KSvgType ) + { + ERROR_1( KErrNotSupported, "Unsupported file type: %d", header().iType ); + + User::Leave( KErrNotSupported ); + } + + HBufC8* data = HBufC8::NewLC( header().iDataLength ); + TPtr8 dataPtr = data->Des(); + errorCode = aFile.Read( element().iOffset + header().iDataOffset, dataPtr ); + ERROR( errorCode, "CSAnimMifPlugin::ReadIconOffsetElementL failed to read from file" ); + User::LeaveIfError( errorCode ); + + CFbsBitmap* mask = new ( ELeave ) CFbsBitmap(); + CleanupStack::PushL( mask ); + User::LeaveIfError( mask->Create( iSize, EGray256 ) ); + + CFbsBitmap* bmp = new ( ELeave ) CFbsBitmap(); + CleanupStack::PushL( bmp ); + User::LeaveIfError( + bmp->Create( iSize, static_cast( header().iDepth ) ) ); + + TInt handle( 0 ); + errorCode = SvgToSymbianErr( iEngine->PrepareDom( dataPtr, handle ) ); + ERROR( errorCode, "Failed to prepare DOM" ); + User::LeaveIfError( errorCode ); + + errorCode = SvgToSymbianErr( iEngine->UseDom( handle, bmp, mask ) ); + ERROR( errorCode, "Failed to use DOM" ); + User::LeaveIfError( errorCode ); + + iEngine->SetPreserveAspectRatio( + NULL, ESvgPreserveAspectRatio_XmidYmid, ESvgMeetOrSlice_Meet, ETrue ); + + MSvgError* error = NULL; + iEngine->Start( error ); + errorCode = SvgToSymbianErr( error ); + ERROR( errorCode, "Failed to start engine" ); + User::LeaveIfError( errorCode ); + + errorCode = SvgToSymbianErr( iEngine->UseDom( handle, NULL, NULL ) ); + ERROR( errorCode, "Failed to use DOM (empty)" ); + User::LeaveIfError( errorCode ); + + iEngine->DeleteDom( handle ); + + iFrames.AppendL( bmp ); + CleanupStack::Pop( bmp ); // It's now in the array. + + iFrames.AppendL( mask ); + CleanupStack::Pop( mask ); // It's now in the array. + + CleanupStack::PopAndDestroy( data ); + } + + +// --------------------------------------------------------------------------- +// CSAnimMifPlugin::RefreshView +// +// --------------------------------------------------------------------------- +// +void CSAnimMifPlugin::RefreshView() + { + FUNC_LOG; + ASSERT_TRACE( iCurrentFrame < iFrames.Count() - 1, SAnimPanic::EInternalError ); + + iObserver.UpdateScreen( + *( iFrames[iCurrentFrame] ), *( iFrames[iCurrentFrame + 1] ) ); + }