diff -r 000000000000 -r 05e9090e2422 uigraphics/AknIcon/srvsrc/AknIconSrv.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uigraphics/AknIcon/srvsrc/AknIconSrv.cpp Thu Dec 17 09:14:12 2009 +0200 @@ -0,0 +1,1489 @@ +/* +* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "Symbian Foundation License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Implementation of class CAknIconSrv. +* +*/ + + + +// INCLUDE FILES + +#include +#include +#include +#include +#include +#include + +#ifdef PRECACHELOG +#include +#endif +#include "AknIconSrv.h" +#include "AknIconSrvScheduler.h" +#include "AknIconSrvSession.h" +#include "AknIconSrvDef.h" +#include "AknIconSrvIconItem.h" +#include "AknIconFormatHandler.h" +#include "AknIconFormatHandlerFactory.h" +#include "AknIconLoader.h" +#include "AknIconSrvCache.h" +#include "AknIconSrvPanic.h" +#include "AknIconUtils.h" +#include "AknIconDataPreserver.h" +#include "AknIconDataItem.h" +#include "AknIconSrvUtils.h" +#include "AknIconFileNameCache.h" +#include "akniconconfig.h" +#include "AknIconTraces.h" + +#include "AknBitmap.h" +#include +#include // KUikLayoutState +#include // KAknQwertyInputModeActive +#include // KAknPowerMenuStatus +#include +// CONSTANTS + +const TUid KZiUdbProterty = {0x101F8614}; +const TInt KZiUdbPropertyKey = 1; +const TUid KT9UdbProterty = {0x101F8615}; +const TInt KT9UdbPropertyKey = 1; + +const TInt KIconItemArrayGranularity = 4; + +// Value -1 is used to indicate 'automatic' layout ID detection. +const TInt KAvkonAutomaticLayoutDetectionValue = -1; + +_LIT( KAvkonIconFileName, "z:\\resource\\apps\\avkon2.mif" ); +_LIT( KAknIconServerStartupSemaphore, "AknIconSem" ); + +// ================= MEMBER FUNCTIONS ======================= + +CAknIconServer::CAknIconServer() + : CServer2( CActive::EPriorityStandard ), + iIconItems( KIconItemArrayGranularity ) + { + } + +// Create and start a new server. +CAknIconServer* CAknIconServer::NewL() + { + CAknIconServer* server = new( ELeave ) CAknIconServer; + CleanupStack::PushL( server ); + server->ConstructL(); + CleanupStack::Pop(); + return server; + } + +void CAknIconServer::ConstructL() + { + User::LeaveIfError( iFsSession.Connect() ); + User::LeaveIfError( RFbsSession::Connect() ); + User::LeaveIfError( Start( KAknIconSrvName ) ); + + iFileNameCache = CAknIconFileNameCache::NewL(); + iIconDataPreserver = CAknIconDataPreserver::NewL( *this ); + + + _LIT_SECURITY_POLICY_PASS(KPassReadPolicy); + _LIT_SECURITY_POLICY_PASS(KPassWritePolicy); + + _LIT_SECURITY_POLICY_C1(KWriteDDPolicy, ECapabilityWriteDeviceData); + _LIT_SECURITY_POLICY_C1(KWriteTUPolicy, ECapabilityTrustedUI); + + TInt err1 = RProperty::Define(KCRUidAvkon, KAknQwertyInputModeActive, RProperty::EInt, KPassReadPolicy, KWriteDDPolicy); + TInt err2 = RProperty::Define(KPSUidUikon, KUikLayoutState, RProperty::EInt, KPassReadPolicy, KWriteDDPolicy); + TInt err3 = RProperty::Define(KPSUidUikon, KUikOOMWatchdogStatus, RProperty::EInt, KPassReadPolicy, KPassWritePolicy); + TInt err4 = RProperty::Define(KPSUidUikon, KUikVideoCallTopApp, RProperty::EInt, KPassReadPolicy, KWriteDDPolicy); + TInt err5 = RProperty::Define(KPSUidUikon, KUikFFSFreeLevel, RProperty::EInt, KPassReadPolicy, KWriteTUPolicy); + TInt err6 = RProperty::Define(KPSUidUikon, KUikMmcFFSFreeLevel, RProperty::EInt, KPassReadPolicy, KWriteTUPolicy); + TInt err7 = RProperty::Define(KPSUidUikon, KUikGlobalNotesAllowed, RProperty::EInt, KPassReadPolicy, KWriteDDPolicy); + TInt err8 = RProperty::Define(KZiUdbProterty, KZiUdbPropertyKey, RProperty::EInt, KPassReadPolicy, KPassWritePolicy); + TInt err9 = RProperty::Define(KT9UdbProterty, KT9UdbPropertyKey, RProperty::EInt, KPassReadPolicy, KPassWritePolicy); + TInt err10 = RProperty::Define(KPSUidAvkonDomain, KAknPowerMenuStatus, RProperty::EInt, KPassReadPolicy, KWriteDDPolicy); + TInt err11 = RProperty::Define(KPSUidAvkonDomain, KAknEndKeyEvent, RProperty::EInt, KPassReadPolicy, KWriteDDPolicy); + +#ifdef _DEBUG + RDebug::Print(_L("xxxx KAknQwertyInputModeActive err=%d"), err1); + RDebug::Print(_L("xxxx KUikLayoutState err=%d"), err2); + RDebug::Print(_L("xxxx KUikOOMWatchdogStatus err=%d"), err3); + RDebug::Print(_L("xxxx KUikVideoCallTopApp err=%d"), err4); + RDebug::Print(_L("xxxx KUikFFSFreeLevel err=%d"), err5); + RDebug::Print(_L("xxxx KUikMmcFFSFreeLevel err=%d"), err6); + RDebug::Print(_L("xxxx KUikGlobalNotesAllowed err=%d"), err7); + RDebug::Print(_L("xxxx KZiUdbProterty err=%d"), err8); + RDebug::Print(_L("xxxx KT9UdbProterty err=%d"), err9); + RDebug::Print(_L("xxxx KAknPowerMenuStatus err=%d"), err10); + RDebug::Print(_L("xxxx KAknEndKeyEvent err=%d"), err11); +#endif + + CRepository* repository = NULL; + TRAPD(ret, repository = CRepository::NewL(KCRUidAvkon)); + if (ret == KErrNone) + { + // Reset value of KAknLayoutId on the boot. + // Return value ignored. + ret = repository->Set(KAknLayoutId, KAvkonAutomaticLayoutDetectionValue); + } + delete repository; + repository = NULL; + +#ifdef _NGATESTING + + do { + + iConfigIconType = -1; + + TRAPD(leaveError, LoadConfigurationL(iFsSession)); + + if(leaveError!=KErrNone) + { + #ifdef _DEBUG + RDebug::Print(_L("xxxx LoadConfigurationL err=%d"), leaveError); + #endif + } + + } while (0); + +#endif + iThreadLaunchStatus = KRequestPending; + // This launches SVG precache thread, if required. + + iCache = CAknIconSrvCache::NewL( *this ); + User::WaitForRequest( iThreadLaunchStatus ); + } + +CAknIconServer::~CAknIconServer() + { + iIconItems.ResetAndDestroy(); + + delete iAvkonIconLoader; + delete iOtherIconLoader; + delete iCurrentIconFile; + delete iCache; + delete iIconDataPreserver; + delete iFileNameCache; + + iHandlerList.ResetAndDestroy(); + RFbsSession::Disconnect(); + iFsSession.Close(); + } + +// ----------------------------------------------------------------------------- +// CAknIconServer::NewSessionL() +// ----------------------------------------------------------------------------- + +CSession2* CAknIconServer::NewSessionL( + const TVersion& /*aVersion*/, const RMessage2& /*aMessage*/) const + { + return new( ELeave ) CAknIconSrvSession( ); + } + +// ----------------------------------------------------------------------------- +// CAknIconServer::RetrieveOrCreateSharedIconL +// ----------------------------------------------------------------------------- +// +const CAknIconSrvIconItem* CAknIconServer::RetrieveOrCreateSharedIconL() + { + #ifdef __AKNICON_TRACES + RDebug::Print(_L("AKNICON start")); + #endif + + TAknIconParams info; + TPckg infoPack( info ); + TRAPD( err, Message().ReadL( 0, infoPack ) ); + if ( err != KErrNone ) + { + ((CAknIconSrvSession*)(Message().Session()))->SetClientPanicCode(EBadDescriptor); + User::Leave(KAknIconSrvCodePanicClient); + } + + TAknIconSrvReturnData retData; + TPckg dataPack( retData ); + + CAknIconSrvIconItem* item = NULL; + +#ifdef __AKNICON_TRACES + info.PrintInfo(); +#endif +#ifdef PRECACHE2 + // bitmap handles of precached icons need to be duplicated + while(iNewPrecachedItems.Count()) + { + #ifdef __AKNICON_TRACES + RDebug::Printf("Precache add,%d",iNewPrecachedItems.Count()); + #endif + + CAknIconSrvIconItem* item = iNewPrecachedItems[0]; + CFbsBitmap* bitmap = new (ELeave) CFbsBitmap; + CleanupStack::PushL(bitmap); + TInt err1 = bitmap->Duplicate(item->iBitmap->Handle()); + iFreePrecacheBitmapHandles.AppendL(item->iBitmap); + CleanupStack::Pop(); + + item->iBitmap = bitmap; + CFbsBitmap* mask = NULL; + if (item->iMask) + { + mask = new (ELeave) CFbsBitmap; + CleanupStack::PushL(mask); + TInt err2 = mask->Duplicate(item->iMask->Handle()); + iFreePrecacheBitmapHandles.AppendL(item->iMask); + CleanupStack::Pop(); + item->iMask = mask; + } + + + err1 = iIconItems.InsertInOrder( item, CAknIconSrvIconItem::LinearOrder ); + if (err1 == KErrAlreadyExists) + { + iNewPrecachedItems.Remove(0); + + #ifdef __AKNICON_TRACES + RDebug::Printf("precache warning, already exists!"); + #endif + + TInt index = iIconItems.FindInOrder(item, CAknIconSrvIconItem::LinearOrder ); + CAknIconSrvIconItem* foundItem = iIconItems[index]; + + foundItem->iPrecacheItem = ETrue; + + //Set this item to be cached + if(foundItem->IsExcludedFromCache()) + { + foundItem->SetCached(); + } + + //Item not in use and hence in Dynamic cache + //Move item from dynamic cache to precache + if( foundItem->iUserCount == 0) + { + iCache->DynamicToPrecache( *foundItem); + } + else + { + } + delete item; + } + else if (err1 == KErrNone) + { + iNewPrecachedItems.Remove(0); + + #ifdef __AKNICON_TRACES + RDebug::Print(_L("precache load,%S,%d,%d,%d,%d,%d,%d,%d"), + item->iFileName, + item->iBitmapId, + item->iMaskId, + item->iSize.iWidth, + item->iSize.iHeight, + item->iModeAndFlags & 0xffff, + item->iRotationAngle, + item->iColor.Internal()); + #endif + + iCurrentIndex = iIconItems.FindInOrder(item, CAknIconSrvIconItem::LinearOrder ); + // delete icon, so it will be moved to icon cache + if (DeleteOrCacheUnusedIcon(item) == EFalse) + { + AknIconConfig::CompressIfPreferred(bitmap, mask,iCompression); + } + else + { + #ifdef __AKNICON_TRACES + RDebug::Printf("Did not insert into dynamic cache, deleting item"); + #endif + } + } + else + { + + #ifdef __AKNICON_TRACES + RDebug::Printf("precache warning, Unable to insert into iIconItems"); + #endif + // No point continuing if one item insertion fails, as + // following requests would result in same error. + break; + } + } + + if (iPrecacheComplete) + { + iPreCacheThread.Resume(); + iPrecacheComplete = EFalse; + } +#endif + TInt index = RetrieveIcon( info ); + if ( index >= 0 ) + { + item = iIconItems[index]; + + item->iUserCount++; + if ( info.iMaskId >= 0 ) + { + // Also mask increases user count. + item->iUserCount++; + } + +#ifdef __AKNICON_TRACES + RDebug::Print( _L("AknIcon: %x CAknIconServer::RetrieveOrCreateSharedIconL: existing item=%x, info=%x"), this, item, &info); +#endif + + } + // Not found in current icon item list + else + { + // MBM icon case + if ( info.IsMbmIcon() ) + { + Message().ReadL( 1, dataPack ); + item = CreateMbmIconL( info, retData ); + } + + // MIF icon case + else + { + + item = iIconDataPreserver->CreateIconL( info ); + + if ( !item ) + { + item = CreateIconL( info ); + } + + //PrecacheCache tool + #ifdef PRECACHELOG + + + _LIT( KFileLoggingDir, "AknIconPreCacher" ); + _LIT( KFileLog, "Traces.txt" ); + + + + _LIT(lMsg, "AKNICON load,%S,%d,%d,%d,%d,%d,%d,%d,%d"); + RFileLogger::WriteFormat(KFileLoggingDir, KFileLog, EFileLoggingModeAppend, lMsg, + &info.iFileName, + info.iBitmapId, + info.iMaskId, + info.iSize.iWidth, + info.iSize.iHeight, + info.iMode, + info.iRotationAngle, + info.iColor.Internal(), + info.IsCompressionDisabled()); + + + + + #endif + //PrecacheCache tool + } + + + if ( info.iAppIcon ) + { + if ( info.IsMbmIcon() ) + { + AknIconSrvUtils::EnsureValidSizeL(item->iBitmap, item->iMask); + } + #ifndef __NVG + else + { + ReCreateSvgL(info,item); + } + #endif /*__NVG*/ + } + +#ifdef __AKNICON_TRACES + RDebug::Print( _L("AknIcon: %x CAknIconServer::RetrieveOrCreateSharedIconL: new item=%x, info=%x"), this, item, &info); +#endif + CleanupStack::PushL( item ); + + // Apply icon color here, if requested. + ApplyIconColorL( item, info.iColor ); + + // Call CompressIfPreferred if bitmap compression is not + // disabled for the icon + if (!item->IsCompressionDisabled()) + { + AknIconConfig::CompressIfPreferred(item->iBitmap, item->iMask,iCompression); + } + + User::LeaveIfError( + iIconItems.InsertInOrder( item, CAknIconSrvIconItem::LinearOrder ) ); + + CleanupStack::Pop(); // item + } + + // No leaving code allowed in the end of the function! + // Otherwise icon item's user count is increased but never decreased, + // because an error code is returned to the client. + + retData.iBitmapHandle = item->iBitmap->Handle(); + if ( item->iMask ) + { + retData.iMaskHandle = item->iMask->Handle(); + } + + retData.iContentDimensions = item->iDimensions; + + // Remove item from cache because it is now used by someone. + iCache->RemoveIfCached( *item ); + + #ifdef __AKNICON_TRACES + RDebug::Print(_L("AKNICON loaded,%S,%d,%d"),&info.iFileName,info.iBitmapId,item->iBitmap->Handle()); + #endif + // Set if the icon will be cached dynamically after it is not used + // Note that if the icon was excluded from cache earlier it will remain + // excluded for its lifetime. + if (info.IsExcludedFromCache()) + { + item->ExcludeFromCache(); + } + + // This does not leave as long as the descriptor is valid in the client side. + Message().WriteL( 1, dataPack ); + + return item; + } + +// ----------------------------------------------------------------------------- +// CAknIconServer::FreeBitmapL +// +// Note: This function can only leave when an ASSERT fails. During normal +// conditions it should never leave. +// ----------------------------------------------------------------------------- +// +const CAknIconSrvIconItem* CAknIconServer::FreeBitmapL() + { + TAknIconParams info; + TPckg paramPack( info ); + TRAPD( err, Message().ReadL( 0, paramPack ) ); + + __ASSERT_ALWAYS( err == KErrNone, + ( + ((CAknIconSrvSession*)(Message().Session()))->SetClientPanicCode(EBadDescriptor), + User::Leave( KAknIconSrvCodePanicClient ) // leave to prevent possible server crash + )); + + + iCurrentIndex = RetrieveIcon( info ); + + __ASSERT_ALWAYS( iCurrentIndex >= 0, + ( + ((CAknIconSrvSession*)(Message().Session()))->SetClientPanicCode(EIconNotFound), + User::Leave( KAknIconSrvCodePanicClient ) // leave to prevent possible server crash + )); + + CAknIconSrvIconItem* item = iIconItems[iCurrentIndex]; + if (info.IsExcludedFromCache()) + { + item->ExcludeFromCache(); + } + + item->iUserCount--; + +#ifdef __AKNICON_TRACES + RDebug::Print( _L("AknIcon: %x CAknIconServer::FreeBitmapL: item=%x, user count=%d"), this, item, item->iUserCount); +#endif + + DeleteOrCacheUnusedIcon( item ); + + // It is safe to return also a pointer to a deleted item. + return item; + } + +// ----------------------------------------------------------------------------- +// CAknIconServer::PreserveIconDataL +// ----------------------------------------------------------------------------- +// +const CAknIconDataItem* CAknIconServer::PreserveIconDataL() + { + TAknIconParams params; + TPckg paramsPack( params ); + TRAPD( err, Message().ReadL( 0, paramsPack ) ); + if ( err != KErrNone ) + { + ((CAknIconSrvSession*)(Message().Session()))->SetClientPanicCode(EBadDescriptor); + User::Leave(KAknIconSrvCodePanicClient); + } + + return iIconDataPreserver->PreserveIconDataL( params ); + } + +// ----------------------------------------------------------------------------- +// CAknIconServer::UnpreserveIconDataL +// +// Note: This function can only leave when an ASSERT fails. During normal +// conditions it should never leave. +// ----------------------------------------------------------------------------- +// +const CAknIconDataItem* CAknIconServer::UnpreserveIconDataL() + { + TAknIconParams params; + TPckg paramsPack( params ); + + TRAPD( err, Message().ReadL( 0, paramsPack ) ); + if ( err != KErrNone ) + { + ((CAknIconSrvSession*)(Message().Session()))->SetClientPanicCode(EBadDescriptor); + User::Leave(KAknIconSrvCodePanicClient); + } + + + return iIconDataPreserver->UnpreserveIconData( params, 1, Message()); + } + +// ----------------------------------------------------------------------------- +// CAknIconServer::GetContentDimensionsL +// ----------------------------------------------------------------------------- +// +void CAknIconServer::GetContentDimensionsL() + { + TAknIconParams params; + TPckg paramsPack( params ); + TRAPD( err, Message().ReadL( 0, paramsPack ) ); + if ( err != KErrNone ) + { + ((CAknIconSrvSession*)(Message().Session()))->SetClientPanicCode(EBadDescriptor); + User::Leave(KAknIconSrvCodePanicClient); + } + + TAknContentDimensions dimensions; + + iIconDataPreserver->GetContentDimensionsL( params, dimensions ); + + TPckg dimensionsPack( dimensions ); + Message().WriteL( 1, dimensionsPack ); + } + +// ----------------------------------------------------------------------------- +// CAknIconServer::CleanupSessionIconItem +// ----------------------------------------------------------------------------- +// +void CAknIconServer::CleanupSessionIconItem( + const TAknIconSrvSessionIconItem& aItem ) + { + TAknIconParams info; + aItem.iIcon->GetInfo( info ); + + iCurrentIndex = RetrieveIcon( info ); + + // The icon must be found otherwise there is a coding error + // in server side. + __ASSERT_DEBUG( iCurrentIndex >= 0, + User::Panic( KAknIconPanicCategory, EIconNotFound )); + + if (iCurrentIndex >= 0) + { + CAknIconSrvIconItem* item = iIconItems[iCurrentIndex]; + + item->iUserCount -= aItem.iUserCount; + DeleteOrCacheUnusedIcon( item ); + } + } + +// ----------------------------------------------------------------------------- +// CAknIconServer::CleanupSessionPreservedItem +// ----------------------------------------------------------------------------- +// +void CAknIconServer::CleanupSessionPreservedItem( + const TAknIconSrvSessionPreservedItem& aItem ) + { + TAknIconParams info; + aItem.iDataItem->GetInfo( info ); + iIconDataPreserver->UnpreserveIconData( info, aItem.iUserCount, Message() ); + } + +// ----------------------------------------------------------------------------- +// CAknIconServer::RemoveCachedItem +// ----------------------------------------------------------------------------- +// +void CAknIconServer::RemoveCachedItem( const CAknIconSrvIconItem& aItem ) + { + TInt index = iIconItems.FindInOrder( + &aItem, CAknIconSrvIconItem::LinearOrder ); + + __ASSERT_DEBUG( index >= 0, + User::Panic( KAknIconSrvPanicCategory, ESrvPanicIconNotFound ) ); + + __ASSERT_DEBUG( aItem.iUserCount == 0, + User::Panic( KAknIconSrvPanicCategory, ESrvPanicCachedItemUserCountNonZero ) ); + + __ASSERT_DEBUG( index != iCurrentIndex, + User::Panic( KAknIconSrvPanicCategory, ESrvPanicCurrentIconItemDeleted ) ); + + iIconItems.Remove( index ); + delete &aItem; + + // Array has changed, so have to keep iCurrentIndex valid. It is used in + // another function, which calls this function. + if ( index < iCurrentIndex ) + { + iCurrentIndex--; + } + } + + + +// ----------------------------------------------------------------------------- +// CAknIconServer::InvalidateItemsCachedFromSkin +// ----------------------------------------------------------------------------- +// +void CAknIconServer::InvalidateItemsCachedFromSkin() + { + for ( TInt i = iIconItems.Count() - 1 ; i >= 0 ; i-- ) + { + CAknIconSrvIconItem* item = iIconItems[i]; + + if ( item->IsCachedFromSkin() ) + { + item->ClearPermanentlyCached(); + + if ( item->iUserCount == 0 ) + { + iIconItems.Remove( i ); + delete item; + } + } + } + } + + + +// ----------------------------------------------------------------------------- +// CAknIconServer::ResetDynamicallyChangingAllocations +// ----------------------------------------------------------------------------- +// +void CAknIconServer::ResetDynamicallyChangingAllocations() + { +#ifdef _DEBUG + // Reset dynamic cache + iCurrentIndex = -1; + iCache->ResetDynamicCache(); + + // Reset dynamically changing icon loader + delete iCurrentIconFile; + iCurrentIconFile = NULL; + delete iOtherIconLoader; + iOtherIconLoader = NULL; + +#endif // _DEBUG + } + +// ----------------------------------------------------------------------------- +// CAknIconServer::SetPreferredIconDisplayMode +// ----------------------------------------------------------------------------- +// +#ifdef _DEBUG +void CAknIconServer::SetPreferredIconDisplayMode( TDisplayMode aMode ) + { + iIconMode = aMode; + } +#else +void CAknIconServer::SetPreferredIconDisplayMode( TDisplayMode /*aMode*/ ) + { + } +#endif + +// ----------------------------------------------------------------------------- +// CAknIconServer::GetInitData +// ----------------------------------------------------------------------------- +// +void CAknIconServer::GetInitData( + TAknIconInitData& aData ) const + { + aData.iCompression = iCompression; + aData.iIconMode = iIconMode; + aData.iIconMaskMode = iIconMaskMode; + aData.iPhotoMode = iPhotoMode; + aData.iVideoMode = iVideoMode; + aData.iOffscreenMode = iOffscreenMode; + aData.iOffscreenMaskMode = iOffscreenMaskMode; + } + +// ----------------------------------------------------------------------------- +// CAknIconServer::RetrieveIcon +// ----------------------------------------------------------------------------- +// +TInt CAknIconServer::RetrieveIcon( const TAknIconParams& aInfo ) + { + // Can be constructed in stack with this constructor. + CAknIconSrvIconItem compareItem( aInfo ); + + return iIconItems.FindInOrder( + &compareItem, CAknIconSrvIconItem::LinearOrder ); + } + + + +// ----------------------------------------------------------------------------- +// CAknIconServer::CreateIconL +// ----------------------------------------------------------------------------- +// +CAknIconSrvIconItem* CAknIconServer::CreateIconL( + const TAknIconParams& aInfo ) + { + CFbsBitmap* bitmap = new (ELeave) CFbsBitmap; + CleanupStack::PushL( bitmap ); + + CFbsBitmap* mask = NULL; + + if ( aInfo.iMaskId >= 0 ) + { + mask = new (ELeave) CFbsBitmap; + CleanupStack::PushL( mask ); + } + MAknIconFormatHandler* handler = NULL; + CAknIconLoader* loader = NULL; + + TInt handle; + + TDisplayMode bitmapDepth; + + // Makes sure that the icon loader is released when required. + + CleanupStack::PushL( TCleanupItem( CleanupIconLoader, this ) ); + + TPtrC8 iconData = InitIconDataAndHandlerLC(aInfo, loader, handler); + + bitmapDepth = (TDisplayMode)loader->IconDepthL( aInfo.iBitmapId ); + + handler->PrepareIconL( iconData, handle ); + + // CleanupIconLoader, InitIconDataAndHandlerLC + CleanupStack::PopAndDestroy( 2 ); + + TAknContentDimensions dimensions; + + TRAPD( err, + { + handler->UsePreparedIconL( handle ); + + dimensions = AknIconSrvUtils::RenderPreparedIconL( + + *handler, + + bitmap, + + mask, + + bitmapDepth, + + iIconMode, + + aInfo.iSize, + + (TScaleMode)aInfo.iMode, + + aInfo.iRotationAngle, + + aInfo.iColor, + + aInfo.iBitmapId, + + aInfo.iMaskId, + + aInfo.iAppIcon); + + } ); + + + + // Below is the code to retrieve the actual rendering size of the icon as per normalizations done above in RenderPreparedIconL + + TSize iconSize(aInfo.iSize); + + if ( aInfo.iMode == EAspectRatioPreservedAndUnusedSpaceRemoved ) + + { + + if ( iconSize.iWidth!=0 && iconSize.iHeight!=0 ) + + { + + AknIconSrvUtils::GetAspectRatioPreservedSize( dimensions, iconSize ); + + } + + } + + + + handler->UnprepareIcon( handle ); + + User::LeaveIfError( err ); + + // Create item definition and insert in the array. + CAknIconSrvIconItem* item = + CAknIconSrvIconItem::NewL( aInfo, bitmap, mask, dimensions, IconFileNameCache() ); + + CleanupStack::Pop(); // bitmap + if ( mask ) + { + CleanupStack::Pop(); // mask + } + + return item; + } + +// ----------------------------------------------------------------------------- +// CAknIconServer::CreateMbmIconL +// ----------------------------------------------------------------------------- +// +CAknIconSrvIconItem* CAknIconServer::CreateMbmIconL( + const TAknIconParams& aInfo, + const TAknIconSrvReturnData& aRetData ) + { + // Create a new bitmap to be stretched to the given size. + CFbsBitmap* bitmap = new (ELeave) CFbsBitmap; + CleanupStack::PushL( bitmap ); + + CFbsBitmap* loadedBitmap = new( ELeave ) CFbsBitmap; + CleanupStack::PushL( loadedBitmap ); + + // Duplicate the loaded bitmap in this thread. + User::LeaveIfError( loadedBitmap->Duplicate( aRetData.iBitmapHandle ) ); + + CFbsBitmap* mask = NULL; + CFbsBitmap* loadedMask = NULL; + + if ( aInfo.iMaskId >= 0 ) + { + // Create a new mask to be stretched to the given size. + mask = new (ELeave) CFbsBitmap; + CleanupStack::PushL( mask ); + + loadedMask = new( ELeave ) CFbsBitmap; + CleanupStack::PushL( loadedMask ); + + User::LeaveIfError( loadedMask->Duplicate( aRetData.iMaskHandle ) ); + } + + // Perform scaling and color filling if required + TBool colorIcon = AknIconSrvUtils::ScaleBitmapIconL( + aInfo.iSize, + (TScaleMode)aInfo.iMode, + aInfo.iRotationAngle, + aInfo.iColor, + loadedBitmap, + loadedMask, + bitmap, + mask ); + + // Create item definition and insert in the array. + // Content dimensions of bitmap icons are not stored in server side, + // so use (-1,-1). + CAknIconSrvIconItem* item = + CAknIconSrvIconItem::NewL( aInfo, + bitmap, + mask, + TAknContentDimensions( -1, -1 ), + IconFileNameCache() ); + + // Set information of the applied color. + if ( colorIcon ) + { + item->iColor = aInfo.iColor; + } + + // Set info that this is an MBM icon. They are not cached the same + // way SVG icons are. + item->SetMbmIcon(); + + CleanupStack::PopAndDestroy(); // loadedBitmap + CleanupStack::Pop(); // bitmap + if ( mask ) + { + CleanupStack::PopAndDestroy(); // loadedMask + CleanupStack::Pop(); // mask + } + + return item; + } + +// ----------------------------------------------------------------------------- +// CAknIconServer::ApplyIconColorL() +// ----------------------------------------------------------------------------- +// +void CAknIconServer::ApplyIconColorL( + CAknIconSrvIconItem* aItem, const TRgb aColor ) + { + // If a color is defined in given parameters, + // create a new icon with that color, if not already done. + if ( aColor != KColorNotDefined && + aColor != aItem->iColor ) + { +#if 0 + TSize size = aItem->iBitmap->SizeInPixels(); + + CFbsBitmap* colorBitmap = new (ELeave) CFbsBitmap; + CleanupStack::PushL( colorBitmap ); + User::LeaveIfError( colorBitmap->Create( size, EColor64K ) ); + + CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL( colorBitmap ); + CleanupStack::PushL( dev ); + CFbsBitGc* gc = NULL; + User::LeaveIfError( dev->CreateContext( gc ) ); + CleanupStack::PushL( gc ); + + gc->SetBrushColor( aColor ); + gc->SetPenStyle( CGraphicsContext::ENullPen ); + gc->SetBrushStyle( CGraphicsContext::ESolidBrush ); + // Fill icon with the given color, mask defines the icon shape. + gc->DrawRect( TRect( TPoint( 0, 0 ), size ) ); + + CleanupStack::PopAndDestroy( 2 ); // dev, gc + + // Change color bitmap in item. + delete aItem->iBitmap; + aItem->iBitmap = colorBitmap; + CleanupStack::Pop(); // colorBitmap + +#endif + // Update information of the applied color in the item + aItem->iColor = aColor; + } + } + +// ----------------------------------------------------------------------------- +// CAknIconServer::DeleteOrCacheUnusedIcon() +// +// Note: iCurrentIndex must be set to the index of aItem in array iIconItems +// before using this function. +// ----------------------------------------------------------------------------- +// +TBool CAknIconServer::DeleteOrCacheUnusedIcon(CAknIconSrvIconItem* aItem) + { +#ifdef __AKNICON_TRACES + RDebug::Print( _L("AknIcon: %x CAknIconServer::DeleteOrCacheUnusedIcon: item=%x"), this, aItem); +#endif + + TBool ret = EFalse; + if ( aItem->iUserCount == 0 && !aItem->IsPermanentlyCached() ) + { + // Note, CacheUnusedIcon potentially changes iIconItems, + // but it takes care of modifying iCurrentIndex accordingly. + + if ( aItem->IsExcludedFromCache() || // Do not cache if the icon is excluded from cache... + aItem->IsMbmIcon() || // Do not cache bitmap icons... + aItem->iRotationAngle != 0 || // Do not cache rotated icons... + !iCache->CacheUnusedIcon( *aItem ) ) + { + iIconItems.Remove( iCurrentIndex ); + delete aItem; + ret = ETrue; + } + } +#ifdef __AKNICON_TRACES + RDebug::Print( _L("AknIcon: %x CAknIconServer::DeleteOrCacheUnusedIcon: item=%x, ret=%d"), this, aItem,ret); +#endif + + return ret; + } + +// ----------------------------------------------------------------------------- +// CAknIconServer::RetrieveFileHandleL() +// ----------------------------------------------------------------------------- +// +RFile& CAknIconServer::RetrieveFileHandleL() + { + CSession2* session = Message().Session(); + return static_cast( session )->AdoptedFileHandle(); + } + +// ----------------------------------------------------------------------------- +// CAknIconServer::ThreadStart() +// ----------------------------------------------------------------------------- + +EXPORT_C TInt CAknIconServer::ThreadStart() + { + // Rename own thread + User::RenameThread( KAknIconSrvName ); + + CAknIconServer* server = NULL; + + CTrapCleanup* cleanup = CTrapCleanup::New(); + CActiveScheduler* scheduler = new CAknIconSrvScheduler; + + TInt err = KErrNone; + + if ( cleanup && scheduler ) + { + CActiveScheduler::Install( scheduler ); + TRAP( err, + { + server = CAknIconServer::NewL(); // adds server in scheduler + } ); + } + else + { + err = KErrNoMemory; + } + + if ( err != KErrNone ) + { + delete cleanup; + delete scheduler; + } + + // signal that we've started + SignalClient(); + + // start fielding requests from clients + if ( err == KErrNone ) + { + CActiveScheduler::Start(); + + // comes here if server gets shut down + delete scheduler; + delete cleanup; + delete server; + } + + // thread/process exit + return err; + } + +// ----------------------------------------------------------------------------- +// CAknIconServer::InitIconLoaderL +// ----------------------------------------------------------------------------- +// +CAknIconLoader* CAknIconServer::InitIconLoaderL( + const TDesC& aFileName, RFile* aFile ) + { + CAknIconLoader* loader = NULL; + + if ( aFileName.CompareF( KAvkonIconFileName ) == 0 ) + { + if ( !iAvkonIconLoader ) + { + iAvkonIconLoader = CAknIconLoader::NewL( iFsSession, KAvkonIconFileName ); +#ifdef _NGATESTING + + iAvkonIconLoader->SetIconTypeConfig(iConfigIconType, iNGADirectory); + +#endif + } + loader = iAvkonIconLoader; + } + + // If not Avkon icon file, check that we got the correct file open. + else if ( !iCurrentIconFile || iCurrentIconFile->CompareF( aFileName ) != 0 ) + { + delete iCurrentIconFile; + iCurrentIconFile = NULL; + + delete iOtherIconLoader; + iOtherIconLoader = NULL; + + if ( aFile ) + { + iOtherIconLoader = CAknIconLoader::NewL( *aFile ); + } + else + { + iOtherIconLoader = CAknIconLoader::NewL( iFsSession, aFileName ); + } + +#ifdef _NGATESTING + + iOtherIconLoader->SetIconTypeConfig(iConfigIconType, iNGADirectory); + +#endif + iCurrentIconFile = aFileName.AllocL(); + loader = iOtherIconLoader; + } + + else + { + // Icon file loader exists. + + loader = iOtherIconLoader; + + // Re-open the file if it is not ROM based file + if (iCurrentIconFile->Left(KDriveLength).CompareF(KDriveZ)) + { + if ( aFile ) + { + loader->OpenFileL( *aFile ); + } + else + { + loader->OpenFileL( iFsSession, aFileName ); + } + } + } + + return loader; + } + +// ----------------------------------------------------------------------------- +// CAknIconServer::IconLoaderUsed +// ----------------------------------------------------------------------------- +// +void CAknIconServer::IconLoaderUsed() + { + // Close the file only if it is not ROM based file + if ( iOtherIconLoader && (!iCurrentIconFile || + iCurrentIconFile->Left(KDriveLength).CompareF(KDriveZ))) + { + iOtherIconLoader->CloseFile(); + } + } + +// ----------------------------------------------------------------------------- +// CAknIconServer::CleanupIconLoader +// ----------------------------------------------------------------------------- +// +void CAknIconServer::CleanupIconLoader( TAny* aServer ) + { + static_cast( aServer )->IconLoaderUsed(); + } + +// ----------------------------------------------------------------------------- +// CAknIconServer::EnableCache +// ----------------------------------------------------------------------------- +// +void CAknIconServer::EnableCache(TBool aEnable) + { +#ifdef __AKNICON_TRACES + RDebug::Print( _L("AknIcon: %x CAknIconServer::EnableCache: %d"), this, aEnable); +#endif + + iCurrentIndex = -1; + iCache->EnableCache(aEnable); + } + +// ----------------------------------------------------------------------------- +// CAknIconServer::InitIconDataAndHandlerLC +// ----------------------------------------------------------------------------- +// +TPtrC8 CAknIconServer::InitIconDataAndHandlerLC( + const TAknIconParams& aParams, + CAknIconLoader*& aLoader, + MAknIconFormatHandler*& aHandler ) + { + TFileName filename; + if ( aParams.IsDefaultIconDirUsed() ) + { + filename = KAknIconDefaultDir; + } + + filename.Append( aParams.iFileName ); + + // Adopt file handle if supplied by client. + RFile* filePtr = NULL; + RFile& file = RetrieveFileHandleL(); + + if ( file.SubSessionHandle() ) + { + filePtr = &file; + } + + aLoader = InitIconLoaderL( filename, filePtr ); + + MAknIconFormatHandler* lHandler = NULL; + TPtrC8 iconData = AknIconSrvUtils::InitIconDataAndHandlerLC( + aLoader, + iHandlerList, + lHandler, + aParams, + EFalse ); + aHandler = lHandler; + return iconData; + } + + +// ----------------------------------------------------------------------------- +// ThreadFunction() +// Needed only in WINS build +// ----------------------------------------------------------------------------- + +#if defined(__WINS__) && !defined(EKA2) + +GLDEF_C TInt ThreadFunction( TAny* /*aThreadParams*/ ) + { + // increase dll's user count so it can't get unloaded when the client + // application terminates + + RLibrary lib; + lib.Load( KAknIconLibName ); + + return CAknIconServer::ThreadStart(); + } + +#endif + +// ----------------------------------------------------------------------------- +// StartServer() +// Create the server thread/process +// ----------------------------------------------------------------------------- +// +GLDEF_C TInt StartServer() + { + TInt ret = KErrNone; + + RSemaphore startupSemaphore; + ret = startupSemaphore.CreateGlobal( KAknIconServerStartupSemaphore, 0 ); + + if ( ret == KErrAlreadyExists ) + { + // The server is starting up, but has not yet started + if ( startupSemaphore.OpenGlobal( KAknIconServerStartupSemaphore ) == + KErrNone ) + { + startupSemaphore.Wait(); // wait until the server has started up. + startupSemaphore.Close(); + } + + // Return info to the client that the server was already started. + return ret; + } + + // launch server process + RProcess server; + ret = server.Create( + KAknIconSrvExe, + KNullDesC, + TUidType( KNullUid, KNullUid, KNullUid ), + EOwnerThread ); + + if ( ret == KErrNone ) + { + server.Resume(); + server.Close(); + + startupSemaphore.Wait(); // wait until the server has started up. + } + + startupSemaphore.Close(); + return ret; + } + +// ----------------------------------------------------------------------------- +// SignalClient() +// ----------------------------------------------------------------------------- +// +GLDEF_C void SignalClient() + { + RSemaphore startupSemaphore; + if ( startupSemaphore.OpenGlobal( + KAknIconServerStartupSemaphore ) == KErrNone ) + { + //Signal the client:The server might have started up successfully or not + startupSemaphore.Signal(); + startupSemaphore.Close(); + } + else + { + // Something fundamentally wrong. + User::Invariant(); + } + } + + + +void CAknIconServer::ReCreateSvgL( TAknIconParams& aInfo, CAknIconSrvIconItem *& aItem) + { + + if ( !aItem ) + { + return; + } + + CFbsBitmap* iBitmap = aItem->iBitmap; + CFbsBitmap* iMask = NULL; + if ( aItem->iMask ) + { + iMask = aItem->iMask; + } + TInt validHeight; + if(iMask != NULL) + { + SEpocBitmapHeader lBmpHeaderMask = iMask->Header(); + if ( lBmpHeaderMask.iBitsPerPixel != 8 ) + { + return; + } + validHeight = AknIconSrvUtils::CheckMaskTransparencyL(iMask); + } + else + { + SEpocBitmapHeader lBmpHeaderBitmap = iBitmap->Header(); + if ( lBmpHeaderBitmap.iBitsPerPixel != 32 ) + { + return; + } + validHeight = AknIconSrvUtils::CheckAlphaTransparencyL(iBitmap); + } + + const TSize& size = iBitmap->SizeInPixels(); + + if(validHeight == size.iHeight) + return; + + const TInt KOffSet = 16; + + //scale image down, leaving margins on sides + //then using fixed point math to get width + const TInt hmul = (validHeight << KOffSet) / size.iHeight; + const TInt validWidth = (size.iWidth * hmul + (1 << (KOffSet - 1))) >> KOffSet; // sz * mul + 0.5 + + TSize lActual = aInfo.iSize; // store the original size request by clien + const TSize sz(validHeight, validWidth); + aInfo.iSize = sz; // valid size after doing transparency operations + + // TRect rect(TPoint((size.iWidth - sz.iWidth) >> 1, 0), sz); + TRect rect(TPoint((size.iWidth - sz.iWidth) >> 1, (size.iHeight - sz.iHeight) >> 1), sz); +// TRect rect(TPoint((size.iWidth - validWidth) >> 1, (size.iHeight - validHeight) >> 1), sz); + + //it look better if even when centrified + rect.iTl.iX &= ~1; + rect.iBr.iX |= 1; + + CAknIconSrvIconItem *lItem = CreateIconL(aInfo); // recreate the svg bmp with valid size. + if ( !lItem ) + { + return; + } + CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL(aItem->iBitmap); + CleanupStack::PushL(dev); + CFbsBitGc* con = NULL; + dev->CreateContext(con); + CleanupStack::PushL(con); + con->SetBrushColor( 0 ); + con->Clear(); + con->SetPenStyle(CGraphicsContext::ESolidPen); + con->SetBrushStyle(CGraphicsContext::ESolidBrush); + TUint32 lFillColor = 0xFF000000; + con->SetPenColor(lFillColor); + con->SetBrushColor(lFillColor); + con->DrawRect(TRect(TPoint(0, 0), aItem->iBitmap->SizeInPixels())); + con->BitBlt(rect.iTl, lItem->iBitmap); + CleanupStack::PopAndDestroy(2); + + if ( lItem->iMask ) + { + CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL(aItem->iMask); + CleanupStack::PushL(dev); + CFbsBitGc* con = NULL; + dev->CreateContext(con); + CleanupStack::PushL(con); + con->SetBrushColor( 0 ); + con->Clear(); + con->SetPenStyle(CGraphicsContext::ESolidPen); + con->SetBrushStyle(CGraphicsContext::ESolidBrush); + lFillColor = lItem->iMask->DisplayMode() != EGray256 ? 0xFFFFFFFFF : 0x0; + con->SetPenColor(lFillColor); + con->SetBrushColor(lFillColor); + con->DrawRect(TRect(TPoint(0, 0), aItem->iMask->SizeInPixels())); + con->BitBlt(rect.iTl, lItem->iMask); + CleanupStack::PopAndDestroy(2); + } + + delete lItem; + lItem = NULL; + aItem->iSize = lActual; // store actual size requested by the client + // so that search can be done successfully. + } + +#ifdef _NGATESTING + +void CAknIconServer::LoadConfigurationL(RFs& aFs) + { + // if the icon type is svg, check if NGA enabled and set type as EIconFormatNGA +#ifdef __ONLYNGAICON + iConfigIconType = EIconFormatNGA; + (void)aFs; +#else + // check for the configuration files + _LIT(KICONTYPECONFIGFILE, "c:\\icontype.cfg"); // TODO: find appropriate place + /* + * sample configuration files is attached below + * + * ICONTYPE=3 + * NGAICONDIR=c:\Data\nvg_mif + */ + RFile lFile; + + if (lFile.Open(aFs, KICONTYPECONFIGFILE , EFileRead) == KErrNone) + { + CleanupClosePushL(lFile); + TInt sekpoint = 0; + lFile.Seek( ESeekStart, sekpoint ); + TInt fileSize = 0; + User::LeaveIfError(lFile.Size( fileSize )); + + HBufC8 * lConfigData = HBufC8::NewLC( fileSize ); + + TPtr8 lptr = lConfigData->Des(); + lFile.Read(lptr, fileSize); + + TLex8 lLexObj(lptr); + lLexObj.SkipSpaceAndMark(); + + TChar aChar; + + do + { + aChar = lLexObj.Get(); + } + while ( aChar != '\n' && + aChar != ' ' && + aChar != '\r' && + aChar != '\t' && + aChar != '='); + + lLexObj.UnGet(); + TPtrC8 kw1 = lLexObj.MarkedToken(); + lLexObj.SkipSpace(); + if (lLexObj.Get() != '=') + { + User::Leave(KErrCorrupt); + } + + lLexObj.SkipSpace(); + lLexObj.Val(iConfigIconType); + + lLexObj.SkipSpaceAndMark(); + do + { + aChar = lLexObj.Get(); + } + while ( aChar != '\n' && + aChar != ' ' && + aChar != '\r' && + aChar != '\t' && + aChar != '='); + + lLexObj.UnGet(); + TPtrC8 kw2 = lLexObj.MarkedToken(); + lLexObj.SkipSpace(); + if (lLexObj.Get() != '=') + { + User::Leave(KErrCorrupt); + } + lLexObj.SkipSpace(); + + iNGADirectory.Copy(lLexObj.NextToken()); + CleanupStack::PopAndDestroy(); + CleanupStack::PopAndDestroy(); + } + else + { + iConfigIconType = EIconFormatNGA; + } +#endif + } +#endif