uiacceltk/hitchcock/coretoolkit/src/HuiTextureManager.cpp
changeset 0 15bf7259bb7c
child 8 10534483575f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uiacceltk/hitchcock/coretoolkit/src/HuiTextureManager.cpp	Tue Feb 02 07:56:43 2010 +0200
@@ -0,0 +1,2505 @@
+/*
+* Copyright (c) 2006-2007 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:   Implementation of CHuiTextureManager, texture objects loading 
+*                and management.
+*
+*/
+
+
+
+#include <eikenv.h>
+#include <eikappui.h>
+#include <eikapp.h>
+
+#include "uiacceltk/HuiTextureManager.h"  // Class definition
+#include "uiacceltk/HuiTextureProcessor.h"
+#include "HuiRenderPlugin.h"
+#include "uiacceltk/HuiEnv.h"
+#include "uiacceltk/HuiTexture.h"
+#include "uiacceltk/HuiFont.h"
+#include "uiacceltk/HuiUtil.h"
+#include "uiacceltk/HuiPanic.h"
+#include "uiacceltk/HuiDisplay.h"
+#include "huitextureanimationstate.h"
+
+/**
+ * Granularity of CHuiTextureManager::iAnimations and 
+ * CHuiTextureManager::iAnimatedTextureGroupItems arrays.
+ */
+const TInt KHuiAnimationsGranularity = 4;
+
+EXPORT_C MHuiBitmapProvider::~MHuiBitmapProvider()
+    {
+    }
+
+EXPORT_C CHuiTextureManager::CHuiTextureManager(CHuiEnv& aEnv)
+        : CActive(EPriorityHigh),
+        iEnv(aEnv), iState(EIdle), iReleaseState(ENormal), iFS(CHuiStatic::FsSession()),
+        iAnimatedTextureGroupItems( KHuiAnimationsGranularity ),
+        iAnimations( KHuiAnimationsGranularity ),
+        iEnableTexMemCalculation( EFalse )  //Texture memory calculation is disabled by default
+    {}
+
+
+EXPORT_C void CHuiTextureManager::BaseConstructL()
+    {
+    iEnv.SetTextureManager(*this);
+
+    SetImagePathL(_L(""));
+
+    // Create a small initial bitmaps for decoder output.
+    iBitmap = new (ELeave) CFbsBitmap();
+    User::LeaveIfError( iBitmap->Create(TSize(4, 4), EColor64K) );
+    iMaskBitmap = new (ELeave) CFbsBitmap();
+    User::LeaveIfError( iMaskBitmap->Create(TSize(4, 4), EGray256) );
+
+    // Create blank texture
+    iBlankTexture = CHuiStatic::Renderer().CreateTextureL();
+    iBlankTexture->SetImageFileNameL(_L("blank"));
+
+    CActiveScheduler::Add(this);
+    
+    // Enabling logging will cause diagnostics and debugging messages to be
+    // printed to a file.
+    CHuiStatic::EnableLogging(EFalse);
+    }
+
+
+EXPORT_C CHuiTextureManager::~CHuiTextureManager()
+    {
+    Cancel();
+
+    delete iAnimationWithoutGroup;
+    iAnimatedTextureGroupItems.Close();
+    iAnimations.ResetAndDestroy();
+    iAnimations.Close();
+
+    // Delete the texture processor.
+    delete iProcessor;
+
+    // Clear any remaining entries in the load queue.
+    for(TInt i = 0; i < iLoadQueue.Count(); ++i)
+        {
+        delete iLoadQueue[i].iDecoder;
+        iLoadQueue[i].iDecoder = 0;
+        }
+    iLoadQueue.Reset();
+
+    delete iBlankTexture;
+
+    // Remove all texture entries (from last to first -order)
+    /*while (iTextures.Count()>0)*/
+    for(TInt i = iTextures.Count()-1; i >= 0; --i)
+        {
+        CTextureEntry * te = iTextures[i];
+        
+        if (te->iTexture)
+            {
+            delete te->iTexture;
+            }
+        else
+            {
+            // This texture was defined but never loaded.
+            HUI_DEBUG2(_L("CHuiTextureManager::~CHuiTextureManager() - Notice, texture id %i (\"%S\") was never loaded!"), te->iId, te->iFileName);
+            }
+        }
+        
+    iTextures.ResetAndDestroy();
+    iStateObservers.Close();
+    iLoadObservers.Close();
+    iAnimatedTextures.Close();
+    iTextureAutoSizeObservers.Close();
+
+    delete iBitmap;
+    delete iMaskBitmap;
+    delete iImagePath;
+    }
+
+
+EXPORT_C CHuiEnv& CHuiTextureManager::Env()
+    {
+    return iEnv;
+    }
+
+
+EXPORT_C CHuiTexture* CHuiTextureManager::Texture(TInt aId)
+    {
+    TInt index = CheckTexture(aId);
+    if(index == -1)
+        {
+        HUI_DEBUG1(_L("CHuiTextureManager::Texture() - Texture id %i not found! Returning blank."), aId);
+        // NOTE: there is a danger of editing the blank texture
+        // instead of the real texture..
+        return &BlankTexture();
+        }
+    CHuiTexture * texture = iTextures[index]->iTexture;
+    if(texture)
+        {
+        return texture;
+        }
+    else
+        {
+        HUI_ASSERT(EFalse); // texture exists but is not loaded! (defined but not loaded)
+        return &BlankTexture();
+        }
+    }
+
+
+EXPORT_C const CHuiTexture* CHuiTextureManager::Texture(TInt aId) const
+    {
+    TInt id = CheckTexture(aId);
+    if(id == -1)
+        {
+        return &BlankTexture();
+        }
+    const CHuiTexture * texture = iTextures[id]->iTexture;
+    if(texture)
+        {
+        return texture;
+        }
+    else
+        {
+        HUI_ASSERT(EFalse); // texture exists but is not loaded! (defined but not loaded)
+        return &BlankTexture();
+        }
+    }
+
+
+EXPORT_C CHuiTexture* CHuiTextureManager::TextureL(TInt aId)
+    {
+    // try to get the index for the texture id
+    TInt index = CheckTexture(aId);
+    if(index != -1)
+        {
+        // If the texture has content and a filename, we can do a load-on-demand.       
+        if(!iTextures[index]->iTexture->HasContent() && iTextures[index]->iFileName)
+            {
+            // we don't want to return textures without content
+            // so load-on-demand      
+                    
+            // texture has an entry but the
+            // actual texture object has not been loaded yet
+
+            // we can load the texture if there's a filename
+            // available for this id
+            return &LoadTextureL(aId);
+            }
+            
+        // texture found  
+        return iTextures[index]->iTexture;
+        }
+
+    User::Leave(KErrNotFound);
+    return NULL; // never
+    }
+
+
+EXPORT_C void CHuiTextureManager::SetImagePathL(const TDesC& aPath)
+    {
+    delete iImagePath;
+    iImagePath = NULL;
+
+    TParsePtrC parse(aPath);
+    CEikonEnv* coe = CEikonEnv::Static();
+    if (aPath.Length() && !parse.DrivePresent() && coe && coe->EikAppUi() && coe->EikAppUi()->Application())
+        {
+        iImagePath = HBufC::NewL(aPath.Size()+2); // two extra characters for drive
+        TPtr ptr = iImagePath->Des();
+        ptr.Append(coe->EikAppUi()->Application()->AppFullName().Left(2));
+        ptr.Append(aPath);
+        }
+    else
+        {
+        iImagePath = aPath.AllocL();        
+        }
+    }
+
+EXPORT_C const TDesC& CHuiTextureManager::ImagePath() const
+    {
+    return *iImagePath;
+    }
+
+
+EXPORT_C const CHuiTexture& CHuiTextureManager::BlankTexture() const
+    {
+    HUI_ASSERT(iBlankTexture!=NULL); // this MUST have a valid pointer otherwise access violation will follow..
+    return *iBlankTexture;
+    }
+
+
+EXPORT_C CHuiTexture& CHuiTextureManager::BlankTexture()
+    {
+    HUI_ASSERT(iBlankTexture!=NULL); // this MUST have a valid pointer otherwise access violation will follow..
+    return *iBlankTexture;
+    }
+
+
+EXPORT_C TBool CHuiTextureManager::SetTextureId(CHuiTexture* aTexture, TInt aId)
+    {
+    
+    if(!aTexture)
+        {
+        // Cannot set texture ID for null texture.
+        return EFalse;
+        }
+    
+    // Iterate through all the managed textures to find the one we
+    // are interested in, and then set its texture ID.
+    for(TInt i = 0; i < iTextures.Count(); ++i)
+        {
+        if(iTextures[i]->iTexture == aTexture)
+            {
+            // Texture was found in the list, so set the new identifier.
+            iTextures[i]->iId = aId;
+            return ETrue;
+            }
+        }
+
+    // Texture was not found in the manager's list.
+    return EFalse;
+    }
+
+EXPORT_C TBool CHuiTextureManager::IsLoaded(const CHuiTexture * texture) const
+    {
+    if(texture != NULL && texture->HasContent() && !IsInLoadQueue(texture))
+        {
+        return ETrue;
+        }
+    return EFalse;
+    }
+
+
+EXPORT_C TBool CHuiTextureManager::IsLoaded(const TDesC& aImageName, const TInt aFrameNumber) const
+    {
+    TFileName fileName = *iImagePath;
+    fileName.Append(aImageName);
+    TInt index = CheckTexture(fileName, aFrameNumber);
+    if(index < 0)
+        {
+        HUI_DEBUG1(_L("CHuiTextureManager::IsLoaded() - Texture \"%S\" was not found. Assuming not loaded."), &aImageName);
+        return EFalse;
+        }
+    return IsLoaded(iTextures[index]->iTexture);
+    }
+
+
+EXPORT_C TBool CHuiTextureManager::IsLoaded(TInt aId) const
+    {
+    HUI_ASSERT(aId!=0);
+    TInt index = CheckTexture(aId);
+    if(index < 0)
+        {
+        HUI_DEBUG1(_L("CHuiTextureManager::IsLoaded() - Texture having id %i was not found. Assuming not loaded."), aId);
+        return EFalse;
+        }
+    return IsLoaded(iTextures[index]->iTexture);
+    }
+
+
+EXPORT_C void CHuiTextureManager::AppendTextureL(CHuiTexture* aTexture, TInt aId)
+    {
+    // Panic if the manager is currently restoring or releasing textures.
+    if(iReleaseState == EReleasing)
+        {
+        THuiPanic::Panic(THuiPanic::ETextureManagerTextureDestroyedDuringRelease);
+        }
+    else if(iReleaseState == ERestoring)
+        {
+        THuiPanic::Panic(THuiPanic::ETextureManagerTextureConstructedDuringRestore);
+        }
+    else
+        {
+        // for PC lint
+        }
+
+    HUI_ASSERT(aTexture != NULL);
+
+#ifdef _DEBUG
+    // Look for an existing entry for this.
+    // There must not be any duplicates present!
+    for(TInt i = 0; i < iTextures.Count(); ++i)
+        {
+        if(iTextures[i]->iTexture == aTexture)
+            {
+            User::Leave(KErrAlreadyExists);
+            }
+        }
+#endif
+
+    // Create a new texture entry
+    CTextureEntry * te = new (ELeave) CTextureEntry(aId, aTexture);
+    CleanupStack::PushL(te);
+    // Add the new entry to the list of new textures
+    User::LeaveIfError( iTextures.Append(te) );
+    CleanupStack::Pop(); // pop the texture entry
+
+    HUI_DEBUG1(_L("CHuiTextureManager::AppendTextureL() - Registered texture 0x%x."), aTexture);
+    }
+
+
+EXPORT_C void CHuiTextureManager::RemoveTexture(CHuiTexture& aTexture)
+    {
+    // Panic if the manager is currently restoring or releasing textures.
+    if(iReleaseState == EReleasing)
+        {
+        THuiPanic::Panic(THuiPanic::ETextureManagerTextureDestroyedDuringRelease);
+        }
+    else if(iReleaseState == ERestoring)
+        {
+        THuiPanic::Panic(THuiPanic::ETextureManagerTextureDestroyedDuringRestore);
+        }
+    else
+        {
+        // for PC lint
+        }
+    
+    // Cancel loading of the texture to be removed.
+    CancelLoadingOfTexture(aTexture);
+
+    // Manual sequential search.
+    for(TInt index = iTextures.Count() - 1; index >= 0; --index)
+        {
+        if(iTextures[index]->iTexture == &aTexture)
+            {
+            CTextureEntry * entry = iTextures[index];
+            if ( entry->iFileName )
+                {
+                HUI_DEBUG4(_L("CHuiTextureManager::RemoveTexture() - Removing texture 0x%x  (Name: \"%S\", Id: %i). Number of textures after deleting: %i."),
+                              &aTexture, &(aTexture.ImageFileName()), entry->iId, iTextures.Count()-1);                     
+                }
+            else
+                {
+                HUI_DEBUG3(_L("CHuiTextureManager::RemoveTexture() - Removing unnamed texture 0x%x  ( Id: %i). Number of textures after deleting: %i."),
+                              &aTexture, entry->iId, iTextures.Count()-1);                     
+                }
+
+            iTextures.Remove(index);
+            delete entry;
+            return;
+            }
+        }
+
+    HUI_DEBUG2(_L("CHuiTextureManager::RemoveTexture() - Error! Failed to remove texture 0x%x \"%S\". Texture not found."), &aTexture, &aTexture.ImageFileName());
+    // this is a programming error.. texturemanager is aware of all textures in the toolkit!!
+    #ifdef _DEBUG
+    HUI_PANIC(THuiPanic::ETextureNotValid)
+    #endif
+    }
+
+
+EXPORT_C CHuiTexture& CHuiTextureManager::LoadTextureL(
+    const TDesC& aImageName,
+    THuiTextureUploadFlags aFlags,
+    TInt aId,
+    TInt aFrameNumber)
+    {
+    return LoadTextureL(aImageName, TSize(0, 0), aFlags, aId, aFrameNumber);
+    }
+
+
+EXPORT_C CHuiTexture& CHuiTextureManager::LoadTextureL(const TInt aId,
+                                       const TSize& aTextureMaxSize,
+                                       THuiTextureUploadFlags aFlags)
+    {
+    return LoadTextureL(KNullDesC(), aTextureMaxSize, aFlags, aId);
+    }
+
+
+EXPORT_C CHuiTexture& CHuiTextureManager::LoadTextureL(const TDesC& aImageName,
+        const TSize& aTextureMaxSize,
+        THuiTextureUploadFlags aFlags,
+        TInt aId,
+        TInt aFrameNumber)
+    {
+    // Ignore EHuiTextureFlagAllowDirectBitmapUsage flag
+   	aFlags = (THuiTextureUploadFlags)(aFlags & ~EHuiTextureFlagAllowDirectBitmapUsage);		
+    
+    TFileName fileName;
+
+    CTextureEntry * entry = NULL;  
+
+    // If the name is invalid, and there was no filename available
+    // based on id, return a dummy texture.
+    if((aImageName.Length() == 0) && (aId == 0))
+        {
+        HUI_DEBUG(_L("CHuiTextureManager::LoadTextureL() - No filename or id provided for texture. Returning blank."));
+        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
+    // a nonzero id has been passed, we
+    // can assume that there's a predefined name available
+    if((aImageName.Length() == 0) && (aId != 0))
+       {
+        // search for a texture filename based on the id.
+        TInt index = CheckTexture(aId);
+        if(index >=0)
+            {
+            entry = iTextures[index];
+            HUI_ASSERT(entry->iFileName);
+            fileName = *(entry->iFileName);
+            }
+        else
+            {
+            HUI_DEBUG1(_L("CHuiTextureManager::LoadTextureL() - Unable to load texture without filename or pre-defined id (filename definition for id %i not found)."), aId);
+            User::Leave(KErrNotFound);
+            }
+       }
+
+    // a guarantee that there's a filename available
+    HUI_ASSERT(	fileName.Length()>0 );
+
+    // Reuse pre-existing entries:
+    // try first finding an entry based on id
+    if(entry == NULL && aId != 0)
+        {
+        TInt previouslyLoadedIndex = CheckTexture(aId);
+        if (previouslyLoadedIndex >= 0)
+            {
+            entry = iTextures[previouslyLoadedIndex];
+            }
+        }
+
+    // We are not allowed to change required texture id so we can't 
+    // try again with the filename unless user does not care about id
+    if(aId == 0 && entry == NULL)
+        {
+        TInt previouslyLoadedIndex = CheckTexture(fileName, aFrameNumber);
+        if (previouslyLoadedIndex >= 0)
+            {
+            entry = iTextures[previouslyLoadedIndex];
+            }
+        }
+
+    // create new texture entry if there's not one
+    // available at this point
+    if(entry == NULL)
+        {
+        HUI_DEBUG(_L("CHuiTextureManager::LoadTextureL() - Creating new texture."));
+
+        // in the case that a previously loaded slot was not found,
+        // create a new texture, which automatically registers a new
+        // texture entry in the iTextures list.
+        CHuiTexture::NewL();
+
+        // we assume that the newest entry was added the last
+        entry = iTextures[iTextures.Count()-1];
+
+        entry->iId = aId;
+        }
+    else
+        {
+        // We have a valid texture name and ID.
+        HUI_ASSERT(entry->iTexture);
+      
+        // we have a pre-existing texture,
+        // but check that the texture is loaded ok, we can also
+        // return unloaded textures that are in the load queue
+        if (entry->iTexture->HasContent() || IsInLoadQueue(entry->iTexture))
+            {
+            // a previous texture exists!
+            HUI_ASSERT(entry->iTexture!=NULL);            
+            
+            HUI_DEBUG3(_L("CHuiTextureManager::LoadTextureL() - Reusing texture 0x%x (\"%S\", id: %i) No need to load."),
+                      entry->iTexture, &entry->iTexture->ImageFileName(), entry->iId);
+            return *(entry->iTexture);
+            }
+        }
+
+    HUI_ASSERT(entry!=NULL);
+    HUI_ASSERT(entry->iTexture!=NULL);
+       
+    // replace filename
+    // File names are relative to the image path.
+    entry->SetFileName(fileName);
+    entry->iTexture->SetImageFileNameL(fileName);
+    entry->iTexture->EnableShadow((aFlags & EHuiTextureUploadFlagGenerateShadow) != 0);
+    entry->iFrameNumber = aFrameNumber;
+
+    // add a content observer so that we can reload the texture
+    // during restoring
+    if (entry->iTexture->iContentObservers.Count()==0)
+        {
+        HUI_DEBUG2(_L("CHuiTextureManager::LoadTextureL() - Adding content observer 0x%x for texture 0x%x."),  entry, entry->iTexture);
+        entry->iTexture->iContentObservers.AppendL(*entry);
+        }
+
+    HUI_DEBUG3(_L("CHuiTextureManager::LoadTextureL() - Enqueuing texture 0x%x (Name: \"%S\", Id: %i)."),
+               entry->iTexture, &entry->iTexture->ImageFileName(), entry->iId);
+
+    // Prepare for loading by creating a load queue entry.
+    SLoadQueueEntry loadqentry;
+    Mem::FillZ(&loadqentry, sizeof(loadqentry));
+    loadqentry.iLoading = entry;
+    entry->iMaxTextureSize = aTextureMaxSize;
+    entry->iFlags = aFlags;
+
+    // Textures are loaded one at a time, in the order they were requested.
+    User::LeaveIfError( iLoadQueue.Append(loadqentry) );
+
+    // Start loading images.
+    if(iState == EIdle)
+        {
+        StartLoading();
+        
+        if(iState == ELoading)
+            {
+            // Notify observers that loading has started.
+            NotifyStateChange();
+            }
+        }
+
+    return *entry->iTexture;
+    }
+
+EXPORT_C CHuiTexture&
+CHuiTextureManager::CreateTextureL(TInt aId,
+                                   MHuiBitmapProvider* aBitmapProvider,
+                                   THuiTextureUploadFlags aFlags)
+    {
+    CHuiTexture* tex;
+    
+    // can't create texture without id (or filename)
+    if (aId==0)
+        {
+        HUI_DEBUG(_L("CHuiTextureManager::CreateTextureL() - ERROR! Can't create texture without valid id. Please use nonzero ids."));
+        User::Leave(KErrArgument);
+        }
+
+    // Provide an already created texture if such exists.
+    CHuiTexture* texture = NULL;
+    TRAPD(err, texture = TextureL(aId));
+    if(err == KErrNone)
+        {
+        ASSERT( texture );
+
+        // Update flags here because there is no other way to change flags. 
+        CTextureEntry* entry = TextureEntry(CheckTexture(aId));
+        if (entry)
+            {
+            entry->iFlags = aFlags;        
+            }
+        
+        return *texture;
+        }
+
+    // Assert that the bitmap provider object exists.
+    HUI_ASSERT(aBitmapProvider != NULL);
+
+    HUI_DEBUG1(_L("CHuiTextureManager::CreateTextureL() - Requesting bitmap content from provider 0x%x .."), aBitmapProvider);
+
+    // Initialize bitmap and mask bitmap pointers to zero.
+    CFbsBitmap* bitmap = NULL;
+    CFbsBitmap* maskBitmap = NULL;
+
+    // Call the bitmapProvider method to load the bitmaps.
+    ASSERT( aBitmapProvider );
+    aBitmapProvider->ProvideBitmapL(aId, bitmap, maskBitmap);
+
+    // Error if main bitmap could not be loaded
+    User::LeaveIfNull(bitmap);
+    CleanupStack::PushL(bitmap);
+    
+    UpdateFlags(*bitmap, maskBitmap, aFlags);
+    
+    if (maskBitmap)
+        {
+        // A mask was provided, so pass this to texture creation.
+        CleanupStack::PushL(maskBitmap);
+        // create textures right away for these bitmaps
+        tex = &CreateTextureL(*bitmap, maskBitmap, aFlags, aId);
+        // get rid of bitmap and mask
+        CleanupStack::PopAndDestroy(maskBitmap);
+        }
+    else
+        {
+        // No mask, so create texture without one.
+        // create textures right away for these bitmaps
+        tex = &CreateTextureL(*bitmap, NULL, aFlags, aId);            
+        }
+        
+    CleanupStack::PopAndDestroy(bitmap);        
+
+    // store the provider with the texture for Restore operations
+    HUI_ASSERT(CheckTexture(aId)>=0);
+    CTextureEntry * entry = TextureEntry(CheckTexture(aId));
+    entry->iBitmapProvider = aBitmapProvider;
+    entry->iFlags = aFlags;
+
+    HUI_ASSERT(entry->iTexture);
+
+    // add a content observer so that we can reload the texture
+    // during restoring
+    if (entry->iTexture->iContentObservers.Count()==0)
+        {
+        HUI_DEBUG2(_L("CHuiTextureManager::CreateTextureL() - Adding content observer 0x%x for texture 0x%x."),  entry, entry->iTexture);
+        entry->iTexture->iContentObservers.AppendL(*entry);
+        }
+
+    return *tex;
+    }
+
+EXPORT_C CHuiTexture& CHuiTextureManager::CreateTextureL(CFbsBitmap& aBitmap,
+                                   const CFbsBitmap* aMask,
+                                   THuiTextureUploadFlags aFlags,
+                                   TInt aId)
+    {
+    TBool hasAlpha = (aMask != NULL);
+    TSize bitmapSize = aBitmap.SizeInPixels();
+
+    CHuiStatic::Tic(2);
+
+    // Verify that the bitmap size is same as the mask size.
+    if(hasAlpha && (bitmapSize != aMask->SizeInPixels()))
+        {
+        HUI_DEBUG(_L("CHuiTextureManager::CreateTextureL() - Bitmap size is not compatible with the mask bitmap!"));
+        User::Leave(KErrArgument);
+        }
+
+    // Leave if the name and the id are empty.
+    if(aId==0)
+        {
+        HUI_DEBUG(_L("CHuiTextureManager::CreateTextureL() - ERROR! Can't create texture without valid id or name."));
+        User::Leave(KErrArgument);
+        }
+
+    // If the texture has already been loaded, just return a reference.
+    TInt previouslyLoadedIndex = CheckTexture(aId);
+
+    if((previouslyLoadedIndex != -1) && IsLoaded(aId))
+        {
+        CHuiTexture * tex = iTextures[previouslyLoadedIndex]->iTexture;
+        HUI_ASSERT(tex);
+        HUI_DEBUG3(_L("CHuiTextureManager::CreateTextureL() - Reusing previously loaded texture (0x%x, \"%S\", id: %i)."),
+                     tex, &tex->ImageFileName(), iTextures[previouslyLoadedIndex]->iId);
+        return *tex;
+        }
+
+    // create and append to the textures list (automatic)
+    CHuiTexture* texture = CHuiTexture::NewL();
+    // Set texture name
+    texture->SetImageFileNameL(_L(""));
+    // Set the texture id.
+    HUI_ASSERT(TextureEntryCount()>0);
+    CTextureEntry * te = TextureEntry(TextureEntryCount()-1);
+    te->iId = aId;
+
+    HUI_DEBUG3(_L("CHuiTextureManager::CreateTextureL() - Created new texture 0x%x (\"%S\", id: %i)."),
+                     texture, &texture->ImageFileName(), aId);
+
+    // Let the texture know its size as soon as possible.
+    texture->SetSize(bitmapSize);
+
+    HUI_DEBUG6(_L("CHuiTextureManager::CreateTextureL() - Image for texture 0x%x is \"%S\": w=%i, h=%i, dm=%i, mdm=%i"),
+               texture,
+               &texture->ImageFileName(),
+               bitmapSize.iWidth,
+               bitmapSize.iHeight,
+               aBitmap.DisplayMode(),
+               (aMask != NULL ? aMask->DisplayMode() : ENone));
+
+    // Enable texture shadow.
+    texture->EnableShadow((aFlags & EHuiTextureUploadFlagGenerateShadow) != 0);
+
+	if (bitmapSize.iWidth != 0 && bitmapSize.iHeight != 0)
+	    {
+    	if (aFlags & EHuiTextureFlagAllowDirectBitmapUsage) 
+    		{
+       		texture->UploadDirectL(aBitmap, aMask, aFlags);		
+    		}
+    	else 
+    		{
+       		texture->UploadL(aBitmap, aMask, aFlags);		
+    		}
+
+	    }
+
+    HUI_DEBUG1(_L("CHuiTextureManager::CreateTextureL() - Upload for texture 0x%x done, notifying possible observers.."), texture);
+
+    // Store bits per pixel info to calculate texture memory usage
+    te->iBitDepth = TDisplayModeUtils::NumDisplayModeBitsPerPixel( aBitmap.DisplayMode() );
+    if( aMask )
+    	{
+    	 te->iBitDepth =  te->iBitDepth + TDisplayModeUtils::NumDisplayModeBitsPerPixel( aMask->DisplayMode() );
+    	}
+
+    // Notify the observers
+    NotifyTextureLoaded(*texture, aId, KErrNone);
+
+    HUI_DEBUG2(_L("CHuiTextureManager::CreateTextureL() - Finished with texture 0x%x, toc: %f seconds"), texture, CHuiStatic::Toc(2));
+    return *texture;
+    }
+
+
+EXPORT_C void CHuiTextureManager::UpdateTextureFromBitmapL(TInt aId, MHuiBitmapProvider* aBitmapProvider)
+    {
+    TInt previouslyLoadedIndex = CheckTexture(aId);
+    if (previouslyLoadedIndex == KErrNotFound)
+    	{
+    	User::Leave(KErrNotFound);
+    	}
+
+	// Unload
+	
+    UnloadTexture(aId);      
+
+	// Upload with the new content
+	
+	CTextureEntry* entry = iTextures[previouslyLoadedIndex];
+    
+    HUI_DEBUG1(_L("CHuiTextureManager::UpdateTextureFromBitmapL() - Requesting bitmap content from provider 0x%x .."), aBitmapProvider);
+
+    // Initialize bitmap and mask bitmap pointers to zero.
+    CFbsBitmap* bitmap = NULL;
+    CFbsBitmap* maskBitmap = NULL;
+
+    // Call the bitmapProvider method to load the bitmaps.
+    if (!aBitmapProvider)
+    	{
+    	aBitmapProvider = entry->iBitmapProvider;
+    	}
+    if (aBitmapProvider)
+    	{
+   	    aBitmapProvider->ProvideBitmapL(aId, bitmap, maskBitmap);
+    	}
+
+    // Error if main bitmap could not be loaded
+    if (!bitmap)
+    	{
+    	User::Leave(KErrNotFound);
+    	}
+    CleanupStack::PushL(bitmap);
+    
+    if (maskBitmap)
+        {
+        CleanupStack::PushL(maskBitmap);
+        }
+
+    TBool hasAlpha = (maskBitmap != NULL);
+    TSize bitmapSize = bitmap->SizeInPixels();
+
+    CHuiStatic::Tic(2);
+
+    // Verify that the bitmap size is same as the mask size.
+    if(hasAlpha && (bitmapSize != maskBitmap->SizeInPixels()))
+        {
+        HUI_DEBUG(_L("CHuiTextureManager::UpdateTextureFromBitmapL() - Bitmap size is not compatible with the mask bitmap!"));
+        User::Leave(KErrArgument);
+        }
+
+    CHuiTexture* texture = entry->iTexture;
+    // Set texture name
+    texture->SetImageFileNameL(_L(""));
+
+    HUI_DEBUG6(_L("CHuiTextureManager::UpdateTextureFromBitmapL() - Image for texture 0x%x is \"%S\": w=%i, h=%i, dm=%i, mdm=%i"),
+               texture,
+               &texture->ImageFileName(),
+               bitmapSize.iWidth,
+               bitmapSize.iHeight,
+               bitmap->DisplayMode(),
+               (maskBitmap != NULL ? maskBitmap->DisplayMode() : ENone));
+
+    UpdateFlags(*bitmap, maskBitmap, entry->iFlags);
+    
+	if (bitmapSize.iWidth != 0 && bitmapSize.iHeight != 0)
+	    {
+    	if (entry->iFlags & EHuiTextureFlagAllowDirectBitmapUsage) 
+    		{
+       		texture->UploadDirectL(*bitmap, maskBitmap, entry->iFlags);		
+    		}
+    	else 
+    		{
+       		texture->UploadL(*bitmap, maskBitmap, entry->iFlags);		
+    		}
+	    }
+    HUI_DEBUG2(_L("CHuiTextureManager::UpdateTextureFromBitmapL() - Finished with texture 0x%x, toc: %f seconds"), texture, CHuiStatic::Toc(2));
+     
+    // Store bits per pixel info to calculate texture memory usage
+    entry->iBitDepth = TDisplayModeUtils::NumDisplayModeBitsPerPixel( bitmap->DisplayMode() );
+    if (maskBitmap)
+    	{
+    	entry->iBitDepth = entry->iBitDepth + TDisplayModeUtils::NumDisplayModeBitsPerPixel( maskBitmap->DisplayMode() );
+    	}
+    
+    if (maskBitmap)    
+    	{
+    	CleanupStack::PopAndDestroy(maskBitmap);   	
+    	}
+    	
+    CleanupStack::PopAndDestroy(bitmap);        
+    
+    // Store provider in case it has changed
+    if (aBitmapProvider)
+    	{
+    	entry->iBitmapProvider = aBitmapProvider;
+    	}
+   }
+    
+ 
+void CHuiTextureManager::UpdateFlags(const CFbsBitmap& aBitmap, const CFbsBitmap* aMaskBitmap, 
+	                                 THuiTextureUploadFlags& aFlags)
+	{
+	// Update EHuiTextureFlagUseBitmapDirectly flag if needed
+	
+	if (aFlags & EHuiTextureFlagAllowDirectBitmapUsage)
+		{
+		TBool isDirectBitmapOk = !aBitmap.IsCompressedInRAM() && 
+		                     (!aMaskBitmap || !aMaskBitmap->IsCompressedInRAM());
+		// Check texture formats from the display
+		// Note: if there is no display the check cannot be done
+		if (isDirectBitmapOk)
+			{
+			isDirectBitmapOk = EFalse;		
+			if (CHuiStatic::Env().DisplayCount() > 0)
+				{
+				RPointerArray<CHuiDisplay::CTextureBitmapFormat> formatArray;
+    			TInt err = CHuiStatic::Env().PrimaryDisplay().GetPreferredTextureFormats(formatArray);
+    			if (!err)
+    				{
+    				for (TInt i = 0; i < formatArray.Count(); i++)
+    					{
+   			   			if ((aBitmap.DisplayMode() == formatArray[i]->iImage) &&
+   			   				((!aMaskBitmap) || (aMaskBitmap->DisplayMode() == formatArray[i]->iMask)))
+   			   				{
+   			   				isDirectBitmapOk = ETrue;
+   			   				}
+    					}
+					}
+				formatArray.ResetAndDestroy();
+				}
+			}
+		// Update	
+		if (!isDirectBitmapOk)
+			{
+   			aFlags = (THuiTextureUploadFlags)(aFlags & ~EHuiTextureFlagAllowDirectBitmapUsage);		
+			}
+		}
+	}
+
+    
+RFs& CHuiTextureManager::FsSession() const
+    {
+    return iFS;
+    }
+
+
+EXPORT_C void CHuiTextureManager::PrependImagePath(TDes& aFileName) const
+    {
+    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(*iImagePath) == KErrNotFound)
+        {
+        buf = *iImagePath;
+        buf.Append(aFileName);
+        aFileName = buf;
+        }
+    }
+
+
+EXPORT_C void CHuiTextureManager::UnloadTexture(const TDesC& aImageName, const TInt aFrameNumber)
+    {
+    TFileName fileName = aImageName;
+    PrependImagePath(fileName);
+    TInt index = CheckTexture(fileName, aFrameNumber);
+    if (index >= 0)
+        {
+        HUI_DEBUG2(_L("CHuiTextureManager::UnloadTexture() - Unloading texture 0x%x (id: %i)."),
+                   iTextures[index]->iTexture,
+                   iTextures[index]->iId);
+        DoUnload(index);
+        return;
+        }
+    HUI_DEBUG1(_L("CHuiTextureManager::UnloadTexture() - Warning! Unable to unload \"%S\" - No such texture(s) found. Already unloaded?"), &fileName);
+    }
+
+
+EXPORT_C void CHuiTextureManager::UnloadTexture(TInt aId)
+    {
+    TInt index = CheckTexture(aId);
+    if (index >= 0)
+        {
+        HUI_DEBUG2(_L("CHuiTextureManager::UnloadTexture() - Unloading texture 0x%x (id: %i)."),
+                   iTextures[index]->iTexture,
+                   iTextures[index]->iId);
+        DoUnload(index);
+        return;
+        }
+    HUI_DEBUG1(_L("CHuiTextureManager::UnloadTexture() - Warning! Unable to unload id %i. No texture with such id. Already unloaded?"), aId);
+    }
+
+
+EXPORT_C void CHuiTextureManager::DefineFileNameL(TInt aId,
+                                                  const TDesC& aImageName)
+    {
+    if (aId==0)
+        {
+        HUI_DEBUG(_L("CHuiTextureManager::DefineFileNameL() - ERROR! Defining filename for texture id 0 is not allowed. Please use nonzero ids."));
+        User::Leave(KErrArgument); // can't specify filename for "no id"
+        }
+
+    // Look for an existing entry for the id.
+    for(TInt i = 0; i < iTextures.Count(); ++i)
+        {
+        if(iTextures[i]->iId == aId)
+            {
+            // Just set the new image name.
+            iTextures[i]->SetFileName(aImageName);
+            return;
+            }
+        }
+
+    // create a new texture, which automatically registers a new
+    // texture entry in the iTextures list.
+    CHuiTexture::NewL();
+    // we assume that the newest entry was added last
+    CTextureEntry* entry = iTextures[iTextures.Count()-1];
+    entry->iId = aId;
+    entry->SetFileName(aImageName);
+    }
+
+
+EXPORT_C TInt CHuiTextureManager::CheckTexture(const TDesC& aImageName, TInt aFrameNumber) const
+    {
+    if(aImageName.Length()==0)
+        {
+        // name empty, can't check
+        return -1;
+        }
+    for(TInt i = 0; i < iTextures.Count(); ++i)
+        {
+        CTextureEntry * te = iTextures[i];
+        // compare against texture manager entry filename (iFileName)
+        if((te->iFileName != NULL)
+            && (aImageName.Compare(*(te->iFileName)) == 0)
+            && te->iFrameNumber == aFrameNumber)
+            {
+            return i;
+            }
+
+        // compare against texture object imagefilename
+        if( te->iTexture 
+            && te->iTexture->ImageFileName().Compare(aImageName) == 0
+            && te->iTexture->iFrameNumber == aFrameNumber)
+            {
+            return i;
+            }
+        }
+    // not found
+    return -1;
+    }
+
+
+EXPORT_C TInt CHuiTextureManager::CheckTexture(TInt aId) const
+    {
+    if(aId == 0)
+        {
+        // id not defined, can't search
+        return -1;
+        }
+    for(TInt i = 0; i < iTextures.Count(); ++i)
+        {
+        if(iTextures[i]->iId == aId)
+            {
+            return i;
+            }
+        }
+    // not found:
+    return -1;
+    }
+
+
+TBool CHuiTextureManager::IsInLoadQueue(const CHuiTexture * texture) const
+    {
+
+    if (texture == NULL)
+        {
+        return EFalse;
+        }
+
+    // textures in the load queue are not loaded yet,
+    // the others are assumed to be loaded..
+    for(TInt i = 0; i < iLoadQueue.Count(); ++i)
+        {
+        CTextureEntry* textureEntry = iLoadQueue[i].iLoading;
+        if(textureEntry->iTexture == texture)
+            {
+            // Still in the queue.
+            return ETrue;
+            }
+        }
+    return EFalse;
+    }
+
+TBool CHuiTextureManager::IsInLoadQueue(TInt id) const
+    {
+    // textures in the load queue are not loaded yet,
+    // the others are assumed to be loaded..
+    for(TInt i = 0; i < iLoadQueue.Count(); ++i)
+        {
+        if(iLoadQueue[i].iLoading->iId == id)
+            {
+            // Still in the queue.
+            return ETrue;
+            }
+        }
+    return EFalse;
+    }
+
+
+void CHuiTextureManager::StartLoading()
+    {
+    // Start the texture load active object if we're not loading
+    if(iState == EIdle)
+        {
+        HUI_DEBUG(_L("CHuiTextureManager::StartLoading() - Starting load queue."));
+
+        // loop that finds next entry to load
+        while (1)
+            {            
+            HUI_DEBUG(_L("CHuiTextureManager::StartLoading() - Find next to be loaded."));
+            
+            // try to schedule next image for loading..
+            TRAPD(err, DoLoadNextL());
+            // ok?
+                
+            if(err != KErrNone)
+                {
+                HUI_DEBUG(_L("CHuiTextureManager::StartLoading() - Found an error."));
+                
+                HUI_ASSERT(iLoadQueue.Count()>0);
+                // remove the entry from the queue
+                SLoadQueueEntry entry = PopLoadedQueueEntry();
+                switch (err)
+                    {
+                    case KErrNoMemory:
+                        {
+                        HUI_DEBUG3( _L("CHuiTextureManager::StartLoading() - Unable to start loading \"%S\" (id %i): Out of memory. Trying to continue with %i items in the queue.."), &(entry.iLoading->iTexture->ImageFileName()), entry.iLoading->iId, iLoadQueue.Count());
+                        break;
+                        }
+                    default:
+                        {
+                        HUI_DEBUG4( _L("CHuiTextureManager::StartLoading() - Unable to start loading \"%S\" (id %i): Leave error code %i. Trying to continue with %i items in the queue.."), &(entry.iLoading->iTexture->ImageFileName()), entry.iLoading->iId, err, iLoadQueue.Count());
+                        break;
+                        }
+                    }
+                // Notify observers about the image loading error
+                NotifyTextureLoaded(*entry.iLoading->iTexture, entry.iLoading->iId, err);
+                // Image loading has been completed.
+                iState = EIdle;
+                continue;
+                }
+            else
+                {
+                HUI_DEBUG(_L("CHuiTextureManager::StartLoading() - Found next texture to load."));
+                if(iLoadQueue.Count() == 0 && iLoadQueueHadValidTexture)
+                    {
+                    // During the load loop that has passed we have succesfully started to load
+                    // at least one texture. So the state has been changed to ELoading, thus
+                    // it is now changed back to EIdle.
+                    NotifyStateChange();
+                    iLoadQueueHadValidTexture = EFalse;
+                    }
+                }
+                
+            // leave the loop if we had no trouble scheduling the next
+            // image decode
+            break;
+            }
+
+        HUI_DEBUG(_L("CHuiTextureManager::StartLoading() - Load queue started."));
+        }                     
+    }
+
+
+CHuiTextureManager::SLoadQueueEntry CHuiTextureManager::PopLoadedQueueEntry()
+    {
+    SLoadQueueEntry entry = iLoadQueue[0];
+    HUI_DEBUG2( _L("CHuiTextureManager::PopLoadedQueueEntry() - Cleaning up load queue entry for \"%S\" (id %i)."),
+                &(entry.iLoading->iTexture->ImageFileName()), entry.iLoading->iId);
+    iLoadQueue.Remove(0);
+    // Delete the decoder.
+    delete entry.iDecoder;
+    entry.iDecoder = 0;
+    return entry;
+    }
+
+
+void CHuiTextureManager::DoLoadNextL()
+    {
+	HUI_DEBUG(_L("CHuiTextureManager::DoLoadNextL() - Going into assert."));    
+    __ASSERT_ALWAYS(iState == EIdle, THuiPanic::Panic(THuiPanic::EInternal));
+    HUI_DEBUG(_L("CHuiTextureManager::DoLoadNextL() - Survived assert."));
+
+    // Any loading tasks left?
+    if(iLoadQueue.Count() == 0)
+        {
+        HUI_DEBUG(_L("CHuiTextureManager::DoLoadNextL() - No more items to load. Changing state to idle."));
+        return; // nothing else to be loaded.
+        }
+
+    // Start timing
+    CHuiStatic::Tic(2);
+
+    // Manager is now busy.
+    iState = ELoading;
+
+    HUI_DEBUG(_L("CHuiTextureManager::DoLoadNextL() - Fetching next load queue entry."));
+
+    // Fetch a load queue entry
+    SLoadQueueEntry& entry = iLoadQueue[0];
+    CHuiTexture* texture = entry.iLoading->iTexture;
+    HUI_ASSERT(texture != NULL);
+    HUI_DEBUG1(_L("CHuiTextureManager::DoLoadNext() - Starting to decode %S"), &texture->ImageFileName());
+
+    // Create a new image decoder for loading the image.
+    TFileName imageFileName = texture->ImageFileName(); // does not include image path
+    PrependImagePath(imageFileName);
+    
+    delete entry.iDecoder;
+    entry.iDecoder = NULL;
+    
+    TRAPD( err,  entry.iDecoder = CImageDecoder::FileNewL(FsSession(), imageFileName, CImageDecoder::EOptionAlwaysThread) );
+    
+    // check for errors..
+    if(err != KErrNone)
+        {
+        // Try to cancel the decoding (if possible)
+        if(entry.iDecoder)
+            {
+            entry.iDecoder->Cancel();
+            }
+        switch (err)
+            {
+            case KEComErrNoInterfaceIdentified:
+                {
+                HUI_DEBUG1( _L("CHuiTextureManager::DoLoadNext() - CImageDecoder failed to decode \"%S\". No plugin decoders were found."), &texture->ImageFileName() );
+                User::Leave(err); // re-leave with the error
+                }
+            case KErrPathNotFound:
+                {
+                HUI_DEBUG1( _L("CHuiTextureManager::DoLoadNext() - CImageDecoder failed to decode \"%S\". Path not found."), &texture->ImageFileName() );
+                User::Leave(err); // re-leave with the error
+                }
+            case KErrAccessDenied:
+            case KErrPermissionDenied:
+                {
+                HUI_DEBUG1( _L("CHuiTextureManager::DoLoadNext() - CImageDecoder failed to decode \"%S\". Access denied."), &texture->ImageFileName() );
+                User::Leave(err); // re-leave with the error
+                }
+            case KErrNotFound:
+                {
+                HUI_DEBUG1( _L("CHuiTextureManager::DoLoadNext() - CImageDecoder failed to decode \"%S\". Resource not found."), &texture->ImageFileName() );
+                User::Leave(err); // re-leave with the error
+                }
+            case KErrUnderflow:
+                {
+                HUI_DEBUG1( _L("CHuiTextureManager::DoLoadNext() - CImageDecoder failed to decode \"%S\". Not enough data in file to identify which plugin decoder to use."), &texture->ImageFileName() );
+                User::Leave(err); // re-leave with the error
+                }
+            case KErrNotSupported:
+                {
+                HUI_DEBUG1( _L("CHuiTextureManager::DoLoadNext() - CImageDecoder failed to decode \"%S\". Format not supported."), &texture->ImageFileName() );
+                User::Leave(err); // re-leave with the error
+                }
+            default:
+                {
+                HUI_DEBUG2( _L("CHuiTextureManager::DoLoadNext() - CImageDecoder failed to decode \"%S\". Unknown error (code %i)."), &texture->ImageFileName(), err );
+                User::Leave(err); // re-leave with the error
+                }
+            }
+        }
+     
+    entry.iDecoder->SetDecoderThreadPriority(EPriorityAbsoluteBackgroundNormal);
+        
+    // There is a valid texture in the load queue that we now start to load.
+    iLoadQueueHadValidTexture = ETrue;        
+        
+    // from decoder's frame info retrieve the framesize
+    const TInt frameCount = entry.iDecoder->FrameCount();
+    entry.iLoading->iFrameCount = frameCount;
+    if (frameCount && entry.iLoading->iFrameNumber>frameCount)
+        {
+        entry.iLoading->iFrameNumber = frameCount-1;
+        }
+
+    CHuiTextureAnimationState* textureAnimationState = NULL;
+    
+    TInt groupId = 0;
+    TBool foundGroup = FindGroupIdByTextureId( entry.iLoading->iId, groupId );
+    
+    if ( frameCount > 1 && NeedsAnimationState( *entry.iDecoder ) )
+        {
+        // It's animated texture which needs to be produced sequentially.
+        if ( !foundGroup )
+            {
+            HUI_DEBUG(_L("CHuiTextureManager::DoLoadNextL() - Animation: Group not found."));
+
+            if ( iAnimationWithoutGroup && 
+                 iAnimationWithoutGroup->CheckIfCanProduce( 
+                    imageFileName,
+                    entry.iLoading->iFrameNumber,
+                    frameCount ) )
+                {
+                // use iAnimationWithoutGroup
+                }
+            else
+                {
+                delete iAnimationWithoutGroup;
+                iAnimationWithoutGroup = NULL;
+                
+                iAnimationWithoutGroup = 
+                    CHuiTextureAnimationState::NewL( 
+                        0, imageFileName, frameCount );
+                }
+            textureAnimationState = iAnimationWithoutGroup;
+            }
+        else
+            {
+            HUI_DEBUG(_L("CHuiTextureManager::DoLoadNextL() - Animation: Group found."));
+            textureAnimationState = CreateAnimationStateL( 
+                groupId, imageFileName, 
+                entry.iLoading->iFrameNumber, frameCount );
+            }
+        }
+    else
+        {
+        // No need to produce sequentially.
+        if ( foundGroup )
+            {
+            RemoveAnimationState( FindAnimationState( groupId ) );
+            }
+        }
+
+    if ( textureAnimationState != iAnimationWithoutGroup )
+        {
+        delete iAnimationWithoutGroup;
+        iAnimationWithoutGroup = NULL;
+        }
+
+    const TInt frameToBeLoaded = 
+        !textureAnimationState ? 
+        entry.iLoading->iFrameNumber : 
+        textureAnimationState->GetNextFrameNumber();
+        
+    TFrameInfo frameInfo(entry.iDecoder->FrameInfo(frameToBeLoaded));
+    entry.iLoading->iFrameInterval = frameInfo.iDelay.Int64();
+
+    if ( textureAnimationState )
+        {
+        textureAnimationState->OfferNextFrameInfo( frameInfo );
+        }
+    
+    // check for alpha channel
+    // Gifs don't have alpha but support tranparency so the alpha flag is ignored currently
+    if(frameInfo.iFlags & TFrameInfo::ETransparencyPossible/* &&
+            frameInfo.iFlags & TFrameInfo::EAlphaChannel*/)
+        {
+        entry.iHasAlpha = ETrue;
+        }
+    else
+        {
+        entry.iHasAlpha = EFalse;
+        }
+
+    // Get the image original size
+    TRect bitmapSize = frameInfo.iFrameCoordsInPixels;
+    TSize overallSize = 
+        !textureAnimationState ? 
+            bitmapSize.Size() : 
+            textureAnimationState->OverallSize();
+    
+    entry.iOriginalSize = overallSize;
+
+    HUI_DEBUG6(_L("CHuiTextureManager::DoLoadNext() - (sub)Image %S (id %i): w=%i, h=%i, bpp=%i, dm=%i"),
+               &texture->ImageFileName(),
+               entry.iLoading->iId,
+               bitmapSize.Size().iWidth,
+               bitmapSize.Size().iHeight,
+               frameInfo.iBitsPerPixel,
+               frameInfo.iFrameDisplayMode);
+
+    HUI_DEBUG(_L("CHuiTextureManager::DoLoadNext() - Setting logical size of the bitmap."));
+
+    // Try to assign the original size to the image
+    texture->SetSize(overallSize);
+
+    // target resolution for texture, initially equal to bitmap size
+    TInt widthResolutionTarget = overallSize.iWidth;
+    TInt heightResolutionTarget = overallSize.iHeight;
+
+    TSize maxTexSize = entry.iLoading->iMaxTextureSize;
+
+    // Assign new texture resolution target dimensions
+    // if we have explicitly requested them
+    if( (entry.iLoading->iFlags & EHuiTextureUploadFlagDoNotRetainResolution)
+            && maxTexSize.iWidth > 0
+            && maxTexSize.iHeight > 0)
+        {
+        HUI_DEBUG3(_L("CHuiTextureManager::DoLoadNext() - Custom texture size for image %S: w=%i, h=%i"),
+                   &texture->ImageFileName(),
+                   maxTexSize.iWidth,
+                   maxTexSize.iHeight);
+
+        // assign new target resolution for decoder-based scaling
+        if(maxTexSize.iWidth < widthResolutionTarget)
+            {
+            widthResolutionTarget = maxTexSize.iWidth;
+            }
+        if(maxTexSize.iHeight < heightResolutionTarget)
+            {
+            heightResolutionTarget = maxTexSize.iHeight;
+            }
+        }
+
+    // Set up segmentation so we know what kind of texture (and texture
+    // size) we are dealing with
+    texture->SetupSegmentsL(overallSize,
+                           TSize(widthResolutionTarget, heightResolutionTarget),
+                           entry.iLoading->iFlags);
+
+    // we can do direct decoder-based scaling,
+    // if only a single segment texture is used
+    if( !textureAnimationState &&
+        texture->SegmentCount() == 1 &&
+        (texture->SegmentTextureSize(0).iWidth < bitmapSize.Size().iWidth ||
+         texture->SegmentTextureSize(0).iHeight < bitmapSize.Size().iHeight))
+        {
+
+        // assign new texture size target dimensions from the calculated segment 0
+        widthResolutionTarget = texture->SegmentTextureSize(0).iWidth;
+        heightResolutionTarget = texture->SegmentTextureSize(0).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
+            HUI_DEBUG3(_L("CHuiTextureManager::DoLoadNext() - Downscaling image %S to size %ix%i."),
+                       &texture->ImageFileName(),
+                       widthResolutionTarget,
+                       heightResolutionTarget);
+            }
+        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 ImageLoadingCompleteL after the bitmap has been decoded
+            HUI_DEBUG4(_L("CHuiTextureManager::DoLoadNext() - Halving image %S size to %ix%i (factor %i)."),
+                       &texture->ImageFileName(),
+                       halvedWidth,
+                       halvedHeight, halveFactor);
+            widthResolutionTarget = halvedWidth;
+            heightResolutionTarget = halvedHeight;
+            }
+        }
+    else
+        {
+        // either multi-segmented or no need for scaling..
+        HUI_DEBUG(_L("CHuiTextureManager::DoLoadNext() - Decoder-based downscaling not required/possible."));
+        }
+
+    if ( textureAnimationState )
+        {
+        // we convert subframe completely
+        widthResolutionTarget = bitmapSize.Size().iWidth;
+        heightResolutionTarget = bitmapSize.Size().iHeight;
+        }
+
+    if (!(entry.iLoading->iFlags & EHuiTextureUploadFlagRetainColorDepth) && iBitmap->DisplayMode()!=EColor64K)
+        {
+        // (Re)Create the bitmap in EColor64K (16bit) mode to save memory
+        iBitmap->Create(TSize(widthResolutionTarget, heightResolutionTarget), EColor64K);
+        }
+    else if ((entry.iLoading->iFlags & EHuiTextureUploadFlagRetainColorDepth) && iBitmap->DisplayMode()==EColor64K)
+        {
+        // (Re)Create the bitmap in EColor16MU (24bit) mode retain the color information
+        iBitmap->Create(TSize(widthResolutionTarget, heightResolutionTarget), EColor16MU);
+        }
+    else
+        {
+        // no need to recreate the bitmap, but assign the new size!
+        iBitmap->Resize(TSize(widthResolutionTarget, heightResolutionTarget));
+        }
+
+    if (iBitmap->DisplayMode()==EColor64K)
+        {
+        HUI_DEBUG(_L("CHuiTextureManager::DoLoadNext() - Decoding to 16bit image to conserve memory."));
+        }
+    // Decode ( and rescale ) to bitmap.
+    if(entry.iHasAlpha)
+        {
+        // set the alpha channel bitmap to the same size than the color bitmap
+        iMaskBitmap->Resize(TSize(widthResolutionTarget, heightResolutionTarget));
+        entry.iDecoder->Convert(&iStatus, *iBitmap, *iMaskBitmap, frameToBeLoaded);
+        }
+    else
+        {
+        // Save some memory by making the unused alpha channel bitmap
+        // very small.
+        iMaskBitmap->Resize(TSize(4, 4));
+        entry.iDecoder->Convert(&iStatus, *iBitmap, frameToBeLoaded);
+        }
+
+    // Wait for completion.
+    SetActive();
+
+    HUI_DEBUG1(_L("CHuiTextureManager::DoLoadNext() - Exiting, toc %.2f sec"), CHuiStatic::Toc(2));
+    }
+
+CHuiTextureAnimationState* CHuiTextureManager::CreateAnimationStateL( 
+        TInt aGroupId, const TDesC& aImageFile, 
+        TInt aFrameNumber, TInt aFrameCount )
+    {
+    CHuiTextureAnimationState* result = FindAnimationState( aGroupId );
+    
+    TBool recreate = !result || !aFrameNumber;
+    if ( !recreate )
+        {
+        // result != NULL => check if result is animation state of some
+        // previous frame
+        recreate = 
+            !result->CheckIfCanProduce( aImageFile, aFrameNumber, aFrameCount );
+        }
+        
+    if ( recreate )
+        {
+        // First frame, let's just recreate animation state.
+        RemoveAnimationState( result );
+        result = NULL;
+        
+        result = CHuiTextureAnimationState::NewL( 
+            aGroupId, aImageFile, aFrameCount );
+        CleanupStack::PushL( result );
+        iAnimations.AppendL( result );
+        CleanupStack::Pop( result );
+        }
+        
+    return result;
+    }
+
+CHuiTextureAnimationState* CHuiTextureManager::FindAnimationState( 
+        TInt aGroupId )
+    {
+    CHuiTextureAnimationState* result = NULL;
+    const TInt count = iAnimations.Count();
+    for ( TInt i = 0; i < count; i++ )
+        {
+        CHuiTextureAnimationState* state = iAnimations[ i ];
+        if ( state->OwnerTextureGroupId() == aGroupId )
+            {
+            result = state;
+            break;
+            }
+        }
+    return result;
+    }
+
+void CHuiTextureManager::RemoveAnimationState( 
+        CHuiTextureAnimationState* aState )
+    {
+    if ( aState )
+        {        
+        TInt pos = iAnimations.Find( aState );
+        if ( pos != KErrNotFound )
+            {
+            iAnimations.Remove( pos );
+            }
+        delete aState;
+        }
+    }
+
+TBool CHuiTextureManager::FindGroupIdByTextureId( 
+        TInt aTextureId, TInt& aGroupId ) const
+    {
+    TBool found = EFalse;
+    const TInt count = iAnimatedTextureGroupItems.Count();
+    TInt i = 0;
+    while ( !found && ( i < count ) )
+        {
+        const TAnimatedTextureGroupItem& item = iAnimatedTextureGroupItems[ i ];
+        if ( item.iTextureId == aTextureId )
+            {
+            found = ETrue;
+            aGroupId = item.iGroupId;
+            }
+        i++;
+        }
+    return found;
+    }
+
+TBool CHuiTextureManager::NeedsAnimationState( const CImageDecoder& aDecoder )
+    {
+    // If this image contains any special image disposal methods, then
+    // use animation state.
+    
+    const TInt frames = aDecoder.FrameCount();
+    TBool result = EFalse;
+    
+    for ( TInt i = 0; !result && i < frames; ++i )
+        {
+        const TFrameInfo& info = aDecoder.FrameInfo( i );
+        const TUint32 disposalFlags =
+            info.iFlags & 
+                ( TFrameInfo::ELeaveInPlace |
+                  TFrameInfo::ERestoreToBackground |
+                  TFrameInfo::ERestoreToPrevious );
+                  
+        result = result || disposalFlags;
+        }
+    
+    return result;
+    }
+
+void CHuiTextureManager::DoUnload(TInt index)
+    {
+    HUI_ASSERT(index>=0 && index < iTextures.Count());
+    CHuiTexture * t = iTextures[index]->iTexture;
+    if (t == NULL)
+        {
+        HUI_DEBUG1(_L("CHuiTextureManager::UnloadTexture() - Not unloading a NULL texture at index %i."), index);
+        return;
+        }
+
+    HUI_DEBUG3(_L("CHuiTextureManager::UnloadTexture() - Unloading texture \"%S\" id %i at index %i."), &t->ImageFileName(), iTextures[index]->iId, index);
+    // Is this in the queue?
+    if(IsInLoadQueue(t))
+        {
+        // Not loaded yet, can't unload. Mark it as unloaded, though,
+        // so it will be discarded when the loading completes.
+        for(TInt i = 0; i < iLoadQueue.Count(); ++i)
+            {
+            if(iLoadQueue[i].iLoading->iTexture == t)
+                {
+                HUI_DEBUG1(_L("CHuiTextureManager::UnloadTexture() - Marking \"%S\" as unloaded (still in the load queue). "), &t->ImageFileName());
+                iLoadQueue[i].iUnloaded = ETrue;
+                return;
+                }
+            }
+        }
+
+    // Just delete the contents of the texture
+    t->Reset();
+    HUI_ASSERT(!t->HasContent());
+    }
+
+
+EXPORT_C TInt CHuiTextureManager::RunError( TInt /*aError*/ )
+    {
+    // Should never be called, RunL is responsible for handling all error cases
+    HUI_ASSERT(EFalse);
+    return KErrNone;
+    }
+
+
+EXPORT_C void CHuiTextureManager::RunL()
+    {
+    if( iReleaseState == EReleased || 
+        iReleaseState == EPartiallyReleased ||
+        iReleaseState == EReleasing )
+        {
+        // Set the loading state to idle, but do not notify observers of this,
+        // since we are released.
+        // This has to be done so that unfinished loading can be restarted in
+        // the RestoreL().
+        iState = EIdle;        
+        // Leave the texture to the load queue and load it again after restore.
+        return;
+        }
+    
+    TInt status = iStatus.Int();
+    
+    if ( status == KErrNone )
+        {
+        status = ImageLoadingContinue();
+        if ( status > KErrNone )
+            {
+            HUI_DEBUG(_L("CHuiTextureManager::RunL() - Animation: Continue loading."));
+            return;
+            }
+        }
+    
+    // remove the loaded entry from the queue
+    SLoadQueueEntry entry = PopLoadedQueueEntry();
+
+    // Image loading has been completed.
+    iState = EIdle;
+
+    // check status
+    if( status == 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)
+            {
+            delete iAnimationWithoutGroup;
+            iAnimationWithoutGroup = NULL;
+            
+            switch (err)
+                {
+                case KErrNoMemory:
+                    {
+                    HUI_DEBUG3( _L("CHuiTextureManager::RunL() - ERROR! Failed to convert image to texture. Out of memory in ImageLoadingCompleteL(). Source image was  \"%S\" (id %i). Trying to continue with %i items in the queue.."),
+                                &(entry.iLoading->iTexture->ImageFileName()), entry.iLoading->iId, iLoadQueue.Count() );
+                    break;                                
+                    }
+                default:
+                    {
+                    HUI_DEBUG4( _L("CHuiTextureManager::RunL() - Error %i occurred during image upload/conversion to texture. Image filename was: \"%S\" (id %i). Trying to continue with %i items in the queue.."),
+                                err, &(entry.iLoading->iTexture->ImageFileName()), entry.iLoading->iId, iLoadQueue.Count() );
+                    break;
+                    }
+                }
+            // Notify observers about the image upload error
+            NotifyTextureLoaded(*entry.iLoading->iTexture, entry.iLoading->iId, err);
+            }
+        }
+    else
+        {
+        HUI_DEBUG2( _L("CHuiTextureManager::RunL() - Image decoding error while decoding \"%S\" (id %i). Bypassing image.."), &(entry.iLoading->iTexture->ImageFileName()), entry.iLoading->iId);
+
+        delete iAnimationWithoutGroup;
+        iAnimationWithoutGroup = NULL;
+
+        // notify sb of failed image load!
+        NotifyTextureLoaded(*entry.iLoading->iTexture, entry.iLoading->iId, status);
+        }
+
+    // Continue loading entries.
+    StartLoading();
+
+    if(iLoadQueue.Count() == 0)
+        {
+        HUI_DEBUG(_L("CHuiTextureManager::RunL() - No more images to load, exiting.."));
+        }
+    }
+
+
+EXPORT_C void CHuiTextureManager::DoCancel()
+    {
+    if(iLoadQueue.Count() > 0)
+        {
+        iLoadQueue[0].iDecoder->Cancel();
+        }
+        
+    iState = EIdle;
+    }
+
+TInt CHuiTextureManager::ImageLoadingContinue()
+    {
+    TInt status = KErrNone;
+    
+    const SLoadQueueEntry& entry = iLoadQueue[0];
+    
+    TInt groupId = 0;
+    CHuiTextureAnimationState* state = NULL;
+    if ( iAnimationWithoutGroup )
+        {
+        state = iAnimationWithoutGroup;
+        }
+    else if ( FindGroupIdByTextureId( entry.iLoading->iId, groupId ) )
+        {
+        state = FindAnimationState( groupId );
+        }
+    else
+        {
+        // state = NULL;
+        }
+        
+    if ( state && 
+         ( state->GetNextFrameNumber() != entry.iLoading->iFrameNumber ) )
+        {
+        // Someone has asked animated frames not in sequence - 
+        // very inefficient!
+        HUI_DEBUG(_L("CHuiTextureManager::ImageLoadingContinue: Frames not requested in sequence."));
+        TRAP( status, 
+            state->ProceedWithoutNextFrameL( 
+                iBitmap, 
+                entry.iHasAlpha ? iMaskBitmap : NULL ) );
+
+        if ( status == KErrNone )
+            {
+            // Image loading has been completed.
+            iState = EIdle;            
+            StartLoading();
+            status = 1; // indicate that started loading.
+            }
+        }
+    
+    return status;
+    }
+
+void CHuiTextureManager::ImageLoadingCompleteL(SLoadQueueEntry& aEntry)
+    {
+    CHuiTexture* tex = aEntry.iLoading->iTexture;
+    HUI_ASSERT(tex);
+    tex->iFrameNumber = aEntry.iLoading->iFrameNumber;
+    tex->iFrameCount = aEntry.iLoading->iFrameCount;
+    tex->iFrameInterval = aEntry.iLoading->iFrameInterval;
+
+    if(iReleaseState != ENormal)
+        {
+        HUI_DEBUG1(_L("CHuiTextureManager::ImageLoadingCompleteL() - Unable to upload bitmap data for \"%S\". Texture manager has been released."), &tex->ImageFileName());
+        return;
+        }
+       
+    if ( tex->iFrameCount > 1 )
+        {
+        ProcessAnimatedFrameL( aEntry );
+        }
+    TBool hasAlpha = aEntry.iHasAlpha;
+    
+    delete iAnimationWithoutGroup;
+    iAnimationWithoutGroup = NULL;
+
+    TSize* maxTexSize = &aEntry.iLoading->iMaxTextureSize;    
+    if(((maxTexSize->iWidth != 0) && (maxTexSize->iHeight != 0)) && iBitmap->SizeInPixels() != aEntry.iLoading->iMaxTextureSize )
+        {
+        // 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();
+        CleanupStack::PushL( dest );
+        User::LeaveIfError( dest->Create(*maxTexSize, iBitmap->DisplayMode()) );
+        HuiUtil::ScaleFbsBitmapL(*iBitmap, *dest);
+        CleanupStack::Pop( dest );
+        delete iBitmap;
+        iBitmap = dest;
+
+        if( hasAlpha )
+            {
+            // Scale the alpha as well.
+            dest = new (ELeave) CFbsBitmap();   
+            CleanupStack::PushL( dest );
+            User::LeaveIfError(
+                dest->Create(*maxTexSize, iMaskBitmap->DisplayMode()) );     
+            HuiUtil::ScaleFbsBitmapL(*iMaskBitmap, *dest);
+            CleanupStack::Pop( dest );
+            delete iMaskBitmap;
+            iMaskBitmap = dest;
+            }                      
+        }        
+
+    HUI_DEBUG3(_L("CHuiTextureManager::ImageLoadingCompleteL() - Loading complete for \"%S\". Uploading %ix%i FBS bitmap to texture.."),
+               &tex->ImageFileName(),
+               iBitmap->SizeInPixels().iWidth,
+               iBitmap->SizeInPixels().iHeight);
+
+    // Upload without compression.
+    tex->UploadL(*iBitmap,
+                (hasAlpha? iMaskBitmap: NULL),
+                 aEntry.iLoading->iFlags);
+
+    // Store bits per pixel info to calculate texture memory usage
+    aEntry.iLoading->iBitDepth = TDisplayModeUtils::NumDisplayModeBitsPerPixel( iBitmap->DisplayMode() );
+    if( iMaskBitmap )
+        {
+        aEntry.iLoading->iBitDepth = aEntry.iLoading->iBitDepth + 
+        TDisplayModeUtils::NumDisplayModeBitsPerPixel( iMaskBitmap->DisplayMode() );
+        }
+    
+    // Now we're setting up the real texture, no more placeholder needed
+    tex->SetPlaceholder(NULL);
+
+    HUI_DEBUG2(_L("CHuiTextureManager::ImageLoadingCompleteL() - ... Upload done. Setting original size of %ix%i pixels."),
+               aEntry.iOriginalSize.iWidth,
+               aEntry.iOriginalSize.iHeight);
+
+    // (Re)set the original size of the image as the logical size
+    tex->SetSize(aEntry.iOriginalSize);
+
+    // Notify the observers of loaded texture
+    NotifyTextureLoaded(*tex, aEntry.iLoading->iId, KErrNone);
+
+    // Unload, if the unloading was already requested while loading!
+    if(aEntry.iUnloaded)
+        {
+        UnloadTexture(tex->ImageFileName(),tex->iFrameNumber);
+        }
+
+    HUI_DEBUG(_L("CHuiTextureManager::ImageLoadingCompleteL() - Done. "));
+    }
+
+void CHuiTextureManager::ProcessAnimatedFrameL(SLoadQueueEntry& aEntry)
+    {
+    // Animated file - produce next frame.
+    CFbsBitmap* frameBitmap = NULL;
+    CFbsBitmap* frameMask = NULL;
+
+    // ImageFileName() does not include image path
+    CHuiTextureAnimationState* state = NULL;
+    TInt groupId = 0;
+    if ( iAnimationWithoutGroup )
+        {
+        state = iAnimationWithoutGroup;
+        }
+    else if ( FindGroupIdByTextureId( aEntry.iLoading->iId, groupId ) )
+        {
+        state = FindAnimationState( groupId );
+        }
+
+    if ( !state )
+        {
+        return;
+        }
+
+    HUI_DEBUG1(_L("CHuiTextureManager::ProcessAnimatedFrameL: Producing next frame (%d)."), 
+        state->GetNextFrameNumber() );
+
+    state->ProduceNextFrameL( 
+        frameBitmap, frameMask, 
+        iBitmap, aEntry.iHasAlpha ? iMaskBitmap : NULL );
+
+    HUI_DEBUG2(_L("CHuiTextureManager::ProcessAnimatedFrameL: Next frame produced (%x, %x)."),
+        frameBitmap, frameMask );
+    
+    aEntry.iHasAlpha = ( frameMask != NULL );
+    if ( frameBitmap != iBitmap )
+        {
+        delete iBitmap;
+        iBitmap = frameBitmap;
+        }
+        
+    if ( frameMask && (frameMask != iMaskBitmap) )
+        {
+        delete iMaskBitmap;
+        iMaskBitmap = frameMask;
+        }        
+    }
+
+EXPORT_C TInt CHuiTextureManager::LoadQueueCount() const
+    {
+    return iLoadQueue.Count();
+    }
+
+
+EXPORT_C void CHuiTextureManager::AdvanceTime(TReal32 aElapsedTime) const
+    {
+    for(TInt i = 0; i < iAnimatedTextures.Count(); ++i)
+        {
+        iAnimatedTextures[i].AdvanceTime(aElapsedTime);
+        }
+    NotifyTextureAutoSizeObservers();
+    // Write total memory consumed on rendering textures as an info message,
+    // if feature is enabled from central repository Rnd flag
+    if ( iEnableTexMemCalculation )
+    	{
+    	TextureMemUsage(); 
+    	}    
+    }
+
+
+EXPORT_C void CHuiTextureManager::SetProcessor(CHuiTextureProcessor* aProcessor)
+    {
+    // Since we have ownership of the processor, delete the previous one if
+    // there is one.
+    if(iProcessor)
+        {
+        delete iProcessor;
+        iProcessor = NULL;
+        }
+
+    iProcessor = aProcessor;
+    }
+
+
+EXPORT_C CHuiTextureProcessor& CHuiTextureManager::Processor()
+    {
+    if(!iProcessor)
+        {
+        THuiPanic::Panic(THuiPanic::ETextureManagerNoProcessor);
+        }
+    return *iProcessor;
+    }
+
+
+void CHuiTextureManager::CancelLoadingOfTexture(CHuiTexture& aTexture)
+    {
+    for(TInt i = 0; i < iLoadQueue.Count(); ++i)
+        {
+        if(iLoadQueue[i].iLoading->iTexture == &aTexture)
+            {
+            // Texture found from the load queue.
+            if(i == 0 && iState == ELoading)
+                {
+                // Texture is currently loading
+                Cancel();
+                PopLoadedQueueEntry();
+                StartLoading();                
+                }
+            else
+                {
+                // Delete the decoder and remove entry.
+                delete iLoadQueue[i].iDecoder;
+                iLoadQueue.Remove(i);
+                }
+            break;
+            }
+        }
+    }
+
+
+void CHuiTextureManager::NotifyStateChange() const
+    {
+    for(TInt index = 0; index < iStateObservers.Count(); ++index)
+        {
+        iStateObservers[index].TextureManagerStateChanged(*this);
+        }
+    }
+
+
+EXPORT_C void CHuiTextureManager::NotifyTextureLoaded(CHuiTexture& aTexture,
+                             TInt aTextureId,
+                             TInt aErrorCode) const
+    {
+    aTexture.SetTextureChanged(ETrue);
+    for(TInt index = 0; index < iLoadObservers.Count(); ++index)
+        {
+        iLoadObservers[index].TextureLoadingCompleted(aTexture, aTextureId, aErrorCode);
+        }
+    }
+
+EXPORT_C CHuiTextureManager::CTextureEntry * CHuiTextureManager::TextureEntry(TInt aIndex)
+    {
+    // check limits
+    if ( aIndex < iTextures.Count() )
+        {
+        return iTextures[aIndex];
+        }
+    else
+        {
+        return NULL;
+        }
+    }
+
+EXPORT_C TInt CHuiTextureManager::TextureEntryCount() const
+    {
+    return iTextures.Count();
+    }
+
+EXPORT_C TBool CHuiTextureManager::Release()
+    {
+    HUI_DEBUG(_L("CHuiTextureManager::Release() - Called."));
+
+    HUI_ASSERT(iReleaseState == ENormal);
+    iReleaseState = EReleasing;
+    
+    TBool allReleased = ETrue; // by default, all texures are released.
+
+    // Release all textures. Use an order inverse to creation order.
+    for(TInt i = iTextures.Count() - 1; i >= 0; --i)
+        {
+        CHuiTexture * tex = iTextures[i]->iTexture;
+        if (tex)
+            {
+            // This is called when application goes into the backgrounf
+            // If release priority is set to 0, the texture should not be released.
+            if ( tex->Priority() == 0 )
+                {
+                HUI_DEBUG5(_L("CHuiTextureManager::Release() - Not releasing priority texture 0x%x (\"%S\", id: %i) [%i/%i]"),
+                          tex, &(tex->ImageFileName()), iTextures[i]->iId, i+1, iTextures.Count());
+                allReleased = EFalse;
+                }
+            else
+                {     
+                HUI_DEBUG5(_L("CHuiTextureManager::Release() - Releasing texture 0x%x (\"%S\", id: %i) [%i/%i]"),
+                          tex, &(tex->ImageFileName()), iTextures[i]->iId, i+1, iTextures.Count());
+                tex->Release();
+                }
+            }
+        else
+            {
+            HUI_DEBUG4(_L("CHuiTextureManager::Release() - Not releasing unloaded texture 0x%x, id: %i) [%i/%i]"),
+                          tex, iTextures[i]->iId, i+1, iTextures.Count());                
+            }
+        }
+
+    HUI_DEBUG(_L("CHuiTextureManager::Release() - Release processor."));
+
+    // Release texture processor.
+    if(iProcessor)
+        {
+        iProcessor->Release();
+        }
+
+    HUI_ASSERT(iReleaseState == EReleasing);
+    if ( allReleased )
+        {
+        HUI_DEBUG(_L("CHuiTextureManager::Release() - Exiting (EReleased)."));
+        iReleaseState = EReleased;
+        }
+    else
+        {
+        HUI_DEBUG(_L("CHuiTextureManager::Release() - Exiting (EPartiallyReleased)."));
+        iReleaseState = EPartiallyReleased;
+        }
+    return allReleased;
+    }
+
+
+EXPORT_C void CHuiTextureManager::RestoreL()
+    {
+    HUI_DEBUG(_L("CHuiTextureManager::RestoreL() - Called."));
+
+    HUI_ASSERT(iReleaseState == EReleased || iReleaseState == EPartiallyReleased );
+    iReleaseState = ERestoring;
+
+    // Restore texture processor.
+    if(iProcessor)
+        {
+        iProcessor->RestoreL();
+        }
+
+    // Restore all textures. Use same order as in which the textures were created.
+    for(TInt i = 0; i < iTextures.Count(); ++i)
+        {
+        CHuiTexture * tex = iTextures[i]->iTexture;
+        if (tex)
+            {
+            if ( tex->HasContent() )
+                {
+                HUI_DEBUG5(_L("CHuiTextureManager::RestoreL() - Alredy has content texture 0x%x (\"%S\", id: %i) [%i/%i]"),
+                          tex, &(tex->ImageFileName()), iTextures[i]->iId, i+1, iTextures.Count());
+                }
+            else
+                {    
+                HUI_DEBUG5(_L("CHuiTextureManager::RestoreL() - Restoring texture 0x%x (\"%S\", id: %i) [%i/%i]"),
+                          tex, &(tex->ImageFileName()), iTextures[i]->iId, i+1, iTextures.Count());
+                // Restore the texture.
+                tex->RestoreL();
+                }
+            }
+        else
+            {
+            HUI_DEBUG4(_L("CHuiTextureManager::RestoreL() - Not restoring unloaded texture 0x%x, id: %i) [%i/%i]"),
+                          tex, iTextures[i]->iId, i+1, iTextures.Count());                
+            }
+        }
+
+    // Restart loading of textures that still might be in the load queue.
+    StartLoading();
+
+    HUI_ASSERT(iReleaseState == ERestoring);
+    iReleaseState = ENormal;
+    }
+
+EXPORT_C void CHuiTextureManager::NotifySkinChangedL()
+    {
+    for(TInt i = iTextures.Count()-1; i >= 0; i--)
+        {
+        CHuiTexture * tex = iTextures[i]->iTexture;
+        if (tex &&
+            tex->HasContent() &&
+            tex->IsSkinContent())
+            {
+            tex->Release();
+            tex->RestoreL();    
+            }
+        }            
+    }
+
+EXPORT_C TInt CHuiTextureManager::AddAnimatedTextureGroupL( 
+        const RArray<TInt>& aTextureIds )
+    {
+    const TInt count = aTextureIds.Count();
+    
+    // Zero ids are not allowed here
+    for ( TInt j = 0; j < count; j++ )
+        {
+        if ( !aTextureIds[ j ] ) 
+            {
+            User::Leave( KErrNotSupported );
+            }
+        }
+        
+    TInt result = 0;
+    if ( count )
+        {
+        result = aTextureIds[ 0 ]; 
+    
+        // Reserve space so next loop cannot fail.
+        iAnimatedTextureGroupItems.ReserveL( 
+            iAnimatedTextureGroupItems.Count() + aTextureIds.Count() );
+    
+        TAnimatedTextureGroupItem item;
+        item.iGroupId = result;
+        
+        for ( TInt i = 0; i < count; i++ )
+            {
+            item.iTextureId = aTextureIds[ i ];
+            
+            (void)iAnimatedTextureGroupItems.
+                Append( item ); // ought not to fail due to Reserve.
+            }
+        }
+        
+    return result;
+    }
+    
+EXPORT_C void CHuiTextureManager::RemoveAnimatedTextureGroup( TInt aGroupId )
+    {
+    // Remove animated texture group items.
+    const TInt count = iAnimatedTextureGroupItems.Count();
+    for ( TInt i = count - 1; i >= 0; --i )
+        {
+        if ( iAnimatedTextureGroupItems[ i ].iGroupId == aGroupId )
+            {
+            iAnimatedTextureGroupItems.Remove( i );
+            }
+        }
+    
+    RemoveAnimationState( FindAnimationState( aGroupId ) );
+    }
+
+// CHuiTextureManager::CTextureEntry
+
+CHuiTextureManager::CTextureEntry::CTextureEntry(
+    TInt aId,
+    const TFileName & aFileName,
+    const TSize& aMaxTextureSize,
+    THuiTextureUploadFlags aFlags,
+    TInt aFrameNumber )
+    : iId(aId), iFileName(NULL),
+      iTexture(NULL),
+      iMaxTextureSize(aMaxTextureSize), iFlags(aFlags),
+      iBitmapProvider(NULL),
+      iFrameNumber(aFrameNumber),
+      iFrameCount(0),
+      iFrameInterval(0)
+    {
+    SetFileName(aFileName);
+    }
+    
+CHuiTextureManager::CTextureEntry::CTextureEntry(TInt aId, CHuiTexture * aTexture)
+                      : iId(aId),
+                        iFileName(NULL),
+                        iTexture(aTexture),
+                        iMaxTextureSize(TSize(0,0)),
+                        iFlags(EHuiTextureUploadFlagDefault),
+                        iBitmapProvider(NULL),
+                        iFrameNumber(0),
+                        iFrameCount(0),
+                        iFrameInterval(0)
+    {
+    }
+            
+CHuiTextureManager::CTextureEntry::CTextureEntry(const CTextureEntry &aSrc)
+                      : iId(aSrc.iId),
+                        iFileName(NULL),
+                        iTexture(aSrc.iTexture),
+                        iMaxTextureSize(aSrc.iMaxTextureSize),
+                        iFlags(aSrc.iFlags),
+                        iBitmapProvider(NULL),
+                        iFrameNumber(aSrc.iFrameNumber),
+                        iFrameCount(0),
+                        iFrameInterval(0)
+    {
+    SetFileName(*aSrc.iFileName);
+    }
+            
+CHuiTextureManager::CTextureEntry & CHuiTextureManager::CTextureEntry::operator=(const CTextureEntry &aSrc)
+    {
+    if ( this == &aSrc )
+        {
+        return *this;
+        }
+            
+    iId = aSrc.iId;
+    if (aSrc.iFileName != NULL)
+        {
+        SetFileName(*aSrc.iFileName);
+        }
+    iMaxTextureSize = aSrc.iMaxTextureSize;
+    iFlags = aSrc.iFlags;
+    iBitmapProvider = aSrc.iBitmapProvider;
+    iFrameNumber = aSrc.iFrameNumber;
+    iFrameCount = aSrc.iFrameCount;
+    iFrameInterval = aSrc.iFrameInterval;
+    return *this;
+    }
+            
+EXPORT_C CHuiTextureManager::CTextureEntry::~CTextureEntry()
+    {
+    delete iFileName; 
+    iFileName = NULL;
+    // CHuiTextureManager deletes the iTexture
+    }
+    
+void CHuiTextureManager::CTextureEntry::SetFileName(const TFileName & aFileName)
+    {
+    delete iFileName;
+    iFileName = NULL;
+    if (aFileName.Length()>0)
+        {
+        // this might fail and therefore the iFileName is left as NULL.
+        iFileName = aFileName.Alloc();
+        }
+    }
+
+void CHuiTextureManager::CTextureEntry::TextureContentUploaded(CHuiTexture& /*aTexture*/)
+    {
+    }
+void CHuiTextureManager::CTextureEntry::TextureContentReleased(CHuiTexture& /*aTexture*/)
+    {
+    }
+void CHuiTextureManager::CTextureEntry::RestoreTextureContentL(CHuiTexture& aTexture)
+    {
+    HUI_DEBUG(_L("CHuiTextureManager::CTextureEntry::RestoreTextureContentL() - Called for entry 0x%x (id: %i)."));
+    if (iBitmapProvider != NULL)
+        {
+        HUI_DEBUG3(_L("CHuiTextureManager::CTextureEntry::RestoreTextureContentL() - Using bitmap provider 0x%x to recreate content for texture 0x%x (id: %i).."), iBitmapProvider, &aTexture, iId);
+        CFbsBitmap* bitmap = NULL;
+        CFbsBitmap* maskBitmap = NULL;
+
+        // call the bitmapProvider method to load the bitmaps
+        iBitmapProvider->ProvideBitmapL(iId, bitmap, maskBitmap);
+
+        if (maskBitmap)
+            {
+            CleanupStack::PushL(maskBitmap);
+            }
+        
+        if (!bitmap)
+            {
+            User::Leave(KErrArgument);
+            }
+        else
+            {
+            CleanupStack::PushL(bitmap);
+            }
+        
+        // recreate texture content..
+
+        // Let the texture know its size as soon as possible.
+        aTexture.SetSize(bitmap->SizeInPixels());
+
+        // Enable texture shadow.
+        aTexture.EnableShadow((iFlags & EHuiTextureUploadFlagGenerateShadow) != 0);
+
+        // Upload!    
+        TSize bitmapSize = bitmap->SizeInPixels();
+    	if (bitmapSize.iWidth != 0 && bitmapSize.iHeight != 0)
+    	    {
+    		if (iFlags & EHuiTextureFlagAllowDirectBitmapUsage) 
+    			{
+       			aTexture.UploadDirectL(*bitmap, maskBitmap, iFlags);		
+    			}
+    		else 
+    			{
+            	aTexture.UploadL(*bitmap, maskBitmap, iFlags);
+    			}
+    	    }
+        // Clean up owned bitmaps
+        CleanupStack::PopAndDestroy(bitmap);        
+        if (maskBitmap)
+            {
+            CleanupStack::PopAndDestroy(maskBitmap);        
+            }       
+        }
+    // check for file-based restore
+    else if (iFileName != NULL)
+        {
+        HUI_DEBUG2(_L("CHuiTextureManager::CTextureEntry::RestoreTextureContentL() - Reloading texture 0x%x from \"%S\".."), &aTexture, iFileName);
+        CHuiStatic::Env().TextureManager().LoadTextureL(*iFileName, iMaxTextureSize, iFlags, iId);
+        return;
+        }
+    else
+        {
+        // for PC lint
+        }
+    }
+
+void CHuiTextureManager::NotifyTextureAutoSizeObservers() const
+    {
+    if (!iTextureAutoSizingEnabled)
+        {
+        return;
+        }
+    
+    TBool somethingWasReported = EFalse;
+    TBool anyAutoSizedTexturesExist = EFalse;
+    
+    for(TInt index = iTextures.Count() - 1; index >= 0; --index)
+        {
+        CTextureEntry * entry = iTextures[index];
+        if (entry->iTexture)
+            {
+            if (entry->iTexture->IsAutoSizeCalculationEnabled())
+                {
+                anyAutoSizedTexturesExist = ETrue;
+                
+                // Calculate preferred size from the previous frame data
+                THuiRealSize preferredSize = entry->iTexture->CalculateAutoSize();
+                
+                // Notify observers if preferred size has changed
+                if (entry->iTexture->CalculatedAutoSizeChanged())
+                    {
+                    HUI_DEBUG3(_L("CHuiTextureManager::NotifyTexturePreferredSizeObservers - To be notified id: %i, width: %f , height %f"), entry->iId, preferredSize.iWidth, preferredSize.iHeight);                    
+
+                    // Notify observers. For now ignore return values.
+                    for(TInt index = 0; index < iTextureAutoSizeObservers.Count(); ++index)
+                        {
+                        iTextureAutoSizeObservers[index].PreferredSizeChanged(*entry->iTexture, entry->iId, preferredSize);
+                        somethingWasReported = ETrue;
+                        }            
+                    }
+                
+                // Restart preferred size calculations for next frame   
+                entry->iTexture->ResetAutoSizeCalculation();        
+                }
+            }
+        }
+    
+    if (somethingWasReported)
+        {
+        for(TInt index = 0; index < iTextureAutoSizeObservers.Count(); ++index)
+            {
+            iTextureAutoSizeObservers[index].PreferredSizeReportCompleted();                
+            }                        
+        }
+
+    // Keep checking autosized textures only if those exist. 
+    // New textures will enable flag when needed.
+    iTextureAutoSizingEnabled = anyAutoSizedTexturesExist;
+    }
+
+EXPORT_C void CHuiTextureManager::ClearChangedTextures()
+    {
+    if (iHasChangedTextures)
+        {
+        for(TInt index = iTextures.Count() - 1; index >= 0; --index)
+            {
+            CTextureEntry * entry = iTextures[index];
+            if (entry->iTexture)
+                {
+                entry->iTexture->TextureClearChanged();
+                }
+            }
+        iHasChangedTextures = EFalse;        
+        }
+    }
+    
+EXPORT_C void CHuiTextureManager::SetHasChangedTextures()
+    {
+    iHasChangedTextures = ETrue;    
+    }
+
+/*
+ * Enables/Disables memory usage calculation.
+ */
+EXPORT_C void CHuiTextureManager::EnableTexMemoryCalculation( TBool aEnableTeMemCal )
+	{
+	iEnableTexMemCalculation = aEnableTeMemCal;
+	}
+
+/*
+ * Calculates memory used by texturemanager to store all the textures.
+ * Texture memory is calculated as ( Texture area ) * ( bits per pixel )
+ * 
+ * This routine prints info message stating toal no of textures and memory consuption by them.
+ */
+void CHuiTextureManager::TextureMemUsage() const
+	{
+	TReal32 totalMemUsage = 0;
+	TReal32 avgBitDepth = 0;
+    for(TInt i = 0; i < iTextures.Count(); ++i)
+        {
+        if( iTextures[i]->iTexture )
+            {            
+            TSize size = iTextures[i]->iTexture->Size();         
+            totalMemUsage = totalMemUsage + size.iWidth * size.iHeight * iTextures[i]->iBitDepth;   
+            avgBitDepth = avgBitDepth + iTextures[i]->iBitDepth;
+            }        
+        }
+    
+    avgBitDepth = avgBitDepth/iTextures.Count();
+    totalMemUsage = totalMemUsage/8000000;
+    TBuf<300> buf;
+    buf.FillZ();
+    buf.AppendNum( totalMemUsage, TRealFormat( 8, 4 ) );
+    buf.Append(_L( "MB;By:" ) );
+    buf.AppendNum( iTextures.Count() );
+    buf.Append(_L( ";BD:" ) );
+    buf.AppendNum( avgBitDepth );
+    User::InfoPrint( buf );      
+	}
+TInt CHuiTextureManager::EstimatedTextureMemUsage(TInt aAverageBitsPerPixel) const
+    {
+    TReal32 averageBytesPerPixel =  TReal32(aAverageBitsPerPixel)/8.f;
+	TReal32 totalMemUsage = 0;
+    TInt pixels = 0;
+    for(TInt i = 0; i < iTextures.Count(); ++i)
+        {
+        // TODO: Exclude NVG textures !
+        if( iTextures[i]->iTexture /*&& 
+            iTextures[i]->iTexture->HasContent()*/)
+            {            
+            TSize size = iTextures[i]->iTexture->Size();         
+            pixels += size.iWidth * size.iHeight;                        
+            }        
+        }
+        
+    totalMemUsage = TReal32(pixels) * averageBytesPerPixel;        
+    return totalMemUsage;
+    }
+
+
+
+EXPORT_C void CHuiTextureManager::TextureManagerExtension(const TUid& /*aExtensionUid*/, TAny** aExtensionParams)
+    {
+    // If no extension with given UID was found, indicate it by returning null
+    *aExtensionParams = NULL;
+    }
+
+void CHuiTextureManager::EnableAutoSizeCalculation(TBool aEnable)
+    {
+    iTextureAutoSizingEnabled = aEnable;
+    }
+