diff -r 000000000000 -r 05e9090e2422 skins/AknSkins/rlpluginsrc/AknsRlEffectPluginMovingLayers.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/skins/AknSkins/rlpluginsrc/AknsRlEffectPluginMovingLayers.cpp Thu Dec 17 09:14:12 2009 +0200 @@ -0,0 +1,499 @@ +/* +* 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: Provides moving layer(s) functionality. +* +*/ + + +// INCLUDE FILES +#include "AknsRlEffectPluginMovingLayers.h" + +// ================= INTERNAL IMPL. OF MOVING LAYERS =========================== +class AknsRlMovingLayers + { + public: + static void RenderTiled( CFbsBitGc& aBitGc, + const TInt aX, const TInt aY, + const TInt aW, const TInt aH, + const CFbsBitmap& aBmp, + const CFbsBitmap* aMask=NULL ) + { + if( 0 == aX && 0 == aY ) // Render 1:1 + { + if( aMask ) + { + aBitGc.BitBltMasked( TPoint( 0, 0 ), &aBmp, + TRect( TPoint( 0, 0 ), + TSize( aW, aH ) ), + aMask, EFalse ); + } + else + { + aBitGc.BitBlt( TPoint( 0, 0 ), &aBmp, + TRect( TPoint( 0, 0 ), + TSize( aW, aH ) ) ); + } + } + else // Draw tiled + { + /* + Output Input + --------- --------- + |4' |3' | |1 |2 | + |---o-----| | | | + |2' |1' | | | | + | | | | | | + | | | |-----o---| + | | | |3 |4 | + --------- --------- + + Output rects: + 1' ( x, y, w - x, h - y ) + 2' ( 0, y, x, h - y ) + 3' ( x, 0, w - x, y ) + 4' ( 0, 0, x, y ) + + Input rects: + 1 ( 0, 0, w - x, h - y ) + 2 ( w - x, 0, x, h - y ) + 3 ( 0, h - y, w - x, y ) + 4 ( w - x, h - y, x, y ) + + */ + TRect source; + + if( aMask ) + { + // Target top left ( 4 -> 4' ) + source.SetRect( TPoint( aW - aX, aH - aY ), TSize( aX, aY ) ); + aBitGc.BitBltMasked( TPoint( 0, 0 ), &aBmp, source, aMask, EFalse ); + // Target top right ( 3 -> 3' ) + source.SetRect( TPoint( 0, aH - aY ), TSize( aW - aX, aY ) ); + aBitGc.BitBltMasked( TPoint( aX, 0 ), &aBmp, source, aMask, EFalse ); + // Target bottom left ( 2 -> 2' ) + source.SetRect( TPoint( aW - aX, 0 ), TSize( aX, aH - aY ) ); + aBitGc.BitBltMasked( TPoint( 0, aY ), &aBmp, source, aMask, EFalse ); + // Target bottom right ( 1 -> 1' ) + source.SetRect( TPoint( 0, 0 ), TSize( aW - aX, aH - aY ) ); + aBitGc.BitBltMasked( TPoint( aX, aY ), &aBmp, source, aMask, EFalse ); + } + else + { + // Target top left ( 4 -> 4' ) + source.SetRect( TPoint( aW - aX, aH - aY ), TSize( aX, aY ) ); + aBitGc.BitBlt( TPoint( 0, 0 ), &aBmp, source ); + // Target top right ( 3 -> 3' ) + source.SetRect( TPoint( 0, aH - aY ), TSize( aW - aX, aY ) ); + aBitGc.BitBlt( TPoint( aX, 0 ), &aBmp, source ); + // Target bottom left ( 2 -> 2' ) + source.SetRect( TPoint( aW - aX, 0 ), TSize( aX, aH - aY ) ); + aBitGc.BitBlt( TPoint( 0, aY ), &aBmp, source ); + // Target bottom right ( 1 -> 1' ) + source.SetRect( TPoint( 0, 0 ), TSize( aW - aX, aH - aY ) ); + aBitGc.BitBlt( TPoint( aX, aY ), &aBmp, source ); + } + } + } + }; + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CAknsRlEffectPluginMovingLayers::CAknsRlEffectPluginMovingLayers +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CAknsRlEffectPluginMovingLayers::CAknsRlEffectPluginMovingLayers() + { + } + +// ----------------------------------------------------------------------------- +// Destructor +// ----------------------------------------------------------------------------- +// +CAknsRlEffectPluginMovingLayers::~CAknsRlEffectPluginMovingLayers() + { + // The user of this plugin should call deactivate...but we ensure deletion + // here (just in case). + DeleteTempBitmap(); //lint !e1551 No exception thrown + } + +// ----------------------------------------------------------------------------- +// CAknsRlEffectPluginMovingLayers::EffectUid +// ----------------------------------------------------------------------------- +// +TUid CAknsRlEffectPluginMovingLayers::EffectUid() const + { + return TUid::Uid( KAknsRlEffectPluginMovingLayersUID ); + } + +// ----------------------------------------------------------------------------- +// CAknsRlEffectPluginMovingLayers::Effect +// ----------------------------------------------------------------------------- +// +MAknsRlEffect* CAknsRlEffectPluginMovingLayers::Effect( const TInt aInterface ) + { + if( aInterface == KAknsRlEffectPluginInterfaceEffect ) + return this; + return NULL; + } + +// ----------------------------------------------------------------------------- +// CAknsRlEffectPluginMovingLayers::InitializeL +// ----------------------------------------------------------------------------- +// +void CAknsRlEffectPluginMovingLayers::InitializeL() + { + iContext = NULL; + } + +// ----------------------------------------------------------------------------- +// CAknsRlEffectPluginMovingLayers::Release +// ----------------------------------------------------------------------------- +// +void CAknsRlEffectPluginMovingLayers::Release() + { + } + +// ----------------------------------------------------------------------------- +// CAknsRlEffectPluginMovingLayers::ActivateL +// ----------------------------------------------------------------------------- +// +void CAknsRlEffectPluginMovingLayers::ActivateL( MAknsRlEffectContext* aContext ) + { + if( !aContext ) // We absolutely need the context + { + User::Leave( KErrArgument ); + } + + iContext = aContext; + + iAx = 0; + iAy = 0; + iBx = 0; + iBy = 0; + + DeleteTempBitmap(); + } + +// ----------------------------------------------------------------------------- +// CAknsRlEffectPluginMovingLayers::Deactivate +// ----------------------------------------------------------------------------- +// +void CAknsRlEffectPluginMovingLayers::Deactivate() + { + DeleteTempBitmap(); + } + +// ----------------------------------------------------------------------------- +// CAknsRlEffectPluginMovingLayers::SetParametersL +// ----------------------------------------------------------------------------- +// +void CAknsRlEffectPluginMovingLayers::SetParametersL( MAknsRlParameterIterator& aParameters ) + { + // Iterate over available parameters + while( aParameters.HasNext() ) + { + const TAknsRlParameterData* param = aParameters.NextL(); + + if( param->iName->Compare( KAknsRlEffectMovingLayersAX ) == 0 ) + { + if( param->iType != EAknsRlParameterTypeNumber ) + User::Leave( KErrArgument ); + + iAx = param->iNumber; + } + else if( param->iName->Compare( KAknsRlEffectMovingLayersAY ) == 0 ) + { + if( param->iType != EAknsRlParameterTypeNumber ) + User::Leave( KErrArgument ); + + iAy = param->iNumber; + } + else if( param->iName->Compare( KAknsRlEffectMovingLayersBX ) == 0 ) + { + if( param->iType != EAknsRlParameterTypeNumber ) + User::Leave( KErrArgument ); + + iBx = param->iNumber; + } + else if( param->iName->Compare( KAknsRlEffectMovingLayersBY ) == 0 ) + { + if( param->iType != EAknsRlParameterTypeNumber ) + User::Leave( KErrArgument ); + + iBy = param->iNumber; + } + else if( param->iName->Compare( KAknsRlEffectMovingLayersAXY ) == 0 ) + { + if( param->iType != EAknsRlParameterTypeString || !param->iString ) + User::Leave( KErrArgument ); + + if( param->iString->Length() < 2 ) + User::Leave( KErrArgument ); + + iAx = (*param->iString)[0]; + iAy = (*param->iString)[1]; + } + else if( param->iName->Compare( KAknsRlEffectMovingLayersBXY ) == 0 ) + { + if( param->iType != EAknsRlParameterTypeString || !param->iString ) + User::Leave( KErrArgument ); + + if( param->iString->Length() < 2 ) + User::Leave( KErrArgument ); + + iBx = (*param->iString)[0]; + iBy = (*param->iString)[1]; + } + } + } + +// ----------------------------------------------------------------------------- +// CAknsRlEffectPluginMovingLayers::GetCapabilities +// ----------------------------------------------------------------------------- +// +void CAknsRlEffectPluginMovingLayers::GetCapabilities( TAknsRlEffectCaps& aCaps ) + { + aCaps.iOutputLayerSupport = KAknsRlLayerRGBOnly; + aCaps.iInputLayerASupport = KAknsRlLayerRGBOnly; + aCaps.iInputLayerBSupport = KAknsRlLayerNone | KAknsRlLayerRGBOnly | KAknsRlLayerRGBA; + } + +// ----------------------------------------------------------------------------- +// CAknsRlEffectPluginMovingLayers::Render +// ----------------------------------------------------------------------------- +// +TInt CAknsRlEffectPluginMovingLayers::Render( const TAknsRlRenderOpParam& aParam ) + { + if( !iContext ) // We absolutely need the context + { + return KErrBadHandle; + } + + TAknsRlLayerData dataT; + TAknsRlLayerData dataA; + TAknsRlLayerData dataB; + + // We need the output layer + if( !( ( aParam.iOutputLayerStatus & KAknsRlLayerRGBOnly ) || + ( aParam.iOutputLayerStatus & KAknsRlLayerRGBA ) ) ) + return KErrArgument; // Output must be some sort of RGB layer + + TRAPD( err, iContext->GetLayerDataL( dataT, aParam.iOutputLayerIndex, + aParam.iOutputLayerStatus, EFalse ) ); + if( KErrNone != err ) + return KErrArgument; + + if( !dataT.iRGBGc || !dataT.iRGBBitmap ) + return KErrBadHandle; + + // We need the input layer A + if( !( ( aParam.iInputLayerAStatus & KAknsRlLayerRGBOnly ) || + ( aParam.iInputLayerAStatus & KAknsRlLayerRGBA ) ) ) + return KErrArgument; // Input layer A must be some sort of RGB layer + + TRAP( err, iContext->GetLayerDataL( dataA, aParam.iInputLayerAIndex, + aParam.iInputLayerAStatus, EFalse ) ); + if( KErrNone != err ) + return KErrArgument; + + if( !dataA.iRGBBitmap ) + return KErrBadHandle; + + // Input layer B is optional + if( ( aParam.iInputLayerBStatus & KAknsRlLayerRGBOnly ) || + ( aParam.iInputLayerBStatus & KAknsRlLayerRGBA ) ) + { + // Input layer B is RGB layer + TRAP( err, iContext->GetLayerDataL( dataB, aParam.iInputLayerBIndex, + aParam.iInputLayerBStatus, EFalse ) ); + if( KErrNone != err ) + return KErrArgument; + + if( !dataB.iRGBBitmap ) + return KErrBadHandle; + } + + // If we got this far we have all the required devices for doing rendering. + + // Tiled rendering does not work correctly if one of the input layers is + // the same as output layer. + if( ( aParam.iInputLayerAIndex == aParam.iOutputLayerIndex && dataA.iRGBBitmap ) || + ( aParam.iInputLayerBIndex == aParam.iOutputLayerIndex && dataB.iRGBBitmap ) ) + { + if( !iTempBitmap ) + { + err = CreateTempBitmap( *dataT.iRGBBitmap ); + if( KErrNone != err ) + return err; + } + else // Temp bitmap already exists + { + // Check if we can reuse the existing bitmap + if( iTempBitmap->SizeInPixels() == dataT.iRGBBitmap->SizeInPixels() && + iTempBitmap->DisplayMode() == dataT.iRGBBitmap->DisplayMode() ) + { + iTempContext->BitBlt( TPoint( 0, 0 ), dataT.iRGBBitmap ); + } + else + { + DeleteTempBitmap(); + err = CreateTempBitmap( *dataT.iRGBBitmap ); + if( KErrNone != err ) + return err; + } + } + } + + // Determine real coordinates (we do tiling) + TSize size = iContext->LayerSize(); + + TInt ax = iAx % size.iWidth; + TInt ay = iAy % size.iHeight; + + if( ax < 0 ) + ax = ax + size.iWidth; + if( ay < 0 ) + ay = ay + size.iHeight; + // ax, bx are now in range [0, size.iWidth - 1] + + TInt bx = iBx % size.iWidth; + TInt by = iBy % size.iHeight; + + if( bx < 0 ) + bx = bx + size.iWidth; + if( by < 0 ) + by = by + size.iHeight; + // bx, by are now in range [0, size.iHeight - 1] + + // Render + if( dataA.iRGBBitmap && !dataB.iRGBBitmap ) // Only A is available + { + if( aParam.iInputLayerAIndex == aParam.iOutputLayerIndex ) + AknsRlMovingLayers::RenderTiled( *dataT.iRGBGc, + ax, ay, size.iWidth, size.iHeight, + *iTempBitmap ); + else + AknsRlMovingLayers::RenderTiled( *dataT.iRGBGc, + ax, ay, size.iWidth, size.iHeight, + *dataA.iRGBBitmap ); + } + // A, B and mask B available + else if( dataA.iRGBBitmap && dataB.iRGBBitmap && dataB.iAlphaBitmap ) + { + if( aParam.iInputLayerAIndex == aParam.iOutputLayerIndex ) + AknsRlMovingLayers::RenderTiled( *dataT.iRGBGc, + ax, ay, size.iWidth, size.iHeight, + *iTempBitmap ); + else + AknsRlMovingLayers::RenderTiled( *dataT.iRGBGc, + ax, ay, size.iWidth, size.iHeight, + *dataA.iRGBBitmap ); + + if( aParam.iInputLayerBIndex == aParam.iOutputLayerIndex ) + AknsRlMovingLayers::RenderTiled( *dataT.iRGBGc, + bx, by, size.iWidth, size.iHeight, + *iTempBitmap ); + else + AknsRlMovingLayers::RenderTiled( *dataT.iRGBGc, + bx, by, size.iWidth, size.iHeight, + *dataB.iRGBBitmap, dataB.iAlphaBitmap ); + } + // A and B available, but no mask for B + else if( dataA.iRGBBitmap && dataB.iRGBBitmap && !dataB.iAlphaBitmap ) + { + // Render B only + if( aParam.iInputLayerBIndex == aParam.iOutputLayerIndex ) + AknsRlMovingLayers::RenderTiled( *dataT.iRGBGc, + bx, by, size.iWidth, size.iHeight, + *iTempBitmap ); + else + AknsRlMovingLayers::RenderTiled( *dataT.iRGBGc, + bx, by, size.iWidth, size.iHeight, + *dataB.iRGBBitmap, dataB.iAlphaBitmap ); + } + + // Clear the target alpha if it exists + if( dataT.iAlphaGc ) + { + dataT.iAlphaGc->SetBrushColor( KRgbWhite ); + dataT.iAlphaGc->Clear(); + } + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CAknsRlEffectPluginMovingLayers::CreateTempBitmap +// ----------------------------------------------------------------------------- +// +TInt CAknsRlEffectPluginMovingLayers::CreateTempBitmap( + const CFbsBitmap& aBitmap ) + { + ASSERT( NULL == iTempBitmap ); + ASSERT( NULL == iTempDevice ); + ASSERT( NULL == iTempContext ); + + iTempBitmap = new CFbsBitmap(); // OOM returns NULL + if( !iTempBitmap ) + { + DeleteTempBitmap(); + return KErrNoMemory; + } + + TInt err = iTempBitmap->Create( aBitmap.SizeInPixels(), aBitmap.DisplayMode() ); + if( KErrNone != err ) + { + DeleteTempBitmap(); + return err; + } + + TRAP( err, iTempDevice = CFbsBitmapDevice::NewL( iTempBitmap ) ); + if( KErrNone != err ) + { + DeleteTempBitmap(); + return err; + } + + err = iTempDevice->CreateContext( iTempContext ); + if( KErrNone != err ) + { + DeleteTempBitmap(); + return err; + } + + // Temp bitmap and related objects created ok, just render the temp bitmap. + iTempContext->BitBlt( TPoint( 0, 0 ), &aBitmap ); + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CAknsRlEffectPluginMovingLayers::DeleteTempBitmap +// ----------------------------------------------------------------------------- +// +void CAknsRlEffectPluginMovingLayers::DeleteTempBitmap() + { + delete iTempBitmap; + iTempBitmap = NULL; + delete iTempDevice; + iTempDevice = NULL; + delete iTempContext; + iTempContext = NULL; + } + +// End of File +