uiacceltk/hitchcock/coretoolkit/src/HuiCanvasTextureCache.cpp
changeset 0 15bf7259bb7c
child 3 d8a3531bc6b8
child 13 8f67d927ea57
equal deleted inserted replaced
-1:000000000000 0:15bf7259bb7c
       
     1 /*
       
     2 * Copyright (c) 2006-2008 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:   
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #include "huicanvastexturecache.h"
       
    21 #include "uiacceltk/HuiImage.h"
       
    22 #include "uiacceltk/HuiTexture.h"
       
    23 #include "uiacceltk/HuiEnv.h"
       
    24 #include "uiacceltk/HuiUtil.h"
       
    25 #include "uiacceltk/HuiStatic.h"
       
    26 #include "huicanvasgc.h"
       
    27 #include "HuiRenderPlugin.h"
       
    28 #include "huicanvasrenderbuffer.h"
       
    29 
       
    30 #include <e32cmn.h>
       
    31 #include <bitdev.h>
       
    32 #include <AknLayoutFont.h>
       
    33 #include <e32property.h>
       
    34 
       
    35 // Enable this for debugging cache usage
       
    36 //#define HUI_DEBUG_PRINT_CANVAS_TEXTURE_CACHE
       
    37 //#define HUI_DEBUG_PRINT_CANVAS_TEXTURE_CACHE_EGL
       
    38 //#define HUI_DEBUG_PRINT_CANVAS_TEXTURE_CACHE_EXTENDED
       
    39 
       
    40 // Enable this for debugging performance
       
    41 //#define HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
       
    42 
       
    43 /** Magic S60 font constant */
       
    44 const TInt KHuiFontVerticalShiftInPixels = 1; 
       
    45 
       
    46 /** Initial touch count value */
       
    47 const TInt KHuiInitialBitmapTouchCount = -1; 
       
    48 
       
    49 /** Estimated bits per pixel for all textures */
       
    50 const TReal32 KHuiTextureEstimatedBpp = 32;
       
    51 
       
    52 /** Estimated bits per pixel for rasterized canvas texts */
       
    53 const TReal32 KHuiCanvasTextEstimatedBpp = 8;
       
    54 
       
    55 /** Estimated bits per pixel for canvas images */
       
    56 const TReal32 KHuiCanvasImageEstimatedBpp = 32;
       
    57 
       
    58 /** Estimated bits per pixel for canvas render buffers */
       
    59 const TReal32 KHuiCanvasRenderBufferEstimatedBpp = 32;
       
    60 
       
    61 /** Constant to define target how much memory UI textures should use, 
       
    62     this is not a hard limit but effects how long unused textures are cached */
       
    63 const TInt KHuiMaxRecommendedTextureAmountInKBytes = 4096;
       
    64 
       
    65 /** Constant to define target how much memory UI render buffers should use, 
       
    66     this is not a hard limit but effects how long unused render buffers are cached */
       
    67 const TInt KHuiMaxRecommendedRenderBufferAmountInKBytes = 0;
       
    68 
       
    69 /** Ratio how cache is divided between canvas texts and images */
       
    70 const TReal32 KHuiCanvasUnusedTextImageCacheRatio = 0.1f;
       
    71 
       
    72 /** Max amount of recycled texture objects */
       
    73 const TInt KHuiMaxRecycledTextureCount = 100;
       
    74 
       
    75 /** Use color modulation or not for setting text color */
       
    76 const TBool KHuiCanvasTextUseColorModulation = ETrue;
       
    77 
       
    78 /** Store bitmap pointers to avoid handle duplication */
       
    79 const TBool KHuiCanvasKeepBitmapPointer = ETrue;
       
    80 
       
    81 CHuiCanvasImage::CHuiCanvasImage() :
       
    82         iTexture(NULL),
       
    83         iCache(NULL)
       
    84     {
       
    85     }
       
    86 
       
    87 CHuiCanvasImage::~CHuiCanvasImage()
       
    88     {
       
    89     if (iCache && iTexture)
       
    90         {
       
    91         iCache->DeleteRecycledTexture(iTexture);
       
    92         }
       
    93     else
       
    94         {
       
    95         delete iTexture;        
       
    96         }    
       
    97     
       
    98     iActiveUsers.Close();            
       
    99     }
       
   100 
       
   101 void CHuiCanvasImage::RefreshUser(const CHuiCanvasVisual& aUser)
       
   102     {
       
   103     if (iActiveUsers.FindInAddressOrder(&aUser) == KErrNotFound)
       
   104         {
       
   105         iActiveUsers.InsertInAddressOrder(&aUser);
       
   106         }
       
   107 
       
   108     // Update last usage time    
       
   109     iLastUsed.UniversalTime();        
       
   110     }
       
   111 
       
   112 void CHuiCanvasImage::RemoveUser(const CHuiCanvasVisual& aUser)
       
   113     {
       
   114     TInt index = iActiveUsers.FindInAddressOrder(&aUser);
       
   115 
       
   116     if (index != KErrNotFound)
       
   117         {
       
   118         iActiveUsers.Remove(index);
       
   119         }    
       
   120     }
       
   121 
       
   122 TBool CHuiCanvasImage::IsUser(const CHuiCanvasVisual& aUser) const
       
   123     {
       
   124     TInt index = iActiveUsers.FindInAddressOrder(&aUser);
       
   125 
       
   126     if (index != KErrNotFound)
       
   127         {
       
   128         return ETrue;
       
   129         }
       
   130     return EFalse;
       
   131     }
       
   132 
       
   133 TBool CHuiCanvasImage::IsAnyUser() const
       
   134     {
       
   135     return iActiveUsers.Count() != 0;
       
   136     }
       
   137 
       
   138 CHuiTexture* CHuiCanvasImage::Texture() const
       
   139     {
       
   140     return iTexture;
       
   141     }
       
   142 
       
   143 void CHuiCanvasImage::CopyAttributes(CHuiCanvasImage& aSrc)
       
   144     {
       
   145     iTexture = aSrc.iTexture;
       
   146     iGcParams = aSrc.iGcParams;
       
   147     iLastUsed = aSrc.iLastUsed;
       
   148     iCache = aSrc.iCache;
       
   149     
       
   150     iActiveUsers.Reset();        
       
   151     for (TInt i=0; i < aSrc.iActiveUsers.Count(); i++)
       
   152         {
       
   153         iActiveUsers.Append(aSrc.iActiveUsers[i]);    
       
   154         }               
       
   155     }
       
   156     
       
   157 void CHuiCanvasImage::Reset()
       
   158     {
       
   159     // Reset does not delete owned items !
       
   160     iTexture = NULL;            
       
   161     iGcParams = THuiCachedGcParams();       
       
   162     iActiveUsers.Reset();
       
   163     }
       
   164 
       
   165 
       
   166 CHuiCanvasGraphicImage::CHuiCanvasGraphicImage() :
       
   167     iBitmapHandle(0),
       
   168     iMaskHandle(0),
       
   169     iBitmap(NULL),
       
   170     iMask(NULL),
       
   171     iInvertedMask(EFalse),
       
   172     iMaskOriginPoint(TPoint(0,0)),
       
   173     iBitmapTouchCount(-1),
       
   174     iMaskTouchCount(-1),
       
   175     iImageSize(TSize(0,0))        
       
   176         {
       
   177         }
       
   178 
       
   179 void CHuiCanvasGraphicImage::CopyAttributes(CHuiCanvasGraphicImage& aSrc)
       
   180     {
       
   181     CHuiCanvasImage::CopyAttributes(aSrc);
       
   182     iBitmap = aSrc.iBitmap;
       
   183     iMask = aSrc.iMask;        
       
   184     iBitmapHandle = aSrc.iBitmapHandle;
       
   185     iMaskHandle = aSrc.iMaskHandle;
       
   186     iInvertedMask = aSrc.iInvertedMask;
       
   187     iMaskOriginPoint = aSrc.iMaskOriginPoint;
       
   188     iTexture = aSrc.iTexture;
       
   189     iBitmapTouchCount = aSrc.iBitmapTouchCount;
       
   190     iMaskTouchCount = aSrc.iMaskTouchCount;
       
   191     iImageSize = aSrc.iImageSize;        
       
   192 
       
   193     iSubImages.Reset();
       
   194     for (TInt i=0; i<aSrc.iSubImages.Count();i++)
       
   195         {
       
   196         iSubImages.Append(aSrc.iSubImages[i]);    
       
   197         }               
       
   198     }
       
   199 
       
   200 void CHuiCanvasGraphicImage::Reset()
       
   201     {
       
   202     // Reset does not delete owned items !        
       
   203     CHuiCanvasImage::Reset();                
       
   204     iBitmap = NULL;
       
   205     iMask = NULL;        
       
   206     iSubImages.Reset();        
       
   207     iBitmapHandle = 0;
       
   208     iMaskHandle = 0;
       
   209     iInvertedMask = EFalse;
       
   210     iMaskOriginPoint = TPoint(0,0);
       
   211     iTexture = NULL;
       
   212     iBitmapTouchCount = -1;
       
   213     iMaskTouchCount = -1;
       
   214     iImageSize = TSize(0,0);        
       
   215     };
       
   216 
       
   217         
       
   218 
       
   219 CHuiCanvasGraphicImage::~CHuiCanvasGraphicImage()
       
   220     {
       
   221     delete iBitmap;
       
   222     delete iMask;
       
   223     for (TInt i=0;i<iSubImages.Count();i++)
       
   224         {
       
   225         delete iSubImages[i].iBitmap;    
       
   226         delete iSubImages[i].iMask;    
       
   227         }
       
   228     iSubImages.Close();
       
   229     }
       
   230 
       
   231 
       
   232 
       
   233 
       
   234 CHuiCanvasTextImage::CHuiCanvasTextImage() :
       
   235     iText(NULL),
       
   236     iFindTextPtr(NULL),
       
   237     iFontHandle(0),
       
   238     iRasterizationOffset(TPoint(0,0)),
       
   239     iTextBoxMaxSize(TSize(KMinTInt,KMinTInt)),
       
   240     iTextWidth(KMinTInt),
       
   241     iBaseLineOffset(KMinTInt),
       
   242     iTextAlign(CGraphicsContext::ELeft),
       
   243     iMargin(0),
       
   244     iAngle(0),
       
   245     iUseColorModulation(EFalse),
       
   246     iFont(NULL)                
       
   247         {
       
   248         }
       
   249         
       
   250 void CHuiCanvasTextImage::CopyAttributes(CHuiCanvasTextImage& aSrc)
       
   251     {
       
   252     CHuiCanvasImage::CopyAttributes(aSrc);
       
   253     iText = aSrc.iText;
       
   254     iFindTextPtr = aSrc.iFindTextPtr;
       
   255     iFontHandle = aSrc.iFontHandle;
       
   256     iRasterizationOffset = aSrc.iRasterizationOffset;
       
   257     iTextBoxMaxSize = aSrc.iTextBoxMaxSize;
       
   258     iTextWidth = aSrc.iTextWidth;
       
   259     iBaseLineOffset = aSrc.iBaseLineOffset;
       
   260     iTextAlign = aSrc.iTextAlign;
       
   261     iMargin = aSrc.iMargin;
       
   262     iAngle = aSrc.iAngle;
       
   263     iUseColorModulation = aSrc.iUseColorModulation;            
       
   264     iTextParams = aSrc.iTextParams;
       
   265     iFont = aSrc.iFont;
       
   266     }
       
   267 
       
   268 void CHuiCanvasTextImage::Reset()
       
   269     {
       
   270     // Reset does not delete owned items !
       
   271     CHuiCanvasImage::Reset();        
       
   272     iText = NULL;
       
   273     iFindTextPtr = NULL;
       
   274     iFontHandle = 0,
       
   275     iRasterizationOffset = TPoint(0,0);
       
   276     iTextBoxMaxSize = TSize(KMinTInt,KMinTInt);
       
   277     iTextWidth = KMinTInt;
       
   278     iBaseLineOffset = KMinTInt;
       
   279     iTextAlign = CGraphicsContext::ELeft;
       
   280     iMargin = 0;
       
   281     iAngle = 0;
       
   282     iUseColorModulation = EFalse;            
       
   283     iFont = NULL;
       
   284     }
       
   285 
       
   286 CHuiCanvasTextImage::~CHuiCanvasTextImage()
       
   287     {
       
   288     }
       
   289 
       
   290 TBool CHuiCanvasTextImage::UseColorModulation() const
       
   291     {
       
   292     return iUseColorModulation; 
       
   293     }
       
   294 
       
   295 NONSHARABLE_CLASS( CHuiCanvasRenderBufferImage ) : public CHuiCanvasImage
       
   296     {
       
   297 public:
       
   298     
       
   299     CHuiCanvasRenderBufferImage();
       
   300 
       
   301     ~CHuiCanvasRenderBufferImage();
       
   302             
       
   303     virtual void CopyAttributes(CHuiCanvasRenderBufferImage& aSrc);
       
   304 
       
   305     virtual void Reset();
       
   306 
       
   307 public:
       
   308 
       
   309     CHuiCanvasRenderBuffer* iCanvasRenderBuffer;
       
   310     TAny* iOwner;
       
   311     };
       
   312 
       
   313 
       
   314 CHuiCanvasRenderBufferImage::CHuiCanvasRenderBufferImage() :
       
   315     iCanvasRenderBuffer(NULL),
       
   316     iOwner(NULL)
       
   317         {
       
   318         }
       
   319         
       
   320 void CHuiCanvasRenderBufferImage::CopyAttributes(CHuiCanvasRenderBufferImage& aSrc)
       
   321     {
       
   322     CHuiCanvasImage::CopyAttributes(aSrc);
       
   323     iCanvasRenderBuffer= aSrc.iCanvasRenderBuffer;
       
   324     iOwner = aSrc.iOwner;
       
   325     }
       
   326 
       
   327 void CHuiCanvasRenderBufferImage::Reset()
       
   328     {
       
   329     // Reset does not delete owned items !
       
   330     CHuiCanvasImage::Reset();        
       
   331     iCanvasRenderBuffer = NULL;
       
   332     iOwner = NULL;
       
   333     }
       
   334 
       
   335 CHuiCanvasRenderBufferImage::~CHuiCanvasRenderBufferImage()
       
   336     {
       
   337     delete iCanvasRenderBuffer;
       
   338     }
       
   339 
       
   340 
       
   341 NONSHARABLE_CLASS( CHuiCanvasImageRasterizer ) : public CBase
       
   342     {
       
   343 public:
       
   344 
       
   345     CHuiCanvasImageRasterizer();
       
   346 
       
   347     ~CHuiCanvasImageRasterizer();
       
   348 
       
   349     void ConstructL(TDisplayMode aPreferredMode = ENone);
       
   350 
       
   351     TBool IsSeparateTextMaskUsed();
       
   352 
       
   353     static CFbsBitmap* CreateMovedMaskL(CFbsBitmap& aOriginalMask, TPoint aNewTopLeftCorner);
       
   354 
       
   355     static CFbsBitmap* CreateInvertedMaskL(CFbsBitmap& aOriginalMask);
       
   356 
       
   357 protected:
       
   358 
       
   359     CFbsBitmap* iTempMask;
       
   360     CFbsBitmapDevice* iTempMaskDevice;
       
   361     CFbsBitGc*  iTempMaskGc;
       
   362     
       
   363     CFbsBitmap* iTempBitmap;
       
   364     CFbsBitmapDevice* iTempBitmapDevice;
       
   365     CFbsBitGc*  iTempBitmapGc;    
       
   366     };
       
   367 
       
   368 CHuiCanvasImageRasterizer::CHuiCanvasImageRasterizer()
       
   369     {    
       
   370     }
       
   371 
       
   372 CHuiCanvasImageRasterizer::~CHuiCanvasImageRasterizer()
       
   373     {
       
   374     delete iTempMaskGc;
       
   375     delete iTempMaskDevice;
       
   376     delete iTempMask;
       
   377 
       
   378     delete iTempBitmapGc;
       
   379     delete iTempBitmapDevice;
       
   380     delete iTempBitmap; 
       
   381     }
       
   382 
       
   383 void CHuiCanvasImageRasterizer::ConstructL(TDisplayMode aPreferredMode)
       
   384     {
       
   385     iTempMask = NULL;
       
   386     iTempMaskDevice = NULL;
       
   387     iTempMaskGc = NULL;
       
   388 
       
   389     iTempBitmap = NULL;
       
   390     iTempBitmapDevice = NULL;
       
   391     iTempBitmapGc = NULL;
       
   392     
       
   393     // Select fastest color mode for uploading rasterized texts, we assume that EColor16MA 
       
   394     // should be best for HW accelrated rendereres (requiring least amount of conversions
       
   395     // needed before uploading to texture memory) and EColor64K is good for
       
   396     // bitgdi because its backbuffer is in that format.
       
   397     //
       
   398     // NOTE: EHuiRendererGles10 and EHuiRendererGles11 temporarely use EColor64K
       
   399     // beacuse it looks as there are some problems with uploading 16MA 
       
   400     // mode bitmaps into multisegmented textures.
       
   401     //
       
   402     TDisplayMode colorMode = EColor16MA;
       
   403     if (aPreferredMode == EGray256 && 
       
   404         CHuiStatic::Env().Renderer() == EHuiRendererVg10)
       
   405         {
       
   406         colorMode = EGray256;
       
   407         }
       
   408     else if (aPreferredMode == EColor64K)
       
   409         {
       
   410         colorMode = EColor64K;
       
   411         }
       
   412     else if (CHuiStatic::Env().Renderer() == EHuiRendererBitgdi || 
       
   413         CHuiStatic::Env().Renderer() == EHuiRendererGles10 || 
       
   414         CHuiStatic::Env().Renderer() == EHuiRendererGles11)
       
   415         {
       
   416         colorMode = EColor64K;           
       
   417         }
       
   418 
       
   419     iTempBitmap = new (ELeave) CFbsBitmap;
       
   420     iTempBitmap->Create(TSize(4,4), colorMode);       
       
   421     iTempBitmapDevice = CFbsBitmapDevice::NewL(iTempBitmap);
       
   422     User::LeaveIfError(iTempBitmapDevice->CreateContext(iTempBitmapGc));             
       
   423     
       
   424     if (colorMode != EGray256)
       
   425         {
       
   426         iTempMask = new (ELeave) CFbsBitmap;
       
   427         iTempMask->Create(TSize(4,4), EGray256);       
       
   428         iTempMaskDevice = CFbsBitmapDevice::NewL(iTempMask);
       
   429         User::LeaveIfError(iTempMaskDevice->CreateContext(iTempMaskGc));                 
       
   430         }
       
   431     }
       
   432 
       
   433 TBool CHuiCanvasImageRasterizer::IsSeparateTextMaskUsed()
       
   434     {
       
   435     if (iTempBitmap && 
       
   436         iTempBitmap->DisplayMode() != EColor16MA && 
       
   437         iTempBitmap->DisplayMode() != EColor16MAP &&
       
   438         iTempBitmap->DisplayMode() != EGray256)
       
   439         {
       
   440         return ETrue;    
       
   441         }
       
   442     else
       
   443         {
       
   444         return EFalse;    
       
   445         }            
       
   446     }
       
   447 
       
   448 CFbsBitmap* CHuiCanvasImageRasterizer::CreateInvertedMaskL(CFbsBitmap& aOriginalMask)
       
   449     {
       
   450     TSize size = aOriginalMask.SizeInPixels();
       
   451     
       
   452     CFbsBitmap* newMask = new(ELeave)CFbsBitmap;                       
       
   453     CleanupStack::PushL(newMask);
       
   454     
       
   455     CFbsBitmap* bitmap = new(ELeave)CFbsBitmap;                       
       
   456     CleanupStack::PushL(bitmap);
       
   457         
       
   458     newMask->Create(size, aOriginalMask.DisplayMode());       
       
   459     bitmap->Create(size, aOriginalMask.DisplayMode());       
       
   460     
       
   461     CFbsDevice* newMaskdevice = NULL;
       
   462     CFbsBitGc* newMaskGc = NULL;
       
   463 
       
   464     CFbsDevice* bitmapDevice = NULL;
       
   465     CFbsBitGc* bitmapGc = NULL;
       
   466 
       
   467     newMaskdevice = CFbsBitmapDevice::NewL(newMask);
       
   468     CleanupStack::PushL(newMaskdevice);
       
   469     User::LeaveIfError(newMaskdevice->CreateContext(newMaskGc));
       
   470 
       
   471     bitmapDevice = CFbsBitmapDevice::NewL(bitmap);
       
   472     CleanupStack::PushL(bitmapDevice);
       
   473     User::LeaveIfError(bitmapDevice->CreateContext(bitmapGc));
       
   474 
       
   475     bitmapGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
       
   476     bitmapGc->SetPenStyle(CGraphicsContext::ESolidPen);
       
   477     bitmapGc->SetPenColor(KRgbBlack);
       
   478     bitmapGc->SetBrushColor(KRgbBlack);
       
   479     bitmapGc->DrawRect(TRect(TPoint(0,0), size));
       
   480     
       
   481     newMaskGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
       
   482     newMaskGc->SetPenStyle(CGraphicsContext::ESolidPen);
       
   483     newMaskGc->SetPenColor(KRgbWhite);
       
   484     newMaskGc->SetBrushColor(KRgbWhite);
       
   485     newMaskGc->DrawRect(TRect(TPoint(0,0), size));
       
   486     newMaskGc->BitBltMasked(TPoint(0,0), bitmap, TRect(TPoint(0,0), size), &aOriginalMask, EFalse);
       
   487     
       
   488     delete bitmapGc;
       
   489     delete newMaskGc;
       
   490     
       
   491     CleanupStack::PopAndDestroy(bitmapDevice);
       
   492     CleanupStack::PopAndDestroy(newMaskdevice);
       
   493     CleanupStack::PopAndDestroy(bitmap);
       
   494     CleanupStack::Pop(newMask);
       
   495     
       
   496     return newMask;
       
   497     }
       
   498 
       
   499 CFbsBitmap* CHuiCanvasImageRasterizer::CreateMovedMaskL(CFbsBitmap& aOriginalMask, TPoint aNewTopLeftCorner)
       
   500     {
       
   501     TSize size = aOriginalMask.SizeInPixels();
       
   502     
       
   503     CFbsBitmap* newMask = new(ELeave)CFbsBitmap;                       
       
   504     CleanupStack::PushL(newMask);
       
   505             
       
   506     newMask->Create(size, aOriginalMask.DisplayMode());       
       
   507     
       
   508     CFbsDevice* newMaskdevice = NULL;
       
   509     CFbsBitGc* newMaskGc = NULL;
       
   510 
       
   511     newMaskdevice = CFbsBitmapDevice::NewL(newMask);
       
   512     CleanupStack::PushL(newMaskdevice);
       
   513     User::LeaveIfError(newMaskdevice->CreateContext(newMaskGc));
       
   514 
       
   515     newMaskGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
       
   516     newMaskGc->SetPenStyle(CGraphicsContext::ESolidPen);
       
   517     newMaskGc->SetPenColor(KRgbWhite);
       
   518     newMaskGc->SetBrushColor(KRgbWhite);
       
   519     newMaskGc->DrawRect(TRect(TPoint(0,0), size));
       
   520     newMaskGc->BitBlt(TPoint(0,0), &aOriginalMask, TRect(aNewTopLeftCorner, size));
       
   521     newMaskGc->BitBlt(aNewTopLeftCorner, &aOriginalMask, TRect(TPoint(0,0), size));
       
   522     
       
   523     delete newMaskGc;    
       
   524     CleanupStack::PopAndDestroy(newMaskdevice);
       
   525     CleanupStack::Pop(newMask);
       
   526     
       
   527     return newMask;
       
   528     }
       
   529     
       
   530 
       
   531 NONSHARABLE_CLASS( CHuiCanvasTextImageRasterizer ) : public CHuiCanvasImageRasterizer
       
   532     {
       
   533 public:
       
   534 
       
   535     CHuiCanvasTextImageRasterizer();
       
   536 
       
   537     ~CHuiCanvasTextImageRasterizer();
       
   538 
       
   539     void RasterizeL(CHuiCanvasTextImage& aTextImage);
       
   540 
       
   541 private:
       
   542 
       
   543     TSize CalculateRasterizedTextSize(const TDesC& aText, CFont* aFont) const;
       
   544 
       
   545     void InitL(CHuiCanvasTextImage& aTextImage, TSize& aTextsize);
       
   546 
       
   547     void DrawL(CHuiCanvasTextImage& aTextImage, TSize& aTextsize, TPoint& aRasterizedOffset);
       
   548 
       
   549     void UploadL(CHuiCanvasTextImage& aTextImage, TPoint& aRasterrizedOffset);
       
   550 
       
   551 private:
       
   552 
       
   553     TInt iFontHandle;
       
   554     CFbsBitGcFont* iFont;
       
   555     };
       
   556 
       
   557 CHuiCanvasTextImageRasterizer::CHuiCanvasTextImageRasterizer()
       
   558     {    
       
   559     }
       
   560 
       
   561 CHuiCanvasTextImageRasterizer::~CHuiCanvasTextImageRasterizer()
       
   562     {
       
   563     delete iFont;
       
   564     }
       
   565     
       
   566 TSize CHuiCanvasTextImageRasterizer::CalculateRasterizedTextSize(const TDesC& aText, CFont* aFont) const
       
   567     {
       
   568     CFont::TMeasureTextInput input; 
       
   569     input.iFlags = CFont::TMeasureTextInput::EFVisualOrder;
       
   570     CFont::TMeasureTextOutput output; 
       
   571     
       
   572     TInt textAdvance = aFont->MeasureText( aText, &input, &output );
       
   573 	
       
   574 	TRect bounds = output.iBounds;
       
   575 	bounds.iTl.iX = Min(bounds.iTl.iX, 0);
       
   576 	bounds.iBr.iX = Max(bounds.iBr.iX, textAdvance);    
       
   577     
       
   578     TSize textSize = TSize(bounds.Width(), aFont->FontMaxHeight());
       
   579  
       
   580     const CAknLayoutFont* layoutFont = 0;
       
   581   
       
   582     if (CCoeEnv::Static())
       
   583         {
       
   584         layoutFont = CAknLayoutFont::AsCAknLayoutFontOrNull( aFont );
       
   585         }
       
   586 		
       
   587     if ( layoutFont )
       
   588         {
       
   589         textSize.iHeight = aFont->HeightInPixels();
       
   590         TInt textPaneHeight = layoutFont->TextPaneHeight();
       
   591         TInt textPaneTopToBaseline = layoutFont->TextPaneTopToBaseline();
       
   592         
       
   593         textSize.iHeight += textPaneHeight - textPaneTopToBaseline;
       
   594         textSize.iHeight += KHuiFontVerticalShiftInPixels;
       
   595         }
       
   596     else
       
   597         {
       
   598         textSize.iHeight = Max(textSize.iHeight, aFont->HeightInPixels());
       
   599         textSize.iHeight += 3; // the best approximation - fails on big (>=72) fonts
       
   600         }
       
   601                    
       
   602     return textSize;            
       
   603     }
       
   604     
       
   605     
       
   606 void CHuiCanvasTextImageRasterizer::RasterizeL(CHuiCanvasTextImage& aTextImage)
       
   607     {
       
   608     TPoint rasterizedOffset(0, 0);
       
   609     
       
   610     if (aTextImage.iFontHandle && (iFontHandle != aTextImage.iFontHandle))
       
   611         {
       
   612         delete iFont;
       
   613         iFont = NULL;    
       
   614 
       
   615         // the font might have been duplicated earlier in order to
       
   616         // find out whether it is an outline font or not. As the CHuiCanvasTextImage
       
   617         // does not own the font pointer by it's member iFont, just copy the pointer
       
   618         // to the instance of this class..        
       
   619         if (aTextImage.iFont)
       
   620             {
       
   621             iFont = aTextImage.iFont;
       
   622             }
       
   623         else
       
   624             {
       
   625             // Font is cached as pointer because next text may same font and in that case
       
   626             // we are much faster as there is no need to do font duplication again.
       
   627             iFont = new (ELeave) CFbsBitGcFont();
       
   628             iFontHandle = aTextImage.iFontHandle;
       
   629             TInt fontDuplicateErrorCode = iFont->Duplicate(iFontHandle);            
       
   630             
       
   631             if (fontDuplicateErrorCode)
       
   632                 {
       
   633                 // Invalid handle which would panic inside fbsbitgc
       
   634                 iFontHandle = 0;
       
   635                 delete iFont;
       
   636                 iFont = NULL;                    
       
   637                 aTextImage.iFont = NULL;
       
   638                 }
       
   639             else
       
   640                 {
       
   641                 // we need a reference to the font in CHuiCanvasTextImage aswell..
       
   642                 aTextImage.iFont = iFont;
       
   643                 }
       
   644             }
       
   645         }
       
   646     
       
   647     if (iFont)
       
   648         {
       
   649         TSize textSize = TSize(0,0);
       
   650         TInt textAscent = 0;
       
   651 
       
   652         // If no max size is provided, we need to approximate the needed texture size.
       
   653         if (aTextImage.iTextBoxMaxSize == TSize(KMinTInt,KMinTInt))
       
   654             {                    
       
   655             textSize = CalculateRasterizedTextSize(*aTextImage.iText, iFont);            
       
   656 
       
   657             // To get most closest values for the font metrics we could try to cast
       
   658             // font into aknlayoutfont, but that does not seem to work when font is
       
   659             // duplicated trough handle. This solution is not accurate and results slightly 
       
   660             // too  large textures but avoids text clipping.
       
   661             TReal32 height = textSize.iHeight;
       
   662             textSize.iHeight = height * 1.2;
       
   663             textAscent = height * 0.9;
       
   664                           
       
   665             // If rotated 90 degress, then flip width and heigths
       
   666             if (aTextImage.iAngle == 90 || aTextImage.iAngle == -90)
       
   667                 {
       
   668                 TSize horizontalTextSize = textSize;
       
   669                 textSize.iWidth = horizontalTextSize.iHeight;
       
   670                 textSize.iHeight = horizontalTextSize.iWidth;                    
       
   671                 }
       
   672             
       
   673             // Since we modify the actual point where drawing is to happen
       
   674             // (so that image size gets minimized), we use rasterizedOffset to specify
       
   675             // offset we have used. That offset needs to be used when image of the text 
       
   676             // is to be drawn because with these coordinates text goes exactly where it ´
       
   677             // is supposed to go. 
       
   678             if (aTextImage.iAngle == 90)
       
   679                 {
       
   680                 // Rotated clockwise
       
   681                 rasterizedOffset.iX = textSize.iWidth-textAscent;                                            
       
   682                 }
       
   683             else if (aTextImage.iAngle == -90)
       
   684                 {
       
   685                 // Rotated anti clockwise
       
   686                 rasterizedOffset.iX = textAscent;                                                                    
       
   687                 // Drawing happens upwards
       
   688                 rasterizedOffset.iY = textSize.iHeight;                                                                    
       
   689                 }
       
   690             else
       
   691                 {
       
   692                 // No rotation, just drawn lower
       
   693                 rasterizedOffset.iY = textAscent;                    
       
   694                 }                                            
       
   695             }
       
   696         else
       
   697             {
       
   698             // Clipping text box is provided, much easier this way.
       
   699             textSize = aTextImage.iTextBoxMaxSize;
       
   700             }
       
   701 
       
   702         // Setup gc parameters
       
   703         InitL(aTextImage, textSize);                                
       
   704         
       
   705         // Draw the text 
       
   706         DrawL(aTextImage, textSize, rasterizedOffset);
       
   707         }
       
   708               
       
   709     // Upload content          
       
   710     UploadL(aTextImage, rasterizedOffset);    
       
   711         
       
   712     }
       
   713     
       
   714 void CHuiCanvasTextImageRasterizer::InitL(CHuiCanvasTextImage& aTextImage, TSize& aTextsize)
       
   715     {
       
   716     TFontUnderline underline = (TFontUnderline)aTextImage.iGcParams.iUnderline;
       
   717     TFontStrikethrough strikethrough = (TFontStrikethrough)aTextImage.iGcParams.iStrikethrough;
       
   718     CGraphicsContext::TBrushStyle brushstyle = (CGraphicsContext::TBrushStyle)aTextImage.iGcParams.iBrushStyle;
       
   719     CGraphicsContext::TPenStyle penstyle = (CGraphicsContext::TPenStyle)aTextImage.iGcParams.iPenStyle;
       
   720     TInt shadowmode = aTextImage.iGcParams.iShadowMode; // TODO: Is this even needed for texts ?
       
   721     TBool outlinefont = iFont->FontSpecInTwips().iFontStyle.IsEffectOn(FontEffect::EOutline);
       
   722     if (IsSeparateTextMaskUsed())
       
   723         {
       
   724         iTempMask->Resize(aTextsize);
       
   725         iTempMaskDevice->Resize(aTextsize);
       
   726 
       
   727         delete iTempMaskGc;
       
   728         iTempMaskGc = NULL;                             
       
   729         User::LeaveIfError(iTempMaskDevice->CreateContext(iTempMaskGc));     
       
   730 
       
   731         // Mask bitmap, this defines the shape of the text.
       
   732     	iTempMaskGc->SetBrushColor(KRgbBlack);
       
   733     	iTempMaskGc->Clear();    	
       
   734    	    iTempMaskGc->SetPenColor(KRgbWhite);
       
   735 
       
   736         // We dont call the UseFont() variant with handle param because it is slower
       
   737         iTempMaskGc->UseFont(iFont);
       
   738 
       
   739         // Set correct gc settings
       
   740         iTempMaskGc->SetPenStyle(penstyle);
       
   741         iTempMaskGc->SetBrushStyle(brushstyle);
       
   742         iTempMaskGc->SetUnderlineStyle(underline);
       
   743         iTempMaskGc->SetStrikethroughStyle(strikethrough);
       
   744         iTempMaskGc->SetShadowMode(shadowmode);            
       
   745         }
       
   746 
       
   747     iTempBitmap->Resize(aTextsize);
       
   748     iTempBitmapDevice->Resize(aTextsize);
       
   749 
       
   750     delete iTempBitmapGc;
       
   751     iTempBitmapGc = NULL;        
       
   752     User::LeaveIfError(iTempBitmapDevice->CreateContext(iTempBitmapGc));                 
       
   753     
       
   754     if (IsSeparateTextMaskUsed())
       
   755         {
       
   756         // Just fill with correct color, text shape comes from mask
       
   757         if (KHuiCanvasTextUseColorModulation)
       
   758             {
       
   759             iTempBitmapGc->SetPenColor(KRgbWhite);
       
   760             }
       
   761         else
       
   762             {
       
   763             iTempBitmapGc->SetPenColor(aTextImage.iGcParams.iPenColor);
       
   764             }    
       
   765 
       
   766         iTempBitmapGc->SetBrushColor(aTextImage.iGcParams.iBrushColor);                
       
   767 	    iTempBitmapGc->Clear();  
       
   768         }
       
   769     else
       
   770         {
       
   771         // First clear
       
   772         TRgb clearColor(KRgbBlack);
       
   773         clearColor.SetAlpha(0);
       
   774         iTempBitmapGc->SetPenColor(clearColor);
       
   775         iTempBitmapGc->SetBrushColor(clearColor);
       
   776         if (iTempBitmap->DisplayMode() == EColor16MA)
       
   777             {
       
   778             iTempBitmapGc->SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha);
       
   779             }
       
   780         else
       
   781             {
       
   782             iTempBitmapGc->SetDrawMode(CGraphicsContext::EDrawModePEN);
       
   783             }
       
   784                             	    
       
   785 	    iTempBitmapGc->Clear();                  
       
   786 
       
   787         // Set correct gc settings
       
   788         if (!outlinefont && KHuiCanvasTextUseColorModulation)
       
   789             {
       
   790             iTempBitmapGc->SetPenColor(KRgbWhite);                        
       
   791             }
       
   792         else
       
   793             {
       
   794             iTempBitmapGc->SetPenColor(aTextImage.iGcParams.iPenColor);        
       
   795             iTempBitmapGc->SetBrushColor(aTextImage.iGcParams.iBrushColor);        
       
   796             }
       
   797         
       
   798         iTempBitmapGc->SetPenStyle(penstyle);
       
   799         if (!outlinefont)
       
   800             {
       
   801             iTempBitmapGc->SetBrushStyle( CGraphicsContext::ENullBrush );
       
   802             }
       
   803         else
       
   804             {
       
   805             iTempBitmapGc->SetBrushStyle( brushstyle );
       
   806             }
       
   807         
       
   808         iTempBitmapGc->SetUnderlineStyle(underline);
       
   809         iTempBitmapGc->SetStrikethroughStyle(strikethrough);
       
   810         iTempBitmapGc->SetShadowMode(shadowmode);            
       
   811         }    
       
   812             
       
   813     // We dont call the UseFont() variant with handle param because it is slower
       
   814     iTempBitmapGc->UseFont(iFont);    
       
   815 
       
   816     // Are we using color modulation, store info to entry
       
   817     aTextImage.iUseColorModulation = outlinefont ? EFalse : KHuiCanvasTextUseColorModulation;
       
   818 
       
   819     // Debug, enable this to see texture outlines.
       
   820     //iTempMaskGc->DrawRect(TRect(TPoint(0,0), textSize));                
       
   821     }
       
   822 
       
   823 void CHuiCanvasTextImageRasterizer::DrawL(CHuiCanvasTextImage& aTextImage, TSize& aTextsize, TPoint& aRasterizedOffset)
       
   824     {
       
   825 #ifdef SYMBIAN_BUILD_GCE            
       
   826     CGraphicsContext::TTextParameters gcTextParams = *(CGraphicsContext::TTextParameters*)& aTextImage.iTextParams;
       
   827 #endif            
       
   828     // Based on supplied params, select the approprite DrawText variant.
       
   829     TBool up = (aTextImage.iAngle == -90);
       
   830     if (aTextImage.iTextBoxMaxSize != TSize(KMinTInt,KMinTInt))
       
   831         {
       
   832         if (aTextImage.iBaseLineOffset != KMinTInt)
       
   833             {
       
   834             CGraphicsContext::TTextAlign align = (CGraphicsContext::TTextAlign) aTextImage.iTextAlign;
       
   835 
       
   836             if (aTextImage.iTextWidth != KMinTInt)
       
   837             
       
   838                 {
       
   839                 if (aTextImage.iAngle == 0)
       
   840                     {                                
       
   841                     if (IsSeparateTextMaskUsed())
       
   842                         {
       
   843                         iTempMaskGc->DrawText(*aTextImage.iText, 
       
   844 #ifdef SYMBIAN_BUILD_GCE            
       
   845                         &gcTextParams,
       
   846 #endif                            
       
   847                         TRect(TPoint(0,0), aTextsize), aTextImage.iBaseLineOffset, aTextImage.iTextWidth, align, aTextImage.iMargin);                            
       
   848                         }
       
   849                     else
       
   850                         {
       
   851                         // No need to draw separate mask, iTempBitmapGc is using EDrawModeWriteAlpha mode
       
   852                         }    
       
   853                     
       
   854                     iTempBitmapGc->DrawText(*aTextImage.iText, 
       
   855 #ifdef SYMBIAN_BUILD_GCE            
       
   856                     &gcTextParams,
       
   857 #endif                                                      
       
   858                     TRect(TPoint(0,0), aTextsize), aTextImage.iBaseLineOffset, aTextImage.iTextWidth, align, aTextImage.iMargin);
       
   859                     }
       
   860                 else
       
   861                     {
       
   862                     if (IsSeparateTextMaskUsed())
       
   863                         {
       
   864                         iTempMaskGc->DrawTextVertical(*aTextImage.iText, 
       
   865 #ifdef SYMBIAN_BUILD_GCE            
       
   866                         &gcTextParams,
       
   867 #endif                                                      
       
   868                         TRect(TPoint(0,0), aTextsize), aTextImage.iBaseLineOffset, aTextImage.iTextWidth, up, align, aTextImage.iMargin);
       
   869                         }
       
   870                     else
       
   871                         {
       
   872                         // No need to draw separate mask, iTempBitmapGc is using EDrawModeWriteAlpha mode
       
   873                         }    
       
   874                     iTempBitmapGc->DrawTextVertical(*aTextImage.iText, 
       
   875 #ifdef SYMBIAN_BUILD_GCE            
       
   876                     &gcTextParams,
       
   877 #endif                            
       
   878                     TRect(TPoint(0,0), aTextsize), aTextImage.iBaseLineOffset, aTextImage.iTextWidth, up, align, aTextImage.iMargin);                                                            
       
   879                     }    
       
   880                 }
       
   881             else
       
   882                 {
       
   883                 if (aTextImage.iAngle == 0)
       
   884                     {                               
       
   885                     if (IsSeparateTextMaskUsed())
       
   886                         {
       
   887                         iTempMaskGc->DrawText(*aTextImage.iText, 
       
   888 #ifdef SYMBIAN_BUILD_GCE            
       
   889                         &gcTextParams,
       
   890 #endif                            
       
   891                         TRect(TPoint(0,0), aTextsize), aTextImage.iBaseLineOffset, align, aTextImage.iMargin);
       
   892                         }
       
   893                     else
       
   894                         {
       
   895                         // No need to draw separate mask, iTempBitmapGc is using EDrawModeWriteAlpha mode
       
   896                         }    
       
   897                     iTempBitmapGc->DrawText(*aTextImage.iText, 
       
   898 #ifdef SYMBIAN_BUILD_GCE            
       
   899                     &gcTextParams,
       
   900 #endif                                                      
       
   901                     TRect(TPoint(0,0), aTextsize), aTextImage.iBaseLineOffset, align, aTextImage.iMargin);                            
       
   902                     }
       
   903                 else
       
   904                     {
       
   905                     if (IsSeparateTextMaskUsed())
       
   906                         {                                
       
   907                         iTempMaskGc->DrawTextVertical(*aTextImage.iText, 
       
   908 #ifdef SYMBIAN_BUILD_GCE            
       
   909                         &gcTextParams,
       
   910 #endif                            
       
   911                         TRect(TPoint(0,0), aTextsize), aTextImage.iBaseLineOffset, up, align, aTextImage.iMargin);
       
   912                         }
       
   913                     else
       
   914                         {
       
   915                         // No need to draw separate mask, iTempBitmapGc is using EDrawModeWriteAlpha mode
       
   916                         }    
       
   917                     iTempBitmapGc->DrawTextVertical(*aTextImage.iText, 
       
   918 #ifdef SYMBIAN_BUILD_GCE            
       
   919                     &gcTextParams,
       
   920 #endif                            
       
   921                     TRect(TPoint(0,0), aTextsize), aTextImage.iBaseLineOffset, up, align, aTextImage.iMargin);                                                            
       
   922                     }    
       
   923                 }                           
       
   924             }
       
   925         else
       
   926             {
       
   927             if (aTextImage.iAngle == 0)
       
   928                 {                               
       
   929                 if (IsSeparateTextMaskUsed())
       
   930                     {                                
       
   931                     iTempMaskGc->DrawText(*aTextImage.iText, 
       
   932 #ifdef SYMBIAN_BUILD_GCE            
       
   933                     &gcTextParams,
       
   934 #endif                            
       
   935                     TRect(TPoint(0,0), aTextsize) );
       
   936                     }
       
   937                 else
       
   938                     {
       
   939                     // No need to draw separate mask, iTempBitmapGc is using EDrawModeWriteAlpha mode
       
   940                     }    
       
   941                     
       
   942                 iTempBitmapGc->DrawText(*aTextImage.iText, 
       
   943 #ifdef SYMBIAN_BUILD_GCE            
       
   944                     &gcTextParams,
       
   945 #endif                            
       
   946                 TRect(TPoint(0,0), aTextsize));                                                        
       
   947                 }
       
   948             else
       
   949                 {
       
   950                 if (IsSeparateTextMaskUsed())
       
   951                     {                          
       
   952                     iTempMaskGc->DrawTextVertical(*aTextImage.iText, 
       
   953 #ifdef SYMBIAN_BUILD_GCE            
       
   954                     &gcTextParams,
       
   955 #endif                            
       
   956                     TRect(TPoint(0,0), aTextsize), up );
       
   957                     }
       
   958                 else
       
   959                     {
       
   960                     // No need to draw separate mask, iTempBitmapGc is using EDrawModeWriteAlpha mode
       
   961                     }    
       
   962                 
       
   963                 iTempBitmapGc->DrawTextVertical(*aTextImage.iText, 
       
   964 #ifdef SYMBIAN_BUILD_GCE            
       
   965                     &gcTextParams,
       
   966 #endif                            
       
   967                 TRect(TPoint(0,0), aTextsize), up);                                                                                    
       
   968                 }    
       
   969             }    
       
   970         }
       
   971     else
       
   972         {
       
   973         if (aTextImage.iAngle == 0)
       
   974             {                                             
       
   975             if (IsSeparateTextMaskUsed())
       
   976                 {                          
       
   977                 iTempMaskGc->DrawText(*aTextImage.iText, 
       
   978 #ifdef SYMBIAN_BUILD_GCE            
       
   979                 &gcTextParams,
       
   980 #endif                            
       
   981                 aRasterizedOffset);
       
   982                 }
       
   983             else
       
   984                 {
       
   985                 // No need to draw separate mask, iTempBitmapGc is using EDrawModeWriteAlpha mode
       
   986                 }
       
   987                     
       
   988             iTempBitmapGc->DrawText(*aTextImage.iText, 
       
   989 #ifdef SYMBIAN_BUILD_GCE            
       
   990                 &gcTextParams,
       
   991 #endif                            
       
   992             aRasterizedOffset);                                    
       
   993             }
       
   994         else
       
   995             {
       
   996             if (IsSeparateTextMaskUsed())
       
   997                 {                          
       
   998                 iTempMaskGc->DrawTextVertical(*aTextImage.iText, 
       
   999 #ifdef SYMBIAN_BUILD_GCE            
       
  1000                 &gcTextParams,
       
  1001 #endif                            
       
  1002                 aRasterizedOffset, up);
       
  1003                 }
       
  1004             else
       
  1005                 {
       
  1006                 // No need to draw separate mask, iTempBitmapGc is using EDrawModeWriteAlpha mode
       
  1007                 }
       
  1008                 
       
  1009             iTempBitmapGc->DrawTextVertical(*aTextImage.iText, 
       
  1010 #ifdef SYMBIAN_BUILD_GCE            
       
  1011                 &gcTextParams,
       
  1012 #endif                                            
       
  1013             aRasterizedOffset, up);                                                            
       
  1014             }    
       
  1015         }        
       
  1016     }
       
  1017 
       
  1018 void CHuiCanvasTextImageRasterizer::UploadL(CHuiCanvasTextImage& aTextImage, TPoint& aRasterizedOffset)
       
  1019     {
       
  1020     // Upload bitmap content...this may be slow depending on used HW acceleration !
       
  1021     
       
  1022     TSize colorBitmapSize = iTempBitmap->SizeInPixels();
       
  1023     TSize maskBitmapSize = IsSeparateTextMaskUsed() ? iTempMask->SizeInPixels() : colorBitmapSize;
       
  1024     CFbsBitmap* textColorBitmap = iTempBitmap;
       
  1025     CFbsBitmap* textMaskBitmap = IsSeparateTextMaskUsed() ? iTempMask : NULL;
       
  1026     
       
  1027            
       
  1028     if (maskBitmapSize.iWidth > 0 && 
       
  1029         maskBitmapSize.iHeight > 0 &&
       
  1030         colorBitmapSize.iWidth > 0 && 
       
  1031         colorBitmapSize.iHeight > 0)
       
  1032         {
       
  1033         // TODO: For BitGdi it might be good to use direct upload, but it would require changes such as 
       
  1034         // making new textColorBitmap, textMaskBitmap everytime.
       
  1035         THuiTextureUploadFlags uploadFlags = THuiTextureUploadFlags(EHuiTextureUploadFlagDoNotRetainResolution | EHuiTextureUploadFlagRetainColorDepth);
       
  1036 
       
  1037 #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
       
  1038         TTime startTime;
       
  1039         startTime.UniversalTime();
       
  1040 #endif
       
  1041 
       
  1042         aTextImage.iRasterizationOffset = aRasterizedOffset;
       
  1043         
       
  1044         CHuiTexture* texture = aTextImage.iTexture;
       
  1045         texture->UploadL(*textColorBitmap, textMaskBitmap, uploadFlags);                
       
  1046 
       
  1047 #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
       
  1048         TTime endTime;
       
  1049         endTime.UniversalTime();
       
  1050         TInt uploadTimeInMilliSeconds = endTime.MicroSecondsFrom( startTime ).Int64()/1000;
       
  1051         RDebug::Print(_L(">>> CHuiCanvasTextImageRasterizer::UpdateCachedTextL: Upload of %ix%i %S took %i ms"), 
       
  1052             texture->Size().iWidth, 
       
  1053             texture->Size().iHeight, 
       
  1054             aTextImage.iText,            
       
  1055             uploadTimeInMilliSeconds);
       
  1056 #endif    
       
  1057         }        
       
  1058     }
       
  1059     
       
  1060 
       
  1061 NONSHARABLE_CLASS( CHuiCanvasGraphicImageRasterizer ) : public CHuiCanvasImageRasterizer
       
  1062     {
       
  1063 public:
       
  1064 
       
  1065     CHuiCanvasGraphicImageRasterizer();
       
  1066 
       
  1067     ~CHuiCanvasGraphicImageRasterizer();
       
  1068 
       
  1069     void ConstructL(TBool aUseGray256 = EFalse);
       
  1070 
       
  1071     void RasterizeL(CHuiCanvasGraphicImage& aImage);
       
  1072 
       
  1073 private:
       
  1074     };
       
  1075 
       
  1076 CHuiCanvasGraphicImageRasterizer::CHuiCanvasGraphicImageRasterizer()
       
  1077     {    
       
  1078     }
       
  1079 
       
  1080 CHuiCanvasGraphicImageRasterizer::~CHuiCanvasGraphicImageRasterizer()
       
  1081     {
       
  1082     }
       
  1083 
       
  1084 void CHuiCanvasGraphicImageRasterizer::ConstructL(TBool /*aUseGray256*/)
       
  1085     {        
       
  1086     }
       
  1087 
       
  1088 void CHuiCanvasGraphicImageRasterizer::RasterizeL(CHuiCanvasGraphicImage& aImage)
       
  1089     {
       
  1090     CFbsBitmap* bitmap = NULL;                       
       
  1091     CFbsBitmap* mask = NULL;                       
       
  1092 
       
  1093     TInt bitmapTouchCount = KHuiInitialBitmapTouchCount;
       
  1094     TInt maskTouchCount = KHuiInitialBitmapTouchCount;
       
  1095 
       
  1096 #ifdef SYMBIAN_BUILD_GCE            
       
  1097     TBool volatileBitmapOrMask = EFalse;
       
  1098 #else
       
  1099     TBool volatileBitmapOrMask = ETrue;
       
  1100 #endif
       
  1101 
       
  1102     TBool originalMaskUsed = ETrue;
       
  1103 
       
  1104 
       
  1105     TInt bitmapHandle = aImage.iBitmapHandle;
       
  1106     TInt maskHandle = aImage.iMaskHandle;
       
  1107     TBool invertMask = aImage.iInvertedMask;
       
  1108     TPoint maskOriginPoint = aImage.iMaskOriginPoint;
       
  1109 
       
  1110     if (!bitmapHandle)
       
  1111         {
       
  1112         return;    
       
  1113         }
       
  1114     
       
  1115     // Lets see if we have already cached the pointer...
       
  1116     if (aImage.iBitmap)
       
  1117         {
       
  1118         // ...yes lets use it
       
  1119         bitmap = aImage.iBitmap;    
       
  1120         }
       
  1121     else
       
  1122         {
       
  1123         // ...no, so we need to duplicate the handle
       
  1124         bitmap = new(ELeave)CFbsBitmap;                       
       
  1125         bitmap->Duplicate(bitmapHandle);
       
  1126         if (bitmap)
       
  1127             {
       
  1128             if (KHuiCanvasKeepBitmapPointer)
       
  1129                 {
       
  1130                 aImage.iBitmap = bitmap;                    
       
  1131                 }
       
  1132             else
       
  1133                 {
       
  1134                 CleanupStack::PushL(bitmap);                
       
  1135                 }                
       
  1136             }           
       
  1137             
       
  1138         }
       
  1139 
       
  1140 #ifdef SYMBIAN_BUILD_GCE            
       
  1141         if (bitmap)
       
  1142             {
       
  1143             bitmapTouchCount = bitmap->TouchCount();        
       
  1144             volatileBitmapOrMask |= bitmap->IsVolatile();
       
  1145             }
       
  1146 #endif            
       
  1147 
       
  1148     // Mask is optional
       
  1149     if (maskHandle)
       
  1150         {
       
  1151         // Lets see if we have already cached the pointer...
       
  1152         if (aImage.iMask)
       
  1153             {
       
  1154             // ...yes lets use it
       
  1155             mask = aImage.iMask;    
       
  1156             }
       
  1157         else
       
  1158             {
       
  1159             // ...no, so we need to duplicate the handle
       
  1160             mask = new(ELeave)CFbsBitmap;                       
       
  1161             mask->Duplicate(maskHandle);
       
  1162             if (mask)
       
  1163                 {
       
  1164                 if (KHuiCanvasKeepBitmapPointer)
       
  1165                     {
       
  1166                     aImage.iMask = mask;    
       
  1167                     }
       
  1168                 else
       
  1169                     {
       
  1170                     CleanupStack::PushL(mask);                                    
       
  1171                     }                
       
  1172                 }                                
       
  1173             }
       
  1174 
       
  1175 #ifdef SYMBIAN_BUILD_GCE            
       
  1176         if (mask)
       
  1177             {
       
  1178             maskTouchCount = mask->TouchCount();    
       
  1179             volatileBitmapOrMask |= mask->IsVolatile();
       
  1180             }
       
  1181 #endif
       
  1182         
       
  1183         // If mask is defined not to be inverted, 
       
  1184         // we must invert it because toolkit assumes they are always inverted. Huh.
       
  1185 #ifdef __NVG
       
  1186         // Inverting masks is done ONLY for non-extended bitmaps!
       
  1187         if (bitmap->ExtendedBitmapType() == KNullUid) // => Bitmap isn't extended
       
  1188             {
       
  1189 #endif
       
  1190             if (invertMask && mask->DisplayMode() == EGray2)
       
  1191                 {
       
  1192                 CFbsBitmap* invertedMask = CreateInvertedMaskL(*mask);
       
  1193                 
       
  1194                 // If we are not using stored pointer, delete it
       
  1195                 if (mask != aImage.iMask)
       
  1196                     {
       
  1197                     CleanupStack::PopAndDestroy(mask);        
       
  1198                     }
       
  1199                 
       
  1200                 mask = invertedMask;
       
  1201                 CleanupStack::PushL(mask);    
       
  1202                 originalMaskUsed = EFalse;
       
  1203                 }
       
  1204             
       
  1205             // Upload expects mask to begin always at TPoint(0,0), so if mask
       
  1206             // offset is defined we re-create mask with the given new
       
  1207             // offset. Note that it might be a good idea to combine this op
       
  1208             // with mask inversion op, but we assume that these are not really used
       
  1209             // very often, even more rarely together. 
       
  1210             if (maskOriginPoint != TPoint(0,0))
       
  1211                 {
       
  1212                 CFbsBitmap* movedMask = CreateMovedMaskL(*mask, maskOriginPoint);
       
  1213 
       
  1214                 // If we are not using stored pointer, delete it
       
  1215                 if (mask != aImage.iMask)
       
  1216                     {
       
  1217                     CleanupStack::PopAndDestroy(mask);
       
  1218                     }
       
  1219                 mask = movedMask;
       
  1220                 CleanupStack::PushL(mask);                            
       
  1221                 originalMaskUsed = EFalse;
       
  1222                 }
       
  1223 #ifdef __NVG
       
  1224             }
       
  1225 #endif
       
  1226         }
       
  1227 
       
  1228     // Bitmap has changed, must be updated ?
       
  1229     TBool touchCountChanged = EFalse;    
       
  1230     touchCountChanged |= volatileBitmapOrMask;
       
  1231     touchCountChanged |= (aImage.iBitmapTouchCount != bitmapTouchCount);
       
  1232     touchCountChanged |= (aImage.iMaskTouchCount != maskTouchCount);
       
  1233 
       
  1234     // Is touch count check enabled ?
       
  1235     TBool touchCountCheckEnabled = CHuiStatic::Env().CanvasTextureCache().IsTouchCountCheckEnabled();
       
  1236     
       
  1237     // Has it old content at all ?
       
  1238     TBool hasContent = aImage.iTexture->HasContent();
       
  1239     
       
  1240     if (!hasContent || (touchCountCheckEnabled && touchCountChanged))
       
  1241         {
       
  1242         // Upload bitmap content...this may be slow depending on used HW acceleration !
       
  1243         if (bitmap->SizeInPixels().iWidth > 0 && 
       
  1244             bitmap->SizeInPixels().iHeight > 0 &&
       
  1245             (!mask || (mask->SizeInPixels().iWidth > 0 && mask->SizeInPixels().iHeight)))
       
  1246             {
       
  1247             // EHuiTextureUploadFlagDoNotRetainResolution should be removed when 
       
  1248             // texturecoordinates with segmented textures work.
       
  1249             // This flag causes ugly scaling to happen with small textures.
       
  1250             THuiTextureUploadFlags uploadFlags = THuiTextureUploadFlags(EHuiTextureUploadFlagDoNotRetainResolution | EHuiTextureUploadFlagRetainColorDepth);
       
  1251 
       
  1252 #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
       
  1253             TTime startTime;
       
  1254             startTime.UniversalTime();
       
  1255 #endif
       
  1256 
       
  1257             CHuiTexture* texture = aImage.iTexture;
       
  1258             texture->UploadL(*bitmap, mask, uploadFlags);
       
  1259 
       
  1260 #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
       
  1261             TTime endTime;
       
  1262             endTime.UniversalTime();
       
  1263             TInt uploadTimeInMilliSeconds = endTime.MicroSecondsFrom( startTime ).Int64()/1000;
       
  1264             
       
  1265             if (volatileBitmapOrMask)
       
  1266                 {
       
  1267                 RDebug::Print(_L(">>> CHuiCanvasGraphicImageRasterizer::UpdateCachedImageL: Reason for uploading is volatileBitmapOrMask"));                     
       
  1268                 }
       
  1269 
       
  1270             if (aImage.iBitmapTouchCount != bitmapTouchCount)
       
  1271                 {
       
  1272                 RDebug::Print(_L(">>> CHuiCanvasGraphicImageRasterizer::UpdateCachedImageL: Reason for uploading is iBitmapTouchCount %i, old was %i "), bitmapTouchCount, aImage.iBitmapTouchCount);                     
       
  1273                 }
       
  1274 
       
  1275             if (aImage.iMaskTouchCount != maskTouchCount)
       
  1276                 {
       
  1277                 RDebug::Print(_L(">>> CHuiCanvasGraphicImageRasterizer::UpdateCachedImageL: Reason for uploading is iMaskTouchCount %i, old was %i "), maskTouchCount, aImage.iMaskTouchCount);                     
       
  1278                 }
       
  1279 
       
  1280             RDebug::Print(_L(">>> CHuiCanvasGraphicImageRasterizer::UpdateCachedImageL: Upload of %ix%i %i+%i took %i ms"), 
       
  1281                 texture->Size().iWidth, 
       
  1282                 texture->Size().iHeight,
       
  1283                 aImage.iBitmapHandle,
       
  1284                 aImage.iMaskHandle,
       
  1285                 uploadTimeInMilliSeconds);
       
  1286 #endif
       
  1287             }            
       
  1288         
       
  1289 #ifdef SYMBIAN_BUILD_GCE            
       
  1290         // Texture upload itself must not modify bitmap or mask touch count.
       
  1291         // Otherwise, it's impossible to detect client data access
       
  1292         // (since there is not necessarily any synchronisation between client & alf).
       
  1293         
       
  1294         aImage.iBitmapTouchCount = bitmapTouchCount;
       
  1295         aImage.iMaskTouchCount = maskTouchCount;
       
  1296 #endif                    
       
  1297         }
       
  1298     else
       
  1299         {
       
  1300         if (touchCountChanged && !touchCountCheckEnabled)
       
  1301             {
       
  1302 #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
       
  1303             RDebug::Print(_L(">>> CHuiCanvasGraphicImageRasterizer::UpdateCachedImageL: skipping uploading because touchcount check is disabled"));
       
  1304 #endif
       
  1305             }        
       
  1306         }
       
  1307 
       
  1308     // If we are not using stored pointer, delete it
       
  1309     if (mask && (mask != aImage.iMask))
       
  1310         {
       
  1311         CleanupStack::PopAndDestroy(mask);
       
  1312         mask = NULL;                    
       
  1313         }
       
  1314 
       
  1315     // If we are not using stored pointer, delete it
       
  1316     if (bitmap && (bitmap != aImage.iBitmap))
       
  1317         {
       
  1318         CleanupStack::PopAndDestroy(bitmap);
       
  1319         bitmap = NULL;                    
       
  1320         }                    
       
  1321     }
       
  1322     
       
  1323 
       
  1324 
       
  1325 NONSHARABLE_CLASS( CHuiCanvasCombinedGraphicImageRasterizer ) : public CHuiCanvasImageRasterizer
       
  1326     {
       
  1327 public:
       
  1328 
       
  1329     CHuiCanvasCombinedGraphicImageRasterizer();
       
  1330 
       
  1331     ~CHuiCanvasCombinedGraphicImageRasterizer();
       
  1332 
       
  1333     void RasterizeL(CHuiCanvasGraphicImage& aImage);
       
  1334 
       
  1335 private:
       
  1336 
       
  1337     void InitL(CHuiCanvasGraphicImage& aImage);
       
  1338 
       
  1339     void DrawL(CHuiCanvasGraphicImage& aImage);
       
  1340 
       
  1341     void UploadL(CHuiCanvasGraphicImage& aImage);
       
  1342 
       
  1343     };
       
  1344 
       
  1345 CHuiCanvasCombinedGraphicImageRasterizer::CHuiCanvasCombinedGraphicImageRasterizer()
       
  1346     {    
       
  1347     }
       
  1348 
       
  1349 CHuiCanvasCombinedGraphicImageRasterizer::~CHuiCanvasCombinedGraphicImageRasterizer()
       
  1350     {
       
  1351     }
       
  1352 
       
  1353 void CHuiCanvasCombinedGraphicImageRasterizer::RasterizeL(CHuiCanvasGraphicImage& aImage)
       
  1354     {
       
  1355     // First check the bitmaps
       
  1356     TBool bitmapsChanged = EFalse;    
       
  1357     for (TInt i=0; i<aImage.iSubImages.Count(); i++)
       
  1358         {
       
  1359         // Lets see if we have already cached the pointer...
       
  1360         if (!aImage.iSubImages[i].iBitmap)
       
  1361             {
       
  1362             // ...no we must duplicate handle
       
  1363             if (aImage.iSubImages[i].iBitmapHandle)
       
  1364                 {
       
  1365                 aImage.iSubImages[i].iBitmap = new (ELeave) CFbsBitmap;                       
       
  1366                 aImage.iSubImages[i].iBitmap->Duplicate(aImage.iSubImages[i].iBitmapHandle);
       
  1367                 }
       
  1368             }
       
  1369                                
       
  1370         if (!aImage.iSubImages[i].iMask)
       
  1371             {
       
  1372             // Lets see if we have already cached the pointer...
       
  1373             if (aImage.iSubImages[i].iMaskHandle)
       
  1374                 {
       
  1375                 aImage.iSubImages[i].iMask = new (ELeave) CFbsBitmap;                       
       
  1376                 aImage.iSubImages[i].iMask->Duplicate(aImage.iSubImages[i].iMaskHandle);
       
  1377                 }
       
  1378             }
       
  1379                 
       
  1380         if (aImage.iSubImages[i].iBitmap)
       
  1381             {
       
  1382             bitmapsChanged |= (aImage.iSubImages[i].iBitmapTouchCount != aImage.iSubImages[i].iBitmap->TouchCount());                        
       
  1383             }
       
  1384             
       
  1385         if (aImage.iSubImages[i].iMask)
       
  1386             {
       
  1387             bitmapsChanged |= (aImage.iSubImages[i].iMaskTouchCount != aImage.iSubImages[i].iMask->TouchCount());        
       
  1388             }                
       
  1389         }
       
  1390          
       
  1391    if (bitmapsChanged)
       
  1392        {        
       
  1393        InitL(aImage);
       
  1394        
       
  1395        DrawL(aImage);
       
  1396        
       
  1397        UploadL(aImage);
       
  1398 
       
  1399        // Touch counts updated after upload in case upload changes the count ?
       
  1400        for (TInt i=0; i<aImage.iSubImages.Count(); i++)
       
  1401            {
       
  1402            if (aImage.iSubImages[i].iBitmap)
       
  1403                aImage.iSubImages[i].iBitmapTouchCount = aImage.iSubImages[i].iBitmap->TouchCount();
       
  1404 
       
  1405            if (aImage.iSubImages[i].iMask)
       
  1406                aImage.iSubImages[i].iMaskTouchCount = aImage.iSubImages[i].iMask->TouchCount();
       
  1407            }
       
  1408        }
       
  1409    
       
  1410    if (!KHuiCanvasKeepBitmapPointer)
       
  1411         {
       
  1412         for (TInt i=0; i<aImage.iSubImages.Count(); i++)
       
  1413             {
       
  1414             delete aImage.iSubImages[i].iBitmap;
       
  1415             aImage.iSubImages[i].iBitmap = NULL;
       
  1416             
       
  1417             delete aImage.iSubImages[i].iMask;
       
  1418             aImage.iSubImages[i].iMask = NULL;
       
  1419             }
       
  1420         }                                       
       
  1421     }
       
  1422 
       
  1423 
       
  1424 void CHuiCanvasCombinedGraphicImageRasterizer::InitL(CHuiCanvasGraphicImage& aImage)
       
  1425     {
       
  1426     if (IsSeparateTextMaskUsed())
       
  1427         {
       
  1428         iTempMask->Resize(aImage.iImageSize);
       
  1429         iTempMaskDevice->Resize(aImage.iImageSize);
       
  1430 
       
  1431         delete iTempMaskGc;
       
  1432         iTempMaskGc = NULL;                             
       
  1433         User::LeaveIfError(iTempMaskDevice->CreateContext(iTempMaskGc));     
       
  1434 
       
  1435         iTempMaskGc->Reset();
       
  1436     	iTempMaskGc->SetBrushColor(KRgbBlack);
       
  1437     	iTempMaskGc->Clear();    	
       
  1438    	    iTempMaskGc->SetPenColor(KRgbWhite);
       
  1439         }
       
  1440 
       
  1441     iTempBitmap->Resize(aImage.iImageSize);
       
  1442     iTempBitmapDevice->Resize(aImage.iImageSize);
       
  1443 
       
  1444     delete iTempBitmapGc;
       
  1445     iTempBitmapGc = NULL;        
       
  1446     User::LeaveIfError(iTempBitmapDevice->CreateContext(iTempBitmapGc));                 
       
  1447     
       
  1448     if (IsSeparateTextMaskUsed())
       
  1449         {
       
  1450         TRgb clearColor(KRgbWhite);
       
  1451         clearColor.SetAlpha(0);
       
  1452         iTempBitmapGc->SetPenColor(clearColor);
       
  1453         iTempBitmapGc->SetBrushColor(clearColor);
       
  1454         iTempBitmapGc->SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha);                    	    
       
  1455 	    iTempBitmapGc->Clear();                  
       
  1456         iTempBitmapGc->SetPenColor(KRgbWhite);                        
       
  1457 
       
  1458         iTempMaskGc->SetPenColor(clearColor);
       
  1459         iTempMaskGc->SetBrushColor(clearColor);
       
  1460         iTempMaskGc->SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha);                    	    
       
  1461 	    iTempMaskGc->Clear();                  
       
  1462         iTempMaskGc->SetPenColor(KRgbWhite);                        
       
  1463         }
       
  1464     else
       
  1465         {
       
  1466         // First clear
       
  1467         TRgb clearColor(KRgbWhite);
       
  1468         clearColor.SetAlpha(0);
       
  1469         iTempBitmapGc->SetPenColor(clearColor);
       
  1470         iTempBitmapGc->SetBrushColor(clearColor);
       
  1471         iTempBitmapGc->SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha);                    	    
       
  1472 	    iTempBitmapGc->Clear();                  
       
  1473         iTempBitmapGc->SetPenColor(KRgbWhite);                        
       
  1474         }    
       
  1475     }
       
  1476 
       
  1477 void CHuiCanvasCombinedGraphicImageRasterizer::DrawL(CHuiCanvasGraphicImage& aImage)
       
  1478     {
       
  1479     for (TInt i=0; i<aImage.iSubImages.Count(); i++)
       
  1480         {        
       
  1481         CFbsBitmap* bitmap = aImage.iSubImages[i].iBitmap;
       
  1482         CFbsBitmap* mask = aImage.iSubImages[i].iMask;
       
  1483         TPoint point = aImage.iSubImages[i].iCombinedBitmapPoint; 
       
  1484 
       
  1485         if (bitmap)
       
  1486             {
       
  1487             if (IsSeparateTextMaskUsed())
       
  1488                 {
       
  1489                 TRect sourceRect = TRect(TPoint(0,0), bitmap->SizeInPixels());                
       
  1490                 if (bitmap)
       
  1491                     {
       
  1492                     iTempBitmapGc->BitBlt(point, bitmap);                                           
       
  1493                     }                                                                        
       
  1494                 if (mask)
       
  1495                     {
       
  1496                     iTempMaskGc->BitBlt(point, mask);                       
       
  1497                     }
       
  1498                 }
       
  1499             else
       
  1500                 {
       
  1501                 TRect sourceRect = TRect(TPoint(0,0), bitmap->SizeInPixels());
       
  1502                 if (mask)
       
  1503                     {
       
  1504                     TBool invertMask = (mask->DisplayMode() == EGray256);                       
       
  1505                     iTempBitmapGc->BitBltMasked(point, bitmap, sourceRect, mask, invertMask);                       
       
  1506                     }
       
  1507                 else
       
  1508                     {
       
  1509                     iTempBitmapGc->BitBlt(point, bitmap);                                           
       
  1510                     }                                                    
       
  1511                 }    
       
  1512             }
       
  1513         }        
       
  1514     }
       
  1515 
       
  1516 void CHuiCanvasCombinedGraphicImageRasterizer::UploadL(CHuiCanvasGraphicImage& aImage)
       
  1517     {
       
  1518     CFbsBitmap* mask = IsSeparateTextMaskUsed() ? iTempMask : NULL; 
       
  1519         
       
  1520     // Upload bitmap content...this may be slow depending on used HW acceleration !
       
  1521     if (iTempBitmap->SizeInPixels().iWidth > 0 && 
       
  1522         iTempBitmap->SizeInPixels().iHeight > 0 &&
       
  1523         (!mask || (mask->SizeInPixels().iWidth > 0 && mask->SizeInPixels().iHeight)))
       
  1524         {
       
  1525         // EHuiTextureUploadFlagDoNotRetainResolution should be removed when 
       
  1526         // texturecoordinates with segmented textures work.
       
  1527         // This flag causes ugly scaling to happen with small textures.
       
  1528         THuiTextureUploadFlags uploadFlags = THuiTextureUploadFlags(EHuiTextureUploadFlagDoNotRetainResolution | EHuiTextureUploadFlagRetainColorDepth);
       
  1529 
       
  1530 #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
       
  1531         TTime startTime;
       
  1532         startTime.UniversalTime();
       
  1533 #endif
       
  1534 
       
  1535         CHuiTexture* texture = aImage.iTexture;                
       
  1536         texture->UploadL(*iTempBitmap, mask, uploadFlags);
       
  1537 
       
  1538 #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
       
  1539         TTime endTime;
       
  1540         endTime.UniversalTime();
       
  1541         TInt uploadTimeInMilliSeconds = endTime.MicroSecondsFrom( startTime ).Int64()/1000;
       
  1542         
       
  1543         RDebug::Print(_L(">>> CHuiCanvasCombinedGraphicImageRasterizer::UploadCombinedImageL: Upload of %ix%i %i+%i took %i ms"), 
       
  1544             texture->Size().iWidth, 
       
  1545             texture->Size().iHeight,
       
  1546             aImage.iBitmapHandle,
       
  1547             aImage.iMaskHandle,
       
  1548             uploadTimeInMilliSeconds);
       
  1549 #endif
       
  1550         }                    
       
  1551     }
       
  1552 // ---------------------------------------------------------------------------
       
  1553 // 
       
  1554 // ---------------------------------------------------------------------------
       
  1555 //
       
  1556 TInt ImageTimeOrderFunc(const CHuiCanvasGraphicImage& aFirst, const CHuiCanvasGraphicImage& aSecond)
       
  1557     {
       
  1558     if (aFirst.iLastUsed < aSecond.iLastUsed)
       
  1559         {
       
  1560         return -1; // less than
       
  1561         }
       
  1562     else if (aFirst.iLastUsed > aSecond.iLastUsed)
       
  1563         {
       
  1564         return 1; // more than	
       
  1565         }
       
  1566     else
       
  1567         {
       
  1568         return 0;
       
  1569         }
       
  1570     }
       
  1571 
       
  1572 // ---------------------------------------------------------------------------
       
  1573 // 
       
  1574 // ---------------------------------------------------------------------------
       
  1575 //
       
  1576 TInt TextTimeOrderFunc(const CHuiCanvasTextImage& aFirst, const CHuiCanvasTextImage& aSecond)
       
  1577     {
       
  1578     if (aFirst.iLastUsed < aSecond.iLastUsed)
       
  1579         {
       
  1580         return -1; // less than
       
  1581         }
       
  1582     else if (aFirst.iLastUsed > aSecond.iLastUsed)
       
  1583         {
       
  1584         return 1; // more than	
       
  1585         }
       
  1586     else
       
  1587         {
       
  1588         return 0;
       
  1589         }
       
  1590     }
       
  1591 
       
  1592 // ---------------------------------------------------------------------------
       
  1593 // 
       
  1594 // ---------------------------------------------------------------------------
       
  1595 //
       
  1596 TInt RenderBufferTimeOrderFunc(const CHuiCanvasRenderBufferImage& aFirst, const CHuiCanvasRenderBufferImage& aSecond)
       
  1597     {
       
  1598     if (aFirst.iLastUsed < aSecond.iLastUsed)
       
  1599         {
       
  1600         return -1; // less than
       
  1601         }
       
  1602     else if (aFirst.iLastUsed > aSecond.iLastUsed)
       
  1603         {
       
  1604         return 1; // more than  
       
  1605         }
       
  1606     else
       
  1607         {
       
  1608         return 0;
       
  1609         }
       
  1610     }
       
  1611 
       
  1612 // ---------------------------------------------------------------------------
       
  1613 // 
       
  1614 // ---------------------------------------------------------------------------
       
  1615 //
       
  1616 TInt GcImageOrderFunc(const THuiCachedGcParams& /*aFirst*/, const THuiCachedGcParams& /*aSecond*/)
       
  1617     {
       
  1618     return 0; // equal enough, note that we don't check every field
       
  1619     }
       
  1620 
       
  1621 
       
  1622 // ---------------------------------------------------------------------------
       
  1623 // 
       
  1624 // ---------------------------------------------------------------------------
       
  1625 //
       
  1626 TInt GcTextOrderFunc(const THuiCachedGcParams& aFirst, const THuiCachedGcParams& aSecond)
       
  1627     {    
       
  1628     if (!KHuiCanvasTextUseColorModulation)
       
  1629         {            
       
  1630         if (aFirst.iPenColor.Value() < aSecond.iPenColor.Value())
       
  1631             {
       
  1632             return -1; // less than
       
  1633             }
       
  1634         else if (aFirst.iPenColor.Value() > aSecond.iPenColor.Value())
       
  1635             {
       
  1636             return 1; // more than	
       
  1637             }
       
  1638         else
       
  1639             {
       
  1640             // For PC-lint
       
  1641             }
       
  1642         }
       
  1643 
       
  1644     if (aFirst.iPenStyle < aSecond.iPenStyle)
       
  1645         {
       
  1646         return -1; // less than
       
  1647         }
       
  1648     else if (aFirst.iPenStyle > aSecond.iPenStyle)
       
  1649         {
       
  1650         return 1; // more than	
       
  1651         }
       
  1652     else
       
  1653         {
       
  1654         // For PC-lint
       
  1655         }
       
  1656 
       
  1657     if (aFirst.iDrawMode < aSecond.iDrawMode)
       
  1658         {
       
  1659         return -1; // less than
       
  1660         }
       
  1661     else if (aFirst.iDrawMode > aSecond.iDrawMode)
       
  1662         {
       
  1663         return 1; // more than	
       
  1664         }
       
  1665     else
       
  1666         {
       
  1667         // For PC-lint
       
  1668         }
       
  1669 
       
  1670     if (aFirst.iStrikethrough < aSecond.iStrikethrough)
       
  1671         {
       
  1672         return -1; // less than
       
  1673         }
       
  1674     else if (aFirst.iStrikethrough > aSecond.iStrikethrough)
       
  1675         {
       
  1676         return 1; // more than	
       
  1677         }
       
  1678     else
       
  1679         {
       
  1680         // For PC-lint
       
  1681         }
       
  1682 
       
  1683     if (aFirst.iUnderline < aSecond.iUnderline)
       
  1684         {
       
  1685         return -1; // less than
       
  1686         }
       
  1687     else if (aFirst.iUnderline > aSecond.iUnderline)
       
  1688         {
       
  1689         return 1; // more than	
       
  1690         }
       
  1691     else
       
  1692         {
       
  1693         // For PC-lint
       
  1694         }
       
  1695 
       
  1696     return 0; // equal enough, note that we don't check every field
       
  1697     }
       
  1698 
       
  1699 // ---------------------------------------------------------------------------
       
  1700 // 
       
  1701 // ---------------------------------------------------------------------------
       
  1702 //
       
  1703 TInt ImageOrderFunc(const CHuiCanvasGraphicImage& aFirst, const CHuiCanvasGraphicImage& aSecond)
       
  1704     {
       
  1705     // Bitmap handle
       
  1706     if (aFirst.iBitmapHandle < aSecond.iBitmapHandle)
       
  1707         {
       
  1708         return -1; // less than
       
  1709         }
       
  1710     else if (aFirst.iBitmapHandle > aSecond.iBitmapHandle)
       
  1711         {
       
  1712         return 1; // more than	
       
  1713         }
       
  1714     else
       
  1715         {
       
  1716         // For PC-lint
       
  1717         }
       
  1718 
       
  1719     // Mask handle
       
  1720     if (aFirst.iMaskHandle < aSecond.iMaskHandle)
       
  1721         {
       
  1722         return -1; // less than
       
  1723         }
       
  1724     else if (aFirst.iMaskHandle > aSecond.iMaskHandle)
       
  1725         {
       
  1726         return 1; // more than	
       
  1727         }
       
  1728     else
       
  1729         {
       
  1730         // For PC-lint
       
  1731         }
       
  1732 
       
  1733     // Inverted mask
       
  1734     if (aFirst.iInvertedMask < aSecond.iInvertedMask)
       
  1735         {
       
  1736         return -1; // less than
       
  1737         }
       
  1738     else if (aFirst.iInvertedMask > aSecond.iInvertedMask)
       
  1739         {
       
  1740         return 1; // more than	
       
  1741         }
       
  1742     else
       
  1743         {
       
  1744         // For PC-lint
       
  1745         }
       
  1746 
       
  1747     // Mask origin point X
       
  1748     if (aFirst.iMaskOriginPoint.iX < aSecond.iMaskOriginPoint.iX)
       
  1749         {
       
  1750         return -1; // less than
       
  1751         }
       
  1752     else if (aFirst.iMaskOriginPoint.iX > aSecond.iMaskOriginPoint.iX)
       
  1753         {
       
  1754         return 1; // more than	
       
  1755         }
       
  1756     else
       
  1757         {
       
  1758         // For PC-lint
       
  1759         }
       
  1760         
       
  1761     // Mask origin point Y
       
  1762     if (aFirst.iMaskOriginPoint.iY < aSecond.iMaskOriginPoint.iY)
       
  1763         {
       
  1764         return -1; // less than
       
  1765         }
       
  1766     else if (aFirst.iMaskOriginPoint.iY > aSecond.iMaskOriginPoint.iY)
       
  1767         {
       
  1768         return 1; // more than	
       
  1769         }
       
  1770     else
       
  1771         {
       
  1772         // For PC-lint
       
  1773         }
       
  1774 
       
  1775     if (aFirst.iImageSize.iHeight < aSecond.iImageSize.iHeight)
       
  1776         {
       
  1777         return -1; // less than
       
  1778         }
       
  1779     else if (aFirst.iImageSize.iHeight > aSecond.iImageSize.iHeight)
       
  1780         {
       
  1781         return 1; // more than	
       
  1782         }
       
  1783     else
       
  1784         {
       
  1785         // For PC-lint
       
  1786         }
       
  1787 
       
  1788     if (aFirst.iImageSize.iWidth < aSecond.iImageSize.iWidth)
       
  1789         {
       
  1790         return -1; // less than
       
  1791         }
       
  1792     else if (aFirst.iImageSize.iWidth > aSecond.iImageSize.iWidth)
       
  1793         {
       
  1794         return 1; // more than	
       
  1795         }
       
  1796     else
       
  1797         {
       
  1798         // For PC-lint
       
  1799         }
       
  1800     
       
  1801     if (aFirst.iSubImages.Count() < aSecond.iSubImages.Count())
       
  1802         {
       
  1803         return -1;    
       
  1804         }
       
  1805     else if (aFirst.iSubImages.Count() > aSecond.iSubImages.Count())
       
  1806         {
       
  1807         return 1;                
       
  1808         }
       
  1809     else
       
  1810         {
       
  1811         // Same amount, must check array content
       
  1812         if (aFirst.iSubImages.Count() && aSecond.iSubImages.Count())
       
  1813             {
       
  1814             for (TInt i=0; i<aFirst.iSubImages.Count();i++)
       
  1815                 {
       
  1816                 if (aFirst.iSubImages[i].iBitmapHandle < aSecond.iSubImages[i].iBitmapHandle)
       
  1817                     {
       
  1818                     return -1;    
       
  1819                     }
       
  1820                 else if (aFirst.iSubImages[i].iBitmapHandle > aSecond.iSubImages[i].iBitmapHandle)
       
  1821                     {
       
  1822                     return 1;                            
       
  1823                     }
       
  1824                 else
       
  1825                     {
       
  1826                     // For PC-lint                                        
       
  1827                     }                        
       
  1828 
       
  1829                 if (aFirst.iSubImages[i].iMaskHandle < aSecond.iSubImages[i].iMaskHandle)
       
  1830                     {
       
  1831                     return -1;    
       
  1832                     }
       
  1833                 else if (aFirst.iSubImages[i].iMaskHandle > aSecond.iSubImages[i].iMaskHandle)
       
  1834                     {
       
  1835                     return 1;                            
       
  1836                     }
       
  1837                 else
       
  1838                     {
       
  1839                     // For PC-lint                                        
       
  1840                     }    
       
  1841                                         
       
  1842                 if (aFirst.iSubImages[i].iCombinedBitmapPoint.iX < aSecond.iSubImages[i].iCombinedBitmapPoint.iX)
       
  1843                     {
       
  1844                     return -1;    
       
  1845                     }
       
  1846                 else if (aFirst.iSubImages[i].iCombinedBitmapPoint.iX > aSecond.iSubImages[i].iCombinedBitmapPoint.iX)
       
  1847                     {
       
  1848                     return 1;                            
       
  1849                     }
       
  1850                 else
       
  1851                     {
       
  1852                     // For PC-lint                                        
       
  1853                     }                        
       
  1854 
       
  1855                 if (aFirst.iSubImages[i].iCombinedBitmapPoint.iY < aSecond.iSubImages[i].iCombinedBitmapPoint.iY)
       
  1856                     {
       
  1857                     return -1;    
       
  1858                     }
       
  1859                 else if (aFirst.iSubImages[i].iCombinedBitmapPoint.iY > aSecond.iSubImages[i].iCombinedBitmapPoint.iY)
       
  1860                     {
       
  1861                     return 1;                            
       
  1862                     }
       
  1863                 else
       
  1864                     {
       
  1865                     // For PC-lint                                        
       
  1866                     }                        
       
  1867 
       
  1868 
       
  1869                 }                
       
  1870             }
       
  1871         else
       
  1872             {
       
  1873             // For PC-lint                
       
  1874             }            
       
  1875         }                
       
  1876     return GcImageOrderFunc(aFirst.iGcParams, aSecond.iGcParams); 
       
  1877     }
       
  1878 
       
  1879 // ---------------------------------------------------------------------------
       
  1880 // 
       
  1881 // ---------------------------------------------------------------------------
       
  1882 //
       
  1883 TInt TextOrderFunc(const CHuiCanvasTextImage& aFirst, const CHuiCanvasTextImage& aSecond)
       
  1884     {
       
  1885     // Font handle
       
  1886     if (aFirst.iFontHandle < aSecond.iFontHandle)
       
  1887         {
       
  1888         return -1; // less than
       
  1889         }
       
  1890     else if (aFirst.iFontHandle > aSecond.iFontHandle)
       
  1891         {
       
  1892         return 1; // more than	
       
  1893         }
       
  1894     else
       
  1895         {
       
  1896         // For PC-lint
       
  1897         }
       
  1898         
       
  1899     // Text width
       
  1900     if (aFirst.iTextWidth < aSecond.iTextWidth)
       
  1901         {
       
  1902         return -1; // less than
       
  1903         }
       
  1904     else if (aFirst.iTextWidth > aSecond.iTextWidth)
       
  1905         {
       
  1906         return 1; // more than	
       
  1907         }
       
  1908     else
       
  1909         {
       
  1910         // For PC-lint
       
  1911         }
       
  1912 
       
  1913     // iTextBoxMaxSize.iWidth
       
  1914     if (aFirst.iTextBoxMaxSize.iWidth < aSecond.iTextBoxMaxSize.iWidth)
       
  1915         {
       
  1916         return -1; // less than
       
  1917         }
       
  1918     else if (aFirst.iTextBoxMaxSize.iWidth > aSecond.iTextBoxMaxSize.iWidth)
       
  1919         {
       
  1920         return 1; // more than	
       
  1921         }
       
  1922     else
       
  1923         {
       
  1924         // For PC-lint
       
  1925         }
       
  1926 
       
  1927     // Text content
       
  1928     TInt textcompare = KErrNotFound;
       
  1929     if ( aFirst.iFindTextPtr )
       
  1930         {
       
  1931         textcompare = aFirst.iFindTextPtr->Compare(*aSecond.iText);     
       
  1932         }
       
  1933     else
       
  1934         {
       
  1935         textcompare = aFirst.iText->Compare(*aSecond.iText);
       
  1936         }
       
  1937     
       
  1938     if (textcompare < 0)
       
  1939         {
       
  1940         return -1;    
       
  1941         }
       
  1942     else if (textcompare > 0)
       
  1943         {
       
  1944         return 1;    
       
  1945         }
       
  1946     else
       
  1947         {
       
  1948         // For PC-lint
       
  1949         }            
       
  1950     
       
  1951     // iBaseLineOffset
       
  1952     if (aFirst.iBaseLineOffset < aSecond.iBaseLineOffset)
       
  1953         {
       
  1954         return -1; // less than
       
  1955         }
       
  1956     else if (aFirst.iBaseLineOffset > aSecond.iBaseLineOffset)
       
  1957         {
       
  1958         return 1; // more than	
       
  1959         }
       
  1960     else
       
  1961         {
       
  1962         // For PC-lint
       
  1963         }
       
  1964 
       
  1965     // iTextAlign
       
  1966     if (aFirst.iTextAlign < aSecond.iTextAlign)
       
  1967         {
       
  1968         return -1; // less than
       
  1969         }
       
  1970     else if (aFirst.iTextAlign > aSecond.iTextAlign)
       
  1971         {
       
  1972         return 1; // more than	
       
  1973         }
       
  1974     else
       
  1975         {
       
  1976         // For PC-lint
       
  1977         }
       
  1978 
       
  1979     // iMargin
       
  1980     if (aFirst.iMargin < aSecond.iMargin)
       
  1981         {
       
  1982         return -1; // less than
       
  1983         }
       
  1984     else if (aFirst.iMargin > aSecond.iMargin)
       
  1985         {
       
  1986         return 1; // more than	
       
  1987         }
       
  1988     else
       
  1989         {
       
  1990         // For PC-lint
       
  1991         }
       
  1992 
       
  1993     // iAngle
       
  1994     if (aFirst.iAngle < aSecond.iAngle)
       
  1995         {
       
  1996         return -1; // less than
       
  1997         }
       
  1998     else if (aFirst.iAngle > aSecond.iAngle)
       
  1999         {
       
  2000         return 1; // more than	
       
  2001         }
       
  2002     else
       
  2003         {
       
  2004         // For PC-lint
       
  2005         }
       
  2006        
       
  2007     // Font handle
       
  2008     if (aFirst.iTextParams.iStart < aSecond.iTextParams.iStart)
       
  2009         {
       
  2010         return -1; // less than
       
  2011         }
       
  2012     else if (aFirst.iTextParams.iStart > aSecond.iTextParams.iStart)
       
  2013         {
       
  2014         return 1; // more than	
       
  2015         }
       
  2016     else
       
  2017         {
       
  2018         // For PC-lint
       
  2019         }
       
  2020 
       
  2021     // Font handle
       
  2022     if (aFirst.iTextParams.iEnd < aSecond.iTextParams.iEnd)
       
  2023         {
       
  2024         return -1; // less than
       
  2025         }
       
  2026     else if (aFirst.iTextParams.iEnd > aSecond.iTextParams.iEnd)
       
  2027         {
       
  2028         return 1; // more than	
       
  2029         }
       
  2030     else
       
  2031         {
       
  2032         // For PC-lint
       
  2033         }
       
  2034 
       
  2035     // Font handle
       
  2036     if (aFirst.iTextParams.iFlags < aSecond.iTextParams.iFlags)
       
  2037         {
       
  2038         return -1; // less than
       
  2039         }
       
  2040     else if (aFirst.iTextParams.iFlags > aSecond.iTextParams.iFlags)
       
  2041         {
       
  2042         return 1; // more than	
       
  2043         }
       
  2044     else
       
  2045         {
       
  2046         // For PC-lint
       
  2047         }
       
  2048                     
       
  2049     return GcTextOrderFunc(aFirst.iGcParams, aSecond.iGcParams); 
       
  2050     }
       
  2051 
       
  2052 
       
  2053 // ---------------------------------------------------------------------------
       
  2054 // 
       
  2055 // ---------------------------------------------------------------------------
       
  2056 //
       
  2057 TInt RenderBufferOrderFunc(const CHuiCanvasRenderBufferImage& aFirst, const CHuiCanvasRenderBufferImage& aSecond)
       
  2058     {
       
  2059     if (aFirst.iOwner < aSecond.iOwner)
       
  2060         {
       
  2061         return -1; // less than
       
  2062         }
       
  2063     else if (aFirst.iOwner > aSecond.iOwner)
       
  2064         {
       
  2065         return 1; // more than  
       
  2066         }
       
  2067     else
       
  2068         {
       
  2069         // For PC-lint
       
  2070         }
       
  2071 
       
  2072     return 0; // Equal
       
  2073     }
       
  2074 
       
  2075 
       
  2076 // ---------------------------------------------------------------------------
       
  2077 // Constructor
       
  2078 // ---------------------------------------------------------------------------
       
  2079 //
       
  2080 CHuiCanvasTextureCache::CHuiCanvasTextureCache()
       
  2081     {
       
  2082     EnableLowMemoryState(EFalse);
       
  2083     CHuiStatic::Env().AddLowMemoryObserver(this);
       
  2084     }
       
  2085 
       
  2086 // ---------------------------------------------------------------------------
       
  2087 // Destructor
       
  2088 // ---------------------------------------------------------------------------
       
  2089 //
       
  2090 CHuiCanvasTextureCache::~CHuiCanvasTextureCache()
       
  2091     {
       
  2092     CHuiStatic::Env().RemoveLowMemoryObserver(this);
       
  2093     iCachedTexts.ResetAndDestroy();
       
  2094     iCachedImages.ResetAndDestroy();        
       
  2095     iRecycledTextures.ResetAndDestroy();
       
  2096     
       
  2097     if (iSearchedTextImageEntry)
       
  2098         {
       
  2099         iSearchedTextImageEntry->Reset();
       
  2100         delete iSearchedTextImageEntry;
       
  2101         }
       
  2102     
       
  2103     if (iSearchedGraphicImageEntry)
       
  2104         {
       
  2105         iSearchedGraphicImageEntry->Reset();
       
  2106         delete iSearchedGraphicImageEntry;
       
  2107         }
       
  2108     
       
  2109     if (iSearchedRenderBufferImageEntry)
       
  2110         {
       
  2111         iSearchedRenderBufferImageEntry->Reset();
       
  2112         delete iSearchedRenderBufferImageEntry;        
       
  2113         }
       
  2114 
       
  2115     delete iTextImageRasterizer;
       
  2116     delete iOutLineTextImageRasterizer;
       
  2117     delete iGraphicImageRasterizer;
       
  2118     delete iCombinedGraphicImageRasterizer;
       
  2119     delete iCanvasGc;
       
  2120     }
       
  2121     
       
  2122 // ---------------------------------------------------------------------------
       
  2123 // 
       
  2124 // ---------------------------------------------------------------------------
       
  2125 //
       
  2126 CHuiCanvasTextureCache* CHuiCanvasTextureCache::NewL()
       
  2127     {
       
  2128     CHuiCanvasTextureCache* self = CHuiCanvasTextureCache::NewLC();
       
  2129     CleanupStack::Pop(self);
       
  2130     return self;        
       
  2131     }
       
  2132 
       
  2133 // ---------------------------------------------------------------------------
       
  2134 // 
       
  2135 // ---------------------------------------------------------------------------
       
  2136 //
       
  2137 CHuiCanvasTextureCache* CHuiCanvasTextureCache::NewLC()
       
  2138     {
       
  2139     CHuiCanvasTextureCache* self = new (ELeave) CHuiCanvasTextureCache();
       
  2140     CleanupStack::PushL(self);
       
  2141     self->ConstructL();
       
  2142     return self;
       
  2143     }
       
  2144 
       
  2145 
       
  2146 // ---------------------------------------------------------------------------
       
  2147 // 
       
  2148 // ---------------------------------------------------------------------------
       
  2149 //
       
  2150 void CHuiCanvasTextureCache::ConstructL()
       
  2151     {
       
  2152     iMemoryLevel = EHuiMemoryLevelNormal;
       
  2153     
       
  2154     iCanvasGc = CHuiStatic::Renderer().CreateCanvasGcL();
       
  2155     
       
  2156     iTextImageRasterizer = new (ELeave) CHuiCanvasTextImageRasterizer;
       
  2157     iTextImageRasterizer->ConstructL(EGray256);
       
  2158     
       
  2159     iOutLineTextImageRasterizer = new (ELeave) CHuiCanvasTextImageRasterizer;
       
  2160     iOutLineTextImageRasterizer->ConstructL(EColor16MA);
       
  2161     
       
  2162     iGraphicImageRasterizer = new (ELeave) CHuiCanvasGraphicImageRasterizer;
       
  2163     iGraphicImageRasterizer->ConstructL();
       
  2164 
       
  2165     iCombinedGraphicImageRasterizer = new (ELeave) CHuiCanvasCombinedGraphicImageRasterizer;    
       
  2166     iCombinedGraphicImageRasterizer->ConstructL(EColor64K);
       
  2167     
       
  2168     iSearchedTextImageEntry = new (ELeave) CHuiCanvasTextImage;
       
  2169     iSearchedGraphicImageEntry = new (ELeave) CHuiCanvasGraphicImage;
       
  2170     iSearchedRenderBufferImageEntry = new (ELeave) CHuiCanvasRenderBufferImage;
       
  2171     }
       
  2172     
       
  2173 
       
  2174 // ---------------------------------------------------------------------------
       
  2175 // 
       
  2176 // 
       
  2177 // ---------------------------------------------------------------------------
       
  2178 //
       
  2179 const CHuiCanvasGraphicImage* CHuiCanvasTextureCache::FindCachedImageL(
       
  2180     const THuiCachedImageParams& aCachedImageParams, 
       
  2181     const CHuiCanvasVisual& aUser)
       
  2182     {    
       
  2183     TInt cachedEntry = KErrNotFound;
       
  2184 
       
  2185     iSearchedGraphicImageEntry->Reset();        
       
  2186     iSearchedGraphicImageEntry->iBitmapHandle = aCachedImageParams.iBitmapHandle;
       
  2187     iSearchedGraphicImageEntry->iMaskHandle = aCachedImageParams.iMaskHandle;
       
  2188     iSearchedGraphicImageEntry->iTexture = NULL;
       
  2189     iSearchedGraphicImageEntry->iInvertedMask = aCachedImageParams.iInvertedMask;
       
  2190     iSearchedGraphicImageEntry->iMaskOriginPoint = aCachedImageParams.iMaskOriginPoint;
       
  2191     iSearchedGraphicImageEntry->iBitmapTouchCount = KHuiInitialBitmapTouchCount;
       
  2192     iSearchedGraphicImageEntry->iMaskTouchCount = KHuiInitialBitmapTouchCount;
       
  2193     iSearchedGraphicImageEntry->iGcParams = aCachedImageParams.iGcParams;
       
  2194     
       
  2195     cachedEntry = iCachedImages.FindInOrder(iSearchedGraphicImageEntry, ImageOrderFunc);
       
  2196     if (cachedEntry == KErrNotFound)
       
  2197         {
       
  2198         User::Leave(KErrNotFound);
       
  2199         }
       
  2200     
       
  2201     iCachedImages[cachedEntry]->RefreshUser(aUser);
       
  2202     return iCachedImages[cachedEntry];    
       
  2203     }
       
  2204 
       
  2205 // ---------------------------------------------------------------------------
       
  2206 // 
       
  2207 // 
       
  2208 // ---------------------------------------------------------------------------
       
  2209 //
       
  2210 const CHuiCanvasGraphicImage* CHuiCanvasTextureCache::CreateCombinedCachedImageL(
       
  2211     const RArray<THuiCachedCombinedImageParams>& aCachedImageParams,
       
  2212     const THuiCachedGcParams& aGcParams,
       
  2213     const TSize& aImageSize, 
       
  2214     const CHuiCanvasVisual& aUser)
       
  2215     {
       
  2216     TBool needUpdate = EFalse;
       
  2217     TInt cachedEntry = KErrNotFound;
       
  2218         
       
  2219     iSearchedGraphicImageEntry->Reset();
       
  2220     iSearchedGraphicImageEntry->iGcParams = aGcParams;
       
  2221     iSearchedGraphicImageEntry->iImageSize = aImageSize;
       
  2222     
       
  2223     
       
  2224     for (TInt i=0; i<aCachedImageParams.Count();i++)
       
  2225         {
       
  2226         THuiCachedBitmap cachedBitmap;
       
  2227         cachedBitmap.iBitmapHandle = aCachedImageParams[i].iBitmapHandle;
       
  2228         cachedBitmap.iMaskHandle = aCachedImageParams[i].iMaskHandle;
       
  2229         cachedBitmap.iCombinedBitmapPoint = aCachedImageParams[i].iCombinedBitmapPoint;        
       
  2230         iSearchedGraphicImageEntry->iSubImages.Append(cachedBitmap);            
       
  2231         }
       
  2232             
       
  2233     cachedEntry = iCachedImages.FindInOrder(iSearchedGraphicImageEntry, ImageOrderFunc);
       
  2234     if (cachedEntry == KErrNotFound)
       
  2235         {
       
  2236         // Create new entry object
       
  2237         CHuiCanvasGraphicImage* newEntry = new (ELeave) CHuiCanvasGraphicImage; 
       
  2238         CleanupStack::PushL(newEntry);                    
       
  2239         newEntry->CopyAttributes(*iSearchedGraphicImageEntry);
       
  2240         
       
  2241         // Create new accelerated image
       
  2242         CHuiTexture* newtexture = CreateRecycledTextureL();
       
  2243         newEntry->iTexture = newtexture;        
       
  2244         
       
  2245         User::LeaveIfError(iCachedImages.InsertInOrder(newEntry, ImageOrderFunc));
       
  2246         cachedEntry = iCachedImages.FindInOrder(newEntry, ImageOrderFunc);
       
  2247 
       
  2248         CleanupStack::Pop(newEntry);
       
  2249         needUpdate = ETrue;            
       
  2250         }
       
  2251     else
       
  2252         {
       
  2253         // Check if needs to be updated by checking active users list
       
  2254         if (!iCachedImages[cachedEntry]->IsUser(aUser))
       
  2255             {
       
  2256             needUpdate = ETrue;            
       
  2257             }
       
  2258         }    
       
  2259 
       
  2260     if (needUpdate)
       
  2261         {
       
  2262         TRAPD(updateError, iCombinedGraphicImageRasterizer->RasterizeL(*iCachedImages[cachedEntry]));
       
  2263         if (updateError == KErrNoMemory)
       
  2264             {                
       
  2265             // Call grim reaper to initiate system level texture memory actions !
       
  2266             HandleOutOfTextureMemory();
       
  2267             User::LeaveIfError(updateError);
       
  2268             }
       
  2269         }
       
  2270 
       
  2271     iCachedImages[cachedEntry]->RefreshUser(aUser);        
       
  2272     return iCachedImages[cachedEntry];    
       
  2273     }
       
  2274 
       
  2275     
       
  2276 // ---------------------------------------------------------------------------
       
  2277 // Improvement idea for HW accelerated, upload all images of the buffer 
       
  2278 // into single texture and use texture coordinates to draw each image. 
       
  2279 // ---------------------------------------------------------------------------
       
  2280 //
       
  2281 const CHuiCanvasGraphicImage* CHuiCanvasTextureCache::CreateCachedImageL(
       
  2282     const THuiCachedImageParams& aCachedImageParams, 
       
  2283     const CHuiCanvasVisual& aUser)
       
  2284     {    
       
  2285     TBool needUpdate = EFalse;
       
  2286     TInt cachedEntry = KErrNotFound;
       
  2287     
       
  2288     iSearchedGraphicImageEntry->Reset();    
       
  2289     iSearchedGraphicImageEntry->iBitmapHandle = aCachedImageParams.iBitmapHandle;
       
  2290     iSearchedGraphicImageEntry->iMaskHandle = aCachedImageParams.iMaskHandle;
       
  2291     iSearchedGraphicImageEntry->iTexture = NULL;
       
  2292     iSearchedGraphicImageEntry->iInvertedMask = aCachedImageParams.iInvertedMask;
       
  2293     iSearchedGraphicImageEntry->iMaskOriginPoint = aCachedImageParams.iMaskOriginPoint;
       
  2294     iSearchedGraphicImageEntry->iBitmapTouchCount = KHuiInitialBitmapTouchCount;
       
  2295     iSearchedGraphicImageEntry->iMaskTouchCount = KHuiInitialBitmapTouchCount;
       
  2296     iSearchedGraphicImageEntry->iGcParams = aCachedImageParams.iGcParams;
       
  2297     
       
  2298     cachedEntry = iCachedImages.FindInOrder(iSearchedGraphicImageEntry, ImageOrderFunc);
       
  2299     if (cachedEntry == KErrNotFound)
       
  2300         {
       
  2301         // Create new entry object
       
  2302         CHuiCanvasGraphicImage* newEntry = new (ELeave) CHuiCanvasGraphicImage; 
       
  2303         CleanupStack::PushL(newEntry);                    
       
  2304         
       
  2305         newEntry->CopyAttributes(*iSearchedGraphicImageEntry);
       
  2306         
       
  2307         // Create new accelerated image
       
  2308         CHuiTexture* newtexture = CreateRecycledTextureL();
       
  2309         newEntry->iTexture = newtexture;        
       
  2310 
       
  2311         User::LeaveIfError(iCachedImages.InsertInOrder(newEntry, ImageOrderFunc));
       
  2312         cachedEntry = iCachedImages.FindInOrder(newEntry, ImageOrderFunc);
       
  2313         CleanupStack::Pop(newEntry);
       
  2314         needUpdate = ETrue;            
       
  2315         }
       
  2316     else
       
  2317         {
       
  2318         // Check if needs to be updated by checking active users list
       
  2319         if (!iCachedImages[cachedEntry]->IsUser(aUser))
       
  2320             {
       
  2321             needUpdate = ETrue;            
       
  2322             }
       
  2323         }    
       
  2324 
       
  2325     if (needUpdate)
       
  2326         {
       
  2327         TRAPD(updateError, iGraphicImageRasterizer->RasterizeL(*iCachedImages[cachedEntry]));
       
  2328         if (updateError == KErrNoMemory)
       
  2329             {                                
       
  2330             // Call grim reaper to initiate system level texture memory actions !
       
  2331             HandleOutOfTextureMemory();
       
  2332             User::LeaveIfError(updateError);
       
  2333             }
       
  2334         }
       
  2335 
       
  2336     iCachedImages[cachedEntry]->RefreshUser(aUser);        
       
  2337     return iCachedImages[cachedEntry];    
       
  2338     }
       
  2339     
       
  2340     
       
  2341 
       
  2342     
       
  2343 // ---------------------------------------------------------------------------
       
  2344 // 
       
  2345 // ---------------------------------------------------------------------------
       
  2346 //
       
  2347 const CHuiCanvasTextImage* CHuiCanvasTextureCache::CreateCachedTextL( 
       
  2348     const THuiCachedTextParams& aCachedTextParams,
       
  2349     const CHuiCanvasVisual& aUser)
       
  2350     {
       
  2351     TBool needUpdate = EFalse;
       
  2352     TInt cachedEntry = KErrNotFound;
       
  2353     
       
  2354     iSearchedTextImageEntry->Reset();        
       
  2355     iSearchedTextImageEntry->iFindTextPtr= aCachedTextParams.iFindTextPtr; // Not owned, gets be updated if not found
       
  2356     iSearchedTextImageEntry->iTexture = NULL; // Gets updated if not found
       
  2357     iSearchedTextImageEntry->iFontHandle = aCachedTextParams.iFontHandle;
       
  2358     iSearchedTextImageEntry->iRasterizationOffset = TPoint(0,0); // Gets updated when text has been rasterized        
       
  2359     Mem::Copy( &iSearchedTextImageEntry->iTextParams, &aCachedTextParams.iTextParams, sizeof(THuiCanvasTextParameters));        
       
  2360     iSearchedTextImageEntry->iTextBoxMaxSize = aCachedTextParams.iTextBoxMaxSize;
       
  2361     iSearchedTextImageEntry->iTextWidth = aCachedTextParams.iTextWidth;
       
  2362     iSearchedTextImageEntry->iBaseLineOffset = aCachedTextParams.iBaseLineOffset;
       
  2363     iSearchedTextImageEntry->iTextAlign = aCachedTextParams.iTextAlign;
       
  2364     iSearchedTextImageEntry->iMargin = aCachedTextParams.iMargin;
       
  2365     iSearchedTextImageEntry->iAngle = aCachedTextParams.iAngle;
       
  2366     iSearchedTextImageEntry->iGcParams = aCachedTextParams.iGcParams;
       
  2367 
       
  2368     
       
  2369     cachedEntry = iCachedTexts.FindInOrder(iSearchedTextImageEntry, TextOrderFunc);
       
  2370     if (cachedEntry == KErrNotFound)
       
  2371         {
       
  2372         // Create new entry object
       
  2373         CHuiCanvasTextImage* newTextEntry = new (ELeave) CHuiCanvasTextImage; 
       
  2374         CleanupStack::PushL(newTextEntry);                    
       
  2375         
       
  2376         newTextEntry->CopyAttributes(*iSearchedTextImageEntry);
       
  2377         
       
  2378         // Create new accelerated image
       
  2379         CHuiTexture* newtexture = CreateRecycledTextureL();
       
  2380         newTextEntry->iTexture = newtexture;
       
  2381 
       
  2382         // Create text which entry will own        
       
  2383         HBufC* ownedText = aCachedTextParams.iFindTextPtr->AllocL();
       
  2384         newTextEntry->iText = ownedText;
       
  2385         newTextEntry->iFindTextPtr = NULL;
       
  2386         TInt insertSuccess = iCachedTexts.InsertInOrder(newTextEntry, TextOrderFunc);
       
  2387         __ASSERT_DEBUG( !insertSuccess, USER_INVARIANT() );
       
  2388         User::LeaveIfError( insertSuccess );
       
  2389         cachedEntry = iCachedTexts.FindInOrder(newTextEntry, TextOrderFunc);
       
  2390 
       
  2391         CleanupStack::Pop(newTextEntry); 
       
  2392         needUpdate = ETrue;            
       
  2393         }
       
  2394     else
       
  2395         {
       
  2396         // If it was found, great. No need to update it.
       
  2397         }        
       
  2398 
       
  2399 
       
  2400     if (needUpdate)
       
  2401         {
       
  2402         TBool outlinefont = EFalse;
       
  2403 
       
  2404         if (!(*iCachedTexts[cachedEntry]).iFont)
       
  2405             {
       
  2406             CFbsBitGcFont* font = new (ELeave) CFbsBitGcFont();
       
  2407             CleanupStack::PushL(font);
       
  2408             User::LeaveIfError(font->Duplicate((*iCachedTexts[cachedEntry]).iFontHandle));
       
  2409             (*iCachedTexts[cachedEntry]).iFont = font;
       
  2410             CleanupStack::Pop(); // font                    
       
  2411             }
       
  2412 
       
  2413         outlinefont = (*iCachedTexts[cachedEntry]).iFont->FontSpecInTwips().iFontStyle.IsEffectOn(FontEffect::EOutline);
       
  2414         TInt updateError(KErrNone);
       
  2415         if (!outlinefont)
       
  2416             {
       
  2417             TRAP(updateError, iTextImageRasterizer->RasterizeL(*iCachedTexts[cachedEntry]));
       
  2418             }
       
  2419         else
       
  2420             {
       
  2421             TRAP(updateError, iOutLineTextImageRasterizer->RasterizeL(*iCachedTexts[cachedEntry]));
       
  2422             }
       
  2423         
       
  2424         
       
  2425         
       
  2426         if (updateError == KErrNoMemory)
       
  2427             {                
       
  2428             // Call grim reaper to initiate system level texture memory actions !
       
  2429             HandleOutOfTextureMemory();
       
  2430             User::LeaveIfError(updateError);
       
  2431             }
       
  2432         }
       
  2433 
       
  2434     iCachedTexts[cachedEntry]->RefreshUser(aUser);
       
  2435     return iCachedTexts[cachedEntry];            
       
  2436     }
       
  2437 
       
  2438 
       
  2439 
       
  2440 
       
  2441 // ---------------------------------------------------------------------------
       
  2442 // 
       
  2443 // ---------------------------------------------------------------------------
       
  2444 //
       
  2445 void CHuiCanvasTextureCache::ReleaseAllCachedEntries(const CHuiCanvasVisual& aUser)
       
  2446     {    
       
  2447     // Texts
       
  2448     for (TInt i=0; i < iCachedTexts.Count(); i++)
       
  2449         {
       
  2450         TInt index = iCachedTexts[i]->iActiveUsers.FindInAddressOrder(&aUser);
       
  2451 
       
  2452         if (index != KErrNotFound)
       
  2453             {
       
  2454             iCachedTexts[i]->iActiveUsers.Remove(index);
       
  2455             iHasReleasedTexts = ETrue;
       
  2456             }
       
  2457         }        
       
  2458 
       
  2459     // Images
       
  2460     for (TInt i=0; i < iCachedImages.Count(); i++)
       
  2461         {
       
  2462         TInt index = iCachedImages[i]->iActiveUsers.FindInAddressOrder(&aUser);
       
  2463 
       
  2464         if (index != KErrNotFound)
       
  2465             {
       
  2466             iCachedImages[i]->iActiveUsers.Remove(index);
       
  2467             iHasReleasedImages = ETrue;
       
  2468             }
       
  2469         }
       
  2470     
       
  2471     // Render buffers are _not_ released together with images and text    
       
  2472     }
       
  2473 
       
  2474 
       
  2475 // ---------------------------------------------------------------------------
       
  2476 // 
       
  2477 // ---------------------------------------------------------------------------
       
  2478 //
       
  2479 void CHuiCanvasTextureCache::DeleteAllReleasedEntries(TBool aAllowKeepCached)
       
  2480     {
       
  2481     // Texts
       
  2482     if (iHasReleasedTexts)
       
  2483         {
       
  2484         RPointerArray<CHuiCanvasTextImage> unusedEntries;
       
  2485         
       
  2486         FindUnusedTextEntries(unusedEntries);
       
  2487             
       
  2488         // Remove unused entries if they fit into the cache, leave last used ones in the cache if cache size allows
       
  2489         if (aAllowKeepCached)
       
  2490             {                
       
  2491             SelectPreservedUnusedTextEntries(unusedEntries);            
       
  2492             }
       
  2493         
       
  2494         DeleteUnusedTextEntries(unusedEntries);
       
  2495 
       
  2496         unusedEntries.Close();                
       
  2497         iHasReleasedTexts = EFalse;                        
       
  2498         }
       
  2499 
       
  2500     // Images
       
  2501     if (iHasReleasedImages)
       
  2502         {
       
  2503         RPointerArray<CHuiCanvasGraphicImage> unusedEntries;
       
  2504 
       
  2505         FindUnusedImageEntries(unusedEntries);
       
  2506 
       
  2507         // Remove unused entries if they fit into the cache, leave last used ones in the cache if cache size allows
       
  2508         if (aAllowKeepCached)
       
  2509             {                
       
  2510             SelectPreservedUnusedImageEntries(unusedEntries);            
       
  2511             }
       
  2512 
       
  2513         DeleteUnusedImageEntries(unusedEntries);
       
  2514             
       
  2515         unusedEntries.Close();                            
       
  2516         iHasReleasedImages = EFalse;                                        
       
  2517         }
       
  2518     
       
  2519     // Render buffers
       
  2520     if (iHasReleasedRenderBuffers)
       
  2521         {
       
  2522         RPointerArray<CHuiCanvasRenderBufferImage> unusedEntries;
       
  2523 
       
  2524         FindUnusedRenderBufferEntries(unusedEntries);
       
  2525 
       
  2526         // Remove unused entries if they fit into the cache, leave last used ones in the cache if cache size allows
       
  2527         if (aAllowKeepCached)
       
  2528             {                
       
  2529             SelectPreservedUnusedRenderBufferEntries(unusedEntries);            
       
  2530             }
       
  2531 
       
  2532         DeleteUnusedRenderBufferEntries(unusedEntries);
       
  2533             
       
  2534         unusedEntries.Close();                            
       
  2535         iHasReleasedRenderBuffers = EFalse;                                        
       
  2536         }    
       
  2537     }
       
  2538 
       
  2539 #ifdef HUI_DEBUG_PRINT_CANVAS_TEXTURE_CACHE_EGL
       
  2540 #include "eglext.h"
       
  2541 typedef EGLBoolean (*NOK_resource_profiling)(EGLDisplay, EGLint, EGLint*, EGLint, EGLint*);
       
  2542 
       
  2543 void ReportGraphicsMemoryUsage()
       
  2544     {
       
  2545 	RDebug::Print(_L("About to ask EGL profiling ext"));
       
  2546     EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
       
  2547 	
       
  2548     /*
       
  2549      ** Search for extName in the extensions string.  Use of strstr()
       
  2550      ** is not sufficient because extension names can be prefixes of
       
  2551      ** other extension names.  Could use strtok() but the constant
       
  2552      ** string returned by glGetString can be in read-only memory.
       
  2553      */
       
  2554    /* TBool extensionFound = EFalse;
       
  2555     char *p = (char *) eglQueryString(dpy,EGL_EXTENSIONS);
       
  2556     char *end;
       
  2557     int extNameLen = strlen("EGL_NOK_resource_profiling");
       
  2558     end = p + strlen(p);
       
  2559 
       
  2560     while (p < end) 
       
  2561         {
       
  2562         int n = strcspn(p, " ");
       
  2563         if ((extNameLen == n) && (strncmp("EGL_NOK_resource_profiling", p, n) == 0)) 
       
  2564             {
       
  2565             extensionFound = ETrue;
       
  2566             break;
       
  2567             }
       
  2568         p += (n + 1);
       
  2569         }
       
  2570   
       
  2571     if (!extensionFound)
       
  2572         {
       
  2573         TRACES("EGL_NOK_resource_profiling not found from EGL_EXTENSIONS");
       
  2574         }*/
       
  2575     // okay, let's fetch the function ptr to our profiling functions
       
  2576     // resource profiling extension function ptr
       
  2577     NOK_resource_profiling eglQueryProfilingData = (NOK_resource_profiling)eglGetProcAddress("eglQueryProfilingDataNOK");
       
  2578     if (!eglQueryProfilingData)
       
  2579         {
       
  2580 	   	RDebug::Print(_L("EGL profiling ext not present"));
       
  2581         return;
       
  2582         }
       
  2583 
       
  2584     EGLint data_count;
       
  2585     EGLint* prof_data;
       
  2586     TInt i(0);
       
  2587 
       
  2588 	/* Find out how much profiling data is available */
       
  2589 	eglQueryProfilingData(dpy, EGL_PROF_QUERY_GLOBAL_BIT_NOK | EGL_PROF_QUERY_MEMORY_USAGE_BIT_NOK,
       
  2590 							NULL, 0, &data_count);
       
  2591 
       
  2592 	/* Allocate room for the profiling data */
       
  2593 	prof_data = (EGLint*)User::Alloc(data_count * sizeof(EGLint));
       
  2594 	if (prof_data == NULL)
       
  2595 		{
       
  2596 		RDebug::Print(_L("Could not get mem for EGL profiling ext"));
       
  2597 		return;
       
  2598 		}
       
  2599 	/* Retrieve the profiling data */
       
  2600 	eglQueryProfilingData(dpy,
       
  2601 							 EGL_PROF_QUERY_GLOBAL_BIT_NOK |
       
  2602 							 EGL_PROF_QUERY_MEMORY_USAGE_BIT_NOK,
       
  2603 							 prof_data,
       
  2604 							 data_count,
       
  2605 							 &data_count);
       
  2606 
       
  2607 	/* Iterate over the returned data */
       
  2608 	while (i < data_count)
       
  2609 		{
       
  2610 		switch (prof_data[i++])
       
  2611 			{
       
  2612 			case EGL_PROF_USED_MEMORY_NOK:
       
  2613 				{
       
  2614 				RDebug::Print(_L("EGL Profiling: used mem %d"), prof_data[i++]);
       
  2615 				break;
       
  2616 				}
       
  2617 			case EGL_PROF_TOTAL_MEMORY_NOK:
       
  2618 				{
       
  2619 				RDebug::Print(_L("EGL Profiling: total mem available: %d"), prof_data[i++]);
       
  2620 				break;
       
  2621 				}
       
  2622 		    case EGL_PROF_THREAD_ID_NOK:
       
  2623                 {
       
  2624                 if (sizeof(EGLNativeThreadIdTypeNOK) == 8)
       
  2625                     {
       
  2626                     i+=2;
       
  2627                     }
       
  2628                 else
       
  2629                     {
       
  2630                     i++;
       
  2631                     }
       
  2632                 break;
       
  2633                 }
       
  2634             case EGL_PROF_THREAD_USED_PRIVATE_MEMORY_NOK:
       
  2635             case EGL_PROF_THREAD_USED_SHARED_MEMORY_NOK:
       
  2636 			default:
       
  2637 				{
       
  2638                 i++;
       
  2639 				break;
       
  2640 				}
       
  2641 			}
       
  2642 		}
       
  2643 
       
  2644 	User::Free(prof_data);
       
  2645     }
       
  2646 
       
  2647 #endif
       
  2648     
       
  2649     
       
  2650 // ---------------------------------------------------------------------------
       
  2651 // 
       
  2652 // ---------------------------------------------------------------------------
       
  2653 //
       
  2654 void CHuiCanvasTextureCache::AdvanceTime()
       
  2655     {
       
  2656 #ifdef HUI_DEBUG_PRINT_CANVAS_TEXTURE_CACHE
       
  2657     RDebug::Print(_L("-- CHuiCanvasTextureCache::AdvanceTime: begin --"));
       
  2658     if (IsLowMemoryStateEnabled())
       
  2659         {        
       
  2660         RDebug::Print(_L("-- CHuiCanvasTextureCache::AdvanceTime: LOW MEMORY STATE ENABLED"));
       
  2661         }    
       
  2662     if(iEglProfiling > 10)
       
  2663         {
       
  2664 #ifdef HUI_DEBUG_PRINT_CANVAS_TEXTURE_CACHE_EGL
       
  2665         ReportGraphicsMemoryUsage();
       
  2666 #endif
       
  2667         iEglProfiling = 0;
       
  2668         }
       
  2669     else
       
  2670         {
       
  2671         iEglProfiling++; 
       
  2672         }           
       
  2673 #endif
       
  2674 
       
  2675     // We do not delete all, by leaving something unused in the cache
       
  2676     // we can improve performance.
       
  2677     CalculateGraphicsMemoryUsage();
       
  2678     DeleteAllReleasedEntries(ETrue);        
       
  2679 
       
  2680     // Reset bitmap sizes to save memory. Commented out as resize appears to
       
  2681     // be relatively slow (0.2 - 0.5 ms). Not resizing here means that it uses
       
  2682     // more RAM between frames.
       
  2683     //iTempMask->Resize(KEmptyBitmapSize);
       
  2684     //iTempBitmap->Resize(KEmptyBitmapSize);                        
       
  2685     
       
  2686     //iFontHandle = 0;
       
  2687     //delete iFont;
       
  2688     //iFont = NULL;
       
  2689 
       
  2690 #ifdef HUI_DEBUG_PRINT_CANVAS_TEXTURE_CACHE
       
  2691     RDebug::Print(_L("-- Cached texts: %i --"), iCachedTexts.Count());
       
  2692     RDebug::Print(_L("-- Cached imgs : %i --"), iCachedImages.Count());
       
  2693 
       
  2694     TInt totalPixels = 0;
       
  2695 
       
  2696     for(TInt i=iCachedTexts.Count() - 1; i >= 0; i--)
       
  2697         {    
       
  2698         TSize size = iCachedTexts[i]->iTexture->Size();    
       
  2699         RDebug::Print(_L("-- Cached text: %ix%i, users=%i, string=%S --"), size.iWidth, size.iHeight, iCachedTexts[i]->iActiveUsers.Count(), iCachedTexts[i]->iText );
       
  2700         totalPixels += size.iWidth * size.iHeight;
       
  2701 
       
  2702 #ifdef HUI_DEBUG_PRINT_CANVAS_TEXTURE_CACHE_EXTENDED
       
  2703 
       
  2704         RDebug::Print(_L("--   iFontHandle: %i --"), iCachedTexts[i]->iFontHandle );
       
  2705         RDebug::Print(_L("--   iTextWidth: %i --"), iCachedTexts[i]->iTextWidth );
       
  2706         RDebug::Print(_L("--   iTextBoxMaxSize.iWidth: %i --"), iCachedTexts[i]->iTextBoxMaxSize.iWidth );
       
  2707         RDebug::Print(_L("--   iBaseLineOffset: %i --"), iCachedTexts[i]->iBaseLineOffset );
       
  2708         RDebug::Print(_L("--   iTextAlign: %i --"), iCachedTexts[i]->iTextAlign );
       
  2709         RDebug::Print(_L("--   iMargin: %i --"), iCachedTexts[i]->iMargin );
       
  2710         RDebug::Print(_L("--   iAngle: %i --"), iCachedTexts[i]->iAngle );
       
  2711         RDebug::Print(_L("--   iTextParams.iStart: %i --"), iCachedTexts[i]->iTextParams.iStart );
       
  2712         RDebug::Print(_L("--   iTextParams.iEnd: %i --"), iCachedTexts[i]->iTextParams.iEnd );
       
  2713         RDebug::Print(_L("--   iTextParams.iFlagst: %i --"), iCachedTexts[i]->iTextParams.iFlags );
       
  2714         
       
  2715 
       
  2716         THuiCachedGcParams p = iCachedTexts[i]->iGcParams;    
       
  2717         RDebug::Print(_L("--    iPenColor: %i --"), p.iPenColor );
       
  2718         RDebug::Print(_L("--    iPenStyle: %i --"), p.iPenStyle );
       
  2719         RDebug::Print(_L("--    iDrawMode: %i --"), p.iDrawMode );
       
  2720         RDebug::Print(_L("--    iBrushColor: %i --"), p.iBrushColor );
       
  2721         RDebug::Print(_L("--    iBrushStyle: %i --"), p.iBrushStyle );
       
  2722         RDebug::Print(_L("--    iShadowMode: %i --"), p.iShadowMode );
       
  2723         RDebug::Print(_L("--    iStrikethrough: %i --"), p.iStrikethrough );
       
  2724         RDebug::Print(_L("--    iUnderline: %i --"), p.iUnderline );
       
  2725         RDebug::Print(_L("--    iUserDisplayMode: %i --"), p.iUserDisplayMode );
       
  2726         RDebug::Print(_L("--    iShadowColor: %i --"), p.iShadowColor );
       
  2727 #endif
       
  2728         }
       
  2729 
       
  2730     for(TInt i=iCachedImages.Count() - 1; i >= 0; i--)
       
  2731         {    
       
  2732         TSize size = iCachedImages[i]->iTexture->Size();    
       
  2733         if (iCachedImages[i]->iSubImages.Count())
       
  2734             {
       
  2735             RDebug::Print(_L("-- Cached combined image: %i+%i  %ix%i, users=%i --"), iCachedImages[i]->iBitmapHandle, iCachedImages[i]->iMaskHandle, size.iWidth, size.iHeight, iCachedImages[i]->iActiveUsers.Count());                        
       
  2736             RDebug::Print(_L("--  Blit size: %ix%i --"), iCachedImages[i]->iImageSize.iWidth, iCachedImages[i]->iImageSize.iHeight);                            
       
  2737             for (TInt j=0; j<iCachedImages[i]->iSubImages.Count();j++)
       
  2738                 {
       
  2739                 RDebug::Print(_L("--  subimage: %i+%i Point: %i,%i--"), 
       
  2740                     iCachedImages[i]->iSubImages[j].iBitmapHandle, 
       
  2741                     iCachedImages[i]->iSubImages[j].iMaskHandle, 
       
  2742                     iCachedImages[i]->iSubImages[j].iCombinedBitmapPoint.iX,
       
  2743                     iCachedImages[i]->iSubImages[j].iCombinedBitmapPoint.iY);        
       
  2744                 }            
       
  2745             }
       
  2746         else
       
  2747             {
       
  2748             RDebug::Print(_L("-- Cached image: %i+%i  %ix%i, users=%i --"), iCachedImages[i]->iBitmapHandle,iCachedImages[i]->iMaskHandle, size.iWidth, size.iHeight, iCachedImages[i]->iActiveUsers.Count());        
       
  2749             }    
       
  2750         
       
  2751         totalPixels += size.iWidth * size.iHeight;
       
  2752         }
       
  2753         
       
  2754     RDebug::Print(_L("-- Estimated canvas texture mem usage with 32bpp %i KBytes --"), totalPixels*4 / 1024);
       
  2755 
       
  2756     TInt unusedCanvasTextures = CalculateUnusedCanvasTextureUsageInKbytes();
       
  2757 
       
  2758     RDebug::Print(_L("-- Estimated canvas unused texture mem usage with 32bpp %i KBytes --"), unusedCanvasTextures);
       
  2759 
       
  2760     TInt totalUsedTextureMemoryInKBytes = CHuiStatic::Env().TextureManager().EstimatedTextureMemUsage(KHuiTextureEstimatedBpp) / 1024;
       
  2761     
       
  2762     RDebug::Print(_L("-- Estimated total texture mem usage with 32bpp %i KBytes --"), totalUsedTextureMemoryInKBytes);
       
  2763 
       
  2764     TInt totalPixelsForRenderBuffers = 0;
       
  2765     for(TInt i=iCachedRenderBuffers.Count() - 1; i >= 0; i--)
       
  2766         {
       
  2767         if (iCachedRenderBuffers[i]->iCanvasRenderBuffer)
       
  2768             {
       
  2769             TSize size = iCachedRenderBuffers[i]->iCanvasRenderBuffer->Size();    
       
  2770             RDebug::Print(_L("-- Cached render buffer: %ix%i, users=%i --"),  size.iWidth, size.iHeight, iCachedRenderBuffers[i]->iActiveUsers.Count());                
       
  2771             totalPixelsForRenderBuffers += size.iWidth * size.iHeight;
       
  2772             }
       
  2773         else
       
  2774             {
       
  2775             RDebug::Print(_L("-- Cached render buffer: 0x0, users=%i --"), iCachedRenderBuffers[i]->iActiveUsers.Count());                
       
  2776             }
       
  2777         }
       
  2778     RDebug::Print(_L("-- Estimated canvas render buffer mem usage with 32bpp %i KBytes --"), totalPixelsForRenderBuffers*4 / 1024);    
       
  2779     
       
  2780     TInt totalAllocSize = 0;
       
  2781     User::AllocSize(totalAllocSize);
       
  2782     RDebug::Print(_L("-- User::AllocSize = %i"), totalAllocSize);
       
  2783 
       
  2784     RDebug::Print(_L("-- CHuiCanvasTextureCache::AdvanceTime: end --"));
       
  2785 #endif
       
  2786     }
       
  2787 
       
  2788 // ---------------------------------------------------------------------------
       
  2789 // 
       
  2790 // ---------------------------------------------------------------------------
       
  2791 //
       
  2792 void CHuiCanvasTextureCache::FindUnusedImageEntries(RPointerArray<CHuiCanvasGraphicImage>& aIndexEntries)
       
  2793     {
       
  2794     for(TInt i=iCachedImages.Count() - 1; i >= 0; i--)
       
  2795         {
       
  2796         CHuiCanvasGraphicImage* entry = iCachedImages[i];    
       
  2797         if (!entry->iActiveUsers.Count())
       
  2798             {
       
  2799             aIndexEntries.InsertInOrderAllowRepeats(entry, ImageTimeOrderFunc);
       
  2800             }
       
  2801         }    
       
  2802     }
       
  2803 
       
  2804 // ---------------------------------------------------------------------------
       
  2805 // 
       
  2806 // ---------------------------------------------------------------------------
       
  2807 //
       
  2808 void CHuiCanvasTextureCache::FindUnusedTextEntries(RPointerArray<CHuiCanvasTextImage>& aIndexEntries)
       
  2809     {
       
  2810     for(TInt i=iCachedTexts.Count() - 1; i >= 0; i--)
       
  2811         {                
       
  2812         CHuiCanvasTextImage* entry = iCachedTexts[i];    
       
  2813 
       
  2814         if (!entry->iActiveUsers.Count())
       
  2815             {
       
  2816             aIndexEntries.InsertInOrderAllowRepeats(entry, TextTimeOrderFunc);
       
  2817             }
       
  2818         }        
       
  2819     }
       
  2820 
       
  2821 // ---------------------------------------------------------------------------
       
  2822 // 
       
  2823 // ---------------------------------------------------------------------------
       
  2824 //
       
  2825 void CHuiCanvasTextureCache::FindUnusedRenderBufferEntries(RPointerArray<CHuiCanvasRenderBufferImage>& aIndexEntries)
       
  2826     {
       
  2827     for(TInt i=iCachedRenderBuffers.Count() - 1; i >= 0; i--)
       
  2828         {                
       
  2829         CHuiCanvasRenderBufferImage* entry = iCachedRenderBuffers[i];    
       
  2830 
       
  2831         if (!entry->iActiveUsers.Count())
       
  2832             {
       
  2833             aIndexEntries.InsertInOrderAllowRepeats(entry, RenderBufferTimeOrderFunc);
       
  2834             }
       
  2835         }            
       
  2836     }
       
  2837 
       
  2838 
       
  2839 // ---------------------------------------------------------------------------
       
  2840 // 
       
  2841 // ---------------------------------------------------------------------------
       
  2842 //
       
  2843 void CHuiCanvasTextureCache::DeleteUnusedImageEntries(RPointerArray<CHuiCanvasGraphicImage>& aIndexEntries)
       
  2844     {
       
  2845     // Remove given entries
       
  2846     for(TInt i=aIndexEntries.Count() - 1; i >= 0; i--)
       
  2847         {
       
  2848         TInt indexEntry = iCachedImages.FindInOrder(aIndexEntries[i], ImageOrderFunc);
       
  2849         if (indexEntry != KErrNotFound)
       
  2850             {                        
       
  2851             CHuiCanvasGraphicImage* entry = iCachedImages[indexEntry];
       
  2852             iCachedImages.Remove(indexEntry); 
       
  2853             delete entry;
       
  2854             }
       
  2855         }
       
  2856     }
       
  2857 
       
  2858 // ---------------------------------------------------------------------------
       
  2859 // 
       
  2860 // ---------------------------------------------------------------------------
       
  2861 //
       
  2862 void CHuiCanvasTextureCache::DeleteUnusedTextEntries(RPointerArray<CHuiCanvasTextImage>& aIndexEntries)
       
  2863     {
       
  2864     // Remove given entries
       
  2865     for(TInt i=aIndexEntries.Count() - 1; i >= 0; i--)
       
  2866         {                
       
  2867         TInt indexEntry = iCachedTexts.FindInOrder(aIndexEntries[i], TextOrderFunc);
       
  2868         if (indexEntry != KErrNotFound)
       
  2869             {                        
       
  2870             CHuiCanvasTextImage* entry = iCachedTexts[indexEntry];
       
  2871             iCachedTexts.Remove(indexEntry); 
       
  2872             delete entry;
       
  2873             }
       
  2874         }
       
  2875     }
       
  2876 
       
  2877 // ---------------------------------------------------------------------------
       
  2878 // 
       
  2879 // ---------------------------------------------------------------------------
       
  2880 //
       
  2881 void CHuiCanvasTextureCache::DeleteUnusedRenderBufferEntries(RPointerArray<CHuiCanvasRenderBufferImage>& aIndexEntries)
       
  2882     {
       
  2883     // Remove given entries
       
  2884     for(TInt i=aIndexEntries.Count() - 1; i >= 0; i--)
       
  2885         {                
       
  2886         TInt indexEntry = iCachedRenderBuffers.FindInOrder(aIndexEntries[i], RenderBufferOrderFunc);
       
  2887         if (indexEntry != KErrNotFound)
       
  2888             {                        
       
  2889             CHuiCanvasRenderBufferImage* entry = iCachedRenderBuffers[indexEntry];
       
  2890             iCachedRenderBuffers.Remove(indexEntry);
       
  2891             delete entry;            
       
  2892             }
       
  2893         }    
       
  2894     }
       
  2895 
       
  2896 
       
  2897 // ---------------------------------------------------------------------------
       
  2898 // 
       
  2899 // ---------------------------------------------------------------------------
       
  2900 //
       
  2901 void CHuiCanvasTextureCache::SelectPreservedUnusedImageEntries(RPointerArray<CHuiCanvasGraphicImage>& aIndexEntries)
       
  2902     {
       
  2903     TInt totalUnusedTextureBytes = 0;
       
  2904 
       
  2905     // Remove unused entries if they fit into the cache, leave last used ones in the cache if cache size allows
       
  2906     for(TInt i=aIndexEntries.Count() - 1; i >= 0; i--)
       
  2907         {
       
  2908         // Always delete bitmaps from unused entries, we can again duplicate pointers from handles when needed.
       
  2909         // Pointers are kept only for perfromance reasons.
       
  2910         CHuiCanvasGraphicImage* entry = aIndexEntries[i];
       
  2911 
       
  2912         delete entry->iBitmap;    
       
  2913         entry->iBitmap = NULL;
       
  2914 
       
  2915         delete entry->iMask;    
       
  2916         entry->iMask = NULL;        
       
  2917         
       
  2918         for (TInt j=0; j < entry->iSubImages.Count(); j++)
       
  2919             {
       
  2920             delete entry->iSubImages[j].iBitmap;
       
  2921             entry->iSubImages[j].iBitmap = NULL;
       
  2922             
       
  2923             delete entry->iSubImages[j].iMask;
       
  2924             entry->iSubImages[j].iMask = NULL;    
       
  2925             }
       
  2926                     
       
  2927         TSize textureSize = entry->iTexture->Size();    
       
  2928         TInt textureEstimatedSizeInBytes = textureSize.iWidth * textureSize.iHeight * KHuiCanvasImageEstimatedBpp/8.f;
       
  2929 
       
  2930         if (totalUnusedTextureBytes + textureEstimatedSizeInBytes < iUnusedCanvasImageTextureCacheSizeInKBytes*1024)
       
  2931             {
       
  2932             // Fits in the cache, remove from unused list, but keep zero size textures                        
       
  2933             if (textureEstimatedSizeInBytes != 0)
       
  2934                 {
       
  2935                 aIndexEntries.Remove(i);        
       
  2936                 }            
       
  2937             }
       
  2938 
       
  2939         totalUnusedTextureBytes += textureEstimatedSizeInBytes;
       
  2940         }                
       
  2941     }
       
  2942 
       
  2943 // ---------------------------------------------------------------------------
       
  2944 // 
       
  2945 // ---------------------------------------------------------------------------
       
  2946 //
       
  2947 void CHuiCanvasTextureCache::SelectPreservedUnusedTextEntries(RPointerArray<CHuiCanvasTextImage>& aIndexEntries)
       
  2948     {
       
  2949     TInt totalUnusedTextureBytes = 0;
       
  2950 
       
  2951     // Remove unused entries if they fit into the cache, leave last used ones in the cache if cache size allows
       
  2952     for(TInt i=aIndexEntries.Count() - 1; i >= 0; i--)
       
  2953         {
       
  2954         TSize textureSize = aIndexEntries[i]->iTexture->Size();    
       
  2955         TInt textureEstimatedSizeInBytes = textureSize.iWidth * textureSize.iHeight * KHuiCanvasTextEstimatedBpp/8.f;
       
  2956             
       
  2957         if (totalUnusedTextureBytes + textureEstimatedSizeInBytes < iUnusedCanvasTextTextureCacheSizeInKBytes*1024)
       
  2958             {
       
  2959             // Fits in the cache, remove from unused list, but keep zero size textures                         
       
  2960             if (textureEstimatedSizeInBytes != 0)
       
  2961                 {
       
  2962                 aIndexEntries.Remove(i);
       
  2963                 }
       
  2964             }
       
  2965 
       
  2966         totalUnusedTextureBytes += textureEstimatedSizeInBytes;        
       
  2967         }        
       
  2968     }
       
  2969 
       
  2970 // ---------------------------------------------------------------------------
       
  2971 // 
       
  2972 // ---------------------------------------------------------------------------
       
  2973 //
       
  2974 void CHuiCanvasTextureCache::SelectPreservedUnusedRenderBufferEntries(RPointerArray<CHuiCanvasRenderBufferImage>& aIndexEntries)
       
  2975     {
       
  2976     TInt totalUnusedRenderBufferBytes = 0;
       
  2977 
       
  2978     // Remove unused entries if they fit into the cache, leave last used ones in the cache if cache size allows
       
  2979     for(TInt i=aIndexEntries.Count() - 1; i >= 0; i--)
       
  2980         {
       
  2981         CHuiCanvasRenderBufferImage* entry = aIndexEntries[i];
       
  2982         if (entry->iCanvasRenderBuffer)
       
  2983             {
       
  2984             TSize renderBufferSize = entry->iCanvasRenderBuffer->Size();    
       
  2985             TInt renderBufferEstimatedSizeInBytes = renderBufferSize.iWidth * renderBufferSize.iHeight * KHuiCanvasRenderBufferEstimatedBpp/8.f;
       
  2986                 
       
  2987             if (totalUnusedRenderBufferBytes + renderBufferEstimatedSizeInBytes < iUnusedCanvasRenderBufferCacheSizeInKBytes*1024)
       
  2988                 {
       
  2989                 aIndexEntries.Remove(i);
       
  2990                 }
       
  2991             totalUnusedRenderBufferBytes += renderBufferEstimatedSizeInBytes;        
       
  2992             }
       
  2993         else
       
  2994             {
       
  2995 #ifdef HUI_DEBUG_PRINT_CANVAS_TEXTURE_CACHE            
       
  2996             RDebug::Print(_L("CHuiCanvasTextureCache::PurgeUnusedRenderBufferEntries: Non existing render buffer, Render does not support canvas render buffers ?"));
       
  2997 #endif
       
  2998             }
       
  2999         }            
       
  3000     }
       
  3001 
       
  3002 
       
  3003 
       
  3004 // ---------------------------------------------------------------------------
       
  3005 // 
       
  3006 // ---------------------------------------------------------------------------
       
  3007 //
       
  3008 void CHuiCanvasTextureCache::HandleOutOfTextureMemory()
       
  3009     {
       
  3010     RDebug::Print(_L("CHuiCanvasTextureCache::HandleOutOfTextureMemory: Out of memory happened !"));
       
  3011 
       
  3012     DeleteAllReleasedEntries(EFalse);    
       
  3013     
       
  3014     // TODO: Who you gonna call when texture memory is full and we cannot ourself
       
  3015     // delete anymore textures ? 
       
  3016     //
       
  3017     // Grim reaper ?!
       
  3018     //
       
  3019     }
       
  3020 
       
  3021 // ---------------------------------------------------------------------------
       
  3022 // 
       
  3023 // ---------------------------------------------------------------------------
       
  3024 //
       
  3025 void CHuiCanvasTextureCache::CalculateGraphicsMemoryUsage()
       
  3026     {
       
  3027     // TODO: This should handle NVG textures
       
  3028 
       
  3029     if (iMaxTextureMemoryInKBytes)
       
  3030         {
       
  3031         // How much all alfred textures use memory currently, this include alf apps and all canvas textures
       
  3032         TInt totalUsedTextureMemoryInKBytes = CHuiStatic::Env().TextureManager().EstimatedTextureMemUsage(KHuiTextureEstimatedBpp) / 1024;
       
  3033 
       
  3034         // How much there are unused textures cached currently
       
  3035         TInt totalUnusedCanvasTextureMemoryUsageInKBytes = CalculateUnusedCanvasTextureUsageInKbytes();
       
  3036 
       
  3037         // Calculate how much there is space for unused textures 
       
  3038         TInt availableCacheSizeInKBytes = iMaxTextureMemoryInKBytes - (totalUsedTextureMemoryInKBytes - totalUnusedCanvasTextureMemoryUsageInKBytes);
       
  3039 
       
  3040         // Divide available space for unused textures between texts and images using defined ratio
       
  3041         if (availableCacheSizeInKBytes > 0)
       
  3042             {
       
  3043             iUnusedCanvasTextTextureCacheSizeInKBytes = availableCacheSizeInKBytes * KHuiCanvasUnusedTextImageCacheRatio;
       
  3044             iUnusedCanvasImageTextureCacheSizeInKBytes = availableCacheSizeInKBytes * (1.f - KHuiCanvasUnusedTextImageCacheRatio);                            
       
  3045             }
       
  3046         else
       
  3047             {
       
  3048             iUnusedCanvasTextTextureCacheSizeInKBytes = 0;
       
  3049             iUnusedCanvasImageTextureCacheSizeInKBytes = 0;  
       
  3050             }    
       
  3051         }
       
  3052     else
       
  3053         {
       
  3054         iUnusedCanvasTextTextureCacheSizeInKBytes = 0;
       
  3055         iUnusedCanvasImageTextureCacheSizeInKBytes = 0;          
       
  3056         }
       
  3057     
       
  3058     if (iMaxRenderBufferMemoryInKBytes)
       
  3059         {
       
  3060         // How much there are render buffers cached currently
       
  3061         TInt totalInKBytes = CalculateTotalCanvasRenderBufferUsageInKbytes();
       
  3062 
       
  3063         // How much available for unused
       
  3064         TInt availableCacheSizeInKBytes = iMaxRenderBufferMemoryInKBytes - totalInKBytes;
       
  3065 
       
  3066         if (availableCacheSizeInKBytes > 0)
       
  3067             {
       
  3068             iUnusedCanvasRenderBufferCacheSizeInKBytes = iMaxRenderBufferMemoryInKBytes - totalInKBytes;
       
  3069             }
       
  3070         else
       
  3071             {
       
  3072             iUnusedCanvasRenderBufferCacheSizeInKBytes = 0;
       
  3073             }    
       
  3074         }
       
  3075     else
       
  3076         {
       
  3077         iUnusedCanvasRenderBufferCacheSizeInKBytes = 0;
       
  3078         }
       
  3079 
       
  3080 #ifdef HUI_DEBUG_PRINT_CANVAS_TEXTURE_CACHE
       
  3081     RDebug::Print(_L("-- CHuiCanvasTextureCache::CalculateTextureUsage: iUnusedCanvasTextTextureCacheSizeInKBytes = %i"), iUnusedCanvasTextTextureCacheSizeInKBytes);
       
  3082     RDebug::Print(_L("-- CHuiCanvasTextureCache::CalculateTextureUsage: iUnusedCanvasImageTextureCacheSizeInKBytes = %i"), iUnusedCanvasImageTextureCacheSizeInKBytes);
       
  3083     RDebug::Print(_L("-- CHuiCanvasTextureCache::CalculateTextureUsage: iUnusedCanvasRenderBufferCacheSizeInKBytes = %i"), iUnusedCanvasRenderBufferCacheSizeInKBytes);
       
  3084 #endif
       
  3085     }
       
  3086 
       
  3087 void CHuiCanvasTextureCache::EnableTouchCountCheck(TBool aEnable)
       
  3088     {
       
  3089     iTouchCountCheckEnabled = aEnable;
       
  3090     }
       
  3091 
       
  3092 TBool CHuiCanvasTextureCache::IsTouchCountCheckEnabled()
       
  3093     {
       
  3094     return iTouchCountCheckEnabled;   
       
  3095     }    
       
  3096     
       
  3097 // ---------------------------------------------------------------------------
       
  3098 // 
       
  3099 // ---------------------------------------------------------------------------
       
  3100 //
       
  3101 TInt CHuiCanvasTextureCache::CalculateUnusedCanvasTextureUsageInKbytes()
       
  3102     {
       
  3103     // TODO: This should handle NVG textures
       
  3104     
       
  3105     TInt totalUnusedTextureBytes = 0;
       
  3106     
       
  3107     // Texts
       
  3108     RPointerArray<CHuiCanvasTextImage> textEntries;
       
  3109     
       
  3110     FindUnusedTextEntries(textEntries);
       
  3111 
       
  3112     for(TInt i=textEntries.Count() - 1; i >= 0; i--)
       
  3113         {
       
  3114         TSize textureSize = textEntries[i]->iTexture->Size();    
       
  3115         totalUnusedTextureBytes += textureSize.iWidth * textureSize.iHeight * KHuiCanvasTextEstimatedBpp/8.f;
       
  3116         }            
       
  3117     
       
  3118     textEntries.Close();        
       
  3119 
       
  3120     // Images
       
  3121     RPointerArray<CHuiCanvasGraphicImage> imageEntries;
       
  3122     
       
  3123     FindUnusedImageEntries(imageEntries);
       
  3124 
       
  3125     for(TInt i=imageEntries.Count() - 1; i >= 0; i--)
       
  3126         {
       
  3127         TSize textureSize = imageEntries[i]->iTexture->Size();    
       
  3128         totalUnusedTextureBytes += textureSize.iWidth * textureSize.iHeight * KHuiCanvasImageEstimatedBpp/8.f;
       
  3129         }            
       
  3130     
       
  3131     imageEntries.Close();        
       
  3132     
       
  3133     return totalUnusedTextureBytes/1024;
       
  3134     }
       
  3135 
       
  3136 // ---------------------------------------------------------------------------
       
  3137 // 
       
  3138 // ---------------------------------------------------------------------------
       
  3139 //
       
  3140 TInt CHuiCanvasTextureCache::CalculateUnusedCanvasRenderBufferUsageInKbytes()
       
  3141     {
       
  3142     TInt totalUnusedRenderBufferBytes = 0;
       
  3143     
       
  3144     RPointerArray<CHuiCanvasRenderBufferImage> entries;
       
  3145     
       
  3146     FindUnusedRenderBufferEntries(entries);
       
  3147 
       
  3148     for(TInt i=entries.Count() - 1; i >= 0; i--)
       
  3149         {
       
  3150         if (iCachedRenderBuffers[i]->iCanvasRenderBuffer)
       
  3151             {        
       
  3152             TSize renderBufferSize = entries[i]->iCanvasRenderBuffer->Size();    
       
  3153             totalUnusedRenderBufferBytes += renderBufferSize.iWidth * renderBufferSize.iHeight * KHuiCanvasRenderBufferEstimatedBpp/8.f;
       
  3154             }
       
  3155         }            
       
  3156     
       
  3157     entries.Close();        
       
  3158 
       
  3159     return totalUnusedRenderBufferBytes/1024;
       
  3160     }
       
  3161 
       
  3162 // ---------------------------------------------------------------------------
       
  3163 // 
       
  3164 // ---------------------------------------------------------------------------
       
  3165 //
       
  3166 TInt CHuiCanvasTextureCache::CalculateTotalCanvasRenderBufferUsageInKbytes()
       
  3167     {
       
  3168     TInt totalRenderBufferBytes = 0;
       
  3169     for(TInt i=iCachedRenderBuffers.Count() - 1; i >= 0; i--)
       
  3170         {
       
  3171         if (iCachedRenderBuffers[i]->iCanvasRenderBuffer)
       
  3172             {
       
  3173             TSize renderBufferSize = iCachedRenderBuffers[i]->iCanvasRenderBuffer->Size();    
       
  3174             totalRenderBufferBytes += renderBufferSize.iWidth * renderBufferSize.iHeight * KHuiCanvasRenderBufferEstimatedBpp/8.f;
       
  3175             }
       
  3176         }     
       
  3177     return totalRenderBufferBytes/1024;
       
  3178     }
       
  3179 
       
  3180 
       
  3181 // ---------------------------------------------------------------------------
       
  3182 // 
       
  3183 // ---------------------------------------------------------------------------
       
  3184 //
       
  3185 CHuiTexture* CHuiCanvasTextureCache::CreateRecycledTextureL()
       
  3186     {
       
  3187     CHuiTexture* texture = NULL;
       
  3188     if (iRecycledTextures.Count())
       
  3189         {
       
  3190         // If there are recycled textures, use one of those
       
  3191         TInt last = iRecycledTextures.Count() - 1;
       
  3192         texture = iRecycledTextures[last];
       
  3193         iRecycledTextures.Remove(last);    
       
  3194         }
       
  3195     else
       
  3196         {
       
  3197         // No recycled textures available, create new one
       
  3198         texture = CHuiTexture::NewL();    
       
  3199         }    
       
  3200     return texture;        
       
  3201     }
       
  3202 
       
  3203 // ---------------------------------------------------------------------------
       
  3204 // 
       
  3205 // ---------------------------------------------------------------------------
       
  3206 //
       
  3207 void CHuiCanvasTextureCache::DeleteRecycledTexture(CHuiTexture* aTexture)
       
  3208     {
       
  3209     aTexture->Reset();
       
  3210 
       
  3211     TInt error = KErrNone;
       
  3212     
       
  3213     if (iRecycledTextures.Count() < KHuiMaxRecycledTextureCount)
       
  3214         {
       
  3215         error = iRecycledTextures.Append(aTexture);            
       
  3216         if (error)
       
  3217             {
       
  3218             delete aTexture;    
       
  3219             }
       
  3220         }
       
  3221     else
       
  3222         {
       
  3223         delete aTexture;        
       
  3224         }            
       
  3225     }
       
  3226 
       
  3227 // ---------------------------------------------------------------------------
       
  3228 // 
       
  3229 // ---------------------------------------------------------------------------
       
  3230 //
       
  3231 CHuiCanvasRenderBuffer* CHuiCanvasTextureCache::CreateCachedRenderBufferL(const CHuiCanvasVisual& aUser, TSize aSizeHint)
       
  3232     {
       
  3233     if (IsLowMemoryStateEnabled())
       
  3234         {
       
  3235         // No canvas render buffers created in low memory state
       
  3236         return NULL;
       
  3237         }    
       
  3238     
       
  3239     TInt cachedEntry = KErrNotFound;
       
  3240     CHuiCanvasRenderBufferImage* newRenderBufferEntry = NULL;
       
  3241     
       
  3242     iSearchedRenderBufferImageEntry->Reset();        
       
  3243     iSearchedRenderBufferImageEntry->iOwner = (TAny*)&aUser;
       
  3244     
       
  3245     cachedEntry = iCachedRenderBuffers.FindInOrder(iSearchedRenderBufferImageEntry, RenderBufferOrderFunc);
       
  3246     
       
  3247     if (cachedEntry == KErrNotFound)
       
  3248         {
       
  3249         // Try first getting reused render buffer
       
  3250         newRenderBufferEntry = ReUseReleasedRenderBuffer(aSizeHint);
       
  3251 
       
  3252         // Create new entry object if needed
       
  3253         if (!newRenderBufferEntry)
       
  3254             {
       
  3255             newRenderBufferEntry = new (ELeave) CHuiCanvasRenderBufferImage;             
       
  3256             }
       
  3257 
       
  3258         // Copy attributes (only iOwner attribute)
       
  3259         newRenderBufferEntry->iOwner = iSearchedRenderBufferImageEntry->iOwner;
       
  3260         
       
  3261         CleanupStack::PushL(newRenderBufferEntry);                    
       
  3262         
       
  3263         // Create new render buffer
       
  3264         if (!newRenderBufferEntry->iCanvasRenderBuffer)
       
  3265             {
       
  3266             newRenderBufferEntry->iCanvasRenderBuffer = iCanvasGc->CreateRenderBufferL(TSize(0,0)); 
       
  3267             }
       
  3268 
       
  3269         // Insert to cache array
       
  3270         TInt insertSuccess = iCachedRenderBuffers.InsertInOrder(newRenderBufferEntry, RenderBufferOrderFunc);
       
  3271         __ASSERT_DEBUG( !insertSuccess, USER_INVARIANT() );
       
  3272         User::LeaveIfError( insertSuccess );
       
  3273         
       
  3274         // We don't know which index it got, so look it up
       
  3275         cachedEntry = iCachedRenderBuffers.FindInOrder(newRenderBufferEntry, RenderBufferOrderFunc);
       
  3276 
       
  3277         CleanupStack::Pop(newRenderBufferEntry); 
       
  3278         }
       
  3279     else
       
  3280         {
       
  3281         // If it was found, great. 
       
  3282         }        
       
  3283     
       
  3284     iCachedRenderBuffers[cachedEntry]->RefreshUser(aUser);
       
  3285 
       
  3286     return iCachedRenderBuffers[cachedEntry]->iCanvasRenderBuffer;                
       
  3287     }
       
  3288 
       
  3289 // ---------------------------------------------------------------------------
       
  3290 // 
       
  3291 // ---------------------------------------------------------------------------
       
  3292 //
       
  3293 CHuiCanvasRenderBuffer* CHuiCanvasTextureCache::FindCachedRenderBuffer(const CHuiCanvasVisual& aUser)
       
  3294     {
       
  3295     TInt cachedEntry = KErrNotFound;
       
  3296     
       
  3297     iSearchedRenderBufferImageEntry->Reset();        
       
  3298     iSearchedRenderBufferImageEntry->iOwner = (TAny*)&aUser;
       
  3299     
       
  3300     cachedEntry = iCachedRenderBuffers.FindInOrder(iSearchedRenderBufferImageEntry, RenderBufferOrderFunc);
       
  3301     if (cachedEntry != KErrNotFound)
       
  3302         {
       
  3303         iCachedRenderBuffers[cachedEntry]->RefreshUser(aUser);
       
  3304         return iCachedRenderBuffers[cachedEntry]->iCanvasRenderBuffer;                    
       
  3305         }
       
  3306     else
       
  3307         {
       
  3308         return NULL;                            
       
  3309         }
       
  3310     }
       
  3311 
       
  3312 // ---------------------------------------------------------------------------
       
  3313 // 
       
  3314 // ---------------------------------------------------------------------------
       
  3315 //
       
  3316 void CHuiCanvasTextureCache::ReleaseCachedRenderBuffer(const CHuiCanvasVisual& aUser)
       
  3317     {
       
  3318     TInt cachedEntry = KErrNotFound;
       
  3319     
       
  3320     iSearchedRenderBufferImageEntry->Reset();        
       
  3321     iSearchedRenderBufferImageEntry->iOwner = (TAny*)&aUser;
       
  3322     
       
  3323     cachedEntry = iCachedRenderBuffers.FindInOrder(iSearchedRenderBufferImageEntry, RenderBufferOrderFunc);
       
  3324     if (cachedEntry != KErrNotFound)
       
  3325         {
       
  3326         CHuiCanvasRenderBufferImage* releasedEntry = iCachedRenderBuffers[cachedEntry];        
       
  3327         iCachedRenderBuffers.Remove(cachedEntry);
       
  3328         releasedEntry->RemoveUser(aUser);
       
  3329         releasedEntry->iOwner = releasedEntry; // No real owner anymore, se it self as owner
       
  3330  
       
  3331         if(!IsLowMemoryStateEnabled())
       
  3332             {
       
  3333             // re-insert released entry (new position in the array order because we clered iOwner)
       
  3334             TInt insertSuccess = iCachedRenderBuffers.InsertInOrder(releasedEntry, RenderBufferOrderFunc);
       
  3335         
       
  3336             if (insertSuccess != KErrNone)
       
  3337                 {
       
  3338                 // oh no re-insert failed, now we must delete the entry to avoid memory leak.
       
  3339                 delete releasedEntry;
       
  3340                 }
       
  3341             }
       
  3342         else
       
  3343             {
       
  3344             delete releasedEntry;
       
  3345             }
       
  3346         
       
  3347         iHasReleasedRenderBuffers = ETrue;
       
  3348         }
       
  3349     }
       
  3350 
       
  3351 // ---------------------------------------------------------------------------
       
  3352 // 
       
  3353 // ---------------------------------------------------------------------------
       
  3354 //
       
  3355 CHuiCanvasRenderBufferImage* CHuiCanvasTextureCache::ReUseReleasedRenderBuffer(TSize aSizeHint)
       
  3356     {
       
  3357     if (aSizeHint == TSize(0,0))
       
  3358         {
       
  3359         return NULL;
       
  3360         }
       
  3361     
       
  3362     for(TInt i=iCachedRenderBuffers.Count() - 1; i >= 0; i--)
       
  3363         {
       
  3364         // Check if there are any released buffers with have requested size
       
  3365         if (!iCachedRenderBuffers[i]->IsAnyUser() && 
       
  3366             iCachedRenderBuffers[i]->iCanvasRenderBuffer && 
       
  3367             iCachedRenderBuffers[i]->iCanvasRenderBuffer->Size() == aSizeHint)
       
  3368             {
       
  3369             // Remove from array and return instance to caller
       
  3370             CHuiCanvasRenderBufferImage* reusedEntry = iCachedRenderBuffers[i];        
       
  3371             iCachedRenderBuffers.Remove(i);
       
  3372             return reusedEntry;
       
  3373             }
       
  3374         }         
       
  3375 
       
  3376     return NULL;
       
  3377     }
       
  3378 
       
  3379 void CHuiCanvasTextureCache::EnableLowMemoryState(TBool aEnable)
       
  3380     {
       
  3381     // deprecated
       
  3382     }
       
  3383 
       
  3384 THuiMemoryLevel CHuiCanvasTextureCache::MemoryLevel()
       
  3385     {
       
  3386     return iMemoryLevel;
       
  3387     }
       
  3388 
       
  3389 void CHuiCanvasTextureCache::SetMemoryLevel(THuiMemoryLevel aLevel)
       
  3390     {
       
  3391     iMemoryLevel = aLevel;
       
  3392 
       
  3393     if (iMemoryLevel <= EHuiMemoryLevelLowest)
       
  3394         {
       
  3395 #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
       
  3396 RDebug::Print(_L("-- CHuiCanvasTextureCache::SetMemoryLevel: Enabling lowest memory state"));
       
  3397 #endif
       
  3398 
       
  3399         // Set cache sizes to minimum
       
  3400         iMaxTextureMemoryInKBytes = 0;
       
  3401         iMaxRenderBufferMemoryInKBytes = 0;
       
  3402 
       
  3403         // Delete images, even if they are in use
       
  3404         for(TInt i=iCachedImages.Count() - 1; i >= 0; i--)
       
  3405             {
       
  3406             CHuiCanvasGraphicImage* entry = iCachedImages[i];    
       
  3407             iCachedImages.Remove(i);
       
  3408             delete entry;
       
  3409             }    
       
  3410 
       
  3411        // Delete texts, even if they are in use
       
  3412         for(TInt i=iCachedTexts.Count() - 1; i >= 0; i--)
       
  3413             {                
       
  3414             CHuiCanvasTextImage* entry = iCachedTexts[i];    
       
  3415             iCachedTexts.Remove(i);
       
  3416             delete entry;
       
  3417             }        
       
  3418         
       
  3419         
       
  3420         // Delete canvas render buffers, even if they are in use
       
  3421         for(TInt i=iCachedRenderBuffers.Count() - 1; i >= 0; i--)
       
  3422             {                
       
  3423             CHuiCanvasRenderBufferImage* entry = iCachedRenderBuffers[i];    
       
  3424             iCachedRenderBuffers.Remove(i);
       
  3425             delete entry;            
       
  3426             }                    
       
  3427         }
       
  3428     else if (iMemoryLevel <= EHuiMemoryLevelLow)
       
  3429         {
       
  3430         #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
       
  3431         RDebug::Print(_L("-- CHuiCanvasTextureCache::SetMemoryLevel: Enabling low memory state"));
       
  3432         #endif
       
  3433         // Set cache sizes to minimum
       
  3434         iMaxTextureMemoryInKBytes = 0;
       
  3435         iMaxRenderBufferMemoryInKBytes = 0;
       
  3436         
       
  3437         // Set flags to make sure we check all entries
       
  3438         iHasReleasedTexts = ETrue;
       
  3439         iHasReleasedImages = ETrue;
       
  3440         iHasReleasedRenderBuffers = ETrue;
       
  3441         
       
  3442         // Delete released cached entries
       
  3443         DeleteAllReleasedEntries(EFalse);
       
  3444 
       
  3445         // Delete canvas render buffers, even if they are in use
       
  3446         for(TInt i=iCachedRenderBuffers.Count() - 1; i >= 0; i--)
       
  3447             {                
       
  3448             CHuiCanvasRenderBufferImage* entry = iCachedRenderBuffers[i];    
       
  3449             iCachedRenderBuffers.Remove(i);
       
  3450             delete entry;            
       
  3451             }                    
       
  3452         }
       
  3453     else
       
  3454         {
       
  3455         #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
       
  3456         RDebug::Print(_L("-- CHuiCanvasTextureCache::SetMemoryLevel: Disabling low memory state"));
       
  3457         #endif
       
  3458 
       
  3459         // TODO: This could be configurable cenrep or something ?
       
  3460         iMaxTextureMemoryInKBytes = KHuiMaxRecommendedTextureAmountInKBytes;
       
  3461         iMaxRenderBufferMemoryInKBytes = KHuiMaxRecommendedRenderBufferAmountInKBytes;       
       
  3462         }    
       
  3463     }
       
  3464 
       
  3465 TBool CHuiCanvasTextureCache::IsLowMemoryStateEnabled() const
       
  3466     {
       
  3467     if (iMemoryLevel < EHuiMemoryLevelReduced)
       
  3468         {
       
  3469         return ETrue;
       
  3470         }
       
  3471     else
       
  3472         {
       
  3473         return EFalse;        
       
  3474         }
       
  3475     }