--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/uigraphics/AknIcon/srvsrc/AknIconSrvCache.cpp Thu Dec 17 09:14:12 2009 +0200
@@ -0,0 +1,495 @@
+/*
+* 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 "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: Dynamic bitmap caching, SVG DOM tree precaching.
+*
+*/
+
+
+
+// INCLUDE FILES
+#include <e32std.h>
+#include <fbs.h>
+#include <barsread.h>
+#include <barsc.h>
+// Skin server client
+#include <AknsSrvClient.h>
+#include <AknIconSrv.rsg>
+#include <mifconvdefs.h>
+#include <mifconvdefs.h>
+
+#include "AknIconSrvCache.h"
+#include "AknIconSrv.h"
+#include "AknIconSrvIconItem.h"
+#include "AknIconSrvPanic.h"
+#include "AknIconSrvScheduler.h"
+#include "AknIconTraces.h"
+
+#ifdef PRECACHE2
+#include "AknIconSrvPrecacher.h"
+#endif
+
+
+// CONSTANTS
+
+// Contains cache configuration, non localized resource file.
+
+_LIT( KAknIconResourceFile, "z:\\resource\\akniconsrv.rsc" );
+#ifdef PRECACHE2
+_LIT( KPrecacheThreadName2, "AknIconPrecache2" );
+#endif
+
+// ================= MEMBER FUNCTIONS ==========================================
+
+CAknIconSrvCache::CAknIconSrvCache( CAknIconServer& aServer ) :
+ iDynamicallyCached( 8 ), iServer( aServer )
+ {
+ }
+
+CAknIconSrvCache::~CAknIconSrvCache()
+ {
+ iDynamicallyCached.Close();
+ iPrecache.Close();
+
+
+ }
+
+CAknIconSrvCache* CAknIconSrvCache::NewL( CAknIconServer& aServer )
+ {
+ CAknIconSrvCache* self = new( ELeave ) CAknIconSrvCache( aServer );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop();
+
+ return self;
+ }
+
+TDisplayMode MapConfigToDspMode(TInt aValue)
+ {
+ if ( aValue == 0 ) // value documented in the resource file
+ {
+ return EColor64K;
+ }
+ else if ( aValue == 2 ) // value documented in the resource file
+ {
+ return EColor16MU;
+ }
+ // Default to EColor16M, which is fastest to render alpha-blended.
+ else
+ {
+ return EColor16M;
+ }
+ }
+
+TDisplayMode MapConfigToMaskMode(TInt aValue)
+ {
+ if ( aValue == 0 ) // value documented in the resource file
+ {
+ return EGray2;
+ }
+ // Default to EGray256
+ else
+ {
+ return EGray256;
+ }
+ }
+
+TInt ReadConfigValue32L(const RResourceFile& aFile, TInt aResourceId)
+ {
+ TInt var;
+ TPckg<TInt> pack( var );
+ aFile.ReadL( pack, aResourceId );
+ return var;
+ }
+
+#ifdef PRECACHE2
+void DoPrecache2L( TAny* aParameters )
+ {
+ CAknIconSrvPrecacher* cacher = NULL;
+ cacher = CAknIconSrvPrecacher::NewL(*(static_cast<CAknIconServer*>( aParameters )) );
+ cacher->Start();
+ delete cacher;
+ }
+
+GLDEF_C TInt PrecacheThreadFunction2( TAny* aParameters )
+ {
+
+ CTrapCleanup* cleanup = CTrapCleanup::New();
+ CActiveScheduler* scheduler = new CActiveScheduler;
+ if(!scheduler)
+ {
+ delete cleanup;
+ return KErrBadHandle;
+ }
+ CActiveScheduler::Install( scheduler );
+ TInt err = KErrNone;
+ TRAP(err,DoPrecache2L(aParameters));
+ delete scheduler;
+ delete cleanup;
+
+
+
+ return err;
+ }
+#endif // PRECACHE2
+void CAknIconSrvCache::ConstructL()
+ {
+#ifdef PRECACHE2
+ User::LeaveIfError( iServer.iPreCacheThread.Create(
+ KPrecacheThreadName2,
+ PrecacheThreadFunction2,
+ 0x2000, // stack size
+ NULL, // uses caller thread's heap
+ (TAny*)&iServer ) );
+ iServer.iPreCacheThread.SetPriority(KPreCache2Priority);
+ iServer.iPreCacheThread.Resume();
+#endif // PRECACHE2
+ // Read resource file configuration.
+ RResourceFile file;
+ // Also prepare to the case that the resource file does not exist.
+ TRAPD( err, file.OpenL( iServer.FsSession(), KAknIconResourceFile ) );
+
+
+
+
+ if ( err == KErrNone )
+ {
+ CleanupClosePushL( file );
+
+ // Read bitmap compression config and set server variable.
+ TUint8 var1;
+ TPckg<TUint8> pack1( var1 );
+ file.ReadL( pack1, R_COMPRESS_BITMAPS );
+ iServer.iCompression = var1;
+
+ // read bitmap depth configs and set the server values
+ TInt value = ReadConfigValue32L(file, R_PREFERRED_ICON_DEPTH);
+ iServer.iIconMode = MapConfigToDspMode(value);
+
+ value = ReadConfigValue32L(file, R_PREFERRED_ICON_MASK_DEPTH);
+ iServer.iIconMaskMode = MapConfigToMaskMode(value);
+
+ value = ReadConfigValue32L(file, R_PREFERRED_PHOTO_DEPTH);
+ iServer.iPhotoMode = MapConfigToDspMode(value);
+
+ value = ReadConfigValue32L(file, R_PREFERRED_VIDEO_DEPTH);
+ iServer.iVideoMode = MapConfigToDspMode(value);
+
+ value = ReadConfigValue32L(file, R_PREFERRED_OFFSCREEN_DEPTH);
+ iServer.iOffscreenMode = MapConfigToDspMode(value);
+
+ value = ReadConfigValue32L(file, R_PREFERRED_OFFSCREEN_MASK_DEPTH);
+ iServer.iOffscreenMaskMode = MapConfigToMaskMode(value);
+
+
+
+
+ TPckg<TInt> pack3( iConfiguredMaxDynamicCacheSize );
+ file.ReadL( pack3, R_MAX_DYNAMIC_CACHE_SIZE );
+ EnableCache( ETrue );
+
+
+
+ CleanupStack::PopAndDestroy( 1); // file
+ }
+
+
+ // If no thread launched, complete request immediately.
+ TRequestStatus* status = &( iServer.ThreadLaunchStatus() );
+ User::RequestComplete( status, KErrNone );
+
+
+
+ }
+
+
+
+
+
+// -----------------------------------------------------------------------------
+// CAknIconSrvCache::CacheUnusedIcon
+//
+// Caches an icon (in bitmap form) that has just become unused.
+// -----------------------------------------------------------------------------
+//
+TBool CAknIconSrvCache::CacheUnusedIcon( CAknIconSrvIconItem& aItem )
+ {
+ // If cache size is set to zero, return EFalse always.
+#ifdef __AKNICON_TRACES
+ RDebug::Print( _L("AknIcon: %x CAknIconSrvCache::CacheUnusedIcon: iMaxDynamicCacheSize=%d"), this, iMaxDynamicCacheSize);
+#endif
+ if ( !iMaxDynamicCacheSize )
+ {
+ return EFalse;
+ }
+
+ TBool ret = EFalse;
+ TInt lCacheSize = iDynamicCacheSize + iPrecacheSize ;
+ TInt iconDataSize = IconDataSize( aItem );
+ if ( iconDataSize <= iMaxDynamicCacheSize )
+ {
+ // If reached max size of the dynamic cache UpdateDynamicCacheSize.
+
+ if (lCacheSize + iconDataSize > iMaxDynamicCacheSize)
+ {
+ UpdateDynamicCacheSize();
+ }
+
+ // If reached max size of the dynamic cache,
+ // remove older cached items.
+ while ( iDynamicallyCached.Count() > 0 &&
+ lCacheSize + iconDataSize > iMaxDynamicCacheSize )
+ {
+ CAknIconSrvIconItem* oldest = iDynamicallyCached[0];
+
+ iDynamicCacheSize -= IconDataSize( *oldest );
+ iDynamicallyCached.Remove( 0 );
+ iServer.RemoveCachedItem( *oldest );
+
+ if (!iDynamicallyCached.Count())
+ {
+#ifdef __AKNICON_TRACES
+ RDebug::Print( _L("AknIcon: %x CAknIconSrvCache::CacheUnusedIcon: reset iDynamicCacheSize=%d to 0"), this, iDynamicCacheSize);
+#endif
+ iDynamicCacheSize = 0;
+ }
+ lCacheSize = iDynamicCacheSize + iPrecacheSize ;
+ }
+ // If dynamic cache is empty
+ // but precache size is greater than maxcachesize
+ // and Precache has some items
+ // and the new item to be added is a precache item
+ // delete the older precache items
+ if (iDynamicallyCached.Count() == 0)
+ {
+ while ( iPrecacheSize + iconDataSize > iMaxDynamicCacheSize
+ && iPrecache.Count() > 0
+ && aItem.iPrecacheItem)
+ {
+ CAknIconSrvIconItem* oldest = iPrecache[0];
+
+ iPrecacheSize -= IconDataSize( *oldest );
+ iPrecache.Remove( 0 );
+ iServer.RemoveCachedItem( *oldest );
+
+ if (!iPrecache.Count())
+ {
+#ifdef __AKNICON_TRACES
+ RDebug::Print( _L("AknIcon: %x CAknIconSrvCache::CacheUnusedIcon: reset iDynamicCacheSize=%d to 0"), this, iPrecacheSize);
+#endif
+ iPrecacheSize = 0;
+ }
+
+ }
+ }
+
+ // this check is needed for one case only
+ // if the cache is filled with precache items, dynamic cache is empty
+ // and a non precache item wants to be put in cache
+ // then dont put it
+ //Insert into dynamicCache or Precache
+ if(lCacheSize + iconDataSize <= iMaxDynamicCacheSize )
+ {
+ TInt lError;
+ if(aItem.iPrecacheItem)
+ {
+ lError = iPrecache.Append(&aItem);
+ }
+ else
+ {
+ lError = iDynamicallyCached.Append(&aItem);
+ }
+
+ // If no error encountered in insertion
+ // set icon as cached
+ if(lError == KErrNone)
+ {
+ aItem.SetCached();
+ if(aItem.iPrecacheItem)
+ {
+ iPrecacheSize += iconDataSize;
+ }
+ else
+ {
+ iDynamicCacheSize += iconDataSize;
+ }
+ ret = ETrue;
+ }
+ }
+ }
+
+ // If return ETrue, the server keeps the icon loaded even though the user
+ // count went to zero.
+#ifdef __AKNICON_TRACES
+ RDebug::Print( _L("AknIcon: %x CAknIconSrvCache::CacheUnusedIcon: ret=%d"), this, ret);
+#endif
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CAknIconSrvCache::UpdateDynamicCacheSize
+//
+// Updates iDynamicCacheSize because its value could be deteriorated over time
+// due to background bitmap compression.
+// -----------------------------------------------------------------------------
+//
+void CAknIconSrvCache::UpdateDynamicCacheSize()
+ {
+#ifdef __AKNICON_TRACES
+ RDebug::Print( _L("AknIcon: %x CAknIconSrvCache::UpdateDynamicCacheSize: old iDynamicCacheSize=%d, iServer.iCompression=%d"), this, iDynamicCacheSize, iServer.iCompression);
+#endif
+ // Recalculate iDynamicCacheSize only if bitmap compression is enabled
+ if (iServer.iCompression)
+ {
+ iDynamicCacheSize = 0;
+ for(TInt i = 0; i < iDynamicallyCached.Count(); i++)
+ {
+ iDynamicCacheSize += IconDataSize(*iDynamicallyCached[i]);
+ }
+ }
+#ifdef __AKNICON_TRACES
+ RDebug::Print( _L("AknIcon: %x CAknIconSrvCache::UpdateDynamicCacheSize: new iDynamicCacheSize=%d"), this, iDynamicCacheSize);
+#endif
+
+ }
+// -----------------------------------------------------------------------------
+// CAknIconSrvCache::RemoveIfCached
+// -----------------------------------------------------------------------------
+//
+void CAknIconSrvCache::RemoveIfCached( CAknIconSrvIconItem& aItem )
+ {
+ if ( aItem.IsCached() )
+ {
+ // search for item in iDynamicallyCached & iPrecache
+ TInt lDynamicIndex = iDynamicallyCached.Find( &aItem );
+ TInt lPrecacheIndex = iPrecache.Find(&aItem);
+
+ __ASSERT_DEBUG( lDynamicIndex >= 0 || lPrecacheIndex >= 0,
+ User::Panic( KAknIconSrvPanicCategory, ESrvPanicCacheCorrupt ) );
+
+ if(lDynamicIndex >= 0)
+ {
+ iDynamicallyCached.Remove( lDynamicIndex );
+ iDynamicCacheSize -= IconDataSize( aItem );
+ }
+ else if(lPrecacheIndex >= 0)
+ {
+ iPrecache.Remove(lPrecacheIndex);
+ iPrecacheSize -= IconDataSize(aItem);
+ }
+
+ aItem.ClearCached();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CAknIconSrvCache::DynamicToPrecache
+// -----------------------------------------------------------------------------
+//
+void CAknIconSrvCache::DynamicToPrecache( CAknIconSrvIconItem& aItem )
+ {
+ if ( aItem.IsCached() )
+ {
+ // search for item in iDynamicallyCached
+ TInt lDynamicIndex = iDynamicallyCached.Find( &aItem );
+ if(lDynamicIndex >= 0)
+ {
+ CAknIconSrvIconItem* moveItem = iDynamicallyCached[lDynamicIndex];
+
+ if (iPrecache.Append(moveItem) == KErrNone)
+ {
+ iPrecacheSize += IconDataSize(aItem);
+
+ iDynamicallyCached.Remove( lDynamicIndex );
+ iDynamicCacheSize -= IconDataSize( aItem );
+ }
+ }
+ }
+
+ }
+
+
+
+// -----------------------------------------------------------------------------
+// CAknIconSrvCache::ResetDynamicCache
+// -----------------------------------------------------------------------------
+//
+void CAknIconSrvCache::ResetDynamicCache()
+ {
+#ifdef _DEBUG
+
+ EnableCache( EFalse );
+
+#endif // _DEBUG
+ }
+
+// -----------------------------------------------------------------------------
+// CAknIconSrvCache::IconDataSize
+// -----------------------------------------------------------------------------
+//
+TInt CAknIconSrvCache::IconDataSize( CAknIconSrvIconItem& aItem )
+ {
+ TInt byteSize = aItem.iBitmap->Header().iBitmapSize;
+
+ if ( aItem.iMask )
+ {
+ byteSize += aItem.iMask->Header().iBitmapSize;
+ }
+
+ return byteSize;
+ }
+
+
+
+
+// -----------------------------------------------------------------------------
+// CAknIconSrvCache::EnableCache
+// -----------------------------------------------------------------------------
+//
+void CAknIconSrvCache::EnableCache( TBool aEnable )
+ {
+ if ( aEnable )
+ {
+ // enable the cache by setting the configured max cache size.
+ iMaxDynamicCacheSize = iConfiguredMaxDynamicCacheSize;
+ }
+ else
+ {
+ // disable the cache by removing all dynamically cached
+ // icons and setting the max cache size to zero, which will
+ // prevent further icons from being added.
+ while ( iDynamicallyCached.Count() )
+ {
+ CAknIconSrvIconItem* item = iDynamicallyCached[0];
+ iDynamicallyCached.Remove( 0 );
+ iServer.RemoveCachedItem( *item );
+ }
+
+ iDynamicCacheSize = 0;
+
+ while(iPrecache.Count())
+ {
+ CAknIconSrvIconItem* item = iPrecache[0];
+ iPrecache.Remove( 0 );
+ iServer.RemoveCachedItem( *item );
+
+ }
+ iPrecacheSize = 0;
+
+ iMaxDynamicCacheSize = 0;
+
+
+ }
+ }
+
+// End of File