uiacceltk/hitchcock/Client/src/alftexturemanager.cpp
changeset 0 15bf7259bb7c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uiacceltk/hitchcock/Client/src/alftexturemanager.cpp	Tue Feb 02 07:56:43 2010 +0200
@@ -0,0 +1,2303 @@
+/*
+* Copyright (c) 2006 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:   Loads textures.
+*
+*/
+
+
+
+#include <e32std.h>
+#include <imageconversion.h>
+#include <eikenv.h>
+#include <eikappui.h>
+#include <eikapp.h>
+
+#include "alf/alftexturemanager.h"
+#include "alf/alftextureprocessor.h"
+#include "alf/alftexture.h"
+#include "alf/alfenv.h"
+#include "alfclient.h"
+#include "alf/alfutil.h"
+#include "alf/alfbitmapprovider.h"
+#include "alflogger.h"
+
+const TInt KFirstAutoGeneratedTextureId = 0x10000000;
+const TInt KAlfDefaultSizeDimension = 4;
+
+/**
+ * Flag to indicate to use the provided bitmap directly for the texture, without conversion or copying. The bitmaps
+ * should be in the correct format and they shall not be compressed or have duplicated handle.
+ * If the direct bitmap cannot be used, this flag is ignored internally.
+ *
+ * NOTE: This flag is not a public since we cannot guarantee that user does not compress
+ * bitmap or otherwise temper with it after providing it to toolkit. 
+ * But internally we can use this in some cases to speed up the texture upload.
+ *
+ */
+enum
+    {
+    EAlfTextureFlagAllowDirectBitmapUsage = 0x20        
+    };
+
+struct TTextureEntry 
+    {
+    public:
+    	~TTextureEntry()
+        {
+        }
+    	TTextureEntry()                      
+                      : iId(0), iTexture(NULL), iRefCount(-1)
+        {                            
+        }
+    	
+    	TTextureEntry(TInt aId,
+                      CAlfTexture* aTexture)                      
+                      : iId(aId), iTexture(aTexture),iRefCount(-1)
+        {
+        }
+
+    /** The texture id. Set to zero for no id. */
+    TInt iId;
+
+    /** The texture entry. */
+    CAlfTexture* iTexture;
+    
+    /** Reference count. */
+    TInt iRefCount;
+    };
+
+struct TLoadQueueEntry
+    {
+    /** The texture entry that is being loaded. */
+    TTextureEntry iLoading;
+
+    /** The image being loaded has an alpha channel. */
+    TBool iHasAlpha;
+
+    /** The original, non-downscaled size of the image. */
+    TSize iOriginalSize;
+
+    /** Image decoder to load bitmap images. */
+    CImageDecoder* iDecoder;
+
+    /** True, if the texture was already unloaded before it finished
+        loading. */
+    TBool iUnloaded;
+    };
+
+
+// Private structure
+struct CAlfTextureManager::TPrivateData
+    {
+    CAlfEnv* iEnv;              // Not owned.  	
+    
+    /**
+     * Registry of all textures within this toolkit.
+     * Accessed by texture ids (iId). 
+     */
+    RArray<TTextureEntry> iTextures;
+
+    /** Queue of loading tasks. */
+    RArray<TLoadQueueEntry> iLoadQueue;
+
+    /** Queue of loading observers. */
+    RPointerArray<MAlfTextureLoadingCompletedObserver> iLoadObserverQueue;
+
+    /** Queue of state observers. */
+    RPointerArray<MAlfTextureManagerStateChangedObserver> iStateObserverQueue;
+
+    /** Blank texture */
+    CAlfTexture* iBlankTexture;
+
+    /** Path where image files are loaded from. */
+    HBufC* iImagePath;
+    
+    /** State of the texture manager. */
+    TState iState;
+
+    /** Bitmap for loading asynchronously into. */
+    CFbsBitmap* iBitmap;
+
+    /** Mask bitmap for loading alpha channels. */
+    CFbsBitmap* iMaskBitmap;
+
+    /** Open file server session for image loading. */
+    RFs iFs;
+    
+    /** Id of this texture manager. */
+    TUid iManagerId;
+
+    /** Texture processor */
+    CAlfTextureProcessor* iProcessor;
+    
+    /** Texture id auto generation */
+    TInt iAutoGeneratedTextureId;
+    TInt iLowestAutoGeneratedTextureId;
+    TInt iHighestAutoGeneratedTextureId;
+    
+    RPointerArray<MAlfTextureAutoSizeObserver> iAutoSizeObserverQueue;
+    
+    // DEBUG
+    TBool iTextureAutoCounterEnabled;
+    TInt iTextureAutoRecreateCounter;
+    TInt iTextureAutoReloadCounter;
+
+    //...add other member variables...
+    CIdle* iDoomBringer;
+    };
+
+
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------------------------
+//
+CAlfTextureManager::CAlfTextureManager() : CActive(EPriorityHigh)
+	{
+		
+	}
+	
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CAlfTextureManager::~CAlfTextureManager()
+	{
+	Cancel();
+	if ( iData )
+	    {
+        delete iData->iImagePath;
+	    
+	    delete iData->iBlankTexture;
+	    
+	    RArray<TTextureEntry>& textures = (iData->iTextures);	
+        // Remove all texture entries (from last to first -order)
+        while (textures.Count())
+            {
+            TTextureEntry te = textures[textures.Count()-1];
+            
+            delete te.iTexture; 
+            te.iTexture = NULL;                
+            }
+
+        textures.Close();   
+
+	    iData->iLoadQueue.Close();	    
+    
+	    iData->iLoadObserverQueue.Close();	
+
+	    iData->iStateObserverQueue.Close();	
+	    
+	    iData->iAutoSizeObserverQueue.Close();
+
+        delete iData->iBitmap;
+        delete iData->iMaskBitmap;
+
+        iData->iFs.Close();
+        
+        delete iData->iProcessor;        
+        if (iData->iDoomBringer)
+            iData->iDoomBringer->Cancel();
+        delete iData->iDoomBringer;
+	    }	
+
+	delete iData;
+	}
+// ---------------------------------------------------------------------------
+// NewL
+// ---------------------------------------------------------------------------
+//
+CAlfTextureManager* CAlfTextureManager::NewL(CAlfEnv& aEnv, TUid aUid)
+	{
+	CAlfTextureManager* self = CAlfTextureManager::NewLC(aEnv, aUid);        
+    CleanupStack::Pop( self );
+    return self;		
+	}
+	
+
+// ---------------------------------------------------------------------------
+// NewLC
+// ---------------------------------------------------------------------------
+//
+CAlfTextureManager* CAlfTextureManager::NewLC(CAlfEnv& aEnv, TUid aUid)
+	{
+    CAlfTextureManager* self = new( ELeave ) CAlfTextureManager();
+    CleanupStack::PushL( self );
+    self->ConstructL(aEnv, aUid);
+    return self;	
+	}
+
+// ---------------------------------------------------------------------------
+// 2nd phase constructor
+// ---------------------------------------------------------------------------
+//
+void CAlfTextureManager::ConstructL(CAlfEnv& aEnv, TUid aUid)
+	{
+    iData = new (ELeave) TPrivateData;
+    
+    // Zero all data
+    iData->iEnv = NULL;  	
+    iData->iTextures.Reset();
+    iData->iLoadQueue.Reset();
+    iData->iLoadObserverQueue.Reset();
+    iData->iAutoSizeObserverQueue.Reset();
+    iData->iBlankTexture = NULL;
+    iData->iImagePath = NULL;
+    iData->iState = EIdle;
+    iData->iBitmap = NULL;
+    iData->iMaskBitmap = NULL;
+    iData->iManagerId = TUid::Uid(0);
+    iData->iProcessor = NULL;
+
+    // Fill data
+    iData->iAutoGeneratedTextureId = KFirstAutoGeneratedTextureId;
+    iData->iLowestAutoGeneratedTextureId = KFirstAutoGeneratedTextureId;
+    iData->iHighestAutoGeneratedTextureId = KMaxTInt;
+    iData->iEnv = &aEnv;    
+    iData->iManagerId = aUid;
+    iData->iBlankTexture = CAlfTexture::NewL(aEnv, aUid);
+    iData->iBitmap = new (ELeave) CFbsBitmap();
+    User::LeaveIfError(iData->iBitmap->Create(
+        TSize(KAlfDefaultSizeDimension, KAlfDefaultSizeDimension), EColor64K));
+    iData->iMaskBitmap = new (ELeave) CFbsBitmap();
+    User::LeaveIfError(iData->iMaskBitmap->Create(
+        TSize(KAlfDefaultSizeDimension, KAlfDefaultSizeDimension), EGray256));	
+    iData->iProcessor = CAlfTextureProcessor::NewL(aEnv); 
+    User::LeaveIfError(iData->iFs.Connect());
+    iData->iDoomBringer = CIdle::NewL(CActive::EPriorityIdle);
+    // DEBUG 
+    iData->iTextureAutoCounterEnabled = EFalse;
+    iData->iTextureAutoRecreateCounter = 0;
+    iData->iTextureAutoReloadCounter = 0;
+    
+    SetImagePathL(_L(""));
+	CActiveScheduler::Add(this);
+	}
+
+// ---------------------------------------------------------------------------
+// Returns env
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CAlfEnv& CAlfTextureManager::Env()
+    {
+    return *iData->iEnv;
+    }
+
+// ---------------------------------------------------------------------------
+// Returns texture with given id
+// ---------------------------------------------------------------------------
+//
+EXPORT_C const CAlfTexture* CAlfTextureManager::Texture(TInt aId) const
+    {
+    TInt index = CheckTexture(aId);
+    if(index == KErrNotFound)
+        {
+        return &BlankTexture();
+        }
+        
+    RArray<TTextureEntry>& textures = (iData->iTextures);	
+    CAlfTexture* texture = textures[index].iTexture;
+    if(texture)
+        {
+        return texture;
+        }
+    else
+        {
+        return &BlankTexture();
+        }    
+    }
+
+// ---------------------------------------------------------------------------
+// Returns texture with given id
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CAlfTexture* CAlfTextureManager::TextureL(TInt aId)
+    {
+    // try to get the index for the texture id
+    TInt index = CheckTexture(aId);
+    if(index != KErrNotFound)
+        {
+        // texture found
+        RArray<TTextureEntry>& textures = (iData->iTextures);	
+        CAlfTexture* texture = textures[index].iTexture;
+        if(texture == NULL)
+            {
+            User::Leave(KErrNotFound);
+            return NULL;                
+            }
+        return texture;
+        }
+
+    User::Leave(KErrNotFound);
+    return NULL;
+    }
+
+// ---------------------------------------------------------------------------
+// Sets image path
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAlfTextureManager::SetImagePathL(const TDesC& aPath)
+    {
+    delete iData->iImagePath;
+    iData->iImagePath = NULL;
+
+    TParsePtrC parse(aPath);
+    CEikonEnv* coe = CEikonEnv::Static();
+    if (aPath.Length() && !parse.DrivePresent() && coe && coe->EikAppUi() && coe->EikAppUi()->Application())
+        {
+        iData->iImagePath = HBufC::NewL(aPath.Size()+2); // two extra characters for drive
+        TPtr ptr = iData->iImagePath->Des();
+        ptr.Append(coe->EikAppUi()->Application()->AppFullName().Left(2));
+        ptr.Append(aPath);
+        }
+    else
+        {
+        iData->iImagePath = aPath.AllocL();        
+        }
+    }
+    
+// ---------------------------------------------------------------------------
+// Gets image path
+// ---------------------------------------------------------------------------
+//
+EXPORT_C const TDesC& CAlfTextureManager::ImagePath() const
+    {
+    return *iData->iImagePath;        
+    }
+
+
+// ---------------------------------------------------------------------------
+// Returns blank texture.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C const CAlfTexture& CAlfTextureManager::BlankTexture() const
+    {
+    return *iData->iBlankTexture;            
+    }
+
+// ---------------------------------------------------------------------------
+// Returns blank texture.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CAlfTexture& CAlfTextureManager::BlankTexture()
+    {
+    return *iData->iBlankTexture;            
+    }
+
+// ---------------------------------------------------------------------------
+// DEPRECATED! Load the animated texture based on the Skin name
+// ---------------------------------------------------------------------------
+//
+
+EXPORT_C CAlfTexture& CAlfTextureManager::LoadAnimatedTextureL(const TDesC& /*aSkinAnimName*/,
+                                       TSize /*aTextureMaxSize*/,
+                                       TAlfTextureFlags /*aFlags*/,
+                                       TInt /*aId*/)
+    {
+    __ALFLOGSTRING( "CAlfTextureManager::LoadAnimatedTextureL FUNCTIONALITY REMOVED. REFER TO ANTRIKSH PROJECT" );
+    CAlfTexture* tex = NULL;
+    return *tex;
+    }
+
+// Loads texture.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CAlfTexture& CAlfTextureManager::LoadTextureL(const TDesC& aImageName,
+                                       TAlfTextureFlags aFlags,
+                                       TInt aId)
+    {
+    return LoadTextureL(aImageName, TSize(0, 0), aFlags, aId);        
+    }
+
+// ---------------------------------------------------------------------------
+// Loads texture.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CAlfTexture& CAlfTextureManager::LoadTextureL(const TInt aId,
+                                       TSize aTextureMaxSize,
+                                       TAlfTextureFlags aFlags)
+    {
+    return LoadTextureL(_L(""), aTextureMaxSize, aFlags, aId);
+    }
+
+// ---------------------------------------------------------------------------
+// Loads texture.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CAlfTexture& CAlfTextureManager::LoadTextureL(const TDesC& aImageName,
+                                       TSize aTextureMaxSize,
+                                       TAlfTextureFlags aFlags,
+                                       TInt aId)
+    {    
+    // Clients are not allowed to let toolkit use bitmaps directly. 
+    // We could use it internally if we had separate bitmaps
+    // for each entry.
+    RemoveFlags(aFlags, EAlfTextureFlagAllowDirectBitmapUsage);
+        
+    if (aId == KAlfAutoGeneratedTextureId)
+        {
+        aId = GenerateTextureId();    
+        }    
+    
+    CAlfTexture* tex = NULL;
+    TFileName fileName;
+
+    // Provide an already created texture if such exists.
+    TRAPD(err, tex = TextureL(aId));
+    if(err == KErrNone && tex->HasContent())
+        {
+        return *tex;
+        }
+
+    // If shared texture manager, then check the existense of the texture first.
+    if (IsShared())
+        {
+        // AutoSize is not supported (yet) for shared textures
+        RemoveFlags(aFlags, EAlfTextureFlagAutoSize);
+
+        TBool sharedTextureAlreadyExists = EFalse;
+        iData->iEnv->Client().TextureHasContent(sharedTextureAlreadyExists, 
+            aId, 
+            iData->iManagerId.iUid);
+        
+        // If shared texture already exists, we don't even start to load it.
+        if (sharedTextureAlreadyExists)
+            {
+            TInt bitmapHandle = 0;
+            TInt maskHandle = 0;
+        	
+        	if (iData->iBitmap)
+        		{
+        		bitmapHandle = iData->iBitmap->Handle();
+        		}
+        	
+        	if (iData->iMaskBitmap)	
+        		{
+        		maskHandle = iData->iMaskBitmap->Handle();	
+        		}
+            
+            // Create CAlfTexture instance.
+        	tex = CAlfTexture::NewL( Env(), 
+        	    iData->iManagerId,
+        	    aId, 
+        	    bitmapHandle, 
+        	    maskHandle, 
+        	    aFlags);             
+            
+            if(aImageName.Length() > 0)
+                {
+                // assume relative pathname and prepend the image path to get full filename
+                fileName = aImageName;
+                PrependImagePath(fileName);
+                tex->SetFileNameL(fileName);
+                }
+            
+            tex->SetMaxTextureSize(aTextureMaxSize);
+
+            return *tex;    
+            }            
+        }
+
+    // If the name is invalid, and there was no filename available
+    // based on id, return a dummy texture.
+    if((aImageName.Length() == 0) && (aId == 0))
+        {
+        return BlankTexture();
+        }
+
+    // add path to filename if filename has been passed
+    if(aImageName.Length() > 0)
+        {
+        // assume relative pathname and prepend the image path to get full filename
+        fileName = aImageName;
+        PrependImagePath(fileName);
+        }
+
+    // if no name has been passed as a parameter but
+    // there's and nonzero id has been passed, we
+    // can assume that there's a predefined name available
+    RArray<TTextureEntry>& textures = (iData->iTextures);	
+    RArray<TLoadQueueEntry>& loadqueue = (iData->iLoadQueue);	
+
+    if((aImageName.Length() == 0) && (aId != 0))
+       {
+        // search for a texture filename based on the id.
+        TInt index = CheckTexture(aId);
+        if(index >=0)
+            {
+            tex = textures[index].iTexture;
+            fileName = *tex->FileName();
+            }
+        else
+            {
+            User::Leave(KErrNotFound);
+            }
+       }
+
+    // Reuse pre-existing entries:
+    // try first finding an entry based on id
+    if(!tex && aId > 0)
+        {
+        TInt previouslyLoadedIndex = CheckTexture(aId);
+        if (previouslyLoadedIndex >= 0)
+            {
+            tex = textures[previouslyLoadedIndex].iTexture;
+            }
+        }
+
+    if (!tex)
+        {
+        TInt bitmapHandle = 0;
+        TInt maskHandle = 0;
+
+        // If LoadAnimAsImage flag is set, we don't check the framecount with ImageDecoder!
+        //
+        // This is useful especially when loading multiple large image files
+        // as textures that don't have more then 1 frame.
+        //
+        // Some test results creating the ImageDecoder: 
+        // - Large Leafs.mbm (2,7MB) took apporx. 280ms
+        // - Big bmp (~1,8MB) took ~130ms 
+        // - Normal sized (100-800kb) jpgs and gifs took approx. 25-40ms
+        TInt frameCount = 1;
+        TSize animFrameSize = TSize(0,0);
+        if ( !(aFlags & EAlfTextureFlagLoadAnimAsImage) )
+            {
+            CImageDecoder* decoder = CImageDecoder::FileNewL(iData->iFs, fileName);
+            CleanupStack::PushL(decoder);
+            frameCount = decoder->FrameCount();
+            if (frameCount > 1)
+                {
+                const TFrameInfo& fInfo =  decoder->FrameInfo(0);
+                animFrameSize = fInfo.iOverallSizeInPixels;
+                }
+            CleanupStack::PopAndDestroy();
+            }
+        
+        if (frameCount > 1)
+            {
+            tex = CAlfTexture::NewL(Env(), iData->iManagerId, aId, bitmapHandle, maskHandle, aFlags, ETrue);        
+            tex->SetMaxTextureSize(aTextureMaxSize);
+            tex->SetSize(animFrameSize);
+            tex->SetFileNameL(fileName);
+            return *tex;
+            }
+        else
+            {
+        	if (iData->iBitmap)
+        		{
+    	    	bitmapHandle = iData->iBitmap->Handle();
+    		    }
+    	
+        	if (iData->iMaskBitmap)	
+    		    {
+    		    maskHandle = iData->iMaskBitmap->Handle();	
+    		    }
+        	tex = CAlfTexture::NewL(Env(), iData->iManagerId, aId, bitmapHandle, maskHandle, aFlags);        
+            }
+        }
+    else
+        {
+        // we have a pre-existing texture which is non-null,
+        // but check that the texture is loaded ok, we can also
+        // return unloaded textures that are in the load queue
+        if (tex->HasContent() || tex->IsAnimated() || IsInLoadQueue(tex))
+            {
+            return *(tex);
+            }
+        }
+
+    // replace filename
+    // File names are relative to the image path.
+    tex->SetFileNameL(fileName);
+    tex->SetMaxTextureSize(aTextureMaxSize);
+
+    // Set not released 
+    tex->SetReleaseFlags(CAlfTexture::EReleaseNone);
+
+    // If autosize used and size is set to zero, we don't yet load at all.
+    if (aFlags & EAlfTextureFlagAutoSize)
+        {            
+        if (aTextureMaxSize.iHeight == 0 && aTextureMaxSize.iWidth == 0)
+            {
+            return *tex;    
+            }        
+        }
+        
+    // Prepare for loading by creating a load queue entry.
+    TTextureEntry entry;
+    entry.iTexture = tex;
+    entry.iId = aId;
+
+    TLoadQueueEntry loadqentry;
+    loadqentry.iUnloaded = EFalse;
+    loadqentry.iLoading = entry;
+    loadqentry.iDecoder = NULL;
+
+    // Textures are loaded one at a time, in the order they were requested.
+    loadqueue.AppendL(loadqentry);
+
+    // Start the texture load active object if we're not loading
+    if(iData->iState == EIdle)
+        {
+        // Start loading images..
+        StartLoading();
+        // Notify observers.
+        NotifyStateChange();
+        }
+
+    return *tex;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Creates texture.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CAlfTexture& CAlfTextureManager::CreateTextureL(TInt aId,
+                                   MAlfBitmapProvider* aBitmapProvider,
+                                   TAlfTextureFlags aFlags)
+    {    
+    // Clients are not allowed to let toolkit use bitmaps directly. It is used only internally.
+    RemoveFlags(aFlags, EAlfTextureFlagAllowDirectBitmapUsage);
+
+    CAlfTexture* tex = NULL;
+    
+    if (aId == KAlfAutoGeneratedTextureId)
+        {
+        aId = GenerateTextureId();    
+        }    
+
+    CFbsBitmap* bitmap = NULL;
+    CFbsBitmap* maskBitmap = NULL;
+
+    if (aId==0)
+        {
+        User::Leave(KErrArgument);
+        }
+
+    // Provide an already created texture if such exists.
+    TRAPD(err, tex = TextureL(aId));
+    if(err == KErrNone && tex->HasContent())
+        {
+        return *tex;
+        }
+
+    // Call the bitmapProvider method to load the bitmaps
+	if (aBitmapProvider)
+		{
+	    aBitmapProvider->ProvideBitmapL(aId, bitmap, maskBitmap);		
+		}
+					
+	if (!bitmap)
+	    { 
+	    // We leave here, otherwise serverside would panic. 
+	    User::Leave(KErrArgument);    
+	    // Bitmap size is checked and handled in serverside, 
+	    // so that we can create empty textures (size = 0,0)
+	    }
+	    	  
+	// "bitmap" pointer should be valid from now on
+    CleanupStack::PushL(bitmap);
+	TInt bitmapHandle = bitmap->Handle();
+	
+	TInt maskHandle = 0;
+	if (maskBitmap)	
+		{
+		maskHandle = maskBitmap->Handle();	
+	    CleanupStack::PushL(maskBitmap);
+		}
+    
+    // Create CAlfTexture instance, this duplicates the bitmaps to server.
+	if (!tex)
+	    {
+    	tex = CAlfTexture::NewL( Env(), 
+    	                         iData->iManagerId,
+    	                         aId, 
+    	                         bitmapHandle, 
+    	                         maskHandle, 
+    	                         aFlags);	        
+	    }
+	else
+	    {
+	    // texture already exists but it does not have content, this creates content.
+      	iData->iEnv->Client().TextureCreateL( aId, bitmapHandle, 
+        	maskHandle, aFlags, iData->iManagerId.iUid );    	            	        
+	    }    
+		
+	tex->SetBitmapProvider(aBitmapProvider);	
+    tex->SetSize(bitmap->SizeInPixels());
+
+    // Set not released 
+    tex->SetReleaseFlags(CAlfTexture::EReleaseNone);
+	
+	// CAlfTexture has at this point duplicated bitmaps, can be deleted here.        
+	if (maskBitmap)	
+		{
+	    CleanupStack::PopAndDestroy( maskBitmap );
+	    maskBitmap = NULL;		
+		}
+    CleanupStack::PopAndDestroy( bitmap ); 
+	bitmap = NULL;		
+
+    // Notify observers
+    NotifyTextureLoaded(*tex, aId, KErrNone);
+
+    return *tex;
+    }
+
+// ---------------------------------------------------------------------------
+//  Unloads texture
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAlfTextureManager::UnloadTexture(const TDesC& aImageName)
+    {
+    TInt index = CheckTexture(aImageName);
+    if (index >= 0)
+        {
+        RArray<TTextureEntry>& textures = (iData->iTextures);	
+        TTextureEntry entry = textures[index];        
+        CancelLoadingOfTexture(*entry.iTexture);
+        if (!entry.iTexture->IsAnimated())
+            {
+            iData->iEnv->Client().TextureUnload(entry.iId, iData->iManagerId.iUid);
+            }
+        else
+            {
+            entry.iTexture->StopAnimation();      
+            }
+        
+        TInt releaseFlags = entry.iTexture->ReleaseFlags();
+        releaseFlags |= CAlfTexture::EReleaseFromUnload;
+        entry.iTexture->SetReleaseFlags(releaseFlags);
+        }
+    }
+
+// ---------------------------------------------------------------------------
+//  Unloads texture
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAlfTextureManager::UnloadTexture(TInt aId)
+    {
+    TInt index = CheckTexture(aId);
+    if (index >= 0)
+        {
+        RArray<TTextureEntry>& textures = (iData->iTextures);	
+        TTextureEntry entry = textures[index];        
+		CancelLoadingOfTexture(*entry.iTexture);
+        if (!entry.iTexture->IsAnimated())
+            {
+            iData->iEnv->Client().TextureUnload( aId, iData->iManagerId.iUid );    	                
+            }
+        else
+            {
+            entry.iTexture->StopAnimation();        
+            }           
+        
+        TInt releaseFlags = entry.iTexture->ReleaseFlags();
+        releaseFlags |= CAlfTexture::EReleaseFromUnload;
+        entry.iTexture->SetReleaseFlags(releaseFlags);
+        }
+    }
+ 
+// ---------------------------------------------------------------------------
+//  Updates texture content
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAlfTextureManager::UpdateTextureFromFileL(TInt aId, const TDesC* aFileName)
+    {
+   	RArray<TTextureEntry>& textureEntries = (iData->iTextures);	
+    TInt index = CheckTexture(aId);
+    if (index >= 0)
+        {
+    	TTextureEntry entry = textureEntries[index];
+    	
+    	TFileName fileName;
+    	if (aFileName != NULL)
+    		{
+    		fileName = *aFileName;
+    		}
+    	else if (entry.iTexture->FileName() == NULL)
+    		{
+    		User::Leave(KErrArgument);
+    		}	
+        entry.iTexture->SetBitmapProvider(NULL);
+        
+        // Set non released
+        entry.iTexture->SetReleaseFlags(CAlfTexture::EReleaseNone);
+
+        if (!entry.iTexture->IsAnimated())
+            {
+           	ReloadTextureL(fileName, entry.iTexture->MaxTextureSize(), entry.iTexture->Flags(), 
+               	entry.iTexture->Id());
+            }
+        else
+            {
+            entry.iTexture->StartAnimation();    
+            }    
+        } 
+    else
+    	{
+    	User::Leave(KErrNotFound);
+    	}           
+    }
+    
+// ---------------------------------------------------------------------------
+//  Updates texture content
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAlfTextureManager::UpdateTextureFromBitmapL(TInt aId, MAlfBitmapProvider* aBitmapProvider)
+    {
+   	RArray<TTextureEntry>& textureEntries = (iData->iTextures);	
+    TInt index = CheckTexture(aId);
+    if (index >= 0)
+        {
+    	TTextureEntry entry = textureEntries[index];
+    	
+    	if (!aBitmapProvider)
+    		{
+    		aBitmapProvider = entry.iTexture->BitmapProvider();
+    		}
+    	TBuf<1> empty;	
+        entry.iTexture->SetFileNameL(empty);
+
+        // Set non released
+        entry.iTexture->SetReleaseFlags(CAlfTexture::EReleaseNone);
+
+        if (!entry.iTexture->IsAnimated())
+            {
+           	RecreateTextureL(entry.iTexture->Id(), aBitmapProvider, entry.iTexture->Flags());
+            }
+        else
+            {
+            entry.iTexture->StartAnimation();     
+            }    
+        }        
+    else
+    	{
+    	User::Leave(KErrNotFound);
+    	}           
+    } 
+    
+    
+// ---------------------------------------------------------------------------
+//  Defines filename for given id.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAlfTextureManager::DefineFileNameL(TInt aId, const TDesC& aFileName)
+    {
+    if (aId==0)
+        {
+        User::Leave(KErrArgument); // can't specify filename for "no id"
+        }
+
+   	RArray<TTextureEntry>& textures = (iData->iTextures);	
+
+    // Look for an existing entry for the id.
+    for(TInt i = 0; i < textures.Count(); ++i)
+        {
+        if(textures[i].iId == aId)
+            {
+            textures[i].iTexture->SetFileNameL(aFileName);
+            return;
+            }
+        }
+
+    // Otherwise just append to the texture list
+	CAlfTexture* tex = CAlfTexture::NewL( Env(), iData->iManagerId, aId );  
+	tex->SetFileNameL(aFileName);
+    }
+    
+// ---------------------------------------------------------------------------
+// Prepends image path
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAlfTextureManager::PrependImagePath(TDes& aFileName)
+    {
+    TFileName buf;
+
+    //allow app to load textures from different drive with complete path
+    TParse p1;
+    p1.Set(aFileName,0,0);
+
+    if (p1.DrivePresent())
+        {
+        return;
+        }
+
+
+    if(aFileName.Find(*iData->iImagePath) == KErrNotFound)
+        {
+        buf = *iData->iImagePath;
+        buf.Append(aFileName);
+        aFileName = buf;
+        }
+    }
+
+
+
+// ---------------------------------------------------------------------------
+// CheckTexture
+// ---------------------------------------------------------------------------
+//
+TInt CAlfTextureManager::CheckTexture(const TDesC& aImageName) const
+    {
+    if(aImageName.Length()==0)
+        {
+        // name empty, can't check
+        return KErrNotFound;
+        }
+
+    RArray<TTextureEntry>& textures = (iData->iTextures);	
+    for(TInt i = 0; i < textures.Count(); ++i)
+        {
+        TTextureEntry te = textures[i];
+        // compare against texture manager entry filename (iFileName)
+        if((te.iTexture->FileName() != NULL)
+            && (aImageName.Compare(*(te.iTexture->FileName())) == 0))
+            {
+            return i;
+            }
+        }
+    // not found
+    return KErrNotFound;
+    }
+
+	
+// ---------------------------------------------------------------------------
+// CheckTexture
+// ---------------------------------------------------------------------------
+//
+TInt CAlfTextureManager::CheckTexture(TInt aId) const
+    {
+    RArray<TTextureEntry>& textures = (iData->iTextures);	
+    if(aId <= 0)
+        {
+        // id not defined, can't search
+        return KErrNotFound;
+        }
+    for(TInt i = 0; i < textures.Count(); i++)
+        {
+        if(textures[i].iId == aId)
+            {
+            return i;
+            }
+        }
+    // not found:
+    return KErrNotFound;
+    }
+    
+    
+
+// ---------------------------------------------------------------------------
+// RunError from CActive
+// ---------------------------------------------------------------------------
+//
+TInt CAlfTextureManager::RunError(TInt /*aError*/)
+    {
+    return KErrNone;
+    // Should never be called, RunL is responsible for handling all error cases
+    }
+
+
+// ---------------------------------------------------------------------------
+// RunL from CActive
+// ---------------------------------------------------------------------------
+//
+void CAlfTextureManager::RunL()
+    {
+    // remove the loaded entry from the queue
+    TLoadQueueEntry entry = PopLoadedQueueEntry();
+
+    // Image loading has been completed.
+    iData->iState = EIdle;
+
+    // check status
+    if(iStatus == KErrNone)
+        {
+        // ok, we have a loaded image, but
+        // we still need to do texture uploads
+        // and possibly some image conversions
+        TRAPD( err, ImageLoadingCompleteL(entry) );
+
+        if(err != KErrNone)
+            {
+            // Notify observers about the image upload error
+            NotifyTextureLoaded(*entry.iLoading.iTexture, entry.iLoading.iId, err);
+            }
+        }
+    else
+        {
+        // notify sb of failed image load!
+        NotifyTextureLoaded(*entry.iLoading.iTexture, entry.iLoading.iId, iStatus.Int());
+        }
+
+    StartLoading();
+    }
+
+// ---------------------------------------------------------------------------
+// Cancels asyncronous loading
+// ---------------------------------------------------------------------------
+//
+void CAlfTextureManager::DoCancel()
+    {
+    RArray<TLoadQueueEntry>& loadqueue = (iData->iLoadQueue);	
+    if(loadqueue.Count() > 0)
+        {
+        loadqueue[0].iDecoder->Cancel();
+        }
+    iData->iState = EIdle;
+    }
+
+// ---------------------------------------------------------------------------
+// Starts asyncronous loading
+// ---------------------------------------------------------------------------
+//
+void CAlfTextureManager::StartLoading()
+    {
+    // loop that finds next entry to load
+    while (1)
+        {
+        // try to schedule next image for loading..
+        TRAPD( err, DoLoadNextL() );
+
+        // ok?            
+        if(err != KErrNone)
+            {            
+            // remove the entry from the queue
+            TLoadQueueEntry entry = PopLoadedQueueEntry();
+            // Notify observers about the image loading error
+            NotifyTextureLoaded(*entry.iLoading.iTexture, entry.iLoading.iId, err);            
+            // Image loading has been completed.
+            iData->iState = EIdle;
+            continue;
+            }
+        // leave the loop if we had no trouble scheduling the next
+        // image decode
+        break;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Loads texture entry from queue. Mostly this code is copied from 
+// CAlfTextureManager::DoLoadNextL but some adjustmets has been made to support
+// better client server paradigm.
+// 
+// ---------------------------------------------------------------------------
+//
+void CAlfTextureManager::DoLoadNextL()
+    {
+    RArray<TLoadQueueEntry>& loadqueue = (iData->iLoadQueue);	
+    // Any loading tasks left?
+    if(loadqueue.Count() == 0)
+        {
+        // No? Notify observers and leave.
+        NotifyStateChange();
+        return; // nothing else to be loaded..
+        }
+
+    // Manager is now busy.
+    iData->iState = ELoading;
+
+    // Fetch a load queue entry
+    TLoadQueueEntry& entry = loadqueue[0];
+    CAlfTexture* texture = entry.iLoading.iTexture;
+
+    // Create a new image decoder for loading the image.
+    TFileName imageFileName = *texture->FileName(); // does not include image path
+    PrependImagePath(imageFileName);
+    entry.iDecoder = 0;
+    // We use fast decode because it seems to be a lot faster with jpegs.
+    TRAPD( err,  entry.iDecoder = CImageDecoder::FileNewL(iData->iFs, imageFileName, CImageDecoder::EPreferFastDecode ));
+
+    // check for errors..
+    if(err != KErrNone)
+        {
+        // Try to cancel the decoding (if possible)
+        if(entry.iDecoder)
+            {
+            entry.iDecoder->Cancel();
+            }
+        User::Leave(err); // re-leave with the error
+        }
+        
+    // from decoder's frame info retrieve the framesize
+    TFrameInfo frameInfo(entry.iDecoder->FrameInfo(0));
+
+    // check for alpha channel 
+    if(frameInfo.iFlags & TFrameInfo::ETransparencyPossible )
+        {
+        entry.iHasAlpha = ETrue;
+        }
+    else
+        {
+        entry.iHasAlpha = EFalse;
+        }
+
+    // Get the image original size
+    TRect bitmapSize = frameInfo.iFrameCoordsInPixels;
+    entry.iOriginalSize = bitmapSize.Size();
+
+    // target resolution for texture, initially equal to bitmap size
+    TInt widthResolutionTarget = bitmapSize.Size().iWidth;
+    TInt heightResolutionTarget = bitmapSize.Size().iHeight;
+
+    TSize maxTexSize = entry.iLoading.iTexture->MaxTextureSize();
+
+    // Assign new texture resolution target dimensions
+    // if we have explicitly requested them
+    if( (entry.iLoading.iTexture->Flags() & EAlfTextureFlagDoNotRetainResolution)
+            && maxTexSize.iWidth > 0
+            && maxTexSize.iHeight > 0)
+        {
+        // assign new target resolution for decoder-based scaling
+        if(maxTexSize.iWidth < widthResolutionTarget)
+            {
+            widthResolutionTarget = maxTexSize.iWidth;
+            }
+        if(maxTexSize.iHeight < heightResolutionTarget)
+            {
+            heightResolutionTarget = maxTexSize.iHeight;
+            }
+        }
+
+    // we need to do some downscaling, but can we do arbitrary
+    // scaling as well?
+    if(frameInfo.iFlags & TFrameInfo::EFullyScaleable)
+        {
+        // .. yes, arbitrary scaling is possible
+        // just assign the new size to the bitmap
+        // so that it will be scaled accordingly during
+        // conversion
+        }
+    else
+        {
+        // all decoders should be able to do 1/2, 1/4, 1/8 DCT Scaling
+        // calculate nearest half size for the decoder-downscaled bitmap
+        // halve image width&height to size which is closest larger match
+        // of the bitmap size
+        TInt halvedWidth = bitmapSize.Size().iWidth;
+        TInt halvedHeight = bitmapSize.Size().iHeight;
+        TInt halveFactor = 1; // this limits the halving to 1/8 max
+        while ( ((halvedWidth >> 1) > widthResolutionTarget) &&
+                ((halvedHeight >> 1) > heightResolutionTarget)
+                && (halveFactor << 1) <= 8)
+            {
+            halveFactor <<= 1;
+            }
+        halvedWidth = halvedWidth / halveFactor;
+        halvedHeight = halvedHeight / halveFactor;
+        // .. the bitmap will be downscaled further to the correct
+        // dimensions by the toolkit after the bitmap has been decoded
+        widthResolutionTarget = halvedWidth;
+        heightResolutionTarget = halvedHeight;
+        }
+
+
+    if (!(entry.iLoading.iTexture->Flags() & EAlfTextureFlagRetainColorDepth) && 
+        iData->iBitmap->DisplayMode()!=EColor64K)
+        {
+        // (Re)Create the bitmap in EColor64K (16bit) mode to save memory
+        iData->iBitmap->Create(TSize(widthResolutionTarget, heightResolutionTarget), EColor64K);
+        }
+    else if ((entry.iLoading.iTexture->Flags() & EAlfTextureFlagRetainColorDepth) && 
+        iData->iBitmap->DisplayMode()==EColor64K)
+        {
+        // (Re)Create the bitmap in EColor16MU (24bit) mode retain the color information
+        iData->iBitmap->Create(TSize(widthResolutionTarget, heightResolutionTarget), EColor16MU);
+        }
+    else
+        {
+        // no need to recreate the bitmap, but assign the new size!
+        iData->iBitmap->Resize(TSize(widthResolutionTarget, heightResolutionTarget));
+        }
+
+    if (iData->iBitmap->DisplayMode()==EColor64K)
+        {
+        }
+    // Decode ( and rescale ) to bitmap.
+    if(entry.iHasAlpha)
+        {
+        // set the alpha channel bitmap to the same size than the color bitmap
+        iData->iMaskBitmap->Resize(TSize(widthResolutionTarget, heightResolutionTarget));
+        entry.iDecoder->Convert(&iStatus, *iData->iBitmap, *iData->iMaskBitmap, 0);
+        }
+    else
+        {
+        // We cannot do resize mask to smaller until serverside works differently
+        iData->iMaskBitmap->Resize(TSize(widthResolutionTarget, heightResolutionTarget));
+        entry.iDecoder->Convert(&iStatus, *iData->iBitmap, 0);
+        }
+    // Wait for completion.
+    SetActive();
+
+    }
+
+
+// ---------------------------------------------------------------------------
+// Pops entry from load queue
+// ---------------------------------------------------------------------------
+//
+TLoadQueueEntry CAlfTextureManager::PopLoadedQueueEntry()
+    {
+    RArray<TLoadQueueEntry>& loadqueue = (iData->iLoadQueue);	
+    TLoadQueueEntry entry = loadqueue[0];
+    loadqueue.Remove(0);
+    // Delete the decoder.
+    delete entry.iDecoder;
+    entry.iDecoder = 0;
+    return entry;
+    }
+
+
+// ---------------------------------------------------------------------------
+// This method gets called when image loading has been completed and server
+// side texture needs to be created.
+// ---------------------------------------------------------------------------
+//
+void CAlfTextureManager::ImageLoadingCompleteL(TLoadQueueEntry& aEntry)
+    {                    
+    TSize maxTexSize = aEntry.iLoading.iTexture->MaxTextureSize();    
+    
+    // Calculate new maxsize keeping the aspect ratio if only one max dimension was
+    // specified.
+    if ((maxTexSize.iWidth == 0 && maxTexSize.iHeight != 0) ||
+        (maxTexSize.iWidth != 0 && maxTexSize.iHeight == 0))
+        {
+        TSize sizeInPixels = iData->iBitmap->SizeInPixels();
+        if (sizeInPixels.iWidth != 0 && sizeInPixels.iHeight != 0)
+            {
+            if (maxTexSize.iWidth == 0)
+                {
+                maxTexSize.iWidth = (maxTexSize.iHeight * sizeInPixels.iWidth)/sizeInPixels.iHeight;                    
+                }
+            else if (maxTexSize.iHeight == 0)
+                {
+                maxTexSize.iHeight = (maxTexSize.iWidth * sizeInPixels.iHeight)/sizeInPixels.iWidth;   
+                }                                
+            }            
+        }
+    
+    
+    if( (maxTexSize.iWidth != 0) && 
+        (maxTexSize.iHeight != 0) && 
+        (iData->iBitmap->SizeInPixels() != aEntry.iLoading.iTexture->MaxTextureSize()))
+        {
+        // The decoder failed to constrain the texture dimensions properly, due to its internal limitations.
+        // So we need to scale the texture(s) down further to the correct size.              
+        CFbsBitmap* dest = new (ELeave) CFbsBitmap();   
+        dest->Create(maxTexSize, iData->iBitmap->DisplayMode());     
+        CleanupStack::PushL(dest);
+        AlfUtil::ScaleFbsBitmapL(*iData->iBitmap, *dest);
+        CleanupStack::Pop(); // dest
+        delete iData->iBitmap;
+        iData->iBitmap = dest;
+
+        if(aEntry.iHasAlpha)
+            {
+            // Scale the alpha as well.
+            dest = new (ELeave) CFbsBitmap();   
+            dest->Create(maxTexSize, iData->iMaskBitmap->DisplayMode());     
+            CleanupStack::PushL(dest);
+            AlfUtil::ScaleFbsBitmapL(*iData->iMaskBitmap, *dest);
+            CleanupStack::Pop(); // dest
+            delete iData->iMaskBitmap;
+            iData->iMaskBitmap = dest;
+            }                                      
+        }        
+
+    TInt bitmapHandle = 0;
+    TInt maskHandle = 0;
+	
+	if (iData->iBitmap)
+		{
+		bitmapHandle = iData->iBitmap->Handle();
+		}
+	
+	if (iData->iMaskBitmap && aEntry.iHasAlpha)	
+		{
+		maskHandle = iData->iMaskBitmap->Handle();	
+		}
+
+    TInt handle = iData->iEnv->Client().TextureLoadL( aEntry.iLoading.iTexture->Id(), 
+   	    bitmapHandle, 
+   	    maskHandle, 
+   	    aEntry.iLoading.iTexture->Flags(), 
+   	    iData->iManagerId.iUid);
+
+    aEntry.iLoading.iTexture->SetServerHandle(handle);   	    
+    
+    if (iData->iBitmap)
+        aEntry.iLoading.iTexture->SetSize(iData->iBitmap->SizeInPixels());
+
+    // Notify the observers of loaded texture
+    NotifyTextureLoaded(*aEntry.iLoading.iTexture, aEntry.iLoading.iId, KErrNone);
+
+    // Resize bitmaps to save memory
+    iData->iBitmap->Reset();
+    iData->iMaskBitmap->Reset();
+    iData->iBitmap->Create(
+        TSize(KAlfDefaultSizeDimension, KAlfDefaultSizeDimension), EColor64K);
+    iData->iMaskBitmap->Create(
+        TSize(KAlfDefaultSizeDimension, KAlfDefaultSizeDimension), EGray256);
+
+    // DEBUG 
+    if (iData->iTextureAutoCounterEnabled)
+        {            
+        TBuf<256> numBuf;
+        numBuf.FillZ();
+        numBuf.Append(_L("Reloads:"));
+        numBuf.AppendNum(iData->iTextureAutoReloadCounter);
+        numBuf.Append(_L(" - Recreates:"));
+        numBuf.AppendNum(iData->iTextureAutoRecreateCounter);
+        User::InfoPrint(numBuf);
+        }
+
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void CAlfTextureManager::NotifyStateChange() const
+    {
+    __ALFLOGSTRING( "CAlfTextureManager::NotifyStateChange" )
+
+    RPointerArray<MAlfTextureManagerStateChangedObserver>& observers = 
+        (iData->iStateObserverQueue);	
+    TInt count = observers.Count();
+    for(TInt i = 0; i < count; i++)
+     	{
+        observers[i]->TextureManagerStateChanged(*this); 								                       
+        }        
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void CAlfTextureManager::NotifyTextureLoaded(CAlfTexture& aTexture,
+                             TInt aTextureId,
+                             TInt aErrorCode) const
+    {
+// NOTE: Commented out because this will prevent alflogging (aTexture.FileName() = NULL => crash)
+//    __ALFLOGSTRING3( "CAlfTextureManager::NotifyTextureLoaded -- filename: %S, textureId: %d, error: %d",
+//          aTexture.FileName(), aTextureId, aErrorCode )
+
+    RPointerArray<MAlfTextureLoadingCompletedObserver>& observers = 
+        (iData->iLoadObserverQueue);	
+    TInt count = observers.Count();
+    for(TInt i = 0; i < count; i++)
+     	{
+        observers[i]->TextureLoadingCompleted(aTexture, aTextureId, 
+            aErrorCode); 								                       
+        }        
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAlfTextureManager::AddLoadObserverL(
+    MAlfTextureLoadingCompletedObserver* aObserver)
+    {
+    iData->iLoadObserverQueue.Append(aObserver);    
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAlfTextureManager::RemoveLoadObserver(
+MAlfTextureLoadingCompletedObserver* aObserver)
+    {
+    RPointerArray<MAlfTextureLoadingCompletedObserver>& observers = 
+            (iData->iLoadObserverQueue);	
+
+    TInt count = observers.Count();
+    for(TInt i = 0; i < count; i++)
+      	{
+    	if (observers[i] == aObserver)
+    		{
+    		observers.Remove(i);
+    		observers.Compress();
+    		break;
+    		}								                       
+        }        
+    }
+    
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+TUid CAlfTextureManager::ManagerUid()
+    {
+    return iData->iManagerId;    
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CAlfTextureProcessor& CAlfTextureManager::Processor()
+    {
+    return *iData->iProcessor;    
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void CAlfTextureManager::AppendTextureL(CAlfTexture* aTexture)
+    {
+    if (CheckTexture(aTexture->Id()) == KErrNotFound)
+        {
+        // Create a new texture entry
+        TTextureEntry entry(aTexture->Id(), aTexture);
+        
+        // Add the new entry to the list of new textures
+        iData->iTextures.AppendL(entry);                    
+        }
+    else
+        {
+        User::Leave(KErrAlreadyExists);    
+        }    
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void CAlfTextureManager::RemoveTexture(CAlfTexture& aTexture)
+    {
+    // Cancel loading of the texture to be removed.
+    CancelLoadingOfTexture(aTexture);
+    
+    RArray<TTextureEntry>& textures = (iData->iTextures);	
+    for(TInt i = 0; i < textures.Count(); i++)
+        {
+        TTextureEntry te = textures[i];
+        if (&aTexture == te.iTexture)
+            {
+            te.iTexture = NULL;                
+            textures.Remove(i);                
+            break;
+            }
+        }        
+    }
+    
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+TBool CAlfTextureManager::IsInLoadQueue(const CAlfTexture* texture) const
+    {
+    TBool retVal = EFalse;
+    RArray<TLoadQueueEntry>& loadQueue = iData->iLoadQueue;	
+    for(TInt i = 0; i < loadQueue.Count(); i++)
+        {
+        TLoadQueueEntry loadEntry = loadQueue[i];
+        if (loadEntry.iLoading.iTexture == texture)
+            {
+            retVal = ETrue;
+            break;    
+            }
+        }
+    return retVal;
+    }
+    
+    
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+CAlfTextureManager::TState CAlfTextureManager::State() const
+    {
+    return iData->iState;    
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAlfTextureManager::AddStateObserverL(
+    MAlfTextureManagerStateChangedObserver* aObserver)
+    {
+    iData->iStateObserverQueue.Append(aObserver);            
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAlfTextureManager::RemoveStateObserver(
+    MAlfTextureManagerStateChangedObserver* aObserver)
+    {
+    RPointerArray<MAlfTextureManagerStateChangedObserver>& observers = 
+            (iData->iStateObserverQueue);	
+
+    TInt count = observers.Count();
+    for(TInt i = 0; i < count; i++)
+      	{
+    	if (observers[i] == aObserver)
+    		{
+    		observers.Remove(i);
+    		observers.Compress();
+    		break;
+    		}								                       
+        }                
+    }
+    
+EXPORT_C TBool CAlfTextureManager::IsLoaded(const CAlfTexture * texture) const
+    {
+    if(texture != NULL && texture->HasContent() && !IsInLoadQueue(texture))
+        {
+        return ETrue;
+        }
+    return EFalse;
+    }
+
+
+EXPORT_C TBool CAlfTextureManager::IsLoaded(const TDesC& aImageName) const
+    {
+    TFileName fileName = *iData->iImagePath;
+    fileName.Append(aImageName);
+    TInt index = CheckTexture(fileName);
+    if(index == KErrNotFound)
+        {
+        return EFalse;
+        }
+    return IsLoaded(iData->iTextures[index].iTexture);
+    }
+
+EXPORT_C TInt CAlfTextureManager::TextureId(const TDesC& aImageName) const
+    {
+    TFileName fileName = *iData->iImagePath;
+    fileName.Append(aImageName);
+    TInt index = CheckTexture(fileName);
+    
+    if(index == KErrNotFound)
+        {
+        return KErrNotFound;
+        }
+    return iData->iTextures[index].iId;
+    }
+
+EXPORT_C TBool CAlfTextureManager::IsLoaded(TInt aId) const
+    {
+    ASSERT(aId!=0);
+    TInt index = CheckTexture(aId);
+    if(index == KErrNotFound)
+        {
+        return EFalse;
+        }
+    return IsLoaded(iData->iTextures[index].iTexture);
+    }
+
+
+
+// ---------------------------------------------------------------------------
+// Release all textures with given priority level (or above)
+// ---------------------------------------------------------------------------
+//
+TBool CAlfTextureManager::Release( TInt aReleasePriorityLevel )
+    {
+    TBool allReleased = ETrue;
+    
+    RArray<TTextureEntry>& textures = (iData->iTextures);	
+    for(TInt i = 0; i < textures.Count(); i++)
+        {
+        if (textures[i].iTexture->Id())
+            {
+            if ( textures[i].iTexture->Priority() < aReleasePriorityLevel )
+                {
+                allReleased = EFalse;
+                }
+            else
+                {
+                if (!textures[i].iTexture->IsAnimated())
+                    {
+                    ReleaseEntry(textures[i]);                    
+                    }
+                else
+                    {
+                    textures[i].iTexture->StopAnimation();    
+                    }                    
+                }
+            }
+        }
+    return allReleased;
+    }
+
+// ---------------------------------------------------------------------------
+// Release a specific entry
+// ---------------------------------------------------------------------------
+//
+void CAlfTextureManager::ReleaseEntry(const TTextureEntry& aEntry)
+    {
+    // Id texture has content, it must be released here using unload,
+    // otherwise we can just notify serverside.
+    if (aEntry.iTexture->HasContent())
+        {        
+        UnloadTexture(aEntry.iTexture->Id());                        
+        }
+    else
+        {
+        iData->iEnv->Client().TextureRelease(aEntry.iTexture->Id(), 
+            iData->iManagerId.iUid);            
+        }    
+    
+    TInt releaseFlags = aEntry.iTexture->ReleaseFlags();
+    releaseFlags |= CAlfTexture::EReleaseFromEnv;
+    aEntry.iTexture->SetReleaseFlags(releaseFlags);
+    }
+
+// ---------------------------------------------------------------------------
+// Restore all textures with given priority level (or lover)
+// ---------------------------------------------------------------------------
+//
+TBool CAlfTextureManager::RestoreL( TInt aRestorePriorityLevel )
+    {
+    TBool allRestored = ETrue;
+    
+    RArray<TTextureEntry>& textures = (iData->iTextures);	
+    for(TInt i = 0; i < textures.Count(); i++)
+        {
+        if ( textures[i].iTexture->Priority() <= aRestorePriorityLevel )
+            {
+            if (!textures[i].iTexture->IsAnimated())
+                {
+                RestoreEntryL(textures[i]);    
+                }
+            else
+                {
+                textures[i].iTexture->StartAnimation();                                                
+                }                
+            }
+        else
+            {
+            allRestored = EFalse;
+            }
+        }    
+    
+    return allRestored;
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void CAlfTextureManager::RestoreEntryL(const TTextureEntry& aEntry)
+    {
+    // Id texture has no content, it must be restored here using create/load
+    // otherwise we can just notify serverside.
+    if (!aEntry.iTexture->HasContent())
+        {
+        // Clear release flags 
+        TInt releaseFlags = aEntry.iTexture->ReleaseFlags();
+        releaseFlags &= ~CAlfTexture::EReleaseFromEnv;    
+        releaseFlags &= ~CAlfTexture::EReleaseFromUnload;                   
+        aEntry.iTexture->SetReleaseFlags(releaseFlags);
+
+        // If there are other release flags, then do not restore.        
+        if (!releaseFlags)
+            {                         
+            // check for provider-based restore               
+            if (aEntry.iTexture->BitmapProvider() != NULL)
+                {
+                CreateTextureL(aEntry.iTexture->Id(),
+                               aEntry.iTexture->BitmapProvider(),
+                               aEntry.iTexture->Flags());
+                }
+            // check for file-based restore
+            else if (aEntry.iTexture->FileName() != NULL)
+                {
+                LoadTextureL(aEntry.iTexture->FileName()->Des(),
+                    aEntry.iTexture->MaxTextureSize(), 
+                    aEntry.iTexture->Flags(), 
+                    aEntry.iTexture->Id());
+                }       
+            else
+                {
+                // for PC lint
+                }
+            }
+        }
+    else
+        {
+        iData->iEnv->Client().TextureRestore(aEntry.iTexture->Id(), 
+            iData->iManagerId.iUid);    
+        }        
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void CAlfTextureManager::CancelLoadingOfTexture(CAlfTexture& aTexture)
+    {
+    RArray<TLoadQueueEntry>& loadQueue = iData->iLoadQueue;    
+    for(TInt i = 0; i < loadQueue.Count(); i++)
+        {
+        if(loadQueue[i].iLoading.iTexture == &aTexture)
+            {
+            // Texture found from the load queue.
+            if(i == 0 && iData->iState == ELoading)
+                {
+                // Texture is currently loading
+                Cancel();
+                PopLoadedQueueEntry();
+                StartLoading();                
+                }
+            else
+                {
+                // Delete the decoder and remove entry.
+                delete loadQueue[i].iDecoder;
+                loadQueue.Remove(i);
+                }
+            break;
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+TInt CAlfTextureManager::GenerateTextureId()
+    {
+    TBool done = EFalse;
+
+    TInt start = iData->iAutoGeneratedTextureId;
+    while (!done)
+        {            
+        if(iData->iAutoGeneratedTextureId == iData->iHighestAutoGeneratedTextureId)
+            {
+            iData->iAutoGeneratedTextureId = iData->iLowestAutoGeneratedTextureId;
+            }
+        else
+            {
+            iData->iAutoGeneratedTextureId++;
+            }
+        
+        if (CheckTexture(iData->iAutoGeneratedTextureId) == KErrNotFound)
+            {
+            done = ETrue;    
+            }
+        
+        if (iData->iAutoGeneratedTextureId == start)
+            {
+            // Error! Free id was not found, already existing id will be used.
+            break;    
+            }            
+        }
+
+    return iData->iAutoGeneratedTextureId;        
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAlfTextureManager::SetAutomaticTextureIdRange(TInt aLow, TInt aHigh)
+    {
+    if (aLow < aHigh)
+        {
+        iData->iAutoGeneratedTextureId = aLow;
+        iData->iLowestAutoGeneratedTextureId = aLow;
+        iData->iHighestAutoGeneratedTextureId = aHigh;                    
+        }
+    }
+    
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void CAlfTextureManager::NotifySkinChangedL()
+    {
+    __ALFLOGSTRING( "CAlfTextureManager::NotifySkinChangedL" )
+    
+    RArray<TTextureEntry>& textures = (iData->iTextures);	
+    for(TInt i = 0; i < textures.Count(); i++)
+        {
+        if (textures[i].iTexture->Id() &&
+            textures[i].iTexture->HasContent() &&
+            (textures[i].iTexture->Flags() & EAlfTextureFlagSkinContent))
+            {
+            iData->iEnv->Client().TextureNotifySkinChanged(textures[i].iTexture->Id(),
+                 iData->iManagerId.iUid);    
+            
+            ReleaseEntry(textures[i]);            
+            RestoreEntryL(textures[i]);
+            }
+        }                        
+    }
+    
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+TBool CAlfTextureManager::IsShared()
+    {
+    return (iData->iManagerId != TUid::Uid(0));        
+    }
+    
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void CAlfTextureManager::ReportTextureInfoL( 
+        TInt aTextureId, const TSize& aTextureRect )
+    {
+    __ALFLOGSTRING1( "CAlfTextureManager::ReportTextureInfo %d", aTextureId )
+    __ALFLOGSTRING2( "texture size = (%d, %d)", aTextureRect.iWidth, aTextureRect.iHeight )
+
+    TBool accepted = EFalse;
+    CAlfTexture* texture = TextureL(aTextureId);
+    
+    RPointerArray<MAlfTextureAutoSizeObserver>& observers = 
+        (iData->iAutoSizeObserverQueue);	
+    TInt count = observers.Count();
+    for(TInt i = 0; i < count; i++)
+     	{
+        accepted |= observers[i]->PreferredSizeChanged(*texture, aTextureRect);
+        }
+
+    // File based textures are updated automatically without observer acceptance
+    if (texture->FileName())
+        {
+        // Update new max size, but leave undefined (zero) values untouched.
+        TSize maxTextureSize = texture->MaxTextureSize();
+        TSize oldMaxTextureSize = maxTextureSize;
+        
+        if (maxTextureSize.iWidth != 0 && maxTextureSize.iHeight == 0)
+            {
+            maxTextureSize.iWidth = aTextureRect.iWidth;    
+            }
+        else if (maxTextureSize.iHeight != 0 && maxTextureSize.iWidth == 0)
+            {
+            maxTextureSize.iHeight = aTextureRect.iHeight;      
+            }
+        else
+            {
+            maxTextureSize = aTextureRect;   
+            }    
+            
+        texture->SetMaxTextureSize(maxTextureSize);
+               
+        if (!texture->ReleaseFlags() && (oldMaxTextureSize != maxTextureSize))
+            {
+            // Update if texture is not released. 
+            UpdateTextureL(aTextureId, aTextureRect);             
+            }
+        }
+    else
+        {
+        if (accepted && !texture->ReleaseFlags())
+            {
+            // If we did notify someone who accepted it, we assume it may now be able to 
+            // provide new size texture. If it is released it should get updated 
+            // automatically to new size when restore happens.   
+            UpdateTextureL(aTextureId, aTextureRect);             
+            }
+        else
+            {
+            // not accepted by any of observers, no use to update then.    
+            }    
+        }                
+
+    }
+    
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAlfTextureManager::AddAutoSizeObserverL(MAlfTextureAutoSizeObserver* aObserver)
+    {
+    iData->iAutoSizeObserverQueue.Append(aObserver);     
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAlfTextureManager::RemoveAutoSizeObserver(MAlfTextureAutoSizeObserver* aObserver)
+    {
+    RPointerArray<MAlfTextureAutoSizeObserver>& observers = 
+            (iData->iAutoSizeObserverQueue);	
+
+    TInt count = observers.Count();
+    for(TInt i = 0; i < count; i++)
+      	{
+    	if (observers[i] == aObserver)
+    		{
+    		observers.Remove(i);
+    		observers.Compress();
+    		break;
+    		}								                       
+        }        
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void CAlfTextureManager::UpdateTextureL(TInt aId, TSize /*aSize*/)
+    {
+    RArray<TTextureEntry>& textures = (iData->iTextures);	
+    for(TInt i = 0; i < textures.Count(); i++)
+        {
+        TTextureEntry te = textures[i];
+        if (te.iTexture && te.iTexture->Id() == aId)
+            {
+            if (te.iTexture->BitmapProvider() != NULL)
+                {
+                UpdateTextureFromBitmapL(aId);
+                break;
+                }
+            else if (te.iTexture->FileName() != NULL)
+                {
+                UpdateTextureFromFileL(aId);
+                break;
+                }       
+            else
+                {
+                // for PC lint
+                break;
+                }
+            }
+        }
+    }
+
+
+void CAlfTextureManager::ReloadTextureL(const TDesC& aImageName,
+                                       TSize aTextureMaxSize,
+                                       TAlfTextureFlags /*aFlags*/,
+                                       TInt aId)
+    {    
+    if (aId == KAlfAutoGeneratedTextureId)
+        {
+        aId = GenerateTextureId();    
+        }    
+    
+    CAlfTexture* tex = NULL;
+    TFileName fileName;
+
+    // Texture must exist.
+    tex = TextureL(aId);
+
+    // add path to filename if filename has been passed
+    if(aImageName.Length() > 0)
+        {
+        // assume relative pathname and prepend the image path to get full filename
+        fileName = aImageName;
+        PrependImagePath(fileName);
+        }
+
+    // if no name has been passed as a parameter but
+    // there's and nonzero id has been passed, we
+    // can assume that there's a predefined name available
+    RArray<TTextureEntry>& textures = (iData->iTextures);	
+    RArray<TLoadQueueEntry>& loadqueue = (iData->iLoadQueue);	
+
+    if((aImageName.Length() == 0) && (aId != 0))
+       {
+        // search for a texture filename based on the id.
+        TInt index = CheckTexture(aId);
+        if(index >=0)
+            {
+            tex = textures[index].iTexture;
+            fileName = *tex->FileName();
+            }
+        else
+            {
+            User::Leave(KErrNotFound);
+            }
+       }
+
+    // return if already in the load queue ??
+   if (IsInLoadQueue(tex))
+       {
+       return;
+       }
+
+    // replace filename
+    // File names are relative to the image path.
+    tex->SetFileNameL(fileName);
+    
+    TSize maxTextureSize = tex->MaxTextureSize();
+    
+    // Update new max size, but leave undefined (zero) values untouched    
+    if (maxTextureSize.iWidth != 0 && maxTextureSize.iHeight == 0)
+        {
+        maxTextureSize.iWidth = aTextureMaxSize.iWidth;    
+        }
+    else if (maxTextureSize.iHeight != 0 && maxTextureSize.iWidth == 0)
+        {
+        maxTextureSize.iHeight = aTextureMaxSize.iHeight;      
+        }
+    else
+        {
+        maxTextureSize = aTextureMaxSize;   
+        }    
+
+    tex->SetMaxTextureSize(maxTextureSize);
+
+    // Prepare for loading by creating a load queue entry.
+    TTextureEntry entry;
+    entry.iTexture = tex;
+    entry.iId = aId;
+
+    TLoadQueueEntry loadqentry;
+    loadqentry.iUnloaded = EFalse;
+    loadqentry.iLoading = entry;
+    loadqentry.iDecoder = NULL;
+
+    // Textures are loaded one at a time, in the order they were requested.
+    loadqueue.AppendL(loadqentry);
+
+    // DEBUG
+    if (iData->iTextureAutoCounterEnabled)
+        {            
+        iData->iTextureAutoReloadCounter++;
+        }
+
+    // Start the texture load active object if we're not loading
+    if(iData->iState == EIdle)
+        {
+        // Start loading images..
+        StartLoading();
+        // Notify observers.
+        NotifyStateChange();
+        }
+    }
+
+void CAlfTextureManager::RecreateTextureL(TInt aId,
+                                          MAlfBitmapProvider* aBitmapProvider,
+                                          TAlfTextureFlags aFlags)
+    {    
+    CAlfTexture* tex = NULL;
+    
+    if (aId == KAlfAutoGeneratedTextureId)
+        {
+        User::Leave(KErrArgument); // texture must already exist !
+        }    
+
+    CFbsBitmap* bitmap = NULL;
+    CFbsBitmap* maskBitmap = NULL;
+
+    // Provide an already created texture if such exists.
+    TRAPD(err, tex = TextureL(aId));
+    if(err != KErrNone)
+        {
+        User::Leave(KErrArgument); // texture must already exist !
+        }
+
+    // Call the bitmapProvider method to load the bitmaps
+	if (aBitmapProvider)
+		{
+	    aBitmapProvider->ProvideBitmapL(aId, bitmap, maskBitmap);		
+		}
+					
+	if (!bitmap)
+	    { 
+	    // We leave here, otherwise serverside would panic. 
+	    User::Leave(KErrArgument);    
+	    // Bitmap size is checked and handled in serverside, 
+	    // so that we can create empty textures (size = 0,0)
+	    }
+	    	  
+	// "bitmap" pointer should be valid from now on
+    CleanupStack::PushL(bitmap);
+	TInt bitmapHandle = bitmap->Handle();
+	
+	TInt maskHandle = 0;
+	if (maskBitmap)	
+		{
+		maskHandle = maskBitmap->Handle();	
+	    CleanupStack::PushL(maskBitmap);
+		}
+    
+    // Create CAlfTexture instance, this duplicates the bitmaps to server.
+    // texture already exists but it does not have content, this creates content.
+   	iData->iEnv->Client().TextureCreateL( aId, bitmapHandle, 
+       	maskHandle, aFlags, iData->iManagerId.iUid );    	            	        
+		
+	tex->SetBitmapProvider(aBitmapProvider);	
+    tex->SetSize(bitmap->SizeInPixels());
+	
+	// CAlfTexture has at this point duplicated bitmaps, can be deleted here.        
+	if (maskBitmap)	
+		{
+	    CleanupStack::PopAndDestroy( maskBitmap );
+	    maskBitmap = NULL;		
+		}
+    CleanupStack::PopAndDestroy( bitmap ); 
+	bitmap = NULL;		
+    
+    // Notify observers
+    NotifyTextureLoaded(*tex, aId, KErrNone);
+    
+    // DEBUG
+    if (iData->iTextureAutoCounterEnabled)
+        {            
+        iData->iTextureAutoRecreateCounter++;
+        TBuf<256> numBuf;
+        numBuf.FillZ();
+        numBuf.Append(_L("Reloads:"));
+        numBuf.AppendNum(iData->iTextureAutoReloadCounter);
+        numBuf.Append(_L(" - Recreates:"));
+        numBuf.AppendNum(iData->iTextureAutoRecreateCounter);
+        User::InfoPrint(numBuf);
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void CAlfTextureManager::IncRefcount(TInt aId)
+    {
+    // do not refcount blanktextures.
+    if (!aId)
+        {
+        return;
+        }
+
+    TInt index = CheckTexture(aId);
+    ASSERT(index!=KErrNotFound);
+    TTextureEntry& te = iData->iTextures[index];
+    if (te.iRefCount==-1)
+        {
+        te.iRefCount = 1;
+        }
+    else
+        {
+        te.iRefCount++;        
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void CAlfTextureManager::DecRefcount(TInt aId)
+    {
+    // do not refcount blanktextures.
+    if (!aId)
+        {
+        return;
+        }
+        
+    TInt index = CheckTexture(aId);
+    if (index == KErrNotFound)
+        {
+        return;
+        }
+    
+    TTextureEntry& te = iData->iTextures[index];
+    if (te.iRefCount >0)
+        {
+        te.iRefCount--;        
+        }
+    if (!te.iRefCount)
+        {
+        // trigger texture cleanup when 
+        // reference count hits zero
+        StartGarbageCollect();
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+TInt CAlfTextureManager::GarbageCollect(TAny* aPtr)
+    {
+    CAlfTextureManager* tm = ((CAlfTextureManager*)(aPtr));
+	RArray<TTextureEntry>& textures = tm->iData->iTextures;	
+    // Cleanup all textures which have refcount 0
+    TInt count = textures.Count()-1;
+    for (int index = count; index >=0; index--)
+        {
+        TTextureEntry& te = textures[index];
+        // delete only textures that have enabled refcounting
+        if (te.iTexture->RefCountingEnabled() && !te.iRefCount)
+            {
+            TInt action = te.iTexture->RefCountingAction();
+            switch (action)
+                {
+                case CAlfTexture::ERefCountingActionUnload:
+                    {
+                    // Unload, but mark as released from ref counting 
+                    TInt releaseFlags = te.iTexture->ReleaseFlags();
+                    tm->UnloadTexture(te.iId);    
+                    releaseFlags |= CAlfTexture::EReleaseFromRefCounting;
+                    te.iTexture->SetReleaseFlags(releaseFlags);
+                    break;
+                    }
+                case CAlfTexture::ERefCountingActionDelete:
+                    {
+                    delete te.iTexture;
+                    te.iTexture = NULL;
+                    break;        
+                    }                    
+                default:
+                    {
+                    // Do nothing
+                    break;    
+                    }                                        
+                }            
+            }
+        }
+    return EFalse;
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void CAlfTextureManager::StartGarbageCollect()
+    {
+    CIdle* doombringer = iData->iDoomBringer;
+    // check if garbagecollecting is already in progress
+    // -> if so, just return
+    if (doombringer->IsActive())
+        {
+        return;
+        }
+    doombringer->Start(TCallBack(GarbageCollect, this));
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void CAlfTextureManager::RemoveFlags(TAlfTextureFlags& aFlags, TInt aFlagsToBeRemoved)
+    {
+    ((TInt&)aFlags) &= ~aFlagsToBeRemoved;      
+    }
+    
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void CAlfTextureManager::SetFlags(TAlfTextureFlags& aFlags, TInt aFlagsToBeSet)
+    {
+    ((TInt&)aFlags) |= aFlagsToBeSet;              
+    }
+