uiacceltk/hitchcock/Client/src/alftexturemanager.cpp
changeset 0 15bf7259bb7c
equal deleted inserted replaced
-1:000000000000 0:15bf7259bb7c
       
     1 /*
       
     2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:   Loads textures.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #include <e32std.h>
       
    21 #include <imageconversion.h>
       
    22 #include <eikenv.h>
       
    23 #include <eikappui.h>
       
    24 #include <eikapp.h>
       
    25 
       
    26 #include "alf/alftexturemanager.h"
       
    27 #include "alf/alftextureprocessor.h"
       
    28 #include "alf/alftexture.h"
       
    29 #include "alf/alfenv.h"
       
    30 #include "alfclient.h"
       
    31 #include "alf/alfutil.h"
       
    32 #include "alf/alfbitmapprovider.h"
       
    33 #include "alflogger.h"
       
    34 
       
    35 const TInt KFirstAutoGeneratedTextureId = 0x10000000;
       
    36 const TInt KAlfDefaultSizeDimension = 4;
       
    37 
       
    38 /**
       
    39  * Flag to indicate to use the provided bitmap directly for the texture, without conversion or copying. The bitmaps
       
    40  * should be in the correct format and they shall not be compressed or have duplicated handle.
       
    41  * If the direct bitmap cannot be used, this flag is ignored internally.
       
    42  *
       
    43  * NOTE: This flag is not a public since we cannot guarantee that user does not compress
       
    44  * bitmap or otherwise temper with it after providing it to toolkit. 
       
    45  * But internally we can use this in some cases to speed up the texture upload.
       
    46  *
       
    47  */
       
    48 enum
       
    49     {
       
    50     EAlfTextureFlagAllowDirectBitmapUsage = 0x20        
       
    51     };
       
    52 
       
    53 struct TTextureEntry 
       
    54     {
       
    55     public:
       
    56     	~TTextureEntry()
       
    57         {
       
    58         }
       
    59     	TTextureEntry()                      
       
    60                       : iId(0), iTexture(NULL), iRefCount(-1)
       
    61         {                            
       
    62         }
       
    63     	
       
    64     	TTextureEntry(TInt aId,
       
    65                       CAlfTexture* aTexture)                      
       
    66                       : iId(aId), iTexture(aTexture),iRefCount(-1)
       
    67         {
       
    68         }
       
    69 
       
    70     /** The texture id. Set to zero for no id. */
       
    71     TInt iId;
       
    72 
       
    73     /** The texture entry. */
       
    74     CAlfTexture* iTexture;
       
    75     
       
    76     /** Reference count. */
       
    77     TInt iRefCount;
       
    78     };
       
    79 
       
    80 struct TLoadQueueEntry
       
    81     {
       
    82     /** The texture entry that is being loaded. */
       
    83     TTextureEntry iLoading;
       
    84 
       
    85     /** The image being loaded has an alpha channel. */
       
    86     TBool iHasAlpha;
       
    87 
       
    88     /** The original, non-downscaled size of the image. */
       
    89     TSize iOriginalSize;
       
    90 
       
    91     /** Image decoder to load bitmap images. */
       
    92     CImageDecoder* iDecoder;
       
    93 
       
    94     /** True, if the texture was already unloaded before it finished
       
    95         loading. */
       
    96     TBool iUnloaded;
       
    97     };
       
    98 
       
    99 
       
   100 // Private structure
       
   101 struct CAlfTextureManager::TPrivateData
       
   102     {
       
   103     CAlfEnv* iEnv;              // Not owned.  	
       
   104     
       
   105     /**
       
   106      * Registry of all textures within this toolkit.
       
   107      * Accessed by texture ids (iId). 
       
   108      */
       
   109     RArray<TTextureEntry> iTextures;
       
   110 
       
   111     /** Queue of loading tasks. */
       
   112     RArray<TLoadQueueEntry> iLoadQueue;
       
   113 
       
   114     /** Queue of loading observers. */
       
   115     RPointerArray<MAlfTextureLoadingCompletedObserver> iLoadObserverQueue;
       
   116 
       
   117     /** Queue of state observers. */
       
   118     RPointerArray<MAlfTextureManagerStateChangedObserver> iStateObserverQueue;
       
   119 
       
   120     /** Blank texture */
       
   121     CAlfTexture* iBlankTexture;
       
   122 
       
   123     /** Path where image files are loaded from. */
       
   124     HBufC* iImagePath;
       
   125     
       
   126     /** State of the texture manager. */
       
   127     TState iState;
       
   128 
       
   129     /** Bitmap for loading asynchronously into. */
       
   130     CFbsBitmap* iBitmap;
       
   131 
       
   132     /** Mask bitmap for loading alpha channels. */
       
   133     CFbsBitmap* iMaskBitmap;
       
   134 
       
   135     /** Open file server session for image loading. */
       
   136     RFs iFs;
       
   137     
       
   138     /** Id of this texture manager. */
       
   139     TUid iManagerId;
       
   140 
       
   141     /** Texture processor */
       
   142     CAlfTextureProcessor* iProcessor;
       
   143     
       
   144     /** Texture id auto generation */
       
   145     TInt iAutoGeneratedTextureId;
       
   146     TInt iLowestAutoGeneratedTextureId;
       
   147     TInt iHighestAutoGeneratedTextureId;
       
   148     
       
   149     RPointerArray<MAlfTextureAutoSizeObserver> iAutoSizeObserverQueue;
       
   150     
       
   151     // DEBUG
       
   152     TBool iTextureAutoCounterEnabled;
       
   153     TInt iTextureAutoRecreateCounter;
       
   154     TInt iTextureAutoReloadCounter;
       
   155 
       
   156     //...add other member variables...
       
   157     CIdle* iDoomBringer;
       
   158     };
       
   159 
       
   160 
       
   161 
       
   162 // ======== MEMBER FUNCTIONS ========
       
   163 
       
   164 // ---------------------------------------------------------------------------
       
   165 // Constructor
       
   166 // ---------------------------------------------------------------------------
       
   167 //
       
   168 CAlfTextureManager::CAlfTextureManager() : CActive(EPriorityHigh)
       
   169 	{
       
   170 		
       
   171 	}
       
   172 	
       
   173 // ---------------------------------------------------------------------------
       
   174 // Destructor
       
   175 // ---------------------------------------------------------------------------
       
   176 //
       
   177 CAlfTextureManager::~CAlfTextureManager()
       
   178 	{
       
   179 	Cancel();
       
   180 	if ( iData )
       
   181 	    {
       
   182         delete iData->iImagePath;
       
   183 	    
       
   184 	    delete iData->iBlankTexture;
       
   185 	    
       
   186 	    RArray<TTextureEntry>& textures = (iData->iTextures);	
       
   187         // Remove all texture entries (from last to first -order)
       
   188         while (textures.Count())
       
   189             {
       
   190             TTextureEntry te = textures[textures.Count()-1];
       
   191             
       
   192             delete te.iTexture; 
       
   193             te.iTexture = NULL;                
       
   194             }
       
   195 
       
   196         textures.Close();   
       
   197 
       
   198 	    iData->iLoadQueue.Close();	    
       
   199     
       
   200 	    iData->iLoadObserverQueue.Close();	
       
   201 
       
   202 	    iData->iStateObserverQueue.Close();	
       
   203 	    
       
   204 	    iData->iAutoSizeObserverQueue.Close();
       
   205 
       
   206         delete iData->iBitmap;
       
   207         delete iData->iMaskBitmap;
       
   208 
       
   209         iData->iFs.Close();
       
   210         
       
   211         delete iData->iProcessor;        
       
   212         if (iData->iDoomBringer)
       
   213             iData->iDoomBringer->Cancel();
       
   214         delete iData->iDoomBringer;
       
   215 	    }	
       
   216 
       
   217 	delete iData;
       
   218 	}
       
   219 // ---------------------------------------------------------------------------
       
   220 // NewL
       
   221 // ---------------------------------------------------------------------------
       
   222 //
       
   223 CAlfTextureManager* CAlfTextureManager::NewL(CAlfEnv& aEnv, TUid aUid)
       
   224 	{
       
   225 	CAlfTextureManager* self = CAlfTextureManager::NewLC(aEnv, aUid);        
       
   226     CleanupStack::Pop( self );
       
   227     return self;		
       
   228 	}
       
   229 	
       
   230 
       
   231 // ---------------------------------------------------------------------------
       
   232 // NewLC
       
   233 // ---------------------------------------------------------------------------
       
   234 //
       
   235 CAlfTextureManager* CAlfTextureManager::NewLC(CAlfEnv& aEnv, TUid aUid)
       
   236 	{
       
   237     CAlfTextureManager* self = new( ELeave ) CAlfTextureManager();
       
   238     CleanupStack::PushL( self );
       
   239     self->ConstructL(aEnv, aUid);
       
   240     return self;	
       
   241 	}
       
   242 
       
   243 // ---------------------------------------------------------------------------
       
   244 // 2nd phase constructor
       
   245 // ---------------------------------------------------------------------------
       
   246 //
       
   247 void CAlfTextureManager::ConstructL(CAlfEnv& aEnv, TUid aUid)
       
   248 	{
       
   249     iData = new (ELeave) TPrivateData;
       
   250     
       
   251     // Zero all data
       
   252     iData->iEnv = NULL;  	
       
   253     iData->iTextures.Reset();
       
   254     iData->iLoadQueue.Reset();
       
   255     iData->iLoadObserverQueue.Reset();
       
   256     iData->iAutoSizeObserverQueue.Reset();
       
   257     iData->iBlankTexture = NULL;
       
   258     iData->iImagePath = NULL;
       
   259     iData->iState = EIdle;
       
   260     iData->iBitmap = NULL;
       
   261     iData->iMaskBitmap = NULL;
       
   262     iData->iManagerId = TUid::Uid(0);
       
   263     iData->iProcessor = NULL;
       
   264 
       
   265     // Fill data
       
   266     iData->iAutoGeneratedTextureId = KFirstAutoGeneratedTextureId;
       
   267     iData->iLowestAutoGeneratedTextureId = KFirstAutoGeneratedTextureId;
       
   268     iData->iHighestAutoGeneratedTextureId = KMaxTInt;
       
   269     iData->iEnv = &aEnv;    
       
   270     iData->iManagerId = aUid;
       
   271     iData->iBlankTexture = CAlfTexture::NewL(aEnv, aUid);
       
   272     iData->iBitmap = new (ELeave) CFbsBitmap();
       
   273     User::LeaveIfError(iData->iBitmap->Create(
       
   274         TSize(KAlfDefaultSizeDimension, KAlfDefaultSizeDimension), EColor64K));
       
   275     iData->iMaskBitmap = new (ELeave) CFbsBitmap();
       
   276     User::LeaveIfError(iData->iMaskBitmap->Create(
       
   277         TSize(KAlfDefaultSizeDimension, KAlfDefaultSizeDimension), EGray256));	
       
   278     iData->iProcessor = CAlfTextureProcessor::NewL(aEnv); 
       
   279     User::LeaveIfError(iData->iFs.Connect());
       
   280     iData->iDoomBringer = CIdle::NewL(CActive::EPriorityIdle);
       
   281     // DEBUG 
       
   282     iData->iTextureAutoCounterEnabled = EFalse;
       
   283     iData->iTextureAutoRecreateCounter = 0;
       
   284     iData->iTextureAutoReloadCounter = 0;
       
   285     
       
   286     SetImagePathL(_L(""));
       
   287 	CActiveScheduler::Add(this);
       
   288 	}
       
   289 
       
   290 // ---------------------------------------------------------------------------
       
   291 // Returns env
       
   292 // ---------------------------------------------------------------------------
       
   293 //
       
   294 EXPORT_C CAlfEnv& CAlfTextureManager::Env()
       
   295     {
       
   296     return *iData->iEnv;
       
   297     }
       
   298 
       
   299 // ---------------------------------------------------------------------------
       
   300 // Returns texture with given id
       
   301 // ---------------------------------------------------------------------------
       
   302 //
       
   303 EXPORT_C const CAlfTexture* CAlfTextureManager::Texture(TInt aId) const
       
   304     {
       
   305     TInt index = CheckTexture(aId);
       
   306     if(index == KErrNotFound)
       
   307         {
       
   308         return &BlankTexture();
       
   309         }
       
   310         
       
   311     RArray<TTextureEntry>& textures = (iData->iTextures);	
       
   312     CAlfTexture* texture = textures[index].iTexture;
       
   313     if(texture)
       
   314         {
       
   315         return texture;
       
   316         }
       
   317     else
       
   318         {
       
   319         return &BlankTexture();
       
   320         }    
       
   321     }
       
   322 
       
   323 // ---------------------------------------------------------------------------
       
   324 // Returns texture with given id
       
   325 // ---------------------------------------------------------------------------
       
   326 //
       
   327 EXPORT_C CAlfTexture* CAlfTextureManager::TextureL(TInt aId)
       
   328     {
       
   329     // try to get the index for the texture id
       
   330     TInt index = CheckTexture(aId);
       
   331     if(index != KErrNotFound)
       
   332         {
       
   333         // texture found
       
   334         RArray<TTextureEntry>& textures = (iData->iTextures);	
       
   335         CAlfTexture* texture = textures[index].iTexture;
       
   336         if(texture == NULL)
       
   337             {
       
   338             User::Leave(KErrNotFound);
       
   339             return NULL;                
       
   340             }
       
   341         return texture;
       
   342         }
       
   343 
       
   344     User::Leave(KErrNotFound);
       
   345     return NULL;
       
   346     }
       
   347 
       
   348 // ---------------------------------------------------------------------------
       
   349 // Sets image path
       
   350 // ---------------------------------------------------------------------------
       
   351 //
       
   352 EXPORT_C void CAlfTextureManager::SetImagePathL(const TDesC& aPath)
       
   353     {
       
   354     delete iData->iImagePath;
       
   355     iData->iImagePath = NULL;
       
   356 
       
   357     TParsePtrC parse(aPath);
       
   358     CEikonEnv* coe = CEikonEnv::Static();
       
   359     if (aPath.Length() && !parse.DrivePresent() && coe && coe->EikAppUi() && coe->EikAppUi()->Application())
       
   360         {
       
   361         iData->iImagePath = HBufC::NewL(aPath.Size()+2); // two extra characters for drive
       
   362         TPtr ptr = iData->iImagePath->Des();
       
   363         ptr.Append(coe->EikAppUi()->Application()->AppFullName().Left(2));
       
   364         ptr.Append(aPath);
       
   365         }
       
   366     else
       
   367         {
       
   368         iData->iImagePath = aPath.AllocL();        
       
   369         }
       
   370     }
       
   371     
       
   372 // ---------------------------------------------------------------------------
       
   373 // Gets image path
       
   374 // ---------------------------------------------------------------------------
       
   375 //
       
   376 EXPORT_C const TDesC& CAlfTextureManager::ImagePath() const
       
   377     {
       
   378     return *iData->iImagePath;        
       
   379     }
       
   380 
       
   381 
       
   382 // ---------------------------------------------------------------------------
       
   383 // Returns blank texture.
       
   384 // ---------------------------------------------------------------------------
       
   385 //
       
   386 EXPORT_C const CAlfTexture& CAlfTextureManager::BlankTexture() const
       
   387     {
       
   388     return *iData->iBlankTexture;            
       
   389     }
       
   390 
       
   391 // ---------------------------------------------------------------------------
       
   392 // Returns blank texture.
       
   393 // ---------------------------------------------------------------------------
       
   394 //
       
   395 EXPORT_C CAlfTexture& CAlfTextureManager::BlankTexture()
       
   396     {
       
   397     return *iData->iBlankTexture;            
       
   398     }
       
   399 
       
   400 // ---------------------------------------------------------------------------
       
   401 // DEPRECATED! Load the animated texture based on the Skin name
       
   402 // ---------------------------------------------------------------------------
       
   403 //
       
   404 
       
   405 EXPORT_C CAlfTexture& CAlfTextureManager::LoadAnimatedTextureL(const TDesC& /*aSkinAnimName*/,
       
   406                                        TSize /*aTextureMaxSize*/,
       
   407                                        TAlfTextureFlags /*aFlags*/,
       
   408                                        TInt /*aId*/)
       
   409     {
       
   410     __ALFLOGSTRING( "CAlfTextureManager::LoadAnimatedTextureL FUNCTIONALITY REMOVED. REFER TO ANTRIKSH PROJECT" );
       
   411     CAlfTexture* tex = NULL;
       
   412     return *tex;
       
   413     }
       
   414 
       
   415 // Loads texture.
       
   416 // ---------------------------------------------------------------------------
       
   417 //
       
   418 EXPORT_C CAlfTexture& CAlfTextureManager::LoadTextureL(const TDesC& aImageName,
       
   419                                        TAlfTextureFlags aFlags,
       
   420                                        TInt aId)
       
   421     {
       
   422     return LoadTextureL(aImageName, TSize(0, 0), aFlags, aId);        
       
   423     }
       
   424 
       
   425 // ---------------------------------------------------------------------------
       
   426 // Loads texture.
       
   427 // ---------------------------------------------------------------------------
       
   428 //
       
   429 EXPORT_C CAlfTexture& CAlfTextureManager::LoadTextureL(const TInt aId,
       
   430                                        TSize aTextureMaxSize,
       
   431                                        TAlfTextureFlags aFlags)
       
   432     {
       
   433     return LoadTextureL(_L(""), aTextureMaxSize, aFlags, aId);
       
   434     }
       
   435 
       
   436 // ---------------------------------------------------------------------------
       
   437 // Loads texture.
       
   438 // ---------------------------------------------------------------------------
       
   439 //
       
   440 EXPORT_C CAlfTexture& CAlfTextureManager::LoadTextureL(const TDesC& aImageName,
       
   441                                        TSize aTextureMaxSize,
       
   442                                        TAlfTextureFlags aFlags,
       
   443                                        TInt aId)
       
   444     {    
       
   445     // Clients are not allowed to let toolkit use bitmaps directly. 
       
   446     // We could use it internally if we had separate bitmaps
       
   447     // for each entry.
       
   448     RemoveFlags(aFlags, EAlfTextureFlagAllowDirectBitmapUsage);
       
   449         
       
   450     if (aId == KAlfAutoGeneratedTextureId)
       
   451         {
       
   452         aId = GenerateTextureId();    
       
   453         }    
       
   454     
       
   455     CAlfTexture* tex = NULL;
       
   456     TFileName fileName;
       
   457 
       
   458     // Provide an already created texture if such exists.
       
   459     TRAPD(err, tex = TextureL(aId));
       
   460     if(err == KErrNone && tex->HasContent())
       
   461         {
       
   462         return *tex;
       
   463         }
       
   464 
       
   465     // If shared texture manager, then check the existense of the texture first.
       
   466     if (IsShared())
       
   467         {
       
   468         // AutoSize is not supported (yet) for shared textures
       
   469         RemoveFlags(aFlags, EAlfTextureFlagAutoSize);
       
   470 
       
   471         TBool sharedTextureAlreadyExists = EFalse;
       
   472         iData->iEnv->Client().TextureHasContent(sharedTextureAlreadyExists, 
       
   473             aId, 
       
   474             iData->iManagerId.iUid);
       
   475         
       
   476         // If shared texture already exists, we don't even start to load it.
       
   477         if (sharedTextureAlreadyExists)
       
   478             {
       
   479             TInt bitmapHandle = 0;
       
   480             TInt maskHandle = 0;
       
   481         	
       
   482         	if (iData->iBitmap)
       
   483         		{
       
   484         		bitmapHandle = iData->iBitmap->Handle();
       
   485         		}
       
   486         	
       
   487         	if (iData->iMaskBitmap)	
       
   488         		{
       
   489         		maskHandle = iData->iMaskBitmap->Handle();	
       
   490         		}
       
   491             
       
   492             // Create CAlfTexture instance.
       
   493         	tex = CAlfTexture::NewL( Env(), 
       
   494         	    iData->iManagerId,
       
   495         	    aId, 
       
   496         	    bitmapHandle, 
       
   497         	    maskHandle, 
       
   498         	    aFlags);             
       
   499             
       
   500             if(aImageName.Length() > 0)
       
   501                 {
       
   502                 // assume relative pathname and prepend the image path to get full filename
       
   503                 fileName = aImageName;
       
   504                 PrependImagePath(fileName);
       
   505                 tex->SetFileNameL(fileName);
       
   506                 }
       
   507             
       
   508             tex->SetMaxTextureSize(aTextureMaxSize);
       
   509 
       
   510             return *tex;    
       
   511             }            
       
   512         }
       
   513 
       
   514     // If the name is invalid, and there was no filename available
       
   515     // based on id, return a dummy texture.
       
   516     if((aImageName.Length() == 0) && (aId == 0))
       
   517         {
       
   518         return BlankTexture();
       
   519         }
       
   520 
       
   521     // add path to filename if filename has been passed
       
   522     if(aImageName.Length() > 0)
       
   523         {
       
   524         // assume relative pathname and prepend the image path to get full filename
       
   525         fileName = aImageName;
       
   526         PrependImagePath(fileName);
       
   527         }
       
   528 
       
   529     // if no name has been passed as a parameter but
       
   530     // there's and nonzero id has been passed, we
       
   531     // can assume that there's a predefined name available
       
   532     RArray<TTextureEntry>& textures = (iData->iTextures);	
       
   533     RArray<TLoadQueueEntry>& loadqueue = (iData->iLoadQueue);	
       
   534 
       
   535     if((aImageName.Length() == 0) && (aId != 0))
       
   536        {
       
   537         // search for a texture filename based on the id.
       
   538         TInt index = CheckTexture(aId);
       
   539         if(index >=0)
       
   540             {
       
   541             tex = textures[index].iTexture;
       
   542             fileName = *tex->FileName();
       
   543             }
       
   544         else
       
   545             {
       
   546             User::Leave(KErrNotFound);
       
   547             }
       
   548        }
       
   549 
       
   550     // Reuse pre-existing entries:
       
   551     // try first finding an entry based on id
       
   552     if(!tex && aId > 0)
       
   553         {
       
   554         TInt previouslyLoadedIndex = CheckTexture(aId);
       
   555         if (previouslyLoadedIndex >= 0)
       
   556             {
       
   557             tex = textures[previouslyLoadedIndex].iTexture;
       
   558             }
       
   559         }
       
   560 
       
   561     if (!tex)
       
   562         {
       
   563         TInt bitmapHandle = 0;
       
   564         TInt maskHandle = 0;
       
   565 
       
   566         // If LoadAnimAsImage flag is set, we don't check the framecount with ImageDecoder!
       
   567         //
       
   568         // This is useful especially when loading multiple large image files
       
   569         // as textures that don't have more then 1 frame.
       
   570         //
       
   571         // Some test results creating the ImageDecoder: 
       
   572         // - Large Leafs.mbm (2,7MB) took apporx. 280ms
       
   573         // - Big bmp (~1,8MB) took ~130ms 
       
   574         // - Normal sized (100-800kb) jpgs and gifs took approx. 25-40ms
       
   575         TInt frameCount = 1;
       
   576         TSize animFrameSize = TSize(0,0);
       
   577         if ( !(aFlags & EAlfTextureFlagLoadAnimAsImage) )
       
   578             {
       
   579             CImageDecoder* decoder = CImageDecoder::FileNewL(iData->iFs, fileName);
       
   580             CleanupStack::PushL(decoder);
       
   581             frameCount = decoder->FrameCount();
       
   582             if (frameCount > 1)
       
   583                 {
       
   584                 const TFrameInfo& fInfo =  decoder->FrameInfo(0);
       
   585                 animFrameSize = fInfo.iOverallSizeInPixels;
       
   586                 }
       
   587             CleanupStack::PopAndDestroy();
       
   588             }
       
   589         
       
   590         if (frameCount > 1)
       
   591             {
       
   592             tex = CAlfTexture::NewL(Env(), iData->iManagerId, aId, bitmapHandle, maskHandle, aFlags, ETrue);        
       
   593             tex->SetMaxTextureSize(aTextureMaxSize);
       
   594             tex->SetSize(animFrameSize);
       
   595             tex->SetFileNameL(fileName);
       
   596             return *tex;
       
   597             }
       
   598         else
       
   599             {
       
   600         	if (iData->iBitmap)
       
   601         		{
       
   602     	    	bitmapHandle = iData->iBitmap->Handle();
       
   603     		    }
       
   604     	
       
   605         	if (iData->iMaskBitmap)	
       
   606     		    {
       
   607     		    maskHandle = iData->iMaskBitmap->Handle();	
       
   608     		    }
       
   609         	tex = CAlfTexture::NewL(Env(), iData->iManagerId, aId, bitmapHandle, maskHandle, aFlags);        
       
   610             }
       
   611         }
       
   612     else
       
   613         {
       
   614         // we have a pre-existing texture which is non-null,
       
   615         // but check that the texture is loaded ok, we can also
       
   616         // return unloaded textures that are in the load queue
       
   617         if (tex->HasContent() || tex->IsAnimated() || IsInLoadQueue(tex))
       
   618             {
       
   619             return *(tex);
       
   620             }
       
   621         }
       
   622 
       
   623     // replace filename
       
   624     // File names are relative to the image path.
       
   625     tex->SetFileNameL(fileName);
       
   626     tex->SetMaxTextureSize(aTextureMaxSize);
       
   627 
       
   628     // Set not released 
       
   629     tex->SetReleaseFlags(CAlfTexture::EReleaseNone);
       
   630 
       
   631     // If autosize used and size is set to zero, we don't yet load at all.
       
   632     if (aFlags & EAlfTextureFlagAutoSize)
       
   633         {            
       
   634         if (aTextureMaxSize.iHeight == 0 && aTextureMaxSize.iWidth == 0)
       
   635             {
       
   636             return *tex;    
       
   637             }        
       
   638         }
       
   639         
       
   640     // Prepare for loading by creating a load queue entry.
       
   641     TTextureEntry entry;
       
   642     entry.iTexture = tex;
       
   643     entry.iId = aId;
       
   644 
       
   645     TLoadQueueEntry loadqentry;
       
   646     loadqentry.iUnloaded = EFalse;
       
   647     loadqentry.iLoading = entry;
       
   648     loadqentry.iDecoder = NULL;
       
   649 
       
   650     // Textures are loaded one at a time, in the order they were requested.
       
   651     loadqueue.AppendL(loadqentry);
       
   652 
       
   653     // Start the texture load active object if we're not loading
       
   654     if(iData->iState == EIdle)
       
   655         {
       
   656         // Start loading images..
       
   657         StartLoading();
       
   658         // Notify observers.
       
   659         NotifyStateChange();
       
   660         }
       
   661 
       
   662     return *tex;
       
   663     }
       
   664 
       
   665 
       
   666 // ---------------------------------------------------------------------------
       
   667 // Creates texture.
       
   668 // ---------------------------------------------------------------------------
       
   669 //
       
   670 EXPORT_C CAlfTexture& CAlfTextureManager::CreateTextureL(TInt aId,
       
   671                                    MAlfBitmapProvider* aBitmapProvider,
       
   672                                    TAlfTextureFlags aFlags)
       
   673     {    
       
   674     // Clients are not allowed to let toolkit use bitmaps directly. It is used only internally.
       
   675     RemoveFlags(aFlags, EAlfTextureFlagAllowDirectBitmapUsage);
       
   676 
       
   677     CAlfTexture* tex = NULL;
       
   678     
       
   679     if (aId == KAlfAutoGeneratedTextureId)
       
   680         {
       
   681         aId = GenerateTextureId();    
       
   682         }    
       
   683 
       
   684     CFbsBitmap* bitmap = NULL;
       
   685     CFbsBitmap* maskBitmap = NULL;
       
   686 
       
   687     if (aId==0)
       
   688         {
       
   689         User::Leave(KErrArgument);
       
   690         }
       
   691 
       
   692     // Provide an already created texture if such exists.
       
   693     TRAPD(err, tex = TextureL(aId));
       
   694     if(err == KErrNone && tex->HasContent())
       
   695         {
       
   696         return *tex;
       
   697         }
       
   698 
       
   699     // Call the bitmapProvider method to load the bitmaps
       
   700 	if (aBitmapProvider)
       
   701 		{
       
   702 	    aBitmapProvider->ProvideBitmapL(aId, bitmap, maskBitmap);		
       
   703 		}
       
   704 					
       
   705 	if (!bitmap)
       
   706 	    { 
       
   707 	    // We leave here, otherwise serverside would panic. 
       
   708 	    User::Leave(KErrArgument);    
       
   709 	    // Bitmap size is checked and handled in serverside, 
       
   710 	    // so that we can create empty textures (size = 0,0)
       
   711 	    }
       
   712 	    	  
       
   713 	// "bitmap" pointer should be valid from now on
       
   714     CleanupStack::PushL(bitmap);
       
   715 	TInt bitmapHandle = bitmap->Handle();
       
   716 	
       
   717 	TInt maskHandle = 0;
       
   718 	if (maskBitmap)	
       
   719 		{
       
   720 		maskHandle = maskBitmap->Handle();	
       
   721 	    CleanupStack::PushL(maskBitmap);
       
   722 		}
       
   723     
       
   724     // Create CAlfTexture instance, this duplicates the bitmaps to server.
       
   725 	if (!tex)
       
   726 	    {
       
   727     	tex = CAlfTexture::NewL( Env(), 
       
   728     	                         iData->iManagerId,
       
   729     	                         aId, 
       
   730     	                         bitmapHandle, 
       
   731     	                         maskHandle, 
       
   732     	                         aFlags);	        
       
   733 	    }
       
   734 	else
       
   735 	    {
       
   736 	    // texture already exists but it does not have content, this creates content.
       
   737       	iData->iEnv->Client().TextureCreateL( aId, bitmapHandle, 
       
   738         	maskHandle, aFlags, iData->iManagerId.iUid );    	            	        
       
   739 	    }    
       
   740 		
       
   741 	tex->SetBitmapProvider(aBitmapProvider);	
       
   742     tex->SetSize(bitmap->SizeInPixels());
       
   743 
       
   744     // Set not released 
       
   745     tex->SetReleaseFlags(CAlfTexture::EReleaseNone);
       
   746 	
       
   747 	// CAlfTexture has at this point duplicated bitmaps, can be deleted here.        
       
   748 	if (maskBitmap)	
       
   749 		{
       
   750 	    CleanupStack::PopAndDestroy( maskBitmap );
       
   751 	    maskBitmap = NULL;		
       
   752 		}
       
   753     CleanupStack::PopAndDestroy( bitmap ); 
       
   754 	bitmap = NULL;		
       
   755 
       
   756     // Notify observers
       
   757     NotifyTextureLoaded(*tex, aId, KErrNone);
       
   758 
       
   759     return *tex;
       
   760     }
       
   761 
       
   762 // ---------------------------------------------------------------------------
       
   763 //  Unloads texture
       
   764 // ---------------------------------------------------------------------------
       
   765 //
       
   766 EXPORT_C void CAlfTextureManager::UnloadTexture(const TDesC& aImageName)
       
   767     {
       
   768     TInt index = CheckTexture(aImageName);
       
   769     if (index >= 0)
       
   770         {
       
   771         RArray<TTextureEntry>& textures = (iData->iTextures);	
       
   772         TTextureEntry entry = textures[index];        
       
   773         CancelLoadingOfTexture(*entry.iTexture);
       
   774         if (!entry.iTexture->IsAnimated())
       
   775             {
       
   776             iData->iEnv->Client().TextureUnload(entry.iId, iData->iManagerId.iUid);
       
   777             }
       
   778         else
       
   779             {
       
   780             entry.iTexture->StopAnimation();      
       
   781             }
       
   782         
       
   783         TInt releaseFlags = entry.iTexture->ReleaseFlags();
       
   784         releaseFlags |= CAlfTexture::EReleaseFromUnload;
       
   785         entry.iTexture->SetReleaseFlags(releaseFlags);
       
   786         }
       
   787     }
       
   788 
       
   789 // ---------------------------------------------------------------------------
       
   790 //  Unloads texture
       
   791 // ---------------------------------------------------------------------------
       
   792 //
       
   793 EXPORT_C void CAlfTextureManager::UnloadTexture(TInt aId)
       
   794     {
       
   795     TInt index = CheckTexture(aId);
       
   796     if (index >= 0)
       
   797         {
       
   798         RArray<TTextureEntry>& textures = (iData->iTextures);	
       
   799         TTextureEntry entry = textures[index];        
       
   800 		CancelLoadingOfTexture(*entry.iTexture);
       
   801         if (!entry.iTexture->IsAnimated())
       
   802             {
       
   803             iData->iEnv->Client().TextureUnload( aId, iData->iManagerId.iUid );    	                
       
   804             }
       
   805         else
       
   806             {
       
   807             entry.iTexture->StopAnimation();        
       
   808             }           
       
   809         
       
   810         TInt releaseFlags = entry.iTexture->ReleaseFlags();
       
   811         releaseFlags |= CAlfTexture::EReleaseFromUnload;
       
   812         entry.iTexture->SetReleaseFlags(releaseFlags);
       
   813         }
       
   814     }
       
   815  
       
   816 // ---------------------------------------------------------------------------
       
   817 //  Updates texture content
       
   818 // ---------------------------------------------------------------------------
       
   819 //
       
   820 EXPORT_C void CAlfTextureManager::UpdateTextureFromFileL(TInt aId, const TDesC* aFileName)
       
   821     {
       
   822    	RArray<TTextureEntry>& textureEntries = (iData->iTextures);	
       
   823     TInt index = CheckTexture(aId);
       
   824     if (index >= 0)
       
   825         {
       
   826     	TTextureEntry entry = textureEntries[index];
       
   827     	
       
   828     	TFileName fileName;
       
   829     	if (aFileName != NULL)
       
   830     		{
       
   831     		fileName = *aFileName;
       
   832     		}
       
   833     	else if (entry.iTexture->FileName() == NULL)
       
   834     		{
       
   835     		User::Leave(KErrArgument);
       
   836     		}	
       
   837         entry.iTexture->SetBitmapProvider(NULL);
       
   838         
       
   839         // Set non released
       
   840         entry.iTexture->SetReleaseFlags(CAlfTexture::EReleaseNone);
       
   841 
       
   842         if (!entry.iTexture->IsAnimated())
       
   843             {
       
   844            	ReloadTextureL(fileName, entry.iTexture->MaxTextureSize(), entry.iTexture->Flags(), 
       
   845                	entry.iTexture->Id());
       
   846             }
       
   847         else
       
   848             {
       
   849             entry.iTexture->StartAnimation();    
       
   850             }    
       
   851         } 
       
   852     else
       
   853     	{
       
   854     	User::Leave(KErrNotFound);
       
   855     	}           
       
   856     }
       
   857     
       
   858 // ---------------------------------------------------------------------------
       
   859 //  Updates texture content
       
   860 // ---------------------------------------------------------------------------
       
   861 //
       
   862 EXPORT_C void CAlfTextureManager::UpdateTextureFromBitmapL(TInt aId, MAlfBitmapProvider* aBitmapProvider)
       
   863     {
       
   864    	RArray<TTextureEntry>& textureEntries = (iData->iTextures);	
       
   865     TInt index = CheckTexture(aId);
       
   866     if (index >= 0)
       
   867         {
       
   868     	TTextureEntry entry = textureEntries[index];
       
   869     	
       
   870     	if (!aBitmapProvider)
       
   871     		{
       
   872     		aBitmapProvider = entry.iTexture->BitmapProvider();
       
   873     		}
       
   874     	TBuf<1> empty;	
       
   875         entry.iTexture->SetFileNameL(empty);
       
   876 
       
   877         // Set non released
       
   878         entry.iTexture->SetReleaseFlags(CAlfTexture::EReleaseNone);
       
   879 
       
   880         if (!entry.iTexture->IsAnimated())
       
   881             {
       
   882            	RecreateTextureL(entry.iTexture->Id(), aBitmapProvider, entry.iTexture->Flags());
       
   883             }
       
   884         else
       
   885             {
       
   886             entry.iTexture->StartAnimation();     
       
   887             }    
       
   888         }        
       
   889     else
       
   890     	{
       
   891     	User::Leave(KErrNotFound);
       
   892     	}           
       
   893     } 
       
   894     
       
   895     
       
   896 // ---------------------------------------------------------------------------
       
   897 //  Defines filename for given id.
       
   898 // ---------------------------------------------------------------------------
       
   899 //
       
   900 EXPORT_C void CAlfTextureManager::DefineFileNameL(TInt aId, const TDesC& aFileName)
       
   901     {
       
   902     if (aId==0)
       
   903         {
       
   904         User::Leave(KErrArgument); // can't specify filename for "no id"
       
   905         }
       
   906 
       
   907    	RArray<TTextureEntry>& textures = (iData->iTextures);	
       
   908 
       
   909     // Look for an existing entry for the id.
       
   910     for(TInt i = 0; i < textures.Count(); ++i)
       
   911         {
       
   912         if(textures[i].iId == aId)
       
   913             {
       
   914             textures[i].iTexture->SetFileNameL(aFileName);
       
   915             return;
       
   916             }
       
   917         }
       
   918 
       
   919     // Otherwise just append to the texture list
       
   920 	CAlfTexture* tex = CAlfTexture::NewL( Env(), iData->iManagerId, aId );  
       
   921 	tex->SetFileNameL(aFileName);
       
   922     }
       
   923     
       
   924 // ---------------------------------------------------------------------------
       
   925 // Prepends image path
       
   926 // ---------------------------------------------------------------------------
       
   927 //
       
   928 EXPORT_C void CAlfTextureManager::PrependImagePath(TDes& aFileName)
       
   929     {
       
   930     TFileName buf;
       
   931 
       
   932     //allow app to load textures from different drive with complete path
       
   933     TParse p1;
       
   934     p1.Set(aFileName,0,0);
       
   935 
       
   936     if (p1.DrivePresent())
       
   937         {
       
   938         return;
       
   939         }
       
   940 
       
   941 
       
   942     if(aFileName.Find(*iData->iImagePath) == KErrNotFound)
       
   943         {
       
   944         buf = *iData->iImagePath;
       
   945         buf.Append(aFileName);
       
   946         aFileName = buf;
       
   947         }
       
   948     }
       
   949 
       
   950 
       
   951 
       
   952 // ---------------------------------------------------------------------------
       
   953 // CheckTexture
       
   954 // ---------------------------------------------------------------------------
       
   955 //
       
   956 TInt CAlfTextureManager::CheckTexture(const TDesC& aImageName) const
       
   957     {
       
   958     if(aImageName.Length()==0)
       
   959         {
       
   960         // name empty, can't check
       
   961         return KErrNotFound;
       
   962         }
       
   963 
       
   964     RArray<TTextureEntry>& textures = (iData->iTextures);	
       
   965     for(TInt i = 0; i < textures.Count(); ++i)
       
   966         {
       
   967         TTextureEntry te = textures[i];
       
   968         // compare against texture manager entry filename (iFileName)
       
   969         if((te.iTexture->FileName() != NULL)
       
   970             && (aImageName.Compare(*(te.iTexture->FileName())) == 0))
       
   971             {
       
   972             return i;
       
   973             }
       
   974         }
       
   975     // not found
       
   976     return KErrNotFound;
       
   977     }
       
   978 
       
   979 	
       
   980 // ---------------------------------------------------------------------------
       
   981 // CheckTexture
       
   982 // ---------------------------------------------------------------------------
       
   983 //
       
   984 TInt CAlfTextureManager::CheckTexture(TInt aId) const
       
   985     {
       
   986     RArray<TTextureEntry>& textures = (iData->iTextures);	
       
   987     if(aId <= 0)
       
   988         {
       
   989         // id not defined, can't search
       
   990         return KErrNotFound;
       
   991         }
       
   992     for(TInt i = 0; i < textures.Count(); i++)
       
   993         {
       
   994         if(textures[i].iId == aId)
       
   995             {
       
   996             return i;
       
   997             }
       
   998         }
       
   999     // not found:
       
  1000     return KErrNotFound;
       
  1001     }
       
  1002     
       
  1003     
       
  1004 
       
  1005 // ---------------------------------------------------------------------------
       
  1006 // RunError from CActive
       
  1007 // ---------------------------------------------------------------------------
       
  1008 //
       
  1009 TInt CAlfTextureManager::RunError(TInt /*aError*/)
       
  1010     {
       
  1011     return KErrNone;
       
  1012     // Should never be called, RunL is responsible for handling all error cases
       
  1013     }
       
  1014 
       
  1015 
       
  1016 // ---------------------------------------------------------------------------
       
  1017 // RunL from CActive
       
  1018 // ---------------------------------------------------------------------------
       
  1019 //
       
  1020 void CAlfTextureManager::RunL()
       
  1021     {
       
  1022     // remove the loaded entry from the queue
       
  1023     TLoadQueueEntry entry = PopLoadedQueueEntry();
       
  1024 
       
  1025     // Image loading has been completed.
       
  1026     iData->iState = EIdle;
       
  1027 
       
  1028     // check status
       
  1029     if(iStatus == KErrNone)
       
  1030         {
       
  1031         // ok, we have a loaded image, but
       
  1032         // we still need to do texture uploads
       
  1033         // and possibly some image conversions
       
  1034         TRAPD( err, ImageLoadingCompleteL(entry) );
       
  1035 
       
  1036         if(err != KErrNone)
       
  1037             {
       
  1038             // Notify observers about the image upload error
       
  1039             NotifyTextureLoaded(*entry.iLoading.iTexture, entry.iLoading.iId, err);
       
  1040             }
       
  1041         }
       
  1042     else
       
  1043         {
       
  1044         // notify sb of failed image load!
       
  1045         NotifyTextureLoaded(*entry.iLoading.iTexture, entry.iLoading.iId, iStatus.Int());
       
  1046         }
       
  1047 
       
  1048     StartLoading();
       
  1049     }
       
  1050 
       
  1051 // ---------------------------------------------------------------------------
       
  1052 // Cancels asyncronous loading
       
  1053 // ---------------------------------------------------------------------------
       
  1054 //
       
  1055 void CAlfTextureManager::DoCancel()
       
  1056     {
       
  1057     RArray<TLoadQueueEntry>& loadqueue = (iData->iLoadQueue);	
       
  1058     if(loadqueue.Count() > 0)
       
  1059         {
       
  1060         loadqueue[0].iDecoder->Cancel();
       
  1061         }
       
  1062     iData->iState = EIdle;
       
  1063     }
       
  1064 
       
  1065 // ---------------------------------------------------------------------------
       
  1066 // Starts asyncronous loading
       
  1067 // ---------------------------------------------------------------------------
       
  1068 //
       
  1069 void CAlfTextureManager::StartLoading()
       
  1070     {
       
  1071     // loop that finds next entry to load
       
  1072     while (1)
       
  1073         {
       
  1074         // try to schedule next image for loading..
       
  1075         TRAPD( err, DoLoadNextL() );
       
  1076 
       
  1077         // ok?            
       
  1078         if(err != KErrNone)
       
  1079             {            
       
  1080             // remove the entry from the queue
       
  1081             TLoadQueueEntry entry = PopLoadedQueueEntry();
       
  1082             // Notify observers about the image loading error
       
  1083             NotifyTextureLoaded(*entry.iLoading.iTexture, entry.iLoading.iId, err);            
       
  1084             // Image loading has been completed.
       
  1085             iData->iState = EIdle;
       
  1086             continue;
       
  1087             }
       
  1088         // leave the loop if we had no trouble scheduling the next
       
  1089         // image decode
       
  1090         break;
       
  1091         }
       
  1092     }
       
  1093 
       
  1094 // ---------------------------------------------------------------------------
       
  1095 // Loads texture entry from queue. Mostly this code is copied from 
       
  1096 // CAlfTextureManager::DoLoadNextL but some adjustmets has been made to support
       
  1097 // better client server paradigm.
       
  1098 // 
       
  1099 // ---------------------------------------------------------------------------
       
  1100 //
       
  1101 void CAlfTextureManager::DoLoadNextL()
       
  1102     {
       
  1103     RArray<TLoadQueueEntry>& loadqueue = (iData->iLoadQueue);	
       
  1104     // Any loading tasks left?
       
  1105     if(loadqueue.Count() == 0)
       
  1106         {
       
  1107         // No? Notify observers and leave.
       
  1108         NotifyStateChange();
       
  1109         return; // nothing else to be loaded..
       
  1110         }
       
  1111 
       
  1112     // Manager is now busy.
       
  1113     iData->iState = ELoading;
       
  1114 
       
  1115     // Fetch a load queue entry
       
  1116     TLoadQueueEntry& entry = loadqueue[0];
       
  1117     CAlfTexture* texture = entry.iLoading.iTexture;
       
  1118 
       
  1119     // Create a new image decoder for loading the image.
       
  1120     TFileName imageFileName = *texture->FileName(); // does not include image path
       
  1121     PrependImagePath(imageFileName);
       
  1122     entry.iDecoder = 0;
       
  1123     // We use fast decode because it seems to be a lot faster with jpegs.
       
  1124     TRAPD( err,  entry.iDecoder = CImageDecoder::FileNewL(iData->iFs, imageFileName, CImageDecoder::EPreferFastDecode ));
       
  1125 
       
  1126     // check for errors..
       
  1127     if(err != KErrNone)
       
  1128         {
       
  1129         // Try to cancel the decoding (if possible)
       
  1130         if(entry.iDecoder)
       
  1131             {
       
  1132             entry.iDecoder->Cancel();
       
  1133             }
       
  1134         User::Leave(err); // re-leave with the error
       
  1135         }
       
  1136         
       
  1137     // from decoder's frame info retrieve the framesize
       
  1138     TFrameInfo frameInfo(entry.iDecoder->FrameInfo(0));
       
  1139 
       
  1140     // check for alpha channel 
       
  1141     if(frameInfo.iFlags & TFrameInfo::ETransparencyPossible )
       
  1142         {
       
  1143         entry.iHasAlpha = ETrue;
       
  1144         }
       
  1145     else
       
  1146         {
       
  1147         entry.iHasAlpha = EFalse;
       
  1148         }
       
  1149 
       
  1150     // Get the image original size
       
  1151     TRect bitmapSize = frameInfo.iFrameCoordsInPixels;
       
  1152     entry.iOriginalSize = bitmapSize.Size();
       
  1153 
       
  1154     // target resolution for texture, initially equal to bitmap size
       
  1155     TInt widthResolutionTarget = bitmapSize.Size().iWidth;
       
  1156     TInt heightResolutionTarget = bitmapSize.Size().iHeight;
       
  1157 
       
  1158     TSize maxTexSize = entry.iLoading.iTexture->MaxTextureSize();
       
  1159 
       
  1160     // Assign new texture resolution target dimensions
       
  1161     // if we have explicitly requested them
       
  1162     if( (entry.iLoading.iTexture->Flags() & EAlfTextureFlagDoNotRetainResolution)
       
  1163             && maxTexSize.iWidth > 0
       
  1164             && maxTexSize.iHeight > 0)
       
  1165         {
       
  1166         // assign new target resolution for decoder-based scaling
       
  1167         if(maxTexSize.iWidth < widthResolutionTarget)
       
  1168             {
       
  1169             widthResolutionTarget = maxTexSize.iWidth;
       
  1170             }
       
  1171         if(maxTexSize.iHeight < heightResolutionTarget)
       
  1172             {
       
  1173             heightResolutionTarget = maxTexSize.iHeight;
       
  1174             }
       
  1175         }
       
  1176 
       
  1177     // we need to do some downscaling, but can we do arbitrary
       
  1178     // scaling as well?
       
  1179     if(frameInfo.iFlags & TFrameInfo::EFullyScaleable)
       
  1180         {
       
  1181         // .. yes, arbitrary scaling is possible
       
  1182         // just assign the new size to the bitmap
       
  1183         // so that it will be scaled accordingly during
       
  1184         // conversion
       
  1185         }
       
  1186     else
       
  1187         {
       
  1188         // all decoders should be able to do 1/2, 1/4, 1/8 DCT Scaling
       
  1189         // calculate nearest half size for the decoder-downscaled bitmap
       
  1190         // halve image width&height to size which is closest larger match
       
  1191         // of the bitmap size
       
  1192         TInt halvedWidth = bitmapSize.Size().iWidth;
       
  1193         TInt halvedHeight = bitmapSize.Size().iHeight;
       
  1194         TInt halveFactor = 1; // this limits the halving to 1/8 max
       
  1195         while ( ((halvedWidth >> 1) > widthResolutionTarget) &&
       
  1196                 ((halvedHeight >> 1) > heightResolutionTarget)
       
  1197                 && (halveFactor << 1) <= 8)
       
  1198             {
       
  1199             halveFactor <<= 1;
       
  1200             }
       
  1201         halvedWidth = halvedWidth / halveFactor;
       
  1202         halvedHeight = halvedHeight / halveFactor;
       
  1203         // .. the bitmap will be downscaled further to the correct
       
  1204         // dimensions by the toolkit after the bitmap has been decoded
       
  1205         widthResolutionTarget = halvedWidth;
       
  1206         heightResolutionTarget = halvedHeight;
       
  1207         }
       
  1208 
       
  1209 
       
  1210     if (!(entry.iLoading.iTexture->Flags() & EAlfTextureFlagRetainColorDepth) && 
       
  1211         iData->iBitmap->DisplayMode()!=EColor64K)
       
  1212         {
       
  1213         // (Re)Create the bitmap in EColor64K (16bit) mode to save memory
       
  1214         iData->iBitmap->Create(TSize(widthResolutionTarget, heightResolutionTarget), EColor64K);
       
  1215         }
       
  1216     else if ((entry.iLoading.iTexture->Flags() & EAlfTextureFlagRetainColorDepth) && 
       
  1217         iData->iBitmap->DisplayMode()==EColor64K)
       
  1218         {
       
  1219         // (Re)Create the bitmap in EColor16MU (24bit) mode retain the color information
       
  1220         iData->iBitmap->Create(TSize(widthResolutionTarget, heightResolutionTarget), EColor16MU);
       
  1221         }
       
  1222     else
       
  1223         {
       
  1224         // no need to recreate the bitmap, but assign the new size!
       
  1225         iData->iBitmap->Resize(TSize(widthResolutionTarget, heightResolutionTarget));
       
  1226         }
       
  1227 
       
  1228     if (iData->iBitmap->DisplayMode()==EColor64K)
       
  1229         {
       
  1230         }
       
  1231     // Decode ( and rescale ) to bitmap.
       
  1232     if(entry.iHasAlpha)
       
  1233         {
       
  1234         // set the alpha channel bitmap to the same size than the color bitmap
       
  1235         iData->iMaskBitmap->Resize(TSize(widthResolutionTarget, heightResolutionTarget));
       
  1236         entry.iDecoder->Convert(&iStatus, *iData->iBitmap, *iData->iMaskBitmap, 0);
       
  1237         }
       
  1238     else
       
  1239         {
       
  1240         // We cannot do resize mask to smaller until serverside works differently
       
  1241         iData->iMaskBitmap->Resize(TSize(widthResolutionTarget, heightResolutionTarget));
       
  1242         entry.iDecoder->Convert(&iStatus, *iData->iBitmap, 0);
       
  1243         }
       
  1244     // Wait for completion.
       
  1245     SetActive();
       
  1246 
       
  1247     }
       
  1248 
       
  1249 
       
  1250 // ---------------------------------------------------------------------------
       
  1251 // Pops entry from load queue
       
  1252 // ---------------------------------------------------------------------------
       
  1253 //
       
  1254 TLoadQueueEntry CAlfTextureManager::PopLoadedQueueEntry()
       
  1255     {
       
  1256     RArray<TLoadQueueEntry>& loadqueue = (iData->iLoadQueue);	
       
  1257     TLoadQueueEntry entry = loadqueue[0];
       
  1258     loadqueue.Remove(0);
       
  1259     // Delete the decoder.
       
  1260     delete entry.iDecoder;
       
  1261     entry.iDecoder = 0;
       
  1262     return entry;
       
  1263     }
       
  1264 
       
  1265 
       
  1266 // ---------------------------------------------------------------------------
       
  1267 // This method gets called when image loading has been completed and server
       
  1268 // side texture needs to be created.
       
  1269 // ---------------------------------------------------------------------------
       
  1270 //
       
  1271 void CAlfTextureManager::ImageLoadingCompleteL(TLoadQueueEntry& aEntry)
       
  1272     {                    
       
  1273     TSize maxTexSize = aEntry.iLoading.iTexture->MaxTextureSize();    
       
  1274     
       
  1275     // Calculate new maxsize keeping the aspect ratio if only one max dimension was
       
  1276     // specified.
       
  1277     if ((maxTexSize.iWidth == 0 && maxTexSize.iHeight != 0) ||
       
  1278         (maxTexSize.iWidth != 0 && maxTexSize.iHeight == 0))
       
  1279         {
       
  1280         TSize sizeInPixels = iData->iBitmap->SizeInPixels();
       
  1281         if (sizeInPixels.iWidth != 0 && sizeInPixels.iHeight != 0)
       
  1282             {
       
  1283             if (maxTexSize.iWidth == 0)
       
  1284                 {
       
  1285                 maxTexSize.iWidth = (maxTexSize.iHeight * sizeInPixels.iWidth)/sizeInPixels.iHeight;                    
       
  1286                 }
       
  1287             else if (maxTexSize.iHeight == 0)
       
  1288                 {
       
  1289                 maxTexSize.iHeight = (maxTexSize.iWidth * sizeInPixels.iHeight)/sizeInPixels.iWidth;   
       
  1290                 }                                
       
  1291             }            
       
  1292         }
       
  1293     
       
  1294     
       
  1295     if( (maxTexSize.iWidth != 0) && 
       
  1296         (maxTexSize.iHeight != 0) && 
       
  1297         (iData->iBitmap->SizeInPixels() != aEntry.iLoading.iTexture->MaxTextureSize()))
       
  1298         {
       
  1299         // The decoder failed to constrain the texture dimensions properly, due to its internal limitations.
       
  1300         // So we need to scale the texture(s) down further to the correct size.              
       
  1301         CFbsBitmap* dest = new (ELeave) CFbsBitmap();   
       
  1302         dest->Create(maxTexSize, iData->iBitmap->DisplayMode());     
       
  1303         CleanupStack::PushL(dest);
       
  1304         AlfUtil::ScaleFbsBitmapL(*iData->iBitmap, *dest);
       
  1305         CleanupStack::Pop(); // dest
       
  1306         delete iData->iBitmap;
       
  1307         iData->iBitmap = dest;
       
  1308 
       
  1309         if(aEntry.iHasAlpha)
       
  1310             {
       
  1311             // Scale the alpha as well.
       
  1312             dest = new (ELeave) CFbsBitmap();   
       
  1313             dest->Create(maxTexSize, iData->iMaskBitmap->DisplayMode());     
       
  1314             CleanupStack::PushL(dest);
       
  1315             AlfUtil::ScaleFbsBitmapL(*iData->iMaskBitmap, *dest);
       
  1316             CleanupStack::Pop(); // dest
       
  1317             delete iData->iMaskBitmap;
       
  1318             iData->iMaskBitmap = dest;
       
  1319             }                                      
       
  1320         }        
       
  1321 
       
  1322     TInt bitmapHandle = 0;
       
  1323     TInt maskHandle = 0;
       
  1324 	
       
  1325 	if (iData->iBitmap)
       
  1326 		{
       
  1327 		bitmapHandle = iData->iBitmap->Handle();
       
  1328 		}
       
  1329 	
       
  1330 	if (iData->iMaskBitmap && aEntry.iHasAlpha)	
       
  1331 		{
       
  1332 		maskHandle = iData->iMaskBitmap->Handle();	
       
  1333 		}
       
  1334 
       
  1335     TInt handle = iData->iEnv->Client().TextureLoadL( aEntry.iLoading.iTexture->Id(), 
       
  1336    	    bitmapHandle, 
       
  1337    	    maskHandle, 
       
  1338    	    aEntry.iLoading.iTexture->Flags(), 
       
  1339    	    iData->iManagerId.iUid);
       
  1340 
       
  1341     aEntry.iLoading.iTexture->SetServerHandle(handle);   	    
       
  1342     
       
  1343     if (iData->iBitmap)
       
  1344         aEntry.iLoading.iTexture->SetSize(iData->iBitmap->SizeInPixels());
       
  1345 
       
  1346     // Notify the observers of loaded texture
       
  1347     NotifyTextureLoaded(*aEntry.iLoading.iTexture, aEntry.iLoading.iId, KErrNone);
       
  1348 
       
  1349     // Resize bitmaps to save memory
       
  1350     iData->iBitmap->Reset();
       
  1351     iData->iMaskBitmap->Reset();
       
  1352     iData->iBitmap->Create(
       
  1353         TSize(KAlfDefaultSizeDimension, KAlfDefaultSizeDimension), EColor64K);
       
  1354     iData->iMaskBitmap->Create(
       
  1355         TSize(KAlfDefaultSizeDimension, KAlfDefaultSizeDimension), EGray256);
       
  1356 
       
  1357     // DEBUG 
       
  1358     if (iData->iTextureAutoCounterEnabled)
       
  1359         {            
       
  1360         TBuf<256> numBuf;
       
  1361         numBuf.FillZ();
       
  1362         numBuf.Append(_L("Reloads:"));
       
  1363         numBuf.AppendNum(iData->iTextureAutoReloadCounter);
       
  1364         numBuf.Append(_L(" - Recreates:"));
       
  1365         numBuf.AppendNum(iData->iTextureAutoRecreateCounter);
       
  1366         User::InfoPrint(numBuf);
       
  1367         }
       
  1368 
       
  1369     }
       
  1370 
       
  1371 // ---------------------------------------------------------------------------
       
  1372 // 
       
  1373 // ---------------------------------------------------------------------------
       
  1374 //
       
  1375 void CAlfTextureManager::NotifyStateChange() const
       
  1376     {
       
  1377     __ALFLOGSTRING( "CAlfTextureManager::NotifyStateChange" )
       
  1378 
       
  1379     RPointerArray<MAlfTextureManagerStateChangedObserver>& observers = 
       
  1380         (iData->iStateObserverQueue);	
       
  1381     TInt count = observers.Count();
       
  1382     for(TInt i = 0; i < count; i++)
       
  1383      	{
       
  1384         observers[i]->TextureManagerStateChanged(*this); 								                       
       
  1385         }        
       
  1386     }
       
  1387 
       
  1388 // ---------------------------------------------------------------------------
       
  1389 // 
       
  1390 // ---------------------------------------------------------------------------
       
  1391 //
       
  1392 void CAlfTextureManager::NotifyTextureLoaded(CAlfTexture& aTexture,
       
  1393                              TInt aTextureId,
       
  1394                              TInt aErrorCode) const
       
  1395     {
       
  1396 // NOTE: Commented out because this will prevent alflogging (aTexture.FileName() = NULL => crash)
       
  1397 //    __ALFLOGSTRING3( "CAlfTextureManager::NotifyTextureLoaded -- filename: %S, textureId: %d, error: %d",
       
  1398 //          aTexture.FileName(), aTextureId, aErrorCode )
       
  1399 
       
  1400     RPointerArray<MAlfTextureLoadingCompletedObserver>& observers = 
       
  1401         (iData->iLoadObserverQueue);	
       
  1402     TInt count = observers.Count();
       
  1403     for(TInt i = 0; i < count; i++)
       
  1404      	{
       
  1405         observers[i]->TextureLoadingCompleted(aTexture, aTextureId, 
       
  1406             aErrorCode); 								                       
       
  1407         }        
       
  1408     }
       
  1409 
       
  1410 // ---------------------------------------------------------------------------
       
  1411 // 
       
  1412 // ---------------------------------------------------------------------------
       
  1413 //
       
  1414 EXPORT_C void CAlfTextureManager::AddLoadObserverL(
       
  1415     MAlfTextureLoadingCompletedObserver* aObserver)
       
  1416     {
       
  1417     iData->iLoadObserverQueue.Append(aObserver);    
       
  1418     }
       
  1419 
       
  1420 // ---------------------------------------------------------------------------
       
  1421 // 
       
  1422 // ---------------------------------------------------------------------------
       
  1423 //
       
  1424 EXPORT_C void CAlfTextureManager::RemoveLoadObserver(
       
  1425 MAlfTextureLoadingCompletedObserver* aObserver)
       
  1426     {
       
  1427     RPointerArray<MAlfTextureLoadingCompletedObserver>& observers = 
       
  1428             (iData->iLoadObserverQueue);	
       
  1429 
       
  1430     TInt count = observers.Count();
       
  1431     for(TInt i = 0; i < count; i++)
       
  1432       	{
       
  1433     	if (observers[i] == aObserver)
       
  1434     		{
       
  1435     		observers.Remove(i);
       
  1436     		observers.Compress();
       
  1437     		break;
       
  1438     		}								                       
       
  1439         }        
       
  1440     }
       
  1441     
       
  1442 // ---------------------------------------------------------------------------
       
  1443 // 
       
  1444 // ---------------------------------------------------------------------------
       
  1445 //
       
  1446 TUid CAlfTextureManager::ManagerUid()
       
  1447     {
       
  1448     return iData->iManagerId;    
       
  1449     }
       
  1450 
       
  1451 // ---------------------------------------------------------------------------
       
  1452 // 
       
  1453 // ---------------------------------------------------------------------------
       
  1454 //
       
  1455 EXPORT_C CAlfTextureProcessor& CAlfTextureManager::Processor()
       
  1456     {
       
  1457     return *iData->iProcessor;    
       
  1458     }
       
  1459 
       
  1460 // ---------------------------------------------------------------------------
       
  1461 // 
       
  1462 // ---------------------------------------------------------------------------
       
  1463 //
       
  1464 void CAlfTextureManager::AppendTextureL(CAlfTexture* aTexture)
       
  1465     {
       
  1466     if (CheckTexture(aTexture->Id()) == KErrNotFound)
       
  1467         {
       
  1468         // Create a new texture entry
       
  1469         TTextureEntry entry(aTexture->Id(), aTexture);
       
  1470         
       
  1471         // Add the new entry to the list of new textures
       
  1472         iData->iTextures.AppendL(entry);                    
       
  1473         }
       
  1474     else
       
  1475         {
       
  1476         User::Leave(KErrAlreadyExists);    
       
  1477         }    
       
  1478     }
       
  1479 
       
  1480 // ---------------------------------------------------------------------------
       
  1481 // 
       
  1482 // ---------------------------------------------------------------------------
       
  1483 //
       
  1484 void CAlfTextureManager::RemoveTexture(CAlfTexture& aTexture)
       
  1485     {
       
  1486     // Cancel loading of the texture to be removed.
       
  1487     CancelLoadingOfTexture(aTexture);
       
  1488     
       
  1489     RArray<TTextureEntry>& textures = (iData->iTextures);	
       
  1490     for(TInt i = 0; i < textures.Count(); i++)
       
  1491         {
       
  1492         TTextureEntry te = textures[i];
       
  1493         if (&aTexture == te.iTexture)
       
  1494             {
       
  1495             te.iTexture = NULL;                
       
  1496             textures.Remove(i);                
       
  1497             break;
       
  1498             }
       
  1499         }        
       
  1500     }
       
  1501     
       
  1502 // ---------------------------------------------------------------------------
       
  1503 // 
       
  1504 // ---------------------------------------------------------------------------
       
  1505 //
       
  1506 TBool CAlfTextureManager::IsInLoadQueue(const CAlfTexture* texture) const
       
  1507     {
       
  1508     TBool retVal = EFalse;
       
  1509     RArray<TLoadQueueEntry>& loadQueue = iData->iLoadQueue;	
       
  1510     for(TInt i = 0; i < loadQueue.Count(); i++)
       
  1511         {
       
  1512         TLoadQueueEntry loadEntry = loadQueue[i];
       
  1513         if (loadEntry.iLoading.iTexture == texture)
       
  1514             {
       
  1515             retVal = ETrue;
       
  1516             break;    
       
  1517             }
       
  1518         }
       
  1519     return retVal;
       
  1520     }
       
  1521     
       
  1522     
       
  1523 // ---------------------------------------------------------------------------
       
  1524 // 
       
  1525 // ---------------------------------------------------------------------------
       
  1526 //
       
  1527 CAlfTextureManager::TState CAlfTextureManager::State() const
       
  1528     {
       
  1529     return iData->iState;    
       
  1530     }
       
  1531 
       
  1532 // ---------------------------------------------------------------------------
       
  1533 // 
       
  1534 // ---------------------------------------------------------------------------
       
  1535 //
       
  1536 EXPORT_C void CAlfTextureManager::AddStateObserverL(
       
  1537     MAlfTextureManagerStateChangedObserver* aObserver)
       
  1538     {
       
  1539     iData->iStateObserverQueue.Append(aObserver);            
       
  1540     }
       
  1541 
       
  1542 // ---------------------------------------------------------------------------
       
  1543 // 
       
  1544 // ---------------------------------------------------------------------------
       
  1545 //
       
  1546 EXPORT_C void CAlfTextureManager::RemoveStateObserver(
       
  1547     MAlfTextureManagerStateChangedObserver* aObserver)
       
  1548     {
       
  1549     RPointerArray<MAlfTextureManagerStateChangedObserver>& observers = 
       
  1550             (iData->iStateObserverQueue);	
       
  1551 
       
  1552     TInt count = observers.Count();
       
  1553     for(TInt i = 0; i < count; i++)
       
  1554       	{
       
  1555     	if (observers[i] == aObserver)
       
  1556     		{
       
  1557     		observers.Remove(i);
       
  1558     		observers.Compress();
       
  1559     		break;
       
  1560     		}								                       
       
  1561         }                
       
  1562     }
       
  1563     
       
  1564 EXPORT_C TBool CAlfTextureManager::IsLoaded(const CAlfTexture * texture) const
       
  1565     {
       
  1566     if(texture != NULL && texture->HasContent() && !IsInLoadQueue(texture))
       
  1567         {
       
  1568         return ETrue;
       
  1569         }
       
  1570     return EFalse;
       
  1571     }
       
  1572 
       
  1573 
       
  1574 EXPORT_C TBool CAlfTextureManager::IsLoaded(const TDesC& aImageName) const
       
  1575     {
       
  1576     TFileName fileName = *iData->iImagePath;
       
  1577     fileName.Append(aImageName);
       
  1578     TInt index = CheckTexture(fileName);
       
  1579     if(index == KErrNotFound)
       
  1580         {
       
  1581         return EFalse;
       
  1582         }
       
  1583     return IsLoaded(iData->iTextures[index].iTexture);
       
  1584     }
       
  1585 
       
  1586 EXPORT_C TInt CAlfTextureManager::TextureId(const TDesC& aImageName) const
       
  1587     {
       
  1588     TFileName fileName = *iData->iImagePath;
       
  1589     fileName.Append(aImageName);
       
  1590     TInt index = CheckTexture(fileName);
       
  1591     
       
  1592     if(index == KErrNotFound)
       
  1593         {
       
  1594         return KErrNotFound;
       
  1595         }
       
  1596     return iData->iTextures[index].iId;
       
  1597     }
       
  1598 
       
  1599 EXPORT_C TBool CAlfTextureManager::IsLoaded(TInt aId) const
       
  1600     {
       
  1601     ASSERT(aId!=0);
       
  1602     TInt index = CheckTexture(aId);
       
  1603     if(index == KErrNotFound)
       
  1604         {
       
  1605         return EFalse;
       
  1606         }
       
  1607     return IsLoaded(iData->iTextures[index].iTexture);
       
  1608     }
       
  1609 
       
  1610 
       
  1611 
       
  1612 // ---------------------------------------------------------------------------
       
  1613 // Release all textures with given priority level (or above)
       
  1614 // ---------------------------------------------------------------------------
       
  1615 //
       
  1616 TBool CAlfTextureManager::Release( TInt aReleasePriorityLevel )
       
  1617     {
       
  1618     TBool allReleased = ETrue;
       
  1619     
       
  1620     RArray<TTextureEntry>& textures = (iData->iTextures);	
       
  1621     for(TInt i = 0; i < textures.Count(); i++)
       
  1622         {
       
  1623         if (textures[i].iTexture->Id())
       
  1624             {
       
  1625             if ( textures[i].iTexture->Priority() < aReleasePriorityLevel )
       
  1626                 {
       
  1627                 allReleased = EFalse;
       
  1628                 }
       
  1629             else
       
  1630                 {
       
  1631                 if (!textures[i].iTexture->IsAnimated())
       
  1632                     {
       
  1633                     ReleaseEntry(textures[i]);                    
       
  1634                     }
       
  1635                 else
       
  1636                     {
       
  1637                     textures[i].iTexture->StopAnimation();    
       
  1638                     }                    
       
  1639                 }
       
  1640             }
       
  1641         }
       
  1642     return allReleased;
       
  1643     }
       
  1644 
       
  1645 // ---------------------------------------------------------------------------
       
  1646 // Release a specific entry
       
  1647 // ---------------------------------------------------------------------------
       
  1648 //
       
  1649 void CAlfTextureManager::ReleaseEntry(const TTextureEntry& aEntry)
       
  1650     {
       
  1651     // Id texture has content, it must be released here using unload,
       
  1652     // otherwise we can just notify serverside.
       
  1653     if (aEntry.iTexture->HasContent())
       
  1654         {        
       
  1655         UnloadTexture(aEntry.iTexture->Id());                        
       
  1656         }
       
  1657     else
       
  1658         {
       
  1659         iData->iEnv->Client().TextureRelease(aEntry.iTexture->Id(), 
       
  1660             iData->iManagerId.iUid);            
       
  1661         }    
       
  1662     
       
  1663     TInt releaseFlags = aEntry.iTexture->ReleaseFlags();
       
  1664     releaseFlags |= CAlfTexture::EReleaseFromEnv;
       
  1665     aEntry.iTexture->SetReleaseFlags(releaseFlags);
       
  1666     }
       
  1667 
       
  1668 // ---------------------------------------------------------------------------
       
  1669 // Restore all textures with given priority level (or lover)
       
  1670 // ---------------------------------------------------------------------------
       
  1671 //
       
  1672 TBool CAlfTextureManager::RestoreL( TInt aRestorePriorityLevel )
       
  1673     {
       
  1674     TBool allRestored = ETrue;
       
  1675     
       
  1676     RArray<TTextureEntry>& textures = (iData->iTextures);	
       
  1677     for(TInt i = 0; i < textures.Count(); i++)
       
  1678         {
       
  1679         if ( textures[i].iTexture->Priority() <= aRestorePriorityLevel )
       
  1680             {
       
  1681             if (!textures[i].iTexture->IsAnimated())
       
  1682                 {
       
  1683                 RestoreEntryL(textures[i]);    
       
  1684                 }
       
  1685             else
       
  1686                 {
       
  1687                 textures[i].iTexture->StartAnimation();                                                
       
  1688                 }                
       
  1689             }
       
  1690         else
       
  1691             {
       
  1692             allRestored = EFalse;
       
  1693             }
       
  1694         }    
       
  1695     
       
  1696     return allRestored;
       
  1697     }
       
  1698 
       
  1699 // ---------------------------------------------------------------------------
       
  1700 // 
       
  1701 // ---------------------------------------------------------------------------
       
  1702 //
       
  1703 void CAlfTextureManager::RestoreEntryL(const TTextureEntry& aEntry)
       
  1704     {
       
  1705     // Id texture has no content, it must be restored here using create/load
       
  1706     // otherwise we can just notify serverside.
       
  1707     if (!aEntry.iTexture->HasContent())
       
  1708         {
       
  1709         // Clear release flags 
       
  1710         TInt releaseFlags = aEntry.iTexture->ReleaseFlags();
       
  1711         releaseFlags &= ~CAlfTexture::EReleaseFromEnv;    
       
  1712         releaseFlags &= ~CAlfTexture::EReleaseFromUnload;                   
       
  1713         aEntry.iTexture->SetReleaseFlags(releaseFlags);
       
  1714 
       
  1715         // If there are other release flags, then do not restore.        
       
  1716         if (!releaseFlags)
       
  1717             {                         
       
  1718             // check for provider-based restore               
       
  1719             if (aEntry.iTexture->BitmapProvider() != NULL)
       
  1720                 {
       
  1721                 CreateTextureL(aEntry.iTexture->Id(),
       
  1722                                aEntry.iTexture->BitmapProvider(),
       
  1723                                aEntry.iTexture->Flags());
       
  1724                 }
       
  1725             // check for file-based restore
       
  1726             else if (aEntry.iTexture->FileName() != NULL)
       
  1727                 {
       
  1728                 LoadTextureL(aEntry.iTexture->FileName()->Des(),
       
  1729                     aEntry.iTexture->MaxTextureSize(), 
       
  1730                     aEntry.iTexture->Flags(), 
       
  1731                     aEntry.iTexture->Id());
       
  1732                 }       
       
  1733             else
       
  1734                 {
       
  1735                 // for PC lint
       
  1736                 }
       
  1737             }
       
  1738         }
       
  1739     else
       
  1740         {
       
  1741         iData->iEnv->Client().TextureRestore(aEntry.iTexture->Id(), 
       
  1742             iData->iManagerId.iUid);    
       
  1743         }        
       
  1744     }
       
  1745 
       
  1746 // ---------------------------------------------------------------------------
       
  1747 // 
       
  1748 // ---------------------------------------------------------------------------
       
  1749 //
       
  1750 void CAlfTextureManager::CancelLoadingOfTexture(CAlfTexture& aTexture)
       
  1751     {
       
  1752     RArray<TLoadQueueEntry>& loadQueue = iData->iLoadQueue;    
       
  1753     for(TInt i = 0; i < loadQueue.Count(); i++)
       
  1754         {
       
  1755         if(loadQueue[i].iLoading.iTexture == &aTexture)
       
  1756             {
       
  1757             // Texture found from the load queue.
       
  1758             if(i == 0 && iData->iState == ELoading)
       
  1759                 {
       
  1760                 // Texture is currently loading
       
  1761                 Cancel();
       
  1762                 PopLoadedQueueEntry();
       
  1763                 StartLoading();                
       
  1764                 }
       
  1765             else
       
  1766                 {
       
  1767                 // Delete the decoder and remove entry.
       
  1768                 delete loadQueue[i].iDecoder;
       
  1769                 loadQueue.Remove(i);
       
  1770                 }
       
  1771             break;
       
  1772             }
       
  1773         }
       
  1774     }
       
  1775 
       
  1776 // ---------------------------------------------------------------------------
       
  1777 // 
       
  1778 // ---------------------------------------------------------------------------
       
  1779 //
       
  1780 TInt CAlfTextureManager::GenerateTextureId()
       
  1781     {
       
  1782     TBool done = EFalse;
       
  1783 
       
  1784     TInt start = iData->iAutoGeneratedTextureId;
       
  1785     while (!done)
       
  1786         {            
       
  1787         if(iData->iAutoGeneratedTextureId == iData->iHighestAutoGeneratedTextureId)
       
  1788             {
       
  1789             iData->iAutoGeneratedTextureId = iData->iLowestAutoGeneratedTextureId;
       
  1790             }
       
  1791         else
       
  1792             {
       
  1793             iData->iAutoGeneratedTextureId++;
       
  1794             }
       
  1795         
       
  1796         if (CheckTexture(iData->iAutoGeneratedTextureId) == KErrNotFound)
       
  1797             {
       
  1798             done = ETrue;    
       
  1799             }
       
  1800         
       
  1801         if (iData->iAutoGeneratedTextureId == start)
       
  1802             {
       
  1803             // Error! Free id was not found, already existing id will be used.
       
  1804             break;    
       
  1805             }            
       
  1806         }
       
  1807 
       
  1808     return iData->iAutoGeneratedTextureId;        
       
  1809     }
       
  1810 
       
  1811 // ---------------------------------------------------------------------------
       
  1812 // 
       
  1813 // ---------------------------------------------------------------------------
       
  1814 //
       
  1815 EXPORT_C void CAlfTextureManager::SetAutomaticTextureIdRange(TInt aLow, TInt aHigh)
       
  1816     {
       
  1817     if (aLow < aHigh)
       
  1818         {
       
  1819         iData->iAutoGeneratedTextureId = aLow;
       
  1820         iData->iLowestAutoGeneratedTextureId = aLow;
       
  1821         iData->iHighestAutoGeneratedTextureId = aHigh;                    
       
  1822         }
       
  1823     }
       
  1824     
       
  1825 // ---------------------------------------------------------------------------
       
  1826 // 
       
  1827 // ---------------------------------------------------------------------------
       
  1828 //
       
  1829 void CAlfTextureManager::NotifySkinChangedL()
       
  1830     {
       
  1831     __ALFLOGSTRING( "CAlfTextureManager::NotifySkinChangedL" )
       
  1832     
       
  1833     RArray<TTextureEntry>& textures = (iData->iTextures);	
       
  1834     for(TInt i = 0; i < textures.Count(); i++)
       
  1835         {
       
  1836         if (textures[i].iTexture->Id() &&
       
  1837             textures[i].iTexture->HasContent() &&
       
  1838             (textures[i].iTexture->Flags() & EAlfTextureFlagSkinContent))
       
  1839             {
       
  1840             iData->iEnv->Client().TextureNotifySkinChanged(textures[i].iTexture->Id(),
       
  1841                  iData->iManagerId.iUid);    
       
  1842             
       
  1843             ReleaseEntry(textures[i]);            
       
  1844             RestoreEntryL(textures[i]);
       
  1845             }
       
  1846         }                        
       
  1847     }
       
  1848     
       
  1849 // ---------------------------------------------------------------------------
       
  1850 // 
       
  1851 // ---------------------------------------------------------------------------
       
  1852 //
       
  1853 TBool CAlfTextureManager::IsShared()
       
  1854     {
       
  1855     return (iData->iManagerId != TUid::Uid(0));        
       
  1856     }
       
  1857     
       
  1858 // ---------------------------------------------------------------------------
       
  1859 // 
       
  1860 // ---------------------------------------------------------------------------
       
  1861 //
       
  1862 void CAlfTextureManager::ReportTextureInfoL( 
       
  1863         TInt aTextureId, const TSize& aTextureRect )
       
  1864     {
       
  1865     __ALFLOGSTRING1( "CAlfTextureManager::ReportTextureInfo %d", aTextureId )
       
  1866     __ALFLOGSTRING2( "texture size = (%d, %d)", aTextureRect.iWidth, aTextureRect.iHeight )
       
  1867 
       
  1868     TBool accepted = EFalse;
       
  1869     CAlfTexture* texture = TextureL(aTextureId);
       
  1870     
       
  1871     RPointerArray<MAlfTextureAutoSizeObserver>& observers = 
       
  1872         (iData->iAutoSizeObserverQueue);	
       
  1873     TInt count = observers.Count();
       
  1874     for(TInt i = 0; i < count; i++)
       
  1875      	{
       
  1876         accepted |= observers[i]->PreferredSizeChanged(*texture, aTextureRect);
       
  1877         }
       
  1878 
       
  1879     // File based textures are updated automatically without observer acceptance
       
  1880     if (texture->FileName())
       
  1881         {
       
  1882         // Update new max size, but leave undefined (zero) values untouched.
       
  1883         TSize maxTextureSize = texture->MaxTextureSize();
       
  1884         TSize oldMaxTextureSize = maxTextureSize;
       
  1885         
       
  1886         if (maxTextureSize.iWidth != 0 && maxTextureSize.iHeight == 0)
       
  1887             {
       
  1888             maxTextureSize.iWidth = aTextureRect.iWidth;    
       
  1889             }
       
  1890         else if (maxTextureSize.iHeight != 0 && maxTextureSize.iWidth == 0)
       
  1891             {
       
  1892             maxTextureSize.iHeight = aTextureRect.iHeight;      
       
  1893             }
       
  1894         else
       
  1895             {
       
  1896             maxTextureSize = aTextureRect;   
       
  1897             }    
       
  1898             
       
  1899         texture->SetMaxTextureSize(maxTextureSize);
       
  1900                
       
  1901         if (!texture->ReleaseFlags() && (oldMaxTextureSize != maxTextureSize))
       
  1902             {
       
  1903             // Update if texture is not released. 
       
  1904             UpdateTextureL(aTextureId, aTextureRect);             
       
  1905             }
       
  1906         }
       
  1907     else
       
  1908         {
       
  1909         if (accepted && !texture->ReleaseFlags())
       
  1910             {
       
  1911             // If we did notify someone who accepted it, we assume it may now be able to 
       
  1912             // provide new size texture. If it is released it should get updated 
       
  1913             // automatically to new size when restore happens.   
       
  1914             UpdateTextureL(aTextureId, aTextureRect);             
       
  1915             }
       
  1916         else
       
  1917             {
       
  1918             // not accepted by any of observers, no use to update then.    
       
  1919             }    
       
  1920         }                
       
  1921 
       
  1922     }
       
  1923     
       
  1924 
       
  1925 // ---------------------------------------------------------------------------
       
  1926 // 
       
  1927 // ---------------------------------------------------------------------------
       
  1928 //
       
  1929 EXPORT_C void CAlfTextureManager::AddAutoSizeObserverL(MAlfTextureAutoSizeObserver* aObserver)
       
  1930     {
       
  1931     iData->iAutoSizeObserverQueue.Append(aObserver);     
       
  1932     }
       
  1933 
       
  1934 // ---------------------------------------------------------------------------
       
  1935 // 
       
  1936 // ---------------------------------------------------------------------------
       
  1937 //
       
  1938 EXPORT_C void CAlfTextureManager::RemoveAutoSizeObserver(MAlfTextureAutoSizeObserver* aObserver)
       
  1939     {
       
  1940     RPointerArray<MAlfTextureAutoSizeObserver>& observers = 
       
  1941             (iData->iAutoSizeObserverQueue);	
       
  1942 
       
  1943     TInt count = observers.Count();
       
  1944     for(TInt i = 0; i < count; i++)
       
  1945       	{
       
  1946     	if (observers[i] == aObserver)
       
  1947     		{
       
  1948     		observers.Remove(i);
       
  1949     		observers.Compress();
       
  1950     		break;
       
  1951     		}								                       
       
  1952         }        
       
  1953     }
       
  1954 
       
  1955 // ---------------------------------------------------------------------------
       
  1956 // 
       
  1957 // ---------------------------------------------------------------------------
       
  1958 //
       
  1959 void CAlfTextureManager::UpdateTextureL(TInt aId, TSize /*aSize*/)
       
  1960     {
       
  1961     RArray<TTextureEntry>& textures = (iData->iTextures);	
       
  1962     for(TInt i = 0; i < textures.Count(); i++)
       
  1963         {
       
  1964         TTextureEntry te = textures[i];
       
  1965         if (te.iTexture && te.iTexture->Id() == aId)
       
  1966             {
       
  1967             if (te.iTexture->BitmapProvider() != NULL)
       
  1968                 {
       
  1969                 UpdateTextureFromBitmapL(aId);
       
  1970                 break;
       
  1971                 }
       
  1972             else if (te.iTexture->FileName() != NULL)
       
  1973                 {
       
  1974                 UpdateTextureFromFileL(aId);
       
  1975                 break;
       
  1976                 }       
       
  1977             else
       
  1978                 {
       
  1979                 // for PC lint
       
  1980                 break;
       
  1981                 }
       
  1982             }
       
  1983         }
       
  1984     }
       
  1985 
       
  1986 
       
  1987 void CAlfTextureManager::ReloadTextureL(const TDesC& aImageName,
       
  1988                                        TSize aTextureMaxSize,
       
  1989                                        TAlfTextureFlags /*aFlags*/,
       
  1990                                        TInt aId)
       
  1991     {    
       
  1992     if (aId == KAlfAutoGeneratedTextureId)
       
  1993         {
       
  1994         aId = GenerateTextureId();    
       
  1995         }    
       
  1996     
       
  1997     CAlfTexture* tex = NULL;
       
  1998     TFileName fileName;
       
  1999 
       
  2000     // Texture must exist.
       
  2001     tex = TextureL(aId);
       
  2002 
       
  2003     // add path to filename if filename has been passed
       
  2004     if(aImageName.Length() > 0)
       
  2005         {
       
  2006         // assume relative pathname and prepend the image path to get full filename
       
  2007         fileName = aImageName;
       
  2008         PrependImagePath(fileName);
       
  2009         }
       
  2010 
       
  2011     // if no name has been passed as a parameter but
       
  2012     // there's and nonzero id has been passed, we
       
  2013     // can assume that there's a predefined name available
       
  2014     RArray<TTextureEntry>& textures = (iData->iTextures);	
       
  2015     RArray<TLoadQueueEntry>& loadqueue = (iData->iLoadQueue);	
       
  2016 
       
  2017     if((aImageName.Length() == 0) && (aId != 0))
       
  2018        {
       
  2019         // search for a texture filename based on the id.
       
  2020         TInt index = CheckTexture(aId);
       
  2021         if(index >=0)
       
  2022             {
       
  2023             tex = textures[index].iTexture;
       
  2024             fileName = *tex->FileName();
       
  2025             }
       
  2026         else
       
  2027             {
       
  2028             User::Leave(KErrNotFound);
       
  2029             }
       
  2030        }
       
  2031 
       
  2032     // return if already in the load queue ??
       
  2033    if (IsInLoadQueue(tex))
       
  2034        {
       
  2035        return;
       
  2036        }
       
  2037 
       
  2038     // replace filename
       
  2039     // File names are relative to the image path.
       
  2040     tex->SetFileNameL(fileName);
       
  2041     
       
  2042     TSize maxTextureSize = tex->MaxTextureSize();
       
  2043     
       
  2044     // Update new max size, but leave undefined (zero) values untouched    
       
  2045     if (maxTextureSize.iWidth != 0 && maxTextureSize.iHeight == 0)
       
  2046         {
       
  2047         maxTextureSize.iWidth = aTextureMaxSize.iWidth;    
       
  2048         }
       
  2049     else if (maxTextureSize.iHeight != 0 && maxTextureSize.iWidth == 0)
       
  2050         {
       
  2051         maxTextureSize.iHeight = aTextureMaxSize.iHeight;      
       
  2052         }
       
  2053     else
       
  2054         {
       
  2055         maxTextureSize = aTextureMaxSize;   
       
  2056         }    
       
  2057 
       
  2058     tex->SetMaxTextureSize(maxTextureSize);
       
  2059 
       
  2060     // Prepare for loading by creating a load queue entry.
       
  2061     TTextureEntry entry;
       
  2062     entry.iTexture = tex;
       
  2063     entry.iId = aId;
       
  2064 
       
  2065     TLoadQueueEntry loadqentry;
       
  2066     loadqentry.iUnloaded = EFalse;
       
  2067     loadqentry.iLoading = entry;
       
  2068     loadqentry.iDecoder = NULL;
       
  2069 
       
  2070     // Textures are loaded one at a time, in the order they were requested.
       
  2071     loadqueue.AppendL(loadqentry);
       
  2072 
       
  2073     // DEBUG
       
  2074     if (iData->iTextureAutoCounterEnabled)
       
  2075         {            
       
  2076         iData->iTextureAutoReloadCounter++;
       
  2077         }
       
  2078 
       
  2079     // Start the texture load active object if we're not loading
       
  2080     if(iData->iState == EIdle)
       
  2081         {
       
  2082         // Start loading images..
       
  2083         StartLoading();
       
  2084         // Notify observers.
       
  2085         NotifyStateChange();
       
  2086         }
       
  2087     }
       
  2088 
       
  2089 void CAlfTextureManager::RecreateTextureL(TInt aId,
       
  2090                                           MAlfBitmapProvider* aBitmapProvider,
       
  2091                                           TAlfTextureFlags aFlags)
       
  2092     {    
       
  2093     CAlfTexture* tex = NULL;
       
  2094     
       
  2095     if (aId == KAlfAutoGeneratedTextureId)
       
  2096         {
       
  2097         User::Leave(KErrArgument); // texture must already exist !
       
  2098         }    
       
  2099 
       
  2100     CFbsBitmap* bitmap = NULL;
       
  2101     CFbsBitmap* maskBitmap = NULL;
       
  2102 
       
  2103     // Provide an already created texture if such exists.
       
  2104     TRAPD(err, tex = TextureL(aId));
       
  2105     if(err != KErrNone)
       
  2106         {
       
  2107         User::Leave(KErrArgument); // texture must already exist !
       
  2108         }
       
  2109 
       
  2110     // Call the bitmapProvider method to load the bitmaps
       
  2111 	if (aBitmapProvider)
       
  2112 		{
       
  2113 	    aBitmapProvider->ProvideBitmapL(aId, bitmap, maskBitmap);		
       
  2114 		}
       
  2115 					
       
  2116 	if (!bitmap)
       
  2117 	    { 
       
  2118 	    // We leave here, otherwise serverside would panic. 
       
  2119 	    User::Leave(KErrArgument);    
       
  2120 	    // Bitmap size is checked and handled in serverside, 
       
  2121 	    // so that we can create empty textures (size = 0,0)
       
  2122 	    }
       
  2123 	    	  
       
  2124 	// "bitmap" pointer should be valid from now on
       
  2125     CleanupStack::PushL(bitmap);
       
  2126 	TInt bitmapHandle = bitmap->Handle();
       
  2127 	
       
  2128 	TInt maskHandle = 0;
       
  2129 	if (maskBitmap)	
       
  2130 		{
       
  2131 		maskHandle = maskBitmap->Handle();	
       
  2132 	    CleanupStack::PushL(maskBitmap);
       
  2133 		}
       
  2134     
       
  2135     // Create CAlfTexture instance, this duplicates the bitmaps to server.
       
  2136     // texture already exists but it does not have content, this creates content.
       
  2137    	iData->iEnv->Client().TextureCreateL( aId, bitmapHandle, 
       
  2138        	maskHandle, aFlags, iData->iManagerId.iUid );    	            	        
       
  2139 		
       
  2140 	tex->SetBitmapProvider(aBitmapProvider);	
       
  2141     tex->SetSize(bitmap->SizeInPixels());
       
  2142 	
       
  2143 	// CAlfTexture has at this point duplicated bitmaps, can be deleted here.        
       
  2144 	if (maskBitmap)	
       
  2145 		{
       
  2146 	    CleanupStack::PopAndDestroy( maskBitmap );
       
  2147 	    maskBitmap = NULL;		
       
  2148 		}
       
  2149     CleanupStack::PopAndDestroy( bitmap ); 
       
  2150 	bitmap = NULL;		
       
  2151     
       
  2152     // Notify observers
       
  2153     NotifyTextureLoaded(*tex, aId, KErrNone);
       
  2154     
       
  2155     // DEBUG
       
  2156     if (iData->iTextureAutoCounterEnabled)
       
  2157         {            
       
  2158         iData->iTextureAutoRecreateCounter++;
       
  2159         TBuf<256> numBuf;
       
  2160         numBuf.FillZ();
       
  2161         numBuf.Append(_L("Reloads:"));
       
  2162         numBuf.AppendNum(iData->iTextureAutoReloadCounter);
       
  2163         numBuf.Append(_L(" - Recreates:"));
       
  2164         numBuf.AppendNum(iData->iTextureAutoRecreateCounter);
       
  2165         User::InfoPrint(numBuf);
       
  2166         }
       
  2167     }
       
  2168 
       
  2169 // ---------------------------------------------------------------------------
       
  2170 // 
       
  2171 // ---------------------------------------------------------------------------
       
  2172 //
       
  2173 void CAlfTextureManager::IncRefcount(TInt aId)
       
  2174     {
       
  2175     // do not refcount blanktextures.
       
  2176     if (!aId)
       
  2177         {
       
  2178         return;
       
  2179         }
       
  2180 
       
  2181     TInt index = CheckTexture(aId);
       
  2182     ASSERT(index!=KErrNotFound);
       
  2183     TTextureEntry& te = iData->iTextures[index];
       
  2184     if (te.iRefCount==-1)
       
  2185         {
       
  2186         te.iRefCount = 1;
       
  2187         }
       
  2188     else
       
  2189         {
       
  2190         te.iRefCount++;        
       
  2191         }
       
  2192     }
       
  2193 
       
  2194 // ---------------------------------------------------------------------------
       
  2195 // 
       
  2196 // ---------------------------------------------------------------------------
       
  2197 //
       
  2198 void CAlfTextureManager::DecRefcount(TInt aId)
       
  2199     {
       
  2200     // do not refcount blanktextures.
       
  2201     if (!aId)
       
  2202         {
       
  2203         return;
       
  2204         }
       
  2205         
       
  2206     TInt index = CheckTexture(aId);
       
  2207     if (index == KErrNotFound)
       
  2208         {
       
  2209         return;
       
  2210         }
       
  2211     
       
  2212     TTextureEntry& te = iData->iTextures[index];
       
  2213     if (te.iRefCount >0)
       
  2214         {
       
  2215         te.iRefCount--;        
       
  2216         }
       
  2217     if (!te.iRefCount)
       
  2218         {
       
  2219         // trigger texture cleanup when 
       
  2220         // reference count hits zero
       
  2221         StartGarbageCollect();
       
  2222         }
       
  2223     }
       
  2224 
       
  2225 // ---------------------------------------------------------------------------
       
  2226 // 
       
  2227 // ---------------------------------------------------------------------------
       
  2228 //
       
  2229 TInt CAlfTextureManager::GarbageCollect(TAny* aPtr)
       
  2230     {
       
  2231     CAlfTextureManager* tm = ((CAlfTextureManager*)(aPtr));
       
  2232 	RArray<TTextureEntry>& textures = tm->iData->iTextures;	
       
  2233     // Cleanup all textures which have refcount 0
       
  2234     TInt count = textures.Count()-1;
       
  2235     for (int index = count; index >=0; index--)
       
  2236         {
       
  2237         TTextureEntry& te = textures[index];
       
  2238         // delete only textures that have enabled refcounting
       
  2239         if (te.iTexture->RefCountingEnabled() && !te.iRefCount)
       
  2240             {
       
  2241             TInt action = te.iTexture->RefCountingAction();
       
  2242             switch (action)
       
  2243                 {
       
  2244                 case CAlfTexture::ERefCountingActionUnload:
       
  2245                     {
       
  2246                     // Unload, but mark as released from ref counting 
       
  2247                     TInt releaseFlags = te.iTexture->ReleaseFlags();
       
  2248                     tm->UnloadTexture(te.iId);    
       
  2249                     releaseFlags |= CAlfTexture::EReleaseFromRefCounting;
       
  2250                     te.iTexture->SetReleaseFlags(releaseFlags);
       
  2251                     break;
       
  2252                     }
       
  2253                 case CAlfTexture::ERefCountingActionDelete:
       
  2254                     {
       
  2255                     delete te.iTexture;
       
  2256                     te.iTexture = NULL;
       
  2257                     break;        
       
  2258                     }                    
       
  2259                 default:
       
  2260                     {
       
  2261                     // Do nothing
       
  2262                     break;    
       
  2263                     }                                        
       
  2264                 }            
       
  2265             }
       
  2266         }
       
  2267     return EFalse;
       
  2268     }
       
  2269 
       
  2270 // ---------------------------------------------------------------------------
       
  2271 // 
       
  2272 // ---------------------------------------------------------------------------
       
  2273 //
       
  2274 void CAlfTextureManager::StartGarbageCollect()
       
  2275     {
       
  2276     CIdle* doombringer = iData->iDoomBringer;
       
  2277     // check if garbagecollecting is already in progress
       
  2278     // -> if so, just return
       
  2279     if (doombringer->IsActive())
       
  2280         {
       
  2281         return;
       
  2282         }
       
  2283     doombringer->Start(TCallBack(GarbageCollect, this));
       
  2284     }
       
  2285 
       
  2286 // ---------------------------------------------------------------------------
       
  2287 // 
       
  2288 // ---------------------------------------------------------------------------
       
  2289 //
       
  2290 void CAlfTextureManager::RemoveFlags(TAlfTextureFlags& aFlags, TInt aFlagsToBeRemoved)
       
  2291     {
       
  2292     ((TInt&)aFlags) &= ~aFlagsToBeRemoved;      
       
  2293     }
       
  2294     
       
  2295 // ---------------------------------------------------------------------------
       
  2296 // 
       
  2297 // ---------------------------------------------------------------------------
       
  2298 //
       
  2299 void CAlfTextureManager::SetFlags(TAlfTextureFlags& aFlags, TInt aFlagsToBeSet)
       
  2300     {
       
  2301     ((TInt&)aFlags) |= aFlagsToBeSet;              
       
  2302     }
       
  2303