--- /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 <AknIconUtils.h>
+#include <AknsSrvClient.h>
+
+#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<CFbsBitmap*>(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; yTile<iTilesY; yTile++ )
+ {
+ drawPoint.iX = 0;
+ if (iGenericImage)
+ {
+ if (bitmap->SizeInPixels().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; xTile<iTilesX; xTile++ )
+ {
+ if( layerData.iRGBGc )
+ {
+ layerData.iRGBGc->SetBrushStyle(
+ 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