diff -r 000000000000 -r 05e9090e2422 skins/AknSkins/rlpluginsrc/AknsRlEffectPluginApplyGfx.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/skins/AknSkins/rlpluginsrc/AknsRlEffectPluginApplyGfx.cpp Thu Dec 17 09:14:12 2009 +0200 @@ -0,0 +1,663 @@ +/* +* Copyright (c) 2004-2008 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: Effect that applies the given bitmap or SVG icon to the layer. +* +*/ + + +// INCLUDE FILES +#include "AknsRlEffectPluginApplyGfx.h" + +#include +#include + +#include "AknsFsHandleProvider.h" + +// CONSTANTS +/*lint -save -e618 */ // Disables lint nag about _LIT +const TInt KApplyGfxEffectUID = 0x101F8748; +_LIT( KApplyGfxParamFilename, "f" ); +_LIT( KApplyGfxParamScaleMode, "ms" ); +static const TInt KApplyGfxValueScaleModePreserveAspect = 0; +static const TInt KApplyGfxValueScaleModeStretch = 1; +_LIT( KApplyGfxParamXTiles, "tx" ); +_LIT( KApplyGfxParamYTiles, "ty" ); +_LIT( KApplyGfxParamTileW, "tw" ); +_LIT( KApplyGfxParamTileH, "th" ); +_LIT( KApplyGfxParamAspectLT, "alt" ); +_LIT( KApplyGfxParamAspectGT, "agt" ); +_LIT( KApplyGfxParamGenImg, "g" ); +/*lint -restore */ + +_LIT(KAknsSrvPrivateLocation, "private\\10207114\\"); + + +// ============================= LOCAL FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// DivAndRoundUp +// +// Divides the given number by the given divider, and rounds the resulting +// integer upward, if there is a non-zero remainder. +// +// Returns: Divedend as an integer. +// ----------------------------------------------------------------------------- +// +TInt DivAndRoundUp( const TInt aNumber, const TInt aDivider ) + { + TInt result = aNumber/aDivider; + if( aNumber%aDivider ) + { + result+=1; + } + return result; + } + +// Destroys preserved icon. +void DestroyPreservedIcon( TAny* aBitmap ) + { + CFbsBitmap* bitmap = static_cast(aBitmap); + if ( bitmap ) + { + AknIconUtils::DestroyIconData( bitmap ); + } + } + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CAknsRlEffectPluginApplyGfx::CAknsRlEffectPluginApplyGfx +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CAknsRlEffectPluginApplyGfx::CAknsRlEffectPluginApplyGfx() + { + } + +// ----------------------------------------------------------------------------- +// Destructor +// ----------------------------------------------------------------------------- +// +CAknsRlEffectPluginApplyGfx::~CAknsRlEffectPluginApplyGfx() + { + iContext = NULL; // Removes lint nag + iFilename = NULL; // Removes lint nag + } + +// ----------------------------------------------------------------------------- +// CAknsRlEffectPluginApplyGfx::EffectUid +// ----------------------------------------------------------------------------- +// +TUid CAknsRlEffectPluginApplyGfx::EffectUid() const + { + return TUid::Uid( KApplyGfxEffectUID ); + } + +// ----------------------------------------------------------------------------- +// CAknsRlEffectPluginApplyGfx::Effect +// ----------------------------------------------------------------------------- +// +MAknsRlEffect* CAknsRlEffectPluginApplyGfx::Effect( const TInt aInterface ) + { + if( aInterface == KAknsRlEffectPluginInterfaceEffect ) + { + return this; + } + return NULL; + } + +// ----------------------------------------------------------------------------- +// CAknsRlEffectPluginApplyGfx::InitializeL +// ----------------------------------------------------------------------------- +// +void CAknsRlEffectPluginApplyGfx::InitializeL() + { + iContext = NULL; + } + +// ----------------------------------------------------------------------------- +// CAknsRlEffectPluginApplyGfx::Release +// ----------------------------------------------------------------------------- +// +void CAknsRlEffectPluginApplyGfx::Release() + { + } + +// ----------------------------------------------------------------------------- +// CAknsRlEffectPluginApplyGfx::ActivateL +// ----------------------------------------------------------------------------- +// +void CAknsRlEffectPluginApplyGfx::ActivateL( MAknsRlEffectContext* aContext ) + { + if( !aContext ) // We absolutely need the context + { + User::Leave( KErrArgument ); + } + + iContext = aContext; + + iFilename = NULL; + iBmpIndex = -1; + iMaskIndex = -1; + + iScaleMode = KApplyGfxValueScaleModeStretch; + iTiled = EFalse; + iTilesX = 1; + iTilesY = 1; + iTileW = 0; + iTileH = 0; + + iMaxAspect = -1; + iMinAspect = -1; + iGenericImage = 0; + } + +// ----------------------------------------------------------------------------- +// CAknsRlEffectPluginApplyGfx::Deactivate +// ----------------------------------------------------------------------------- +// +void CAknsRlEffectPluginApplyGfx::Deactivate() + { + delete iFilename; + iFilename = NULL; + } + +// ----------------------------------------------------------------------------- +// CAknsRlEffectPluginApplyGfx::SetParametersL +// ----------------------------------------------------------------------------- +// +void CAknsRlEffectPluginApplyGfx::SetParametersL( + MAknsRlParameterIterator& aParameters ) + { + while( aParameters.HasNext() ) + { + const TAknsRlParameterData* param = aParameters.NextL(); + + if( param->iName->Compare(KApplyGfxParamFilename) == 0 ) + { + if( param->iType != EAknsRlParameterTypeGraphics ) + { + User::Leave( KErrArgument ); + } + delete iFilename; + iFilename = NULL; + iFilename = param->iGfx->iFilename->AllocL(); + iBmpIndex = param->iGfx->iIndex; + iMaskIndex = param->iGfx->iMaskIndex; + } + else if( param->iName->Compare(KApplyGfxParamScaleMode) == 0 ) + { + if( param->iType != EAknsRlParameterTypeNumber ) + { + User::Leave( KErrArgument ); + } + iScaleMode = param->iNumber; + } + else if( param->iName->Compare(KApplyGfxParamXTiles) == 0 ) + { + if( param->iType != EAknsRlParameterTypeNumber ) + { + User::Leave( KErrArgument ); + } + iTilesX = param->iNumber; + iTiled = ETrue; + } + else if( param->iName->Compare(KApplyGfxParamYTiles) == 0 ) + { + if( param->iType != EAknsRlParameterTypeNumber ) + { + User::Leave( KErrArgument ); + } + iTilesY = param->iNumber; + iTiled = ETrue; + } + else if( param->iName->Compare(KApplyGfxParamTileW) == 0 ) + { + if( param->iType != EAknsRlParameterTypeNumber ) + { + User::Leave( KErrArgument ); + } + iTileW = param->iNumber; + iTiled = ETrue; + } + else if( param->iName->Compare(KApplyGfxParamTileH) == 0 ) + { + if( param->iType != EAknsRlParameterTypeNumber ) + { + User::Leave( KErrArgument ); + } + iTileH = param->iNumber; + iTiled = ETrue; + } + else if( param->iName->Compare(KApplyGfxParamAspectGT) == 0 ) + { + if( param->iType != EAknsRlParameterTypeNumber ) + { + User::Leave( KErrArgument ); + } + iMinAspect = param->iNumber; + } + else if( param->iName->Compare(KApplyGfxParamAspectLT) == 0 ) + { + if( param->iType != EAknsRlParameterTypeNumber ) + { + User::Leave( KErrArgument ); + } + iMaxAspect = param->iNumber; + } + else if( param->iName->Compare(KApplyGfxParamGenImg) == 0 ) + { + if( param->iType != EAknsRlParameterTypeNumber ) + { + User::Leave( KErrArgument ); + } + iGenericImage = param->iNumber; + } + } + } + +// ----------------------------------------------------------------------------- +// CAknsRlEffectPluginApplyGfx::GetCapabilities +// ----------------------------------------------------------------------------- +// +void CAknsRlEffectPluginApplyGfx::GetCapabilities( TAknsRlEffectCaps& aCaps ) + { + // Input layers are not used + aCaps.iInputLayerASupport = KAknsRlLayerNone; + aCaps.iInputLayerBSupport = KAknsRlLayerNone; + aCaps.iOutputLayerSupport = KAknsRlLayerRGBOnly | + KAknsRlLayerAlphaOnly | KAknsRlLayerRGBA; + } + +// ----------------------------------------------------------------------------- +// CAknsRlEffectPluginApplyGfx::Render +// ----------------------------------------------------------------------------- +// +TInt CAknsRlEffectPluginApplyGfx::Render( const TAknsRlRenderOpParam& aParam ) + { + TRAPD( err, DoRenderL( aParam ) ); + return err; + } + +// ----------------------------------------------------------------------------- +// CAknsRlEffectPluginApplyGfx::DoRenderL +// ----------------------------------------------------------------------------- +// +void CAknsRlEffectPluginApplyGfx::DoRenderL( const TAknsRlRenderOpParam& aParam ) + { + TSize layoutSize = iContext->LayerSize(); + TInt aspect = KMaxTInt; + if( layoutSize.iHeight != 0 ) + { + aspect = (layoutSize.iWidth*256) / layoutSize.iHeight; + } + + if( iMaxAspect >= 0 ) + { + if( aspect >= iMaxAspect ) return; + } + if( iMinAspect >= 0 ) + { + if( aspect <= iMinAspect ) return; + } + + TAknsRlLayerData layerData; + iContext->GetLayerDataL( layerData, aParam.iOutputLayerIndex, + aParam.iOutputLayerStatus, ETrue ); + + if( !iFilename ) User::Leave( KErrArgument ); + if( iBmpIndex<0 ) User::Leave( KErrArgument ); + + TBool hasMask = ETrue; + if( iMaskIndex<0 ) hasMask = EFalse; + + CFbsBitmap* bitmap = NULL; + CFbsBitmap* mask = NULL; + + RAknsSrvSession* skinsrvsession = NULL; + + TBool altbmplocation = ETrue; +#ifdef AKNS_RL_TEST_FRAMEWORK +// Note: Pragma message causes CodeTest compiler to go berserk. +#pragma message("Compiling ApplyGfx WITHOUT filename check <----------------") + // Don't compile filename check to test framework. This is required to make + // ApplyGfx behave with unit tests. +#else + + if (iGenericImage) + { + hasMask = EFalse; + } + else + { + TInt res = (*iFilename).FindF(KAknsSrvPrivateLocation); + if (res >= 0) // location found + { + altbmplocation = EFalse; + } + } +#endif + + skinsrvsession = iContext->GetSkinSrvSession(); + if (!skinsrvsession) + { + User::Leave(KErrArgument); + } + + if( hasMask && !iGenericImage) + { + if (!altbmplocation) + { + // AknIconUtils will call CAknsFsHandleProvider::Finished when it is ready => deletes the object + CAknsFsHandleProvider* provider = CAknsFsHandleProvider::NewL(skinsrvsession, *iFilename); + AknIconUtils::CreateIconL( + bitmap, mask, *provider, iBmpIndex, iMaskIndex ); + } + else + { + AknIconUtils::CreateIconL( + bitmap, mask, *iFilename, iBmpIndex, iMaskIndex ); + } + + CleanupStack::PushL( bitmap ); + CleanupStack::PushL( mask ); + if( !bitmap || !mask ) + { + User::Leave( KErrNotFound ); + } + } + else if (!iGenericImage) + { + if (!altbmplocation) + { + // AknIconUtils will call CAknsFsHandleProvider::Finished when it is ready => deletes the object + CAknsFsHandleProvider* provider = CAknsFsHandleProvider::NewL(skinsrvsession, *iFilename); + bitmap = AknIconUtils::CreateIconL( *provider, iBmpIndex ); + } + else + { + bitmap = AknIconUtils::CreateIconL( *iFilename, iBmpIndex ); + } + + CleanupStack::PushL( bitmap ); // bitmap + if( !bitmap ) + { + User::Leave( KErrNotFound ); + } + } + else // isGenericImage + { + TInt decodeErr = KErrNone; + TRAP(decodeErr, + skinsrvsession->DecodeWallpaperImageL(*iFilename, layoutSize, bitmap, mask)); + if (decodeErr == KErrNoMemory) + { + // ignore OOM errors, so that the phone will + // not try to do this whole time + return; + } + else + { + User::LeaveIfError(decodeErr); + } + + if (!bitmap) + { + User::Leave( KErrNotFound ); + } + CleanupStack::PushL(bitmap); + if (mask) + { + hasMask = ETrue; + CleanupStack::PushL(mask); + } + } + + TSize srcSize; + TBool svg = AknIconUtils::IsMifIcon( bitmap ); + TBool svgIconDataPreserved = EFalse; + if( svg && !iGenericImage) + { + svgIconDataPreserved = ETrue; + AknIconUtils::PreserveIconData( bitmap ); + CleanupStack::PushL( TCleanupItem( DestroyPreservedIcon, bitmap ) ); + if( AknIconUtils::GetContentDimensions( bitmap, srcSize ) ) + { + User::Leave( KErrUnknown ); + } + } + else + { + srcSize = bitmap->SizeInPixels(); + } + TInt srcAspect = KMaxTInt; + if( srcSize.iHeight ) + { + srcAspect = (srcSize.iWidth<<16) / srcSize.iHeight; + } + + TInt layoutAspect = KMaxTInt; + if( layoutSize.iHeight ) + { + layoutAspect = (layoutSize.iWidth<<16) / layoutSize.iHeight; + } + + TRect imgRect; + if( iTiled ) + { + // Zero checks + if( (iTilesX<1) || (iTilesY<1) ) { + User::Leave( KErrArgument ); + } + + TSize tileSize( + DivAndRoundUp( layoutSize.iWidth, iTilesX ), + DivAndRoundUp( layoutSize.iHeight, iTilesY ) ); + + if( iTileW>0 ) + { + tileSize.iWidth = iTileW; + iTilesX = DivAndRoundUp( layoutSize.iWidth, tileSize.iWidth ); + } + + if( iTileH>0 ) + { + tileSize.iHeight = iTileH; + iTilesY = DivAndRoundUp( layoutSize.iHeight, tileSize.iHeight ); + } + AknIconUtils::ExcludeFromCache( bitmap ); + User::LeaveIfError( + AknIconUtils::SetSize( + bitmap, tileSize, EAspectRatioNotPreserved ) ); + + imgRect = TRect( TPoint(0,0), tileSize ); + } + else + { + // Disable tiling in drawing + iTilesX = 1; + iTilesY = 1; + + if( iScaleMode == KApplyGfxValueScaleModePreserveAspect ) + { + if( srcAspect > layoutAspect ) + { + if (!iGenericImage) + { + //28-Apr-2008 Modified by Ding Long + //according to Merila Sami suggestion. + //Comment out to speed up Screen Rotation. + //(Refer to defect AVAO-7D4BXY.) + //AknIconUtils::ExcludeFromCache( bitmap ); + User::LeaveIfError( + AknIconUtils::SetSize( + bitmap, TSize(KMaxTInt, layoutSize.iHeight), + EAspectRatioPreservedAndUnusedSpaceRemoved ) ); + } + } + else + { + if (!iGenericImage) + { + //28-Apr-2008 Modified by Ding Long + //according to Merila Sami suggestion. + //Comment out to speed up Screen Rotation. + //(Refer to defect AVAO-7D4BXY.) + //AknIconUtils::ExcludeFromCache( bitmap ); + User::LeaveIfError( + AknIconUtils::SetSize( + bitmap, TSize(layoutSize.iWidth, KMaxTInt), + EAspectRatioPreservedAndUnusedSpaceRemoved ) ); + } + } + TSize bmpSize = bitmap->SizeInPixels(); + imgRect = TRect( TPoint( + (bmpSize.iWidth-layoutSize.iWidth)/2, + (bmpSize.iHeight-layoutSize.iHeight)/2), layoutSize ); + } + else if( iScaleMode == KApplyGfxValueScaleModeStretch ) + { + if (!iGenericImage) + { + //28-Apr-2008 Modified by Ding Long + //according to Merila Sami suggestion. + //Comment out to speed up Screen Rotation. + //(Refer to defect AVAO-7D4BXY.) + //AknIconUtils::ExcludeFromCache( bitmap ); + User::LeaveIfError( + AknIconUtils::SetSize( + bitmap, layoutSize, + EAspectRatioNotPreserved ) ); + } + imgRect = TRect( TPoint(0,0), layoutSize ); + } + else + { + User::Leave( KErrNotSupported ); + } + } + + // @TODO This does not do mask inversion for hard->soft. + + // Icon operations should be done by now + if (!iGenericImage) + { + if ( svgIconDataPreserved ) + { + svgIconDataPreserved = EFalse; + CleanupStack::PopAndDestroy(); // DestroyPreservedIcon + } + } + TPoint drawPoint( 0, 0 ); + TBool generatedMask = EFalse; + for( TInt yTile=0; yTileSizeInPixels().iWidth < layoutSize.iWidth) + { + drawPoint.iX = (layoutSize.iWidth / 2) - (bitmap->SizeInPixels().iWidth /2); + if (!hasMask) + { + generatedMask = ETrue; + } + } + if (bitmap->SizeInPixels().iHeight < layoutSize.iHeight) + { + drawPoint.iY = (layoutSize.iHeight / 2) - (bitmap->SizeInPixels().iHeight /2); + if (!hasMask) + { + generatedMask = ETrue; + } + } + } + for( TInt xTile=0; xTileSetBrushStyle( + CGraphicsContext::ENullBrush ); + } + if( layerData.iAlphaGc ) + { + layerData.iAlphaGc->SetBrushStyle( + CGraphicsContext::ENullBrush ); + } + + if( (aParam.iOutputLayerStatus==KAknsRlLayerRGBOnly) || + (aParam.iOutputLayerStatus==KAknsRlLayerRGBA) ) + { + layerData.iRGBGc->BitBlt( drawPoint, bitmap, imgRect ); + // When RGBOnly is queried alpha information is not filled -> + // we need to check alphaGc exists. + if (generatedMask && layerData.iAlphaGc) + { + layerData.iAlphaGc->SetBrushColor( KRgbBlack ); + layerData.iAlphaGc->Clear(); + layerData.iAlphaGc->SetBrushStyle( + CGraphicsContext::ESolidBrush ); + + layerData.iAlphaGc->SetPenColor(KRgbWhite); + layerData.iAlphaGc->SetPenStyle(CGraphicsContext::ESolidPen); + layerData.iAlphaGc->SetBrushColor( KRgbWhite ); + TRect rect(drawPoint, bitmap->SizeInPixels()); + layerData.iAlphaGc->DrawRect(rect); + layerData.iAlphaGc->SetBrushStyle( + CGraphicsContext::ENullBrush ); + layerData.iAlphaGc->SetPenStyle(CGraphicsContext::ENullPen); + } + } + if( aParam.iOutputLayerStatus==KAknsRlLayerRGBA && hasMask) + { + layerData.iAlphaGc->BitBlt( drawPoint, mask, imgRect ); + } + if( aParam.iOutputLayerStatus==KAknsRlLayerAlphaOnly ) + { + // If there is no mask, draw bitmap to alpha channel + CFbsBitmap* srcBitmap = bitmap; + if( hasMask ) + { + // ... otherwise, draw mask to alpha channel + srcBitmap = mask; + } + layerData.iAlphaGc->BitBlt( drawPoint, srcBitmap, imgRect ); + } + + drawPoint.iX += imgRect.Size().iWidth; + } + + drawPoint.iY += imgRect.Size().iHeight; + } + + if( aParam.iOutputLayerStatus==KAknsRlLayerRGBA && !hasMask && !generatedMask ) + { + // RGBA and no mask, clear with white + layerData.iAlphaGc->SetBrushColor( KRgbWhite ); + layerData.iAlphaGc->Clear(); + } + if ( svgIconDataPreserved ) + { + CleanupStack::PopAndDestroy(); // DestroyPreservedIcon + } + + if( hasMask ) + { + CleanupStack::PopAndDestroy( mask ); + } + CleanupStack::PopAndDestroy( bitmap ); + } + +// End of File