uiacceltk/hitchcock/coretoolkit/src/huicanvaswspainter.cpp
changeset 0 15bf7259bb7c
child 3 d8a3531bc6b8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uiacceltk/hitchcock/coretoolkit/src/huicanvaswspainter.cpp	Tue Feb 02 07:56:43 2010 +0200
@@ -0,0 +1,2646 @@
+/*
+* Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:   Definition of CHuiCanvasWsPainter.
+*
+*/
+
+
+
+#include "huicanvaswspainter.h"
+
+#include "uiacceltk/HuiCanvasVisual.h"
+#include "HuiRenderPlugin.h"
+#include "uiacceltk/HuiGc.h"
+#include "uiacceltk/HuiPanic.h"
+#include "uiacceltk/HuiUtil.h"
+#include "uiacceltk/HuiStatic.h"
+#include "uiacceltk/HuiEnv.h"
+#include "uiacceltk/HuiControl.h"
+#include "uiacceltk/HuiVisual.h"
+#include "uiacceltk/HuiTextMesh.h"
+#include "uiacceltk/HuiCanvasCmdBufferReader.h"
+#include "huicanvasgc.h"
+#include "huicanvaswsgc.h"
+#include "HuiRenderSurface.h"
+#include "huicanvastexturecache.h"
+#include "huicanvasbackground.h"
+#include "huicanvaswsswgc.h"
+#include "huicanvasdebugwsgc.h"
+#include "huicanvaswsbitgc.h"
+#include "../../CommonInc/huiwscanvascommands.h"
+#include <graphics/wsgraphicscontext.h>
+
+#ifdef HUI_DEBUG_TRACK_DRAWING
+#include "alfloggingconfiguration.h"
+#include "alfcommanddebug.h"
+#endif
+#include <e32cmn.h>
+#include <AknLayoutFont.h>
+#include <graphics/lookuptable.h>
+
+#include "HuiCmdBufferBrush.h"
+
+/** 
+ * Constants to define enabling/disabling render buffer automatically 
+ *  incase there are frequently new buffers posted. 
+ * 
+ *  This may improve performance in some HW platforms.
+ * 
+ */
+const TBool KHuiCanvasAutomaticRenderBufferUsage = EFalse; // Disbaled until all UI isses has been solved  
+const TInt KHuiCanvasDisableRenderBufferHandleInterval = 100; // Milliseconds 
+const TInt KHuiCanvasEnableRenderBufferHandleInterval = 500;  // Milliseconds
+
+/** Internal constant to identify complex command buffers */
+const TInt KPossiblePerformanceProblemInWindow = 64;
+
+
+/** ETrue - use SelectGcL to select gc implementation, 
+    EFalse - use KHuiDefaultCanvasWsGc. */
+const TBool KHuiUseSelectGc = ETrue;
+
+/** Change this to select default rendering ws gc implementation.
+    Only used when KHuiUseSelectGc does not hold. */
+const THuiCanvasWsGcType KHuiDefaultCanvasWsGc = EHuiCanvasWsHw;
+
+//#define HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+
+CHuiCanvasWsPainter* CHuiCanvasWsPainter::NewL()
+	{
+	CHuiCanvasWsPainter* self    = new ( ELeave ) CHuiCanvasWsPainter;
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop();
+	return self;
+    }
+
+
+CHuiCanvasWsPainter::CHuiCanvasWsPainter()
+    {
+    }
+
+void CHuiCanvasWsPainter::ConstructL()
+    {
+    CHuiStatic::Env().AddMemoryLevelObserver(this);
+    iWsCommandBufferReader = NULL;
+    iPartialCommandBuffer = NULL;
+    iCacheCleared = EFalse;
+
+    if ( KHuiUseSelectGc )
+        {
+        SelectGcL();
+        }
+    else if (KHuiDefaultCanvasWsGc == EHuiCanvasWsHw)
+        {
+        iCanvasWsHwGc = CHuiCanvasWsHwGc::NewL();
+        iCanvasWsGc = iCanvasWsHwGc;        
+        }
+    else if (KHuiDefaultCanvasWsGc == EHuiCanvasWsSw)
+        {
+        iCanvasWsSwGc = CHuiCanvasWsSwGc::NewL();
+        iCanvasWsGc = iCanvasWsSwGc;            
+        }    
+    else if (KHuiDefaultCanvasWsGc == EHuiCanvasWsBit)
+        {
+        iCanvasWsBitGc = CHuiCanvasWsBitGc::NewL();
+        iCanvasWsGc = iCanvasWsBitGc;            
+        }    
+    else
+        {
+        // Never happens, right.
+        }
+    
+    iWsCommandBufferReader = new (ELeave) CHuiCanvasCmdBufferReader();    
+#ifdef HUI_DEBUG_TRACK_DRAWING
+    iCommandDebugger = CAlfCommandDebug::NewL();
+    CHuiCanvasWsGc* realGc = iCanvasWsGc;
+    iCanvasWsGc = CHuiCanvasDebugWsGc::NewL( realGc, *iCommandDebugger );
+    
+#endif
+    }
+
+
+CHuiCanvasWsPainter::~CHuiCanvasWsPainter()
+    {
+    if (iCanvasVisual)
+        {
+        iCanvasVisual->Env().CanvasTextureCache().ReleaseAllCachedEntries(*iCanvasVisual);
+        iCanvasVisual->Env().RemoveMemoryLevelObserver(this);
+        }
+    else
+        {
+        CHuiStatic::Env().RemoveMemoryLevelObserver(this);
+        }
+    
+    ClearCommandSet();	
+    delete iWsCommandBufferReader;	
+    delete iCanvasWsHwGc;
+    delete iCanvasWsSwGc;
+    delete iCanvasWsBitGc;
+
+    iTempRegion.Close();
+    iTempCurrentSubRegion.Close();
+    iTempIntersectingRegion.Close();
+#ifdef HUI_DEBUG_TRACK_DRAWING
+    delete iCommandDebugger;
+#endif
+    iFullUpdateRegion.Close();
+    iShapeRegion.Close();
+    }
+    
+
+CHuiGc::TOrientation CHuiCanvasWsPainter::CalculateRelativeOrientation()
+    {
+    // Calculate drawing command rotation as relative to the current display rotation.
+    // It may be that drawing commands has been sent when display was in different rotation.
+    TInt last = iCommandBuffers.Count() - 1;
+    CHuiGc::TOrientation relativeOrientation = CHuiGc::EOrientationNormal;    
+    CHuiGc::TOrientation displayOrientation = CHuiStatic::Env().PrimaryDisplay().Orientation(); 
+    CHuiGc::TOrientation drawingCommandOrientation = iCommandBuffers[last]->iOrientation; 
+    
+    TInt rotationAngle[] =
+        {
+        0, 
+        270, 
+        90, 
+        180
+        };
+        
+    TInt displayOrientationAngle = rotationAngle[displayOrientation];
+    TInt drawingCommandOrientationAngle = rotationAngle[drawingCommandOrientation];    
+    TInt relativeOrientationAngle = drawingCommandOrientationAngle - displayOrientationAngle;
+    
+    // Check over/underflow
+    if (relativeOrientationAngle > 360)
+        {
+        relativeOrientationAngle -= 360;
+        }
+    else if (relativeOrientationAngle < 0)
+        {
+        relativeOrientationAngle += 360;
+        }
+    
+    switch (relativeOrientationAngle)
+        {
+        case 0:
+            {
+            relativeOrientation = CHuiGc::EOrientationNormal;
+            break;
+            }
+        case 90:
+            {
+            relativeOrientation = CHuiGc::EOrientationCW90;            
+            break;
+            }
+        case 270:
+            {
+            relativeOrientation = CHuiGc::EOrientationCCW90;            
+            break;
+            }
+        case 180:
+            {
+            relativeOrientation = CHuiGc::EOrientation180;            
+            break;
+            }
+        default:
+            {
+            // As usual, this should not happen...but just in case it does use normal rotation
+            relativeOrientation = CHuiGc::EOrientationNormal;
+            break;
+            }        
+        }
+    return relativeOrientation;
+    }
+
+void CHuiCanvasWsPainter::HandleBufferL(TRect& aDisplayRect, TInt aAction, const CHuiCanvasVisual& aUser, CHuiGc* aGc, TPoint aPos ) 
+    {   
+	#ifdef __ALF_SYMBIAN_RWINDOW_CLEARING_BUG_WORKAROUND__
+    iTestFullDisplayRect = aDisplayRect;
+	#endif
+    
+    // Store user so that we can clear cache later
+    iCanvasVisual = (CHuiCanvasVisual*)&aUser;
+
+    // Let canvas know about user and gc
+    CHuiCanvasGc& canvasGc = iCanvasWsGc->CanvasGc();
+    canvasGc.SetVisual(aUser);
+    if (aGc)
+        {
+        canvasGc.SetGc(*aGc);
+        }
+    
+    if (iCommandBuffers.Count() != 0)
+        {
+#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+        RDebug::Print(_L(">> CHuiCanvasWsPainter::HandleBufferL this = %i, Action = %i"), this, aAction );
+        TTime startTime;
+        startTime.UniversalTime();
+#endif
+
+        // Initialize canvas
+        canvasGc.SetDefaults();   
+
+        // Make sure we got up to date update reagion
+        iFullUpdateRegion.Clear();                
+        TInt bufferCount = iCommandBuffers.Count();
+        for (TInt cb = 0; cb < bufferCount; cb++)
+            {        
+            iFullUpdateRegion.Union(iCommandBuffers[cb]->iUpdateRegion);
+            }
+        iFullUpdateRegion.Tidy();
+        
+#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+        const TRect updateRegionBoundingRect = iFullUpdateRegion.BoundingRect();        
+        RDebug::Print(_L(">> CHuiCanvasWsPainter::HandleBufferL iFullUpdateRegion.BoundingRect() = (%i,%i) (%i,%i)"), 
+                updateRegionBoundingRect.iTl.iX,
+                updateRegionBoundingRect.iTl.iY,
+                updateRegionBoundingRect.iBr.iX,
+                updateRegionBoundingRect.iBr.iY
+                );
+
+        if (iCanvasWsGc->Type() == EHuiCanvasWsSw)
+            {
+            RDebug::Print(_L(">> CHuiCanvasWsPainter::HandleBufferL - SW mode is used."));
+            }
+        else if (iCanvasWsGc->Type() == EHuiCanvasWsBit)
+            {
+            RDebug::Print(_L(">> CHuiCanvasWsPainter::HandleBufferL - BITGC mode is used."));
+            }
+        
+        if (aUser.Effect())
+            {
+            RDebug::Print(_L(">> CHuiCanvasWsPainter::HandleBufferL - visual has EFFECT"));
+            }
+        
+        
+#endif
+        
+        if (aAction == EDrawBuffer)
+            {
+            /* Check and enable render buffer if needed */
+            EnableRenderBufferIfNeeded(ETrue);
+
+            // Compenstate possible orientation mismatch between drawing commands and display orientation
+            // by letting iCanvasWsGc know about it. Mismatch usually happens when screen is rotated and
+            // it may cause visually unpleasent things at the screen.
+            CHuiGc::TOrientation relativeOrientation = CalculateRelativeOrientation();
+            iCanvasWsGc->SetRelativeOrientation(relativeOrientation);
+            #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+            RDebug::Print(_L(">> CHuiCanvasWsPainter::HandleBufferL - relativeOrientation = %i "), relativeOrientation);    
+            #endif
+            
+            /* If window shape region has been changed, we should clear the window to get rid of old content. 
+             * We also set all command buffers to "not drawn" state so that everything will be redrawn.
+             */
+            TBool isFullUpdateRegionCleared = EFalse;
+            if(iShapeRegionClearingPending)
+                {
+                #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+                RDebug::Print(_L(">> CHuiCanvasWsPainter::HandleBufferL - Clearing fullupdateregion"));    
+                #endif
+                // Clear the window update region area
+                TBool doClear = ETrue;
+                iCanvasWsGc->EnableUpdateRegion(iFullUpdateRegion, doClear);
+                iCanvasWsGc->DisableUpdateRegion(); 
+                isFullUpdateRegionCleared = ETrue;
+                
+                // Cause a full redraw for the canvas visual
+                SetAllBuffersChanged(ETrue);    
+                ClearAllBufferStatusFlags(EHuiCanvasBufferStatusDrawn);
+                iShapeRegionClearingPending = EFalse;
+                }
+            
+            
+            /* Check if we have buffers that are not yet been drawn (or we render buffer is disabled) */
+            TBool cachePrepared = !HasCommandBuffersWithoutFlags(EHuiCanvasBufferStatusDrawn) || !iCanvasWsGc->IsRenderBufferEnabled();
+
+            /* Begin draw. If render buffer is used this sets up the render buffer if needed */
+            iCanvasWsGc->BeginActionL(aAction,aDisplayRect,aUser,cachePrepared,iFullUpdateRegion);                   
+
+            #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+            if (iCanvasWsGc->IsRenderBufferEnabled())
+                {
+                RDebug::Print(_L(">> CHuiCanvasWsPainter::HandleBufferL renderbuffer is ENABLED"));
+                }
+            else
+                {
+                RDebug::Print(_L(">> CHuiCanvasWsPainter::HandleBufferL renderbuffer is DISABLED"));
+                }
+            #endif
+            
+            /* We do not ignore unchanged buffers currently */
+            TBool ignoreUnChangedBuffers = EFalse; 
+
+            /* We can ignore buffers that only update areas which get clipped */
+            TBool ignoreClippedBuffers = ETrue;            
+            if (relativeOrientation != CHuiGc::EOrientationNormal)
+                {
+                ignoreClippedBuffers = EFalse;
+                }
+            
+            /* We can ignore buffers that has previously already been drawn into render buffer */
+            TBool ignoreHandledBuffers = iCanvasWsGc->IsRenderBufferEnabled() && iCanvasWsGc->IsRenderBufferInitialized();                    
+
+            
+            /* 
+             * We need to clear area if render buffer is used because otherwise it will cause dimming for semitransparent areas.
+             * 
+             * NOTE1: We do not clear if the window is opaque. This is a bit questionable, but Avkon seems to rely
+             * quite much on luck with its drawing and there are areas in the windows which are not always covered
+             * by drawing commands, thus random garabage from previous frames would be visible if such window
+             * update area would always be cleared.
+             * 
+             * NOTE2: We handle window that has background clearing enabled similarly as transparent window
+             *        because their wanted behaviour is similar to transparent window (user wants to see the stuff
+             *        behind window drawing commands and may want to draw commands translucently). 
+             *        
+             * -> So always clear if drawing vie render buffer and window is transparent or has backround.       
+             *        
+             */            
+            TBool clearBeforeHandlingBuffer = iCanvasWsGc->IsRenderBufferEnabled() 
+                && (!(aUser.Flags() & EHuiVisualFlagOpaqueHint) || aUser.IsBackgroundDrawingEnabled())
+                && !isFullUpdateRegionCleared;
+                        
+            // TODO: Should avoid trap, but EndActionL must always be called
+            TRAPD(err, DoHandleAllBuffersL( aDisplayRect, aAction, aUser, aGc, aPos, 
+                    ignoreUnChangedBuffers, 
+                    ignoreClippedBuffers,
+                    ignoreHandledBuffers,
+                    clearBeforeHandlingBuffer));
+            
+            if (err != KErrNone)
+                {
+                RDebug::Print(_L("CHuiCanvasWsPainter::HandleBufferL(): draw error = %i "), err);
+                RenewAllBuffers();
+                }
+            
+            // Workaround for fact that WSERV sends command buffers that do not contain real drawing commands.
+            // If there are no real drawing commnads, just avoid display update at the EndAction so that
+            // we don't write empty pixels to screen and cause flicker. 
+            TBool updateDisplay = HasCommandBuffers(EHuiCanvasBufferContainsDrawing);
+            
+            /* End draw. If render buffer is in use, this will update the screen */
+            iCanvasWsGc->EndActionL(iFullUpdateRegion, updateDisplay);                 
+            
+            /* Mark that cache is not more clear */
+            iCacheCleared = EFalse;
+            }
+        else if (aAction == EScanBuffer)
+            {
+            /* Check and enable render buffer if needed */
+            EnableRenderBufferIfNeeded(ETrue);
+            
+            /* Check if we have buffers that are not yet prepared (or we render buffer is disabled) */
+            TBool cachePrepared = !HasCommandBuffersWithoutFlags(EHuiCanvasBufferStatusScanned) || !iCanvasWsGc->IsRenderBufferEnabled();
+
+            /* Begin scan. If render buffer is used this sets up the render buffer if needed */
+            iCanvasWsGc->BeginActionL(aAction,aDisplayRect,aUser,cachePrepared,iFullUpdateRegion);    
+
+            #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+            if (iCanvasWsGc->IsRenderBufferEnabled())
+                {
+                RDebug::Print(_L(">> CHuiCanvasWsPainter::HandleBufferL renderbuffer is ENABLED"));
+                }
+            else
+                {
+                RDebug::Print(_L(">> CHuiCanvasWsPainter::HandleBufferL renderbuffer is DISABLED"));
+                }
+            #endif
+            
+            /* We do not ignore unchanged buffers currently */
+            TBool ignoreUnChangedBuffers = EFalse;
+            
+            /* We do not ignore clipped buffers as they possibly contain items that may soon appear on the screen */
+            TBool ignoreClippedBuffers = EFalse;                    
+            
+            /* We can ignore buffers that has previously already been scanned */
+            TBool ignoreHandledBuffers = ETrue;     
+
+            /* No need to clear area if scanning */
+            TBool clearBeforeHandlingBuffer = EFalse;
+            
+            // TODO: Should avoid trap, but EndActionL must always be called
+            TRAPD(err, DoHandleAllBuffersL( aDisplayRect, aAction, aUser, aGc, aPos, 
+                    ignoreUnChangedBuffers, 
+                    ignoreClippedBuffers,
+                    ignoreHandledBuffers,
+                    clearBeforeHandlingBuffer));    
+            
+            if (err != KErrNone)
+                {
+                RDebug::Print(_L("CHuiCanvasWsPainter::HandleBufferL(): scan error = %i "), err);
+                RenewAllBuffers();
+                }
+            
+            /* End draw. If render buffer is in use, this will update the screen */
+            iCanvasWsGc->EndActionL(iFullUpdateRegion, EFalse);
+
+            /* Mark that cache is not more clear */
+            iCacheCleared = EFalse;
+            
+            /* Update dirty area to aDisplayRect in case this action is originated from dirty area scan */
+            aDisplayRect = DirtyRect();
+            }
+            
+                        
+#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+        TTime endTime;
+        endTime.UniversalTime();
+        TInt timeInMs =  endTime.MicroSecondsFrom( startTime ).Int64()/1000;           
+        RDebug::Print(_L(">> CHuiCanvasWsPainter::HandleBufferL took %i ms"), timeInMs);
+#endif
+        }
+        
+    }
+
+void CHuiCanvasWsPainter::DoHandleAllBuffersL( TRect& aDisplayRect, 
+                                               TInt aAction, 
+                                               const CHuiCanvasVisual& aUser, 
+                                               CHuiGc* aGc, 
+                                               TPoint& aPos, 
+                                               TBool aIgnoreUnChangedBuffers, 
+                                               TBool aIgnoreClippedBuffers, 
+                                               TBool aIgnoreHandledBuffers,
+                                               TBool aClearBeforeHandlingBuffers) 
+    {   
+    UpdateBufferUpdateRegions(aPos);
+
+    TInt bufferCount = iCommandBuffers.Count();
+    for (TInt cb = 0; cb < bufferCount; cb++)
+        {
+        CHuiCanvasCommandBuffer* cmdbuffer = iCommandBuffers[cb];
+
+        #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+        RDebug::Print(_L(">> CHuiCanvasWsPainter::DoHandleAllBuffersL Buffer size: %i "), iCommandBuffers[cb]->iCommands->Size());                
+        for (TInt k=0; k < cmdbuffer->iUpdateRegion.Count();k++)
+            {
+            RDebug::Print(_L(">> CHuiCanvasWsPainter::DoHandleAllBuffersL Buffer region rect: %i,%i, %i,%i "), 
+                cmdbuffer->iUpdateRegion[k].iTl.iX,
+                cmdbuffer->iUpdateRegion[k].iTl.iY,
+                cmdbuffer->iUpdateRegion[k].iBr.iX,
+                cmdbuffer->iUpdateRegion[k].iBr.iY);                
+            }
+        #endif
+
+        if (aIgnoreUnChangedBuffers && !cmdbuffer->iChanged)
+            {
+            #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+            RDebug::Print(_L(">> CHuiCanvasWsPainter::DoHandleAllBuffersL Skipping buffer, it has not changed"));                
+            #endif            
+            continue;            
+            }
+
+        if (aIgnoreHandledBuffers)
+            {
+            if (aAction == EDrawBuffer && (cmdbuffer->iStatusFlags & EHuiCanvasBufferStatusDrawn))
+                {
+                #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+                RDebug::Print(_L(">> CHuiCanvasWsPainter::DoHandleAllBuffersL Skipping buffer, it has already been drawn."));                
+                #endif                            
+                continue;
+                }
+            else if (aAction == EScanBuffer && (cmdbuffer->iStatusFlags & EHuiCanvasBufferStatusScanned))
+                {
+                #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+                RDebug::Print(_L(">> CHuiCanvasWsPainter::DoHandleAllBuffersL Skipping buffer, it has already been scanned."));                
+                #endif            
+                continue;            
+                }
+            else
+                {
+                // No, we dont ignore.                                
+                }
+            }
+            
+        if (aIgnoreClippedBuffers && IsBufferCompletelyOutisideClippingRegion(*cmdbuffer))
+            {
+            #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+            RDebug::Print(_L(">> CHuiCanvasWsPainter::DoHandleAllBuffersL: Skipping buffer %i, as it is completely clipped"), cb);
+            #endif                    
+            continue;
+            }
+              
+        if (aGc)
+            {
+            #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+            RDebug::Print(_L(">> CHuiCanvasWsPainter::DoHandleAllBuffersL ClipRegion before clipping to updateregion:"));                
+            const TRegion& originalclipregion = aGc->ClipRegion(); 
+            for (TInt k=0; k < originalclipregion.Count();k++)
+                {
+                
+                RDebug::Print(_L(">> CHuiCanvasWsPainter::DoHandleAllBuffersL original clip region rect: %i,%i, %i,%i "), 
+                        originalclipregion[k].iTl.iX,
+                        originalclipregion[k].iTl.iY,
+                        originalclipregion[k].iBr.iX,
+                        originalclipregion[k].iBr.iY);                
+                }
+            #endif
+
+            
+            // If buffers has been scanned, but it does not seem to contain any real drawing commands we discard it            
+            if (!(cmdbuffer->iStatusFlags & EHuiCanvasBufferContainsDrawing) && (cmdbuffer->iStatusFlags & EHuiCanvasBufferStatusScanned))
+                {
+                #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+                RDebug::Print(_L("CHuiCanvasWsPainter::DoHandleAllBuffersL: Hmmm, WSERV has sent buffer without real drawing commands."), cb);
+                #endif
+                continue;
+                }
+            
+            // Clip drawing to update area. This seems to improve performance although
+            // it may depend on used HW.
+            iCanvasWsGc->EnableUpdateRegion(iCommandBuffers[cb]->iUpdateRegion, aClearBeforeHandlingBuffers);
+
+            #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+            RDebug::Print(_L(">> CHuiCanvasWsPainter::DoHandleAllBuffersL ClipRegion after clipping to updateregion:"));                
+            const TRegion& clipregion = aGc->ClipRegion(); 
+            for (TInt k=0; k < originalclipregion.Count();k++)
+                {
+                
+                RDebug::Print(_L(">> CHuiCanvasWsPainter::DoHandleAllBuffersL current clip region rect: %i,%i, %i,%i "), 
+                        clipregion[k].iTl.iX,
+                        clipregion[k].iTl.iY,
+                        clipregion[k].iBr.iX,
+                        clipregion[k].iBr.iY);                
+                }
+            #endif
+            
+            TRAPD(error, DoHandleBufferL(cb, aDisplayRect, aAction, aUser, aGc, aPos ));
+            
+            if (error)
+                {
+                #ifdef _DEBUG
+                RDebug::Print(_L("CHuiCanvasWsPainter::DoHandleAllBuffersL: Error in buffer %i, continuing."), cb);
+                #endif
+                }
+            
+            iCanvasWsGc->DisableUpdateRegion();
+            }
+        else
+            {
+            DoHandleBufferL(cb, aDisplayRect, aAction, aUser, aGc, aPos);
+            }
+        
+        // Update buffer status
+        if (aAction == EDrawBuffer)
+            {
+            cmdbuffer->SetStatusFlags(EHuiCanvasBufferStatusDrawn);
+            }
+        else if (aAction == EScanBuffer)
+            {
+            cmdbuffer->SetStatusFlags(EHuiCanvasBufferStatusScanned);            
+            }
+        else
+            {
+            // This should not happen
+            }
+        }         
+    }
+
+
+void CHuiCanvasWsPainter::HandleBufferL(TRect& aDisplayRect, TInt aAction, const CHuiCanvasVisual& aUser, CHuiGc* aGc, TPoint aPos, TPtrC8 aCommands, CHuiCanvasCommandBuffer * /*buf*/)
+    {
+    TUint8 *ptr = const_cast<TUint8*>(aCommands.Ptr());
+    TInt length = aCommands.Length();
+    TPtr8 cmds(ptr, length, length);
+    CHuiCanvasCommandBuffer *buf = new (ELeave)CHuiCanvasCommandBuffer;
+    CleanupStack::PushL(buf);
+    buf->iUpdateRegion.AddRect(aDisplayRect);
+    if (iCanvasVisual && iCanvasVisual->Display())
+        {
+        buf->iOrientation = iCanvasVisual->Display()->Orientation();
+        }
+    DoHandleBufferStringL(-1, aDisplayRect, aAction, aUser, aGc, aPos, cmds, buf);
+    CleanupStack::PopAndDestroy();
+    }
+
+void CHuiCanvasWsPainter::DoPeekBufferL(TInt aIndex) 
+    {   
+    RMemReadStream& readerStream = iWsCommandBufferReader->Stream();
+    CHuiCanvasCommandBuffer& commandBuffer = *iCommandBuffers[aIndex];
+    HBufC8* cmdBuf = commandBuffer.iCommands;
+    TInt bufLength =  cmdBuf->Length();
+    
+    TPtr8 des = cmdBuf->Des();
+    iWsCommandBufferReader->Init( des, bufLength );
+    TInt offset = 0; 
+    TInt command = 0;
+    TBool donePeeking = EFalse;
+    do
+        {
+        command = readerStream.ReadUint8L();
+        
+        switch ( command )
+            {
+            case EAlfFrameContainsUnsupportedCommands:
+                {
+                TUint8 containsUnsupportedCommands = iWsCommandBufferReader->Stream().ReadUint8L();
+                if ( containsUnsupportedCommands )
+                    {
+                    commandBuffer.iContainsUnsupportedCommands = ETrue;
+                    }
+                break;
+                }
+            case EAlfFrameFlags:
+                {
+                TInt flags;
+                iWsCommandBufferReader->ReadInt32L( flags );
+                if (flags & EAlfTransparentContent)
+                    {
+                    EnableRenderBuffer(ETrue);
+                    }                
+                break;
+                }
+            case EAlfSetUpdateRegion: 
+                {
+                WsSetUpdateRegionL(aIndex);
+				commandBuffer.iPositionForUpdateRegion = Visual()->DisplayRect().iTl.Round();
+                break;
+                }
+            case EAlfCommandIndexArrayHeader:
+                {
+                TInt tmp;
+                iWsCommandBufferReader->ReadInt8L(); // padding
+                iWsCommandBufferReader->ReadInt32L( tmp );
+                iWsCommandBufferReader->ReadInt32L( tmp );
+                break;
+                }
+            case EAlfPacketPadding:
+                {
+                DoDigestPaddingL();
+				break;
+                }
+            case EAlfSetShapeRegion: 
+                {
+                WsSetShapeRegionL( aIndex );
+                break;
+                }
+            default:
+                {
+                donePeeking = ETrue;
+                break;    
+                }     
+            }
+        
+   		offset = readerStream.Source()->TellL( MStreamBuf::ERead ).Offset();
+       	
+        } while( offset < bufLength && !donePeeking);
+    
+    iCommandBuffers[aIndex]->iOriginalDisplayRect = iCanvasVisual->DisplayRect();
+    }
+
+
+#ifdef HUI_DEBUG_TRACK_DRAWING
+void CHuiCanvasWsPainter::DoHandleBufferL(TInt aIndex, TRect& aDisplayRect, TInt aAction, const CHuiCanvasVisual& aUser, CHuiGc* aGc, TPoint& aPos) 
+#else
+void CHuiCanvasWsPainter::DoHandleBufferL(TInt aIndex, TRect& aDisplayRect, TInt aAction, const CHuiCanvasVisual& aUser, CHuiGc* aGc, TPoint& aPos) 
+#endif
+    {
+    CHuiCanvasCommandBuffer* commandBuffer = iCommandBuffers[aIndex];
+    HBufC8* cmdBuf = commandBuffer->iCommands;
+
+#ifdef HUI_DEBUG_TRACK_DRAWING
+    if ( commandBuffer->iTrackedBuffer )
+        {
+        RDebug::Print( _L("CHuiCanvasWsPainter::DoHandleBufferL - Tracked buffer found"));
+        switch ( aAction )
+            {
+            case EDrawBuffer:
+                {
+                RDebug::Print( _L("CHuiCanvasWsPainter::DoHandleBufferL - draw buffer"));
+                break;
+                }
+            case EScanBuffer:
+                {
+                RDebug::Print( _L("CHuiCanvasWsPainter::DoHandleBufferL - scan buffer"));
+                break;
+                }
+            default:;
+            }
+        }
+
+    iCommandDebugger->StartFrame();
+    if ( commandBuffer->iProcessName )
+        {
+        // UNCOMMENT THIS IF YOU WANT TO PRINT EVERYTHING
+        // iCommandDebugger->SetPrint( ETrue );
+        // UNCOMMENT THIS IF YOU WANT PRINTS ONLY FOR CERTAIN PROCESS!
+        // DEFINE PROCESS NAME IN alfcommanddebug.cpp
+        // iCommandDebugger->SetPrint( iCommandDebugger->TrackProcess( commandBuffer->iProcessName ) );
+        RDebug::Print(_L("CHuiCanvasWsPainter::DoHandleBufferL - Process [%S]"), commandBuffer->iProcessName );
+        }
+    else
+        {
+//        RDebug::Print(_L("CHuiCanvasWsPainter::DoHandleBufferL - Process [already dead or not found]"));
+        }
+#endif
+  
+    TPtr8 des = cmdBuf->Des();
+    DoHandleBufferStringL(aIndex, aDisplayRect, aAction, aUser, aGc, aPos, des, commandBuffer);
+    }
+
+void CHuiCanvasWsPainter::DoHandleBufferStringL(TInt aIndex, TRect& /*aDisplayRect*/, TInt /*aAction*/, const CHuiCanvasVisual& /*aUser*/, CHuiGc* /*aGc*/, TPoint& aPos, TPtr8 aCmds, CHuiCanvasCommandBuffer *aCommandBuffer)
+    {
+    RMemReadStream& readerStream = iWsCommandBufferReader->Stream();    
+    TInt bufLength =  aCmds.Length();
+    TPtr8 des = aCmds;
+    CHuiCanvasCommandBuffer *commandBuffer = aCommandBuffer;
+    TPoint deltaPos = aPos - commandBuffer->iOriginalDisplayRect.iTl;
+    
+    iCanvasWsGc->SetPositionDelta( deltaPos );
+    iWsCommandBufferReader->Init( des, bufLength );
+    TInt offset = 0; 
+    TInt command = 0;
+    do
+        {
+        command = readerStream.ReadUint8L();
+#ifdef HUI_DEBUG_TRACK_DRAWING
+        iCommandDebugger->SetDescription( command );
+#endif
+
+		// Command cases are ordered approximately in the order so that most common ones are at first
+        switch ( command )
+            {
+            case EAlfFrameContainsUnsupportedCommands:
+                {
+                TUint8 containsUnsupportedCommands = iWsCommandBufferReader->Stream().ReadUint8L();
+                if (containsUnsupportedCommands )
+                    {
+                    // RDebug::Print(_L("Unsupported commands in this frame"));
+                    }
+                break;
+                }
+            case EAlfFrameFlags:
+                {
+                TInt flags;
+                iWsCommandBufferReader->ReadInt32L( flags );
+                if ( flags != 0 )
+                    {
+                    RDebug::Print(_L("FLAGS: %d"), flags );
+                    }
+                break;
+                }
+            case EAlfSetUpdateRegion: 
+                {
+                WsSetUpdateRegionL(aIndex);                    
+                break;
+                }               
+            case EAlfSetShapeRegion: 
+                {
+                iTempRegion.Clear();                
+                iWsCommandBufferReader->ReadRegionL( iTempRegion );
+                break;
+                }               
+            case EAlfSetBrushStyle:
+                {
+                WsSetBrushStyleL();                  
+                break;
+                }
+            case EAlfSetOrigin:
+                {
+                WsSetOriginL();
+                break;
+                }
+            case EAlfSetPenStyle:
+                {
+                WsSetPenStyleL();
+                break;
+                }
+            case EAlfSetClippingRegion:
+                {        
+                WsSetClippingRegionL();
+                break;
+                }
+            case EAlfResetClippingRegion:
+                {
+                WsResetClippingRegionL();
+                break;
+                }
+            case EAlfSetBrushColor:
+                {
+                WsSetBrushColorL();
+                break;
+                }
+            case EAlfBitBltMasked:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsBitBltMaskedL();
+                break;
+                }
+            case EAlfCombinedBitBlitMasked:
+				{
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+				WsCombinedBitBlitMaskedL();
+				break;
+				}
+            case EAlfReset:
+                {
+                WsResetL();
+                break;
+                }
+            case EAlfSetPenColor:
+                {
+                WsSetPenColorL();
+                break;
+                }
+            case EAlfBitBltRect:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsBitBltRectL();
+                break;
+                }
+            case EAlfSetDrawMode:
+                {
+                WsSetDrawModeL();
+                break;
+                }
+            case EAlfSetCharJustification:
+                {
+                WsSetCharJustificationL();
+                break;
+                }
+            case EAlfDrawBitmapMasked:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsDrawBitmapMaskedL();
+                break;
+                }
+            case EAlfSetUnderlineStyle:
+                {
+                WsSetUnderlineStyleL();
+                break;
+                }
+            case EAlfResetFont:
+                {
+                WsResetFontL();
+                break;
+                }
+            case EAlfSetStrikethroughStyle:
+                {
+                WsSetStrikethroughStyleL();
+                break;
+                }
+            case EAlfBitBlt:
+              	{
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+              	WsBitBltL();
+                break;
+              	}
+            case EAlfBitBltMaskedPoint:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsBitBltMaskedPointL();
+                break;
+                }
+            case EAlfClear:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsClearL();
+                break;
+                }
+            case EAlfClearRect:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsClearRectL();
+                break;
+                }
+            case EAlfResetBrushPattern:
+                {
+                WsResetBrushPatternL();
+                break;
+                }
+            case EAlfDrawText1:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsDrawText1L();
+                break;
+                }
+            case EAlfDrawText2:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsDrawText2L();
+                break;
+                }
+            case EAlfDrawText3:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsDrawText3L();
+                break;
+                }
+            case EAlfDrawText4:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsDrawText4L();
+                break;
+                }                
+            case EAlfDrawText5:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsDrawText5L();
+                break;
+                 }
+            case EAlfDrawArc:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsDrawArcL();
+                break;
+                }
+            case EAlfDrawPie:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsDrawPieL();                    
+                break;
+                }
+            case EAlfDrawBitmap1:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsDrawBitmap1L();                    
+                break;
+                }
+            case EAlfDrawBitmap2:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsDrawBitmap2L();
+                break;
+                }
+            case EAlfDrawBitmap3:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsDrawBitmap3L();
+                break;
+                }
+            case EAlfDrawRoundRect:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsDrawRoundRectL();
+                break;
+                }
+            case EAlfDrawPolyLine:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsDrawPolyLineL();
+                break;
+                }
+            case EAlfDrawPolyLineNoEndPoint:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsDrawPolyLineNoEndPointL();
+                break;
+                }
+            case EAlfDrawPolygon:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsDrawPolygonL();                                     
+                break;
+                }
+            case EAlfDrawEllipse:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsDrawEllipseL();
+                break;
+                }
+            case EAlfDrawLine:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsDrawLineL();
+                break;
+                }
+            case EAlfDrawLineTo:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsDrawLineToL();
+                break;
+                }
+            case EAlfDrawLineBy:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsDrawLineByL();
+                break;
+                }
+            case EAlfDrawRect:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsDrawRectL();
+                break;
+                }
+            case EAlfDrawTextVertical1:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsDrawTextVertical1L();
+                break;
+                }
+            case EAlfDrawTextVertical2:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsDrawTextVertical2L();
+                break;
+                }                
+            case EAlfDrawTextVertical3:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsDrawTextVertical3L();                          
+                break;
+                } 
+            case EAlfDrawTextVertical4: 
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsDrawTextVertical4L();
+                break;
+                }
+            case EAlfDrawTextVertical5:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsDrawTextVertical5L();
+                break;
+                }
+            case EAlfMoveTo:
+                {
+                WsMoveToL();
+                break;
+                }
+            case EAlfMoveBy:
+                {
+                WsMoveByL();
+                break;
+                }
+            case EAlfPlot:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsPlotL();
+                break;
+                }
+            case EAlfSetBrushOrigin:
+                {
+                WsSetBrushOriginL();
+                break;
+                }
+            case EAlfSetPenSize:
+                WsSetPenSizeL();                
+                break;
+            case EAlfSetTextShadowColor:
+                {
+                WsSetTextShadowColorL();
+                break;
+                }
+            case EAlfSetWordJustification:
+                {
+                WsSetWordJustificationL();
+                break;
+                }                
+            case EAlfSetBrushPattern:
+                {
+                WsSetBrushPatternL();
+                break;
+                }
+            case EAlfSetBrushPattern2:
+                {
+                WsSetBrushPatternL();
+                break;
+                }
+            case EAlfSetFont:
+                {
+                WsSetFontL();
+                break;
+                }
+            case EAlfContentTag:
+                {
+                WsContentTagL();
+                break;
+                }
+            case EAlfCopyRect:
+                WsCopyRectL();
+                break;
+            case EAlfUpdateJustification:
+                {
+                WsUpdateJustificationL();                  
+                break;
+                }
+            case EAlfUpdateJustificationVertical:
+                {
+                WsUpdateJustificationVerticalL();
+                break;
+                }
+            case EAlfSetFontNoDuplicate:
+                {
+                WsSetFontNoDuplicateL();
+                break;
+                }
+            case EAlfHasBrushPattern:
+            case EAlfHasFont:
+            case EAlfBrushColor:
+            case EAlfPenColor:
+            case EAlfTextShadowColor:
+                {
+                // these values are cached on client side, we dont do anything.
+                break;
+                }
+            case EAlfCopySettings:
+                {
+                WsCopySettingsL();                    
+                break;    
+                }
+            case EAlfSetClippingRect:
+                {
+                WsSetClippingRectL();
+                break;
+                }
+            case EAlfCancelClippingRect:
+                {
+                WsCancelClippingRectL();
+                break;
+                }
+            case EAlfSetFaded:
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsSetFadedL();
+                }
+                break;
+            case EAlfSetFadingParameters:
+                {
+                WsSetFadingParametersL();
+                break;
+                }
+            case EAlfFadeArea: 
+                {
+                commandBuffer->SetStatusFlags(EHuiCanvasBufferContainsDrawing);
+                WsFadeAreaL();
+                break;
+                }
+            case EAlfMapColors:
+                // MapColors is not supported. Client should never supply this command.
+                User::Leave( KErrNotSupported );
+                break;
+            case EAlfSetUserDisplayMode:
+                {
+                WsSetUserDisplayModeL();
+                break;
+                }
+            case EAlfUseFont:
+                {
+                WsUseFontL();                    
+                break;
+                }
+            case EAlfSendSyncDataBlock:
+                {
+                break;
+                }
+            case EAlfWindowInactivateWindow:
+                {
+                // Nothing to do
+                break;
+                }
+            case EAlfPacketPadding:
+                {
+                DoDigestPaddingL();
+				break;
+                }
+            case EAlfCommandIndexArrayHeader:
+                {
+                TInt tmp;
+                iWsCommandBufferReader->ReadInt8L(); // padding
+                iWsCommandBufferReader->ReadInt32L( tmp );
+                iWsCommandBufferReader->ReadInt32L( tmp );
+                break;
+                }
+            case EAlfCommandIndexArray:
+                {
+                TUint8 a = iWsCommandBufferReader->ReadInt8L();
+                iWsCommandBufferReader->ReadInt8L();
+                iWsCommandBufferReader->ReadInt8L();
+                TInt tmp;
+                TRect tmp2;
+                for(TUint8 i=0;i<a;i++)
+                    {
+                    iWsCommandBufferReader->ReadInt32L(tmp);
+                    iWsCommandBufferReader->ReadInt32L(tmp);
+                    iWsCommandBufferReader->ReadInt32L(tmp);
+                    iWsCommandBufferReader->ReadRectL(tmp2);
+                    }
+                break;
+                }
+              
+                
+            default:
+                {
+                // We should never ever get here
+                    HUI_DEBUG1(_L("CHuiCanvasVisual::HandleWsBufferL. Error: Unknown command=%d"), command);
+                break;
+                }
+            }// end switch
+    		offset = readerStream.Source()->TellL( MStreamBuf::ERead ).Offset();
+       	
+        } while( offset < bufLength );
+#ifdef HUI_DEBUG_TRACK_DRAWING
+    iCommandDebugger->EndFrame();
+#endif    
+    }
+    
+    
+void CHuiCanvasWsPainter::SetCommandSetL( const TDesC8& aCommands )
+    {
+	CHuiCanvasPainter::SetCommandSetL(aCommands);  
+
+    TInt latest = iCommandBuffers.Count() - 1;
+    DoPeekBufferL(latest);
+    SelectGcL();
+       
+    // If shape region has changed recalculate all update regions and remove redundant buffers
+    if (iShapeRegionClippingPending)
+        {
+        TInt bufferCount = iCommandBuffers.Count();
+        for (TInt cb = 0; cb < bufferCount; cb++)
+            {        
+            CHuiCanvasCommandBuffer* cmdbuffer = iCommandBuffers[cb];
+            cmdbuffer->iUpdateRegion.Copy(cmdbuffer->iOriginalUpdateRegion);                
+            cmdbuffer->iUpdateRegion.Intersect(iShapeRegion);
+            cmdbuffer->iUpdateRegion.Tidy();
+            }
+        iShapeRegionClippingPending = EFalse;       
+        RemoveRedundantBuffers();   
+        }    
+    
+	// Release currently cached images. 
+    // They may still be taken into use after next HandleBuffferL call.
+    if (iCanvasVisual)
+        {
+        iCanvasVisual->Env().CanvasTextureCache().ReleaseAllCachedEntries(*iCanvasVisual);         
+        }    
+    }
+    
+
+void CHuiCanvasWsPainter::ClearCommandSet()
+    {
+#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+        RDebug::Print(_L(">> CHuiCanvasWsPainter::ClearCommandSet this = %i"), this );
+        TTime startTime;
+        startTime.UniversalTime();
+#endif
+
+    CHuiCanvasPainter::ClearCommandSet();
+    // Release currently cached images. 
+    // They may still be taken into use after next HandleBuffferL call.
+    if (iCanvasVisual)
+        {
+        iCanvasVisual->Env().CanvasTextureCache().ReleaseAllCachedEntries(*iCanvasVisual); 
+        }
+
+#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+        TTime endTime;
+        endTime.UniversalTime();
+        TInt timeInMs =  endTime.MicroSecondsFrom( startTime ).Int64()/1000;           
+        RDebug::Print(_L(">> CHuiCanvasWsPainter::ClearCommandSet took %i ms"), timeInMs);
+#endif
+    
+    }
+
+struct TArrayHeader
+    {
+    TInt32 iOffset;
+    TInt32 iSize;
+    };
+
+void CHuiCanvasWsPainter::AddCommandSetL( const TDesC8& aMoreCommands )
+    {    
+#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+        RDebug::Print(_L(">> CHuiCanvasWsPainter::AddCommandSetL this = %i"), this );
+        TTime startTime;
+        startTime.UniversalTime();
+#endif
+
+    CHuiCanvasPainter::AddCommandSetL(aMoreCommands);
+    TInt latest = iCommandBuffers.Count() - 1;
+    DoPeekBufferL(latest);     
+    SelectGcL();
+    
+    // If shape region has changed recalculate all update regions
+    if (iShapeRegionClippingPending)
+        {
+        TInt bufferCount = iCommandBuffers.Count();
+        for (TInt cb = 0; cb < bufferCount; cb++)
+            {        
+            CHuiCanvasCommandBuffer* cmdbuffer = iCommandBuffers[cb];
+            cmdbuffer->iUpdateRegion.Copy(cmdbuffer->iOriginalUpdateRegion);                
+            cmdbuffer->iUpdateRegion.Intersect(iShapeRegion);
+            cmdbuffer->iUpdateRegion.Tidy();
+            }
+        iShapeRegionClippingPending = EFalse;       
+        }    
+    
+    RemoveRedundantBuffers();   
+    
+    // New command set may contain BitBlt commands
+    // and those cached images must be refreshed
+    if (iCanvasVisual)
+        {
+        // Release currently cached images. 
+        // They may still be taken into use after next HandleBufferL call.
+        iCanvasVisual->Env().CanvasTextureCache().ReleaseAllCachedEntries(*iCanvasVisual); 
+        }
+
+#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+        TTime endTime;
+        endTime.UniversalTime();
+        TInt timeInMs =  endTime.MicroSecondsFrom( startTime ).Int64()/1000;           
+        RDebug::Print(_L(">> CHuiCanvasWsPainter::AddCommandSetL took %i ms"), timeInMs);
+#endif
+
+#ifdef HUI_ENABLE_SUBWINDOW_FX        
+    TInt count = NumBuffers();
+    if (!count) return;
+    const TDesC8 &more = At(count-1)->iCommands->Des();
+    //RDebug::Print(_L("MoreCommands: %x : %d"), aMoreCommands.Ptr(), aMoreCommands.Length());
+    TPtrC8 header = more.Mid(4, sizeof(TArrayHeader)); // the magic comes from CAlfRsSendBuffer::WriteFollowingFrameOffsetL.
+    TArrayHeader *ptr = (TArrayHeader*)header.Ptr();
+    //RDebug::Print(_L("Ptr: %d : %d"), ptr->iOffset, ptr->iSize);
+    TPtrC8 indexTable = more.Mid(ptr->iOffset, ptr->iSize);
+
+    if (iCanvasVisual->Brushes() && iCanvasVisual)
+        {
+        ParseCmdBufferL(*iCanvasVisual->Brushes(), more, indexTable, CanvasGc(), *CanvasWsGc(), *iCanvasVisual, *this);
+        }
+#endif
+    
+#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+        TTime endTime2;
+        endTime2.UniversalTime();
+        TInt time2InMs =  endTime2.MicroSecondsFrom( startTime ).Int64()/1000;           
+        RDebug::Print(_L(">> CHuiCanvasWsPainter::AddCommandSetL including brush creation took %i ms"), time2InMs);
+#endif
+
+    }
+
+void CHuiCanvasWsPainter::AddPartialCommandSetL( const TDesC8& aMoreCommands, TBool aLastPart )
+    {
+    CHuiCanvasPainter::AddPartialCommandSetL(aMoreCommands,aLastPart); 
+    }
+
+#ifdef HUI_DEBUG_TRACK_DRAWING
+void CHuiCanvasWsPainter::SetTrackCommandSet( TFileName& aFileName, TBool aTrack )
+    {
+    CHuiCanvasPainter::SetTrackCommandSet( aFileName, aTrack );
+    }
+#endif
+
+void CHuiCanvasWsPainter::ClearCache()
+    {
+    if (iCanvasVisual && !iCacheCleared)
+        {
+#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+        RDebug::Print(_L(">> CHuiCanvasWsPainter::ClearCache this = %i"), this );
+        TTime startTime;
+        startTime.UniversalTime();
+#endif
+        TRAP_IGNORE(SelectGcL());
+        RenewAllBuffers();         
+        SetAllBuffersChanged(ETrue);
+        iCanvasWsGc->ClearCache();
+        iCanvasVisual->Env().CanvasTextureCache().ReleaseAllCachedEntries(*iCanvasVisual); 
+        iCacheCleared = ETrue;
+        
+#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+        TTime endTime;
+        endTime.UniversalTime();
+        TInt timeInMs =  endTime.MicroSecondsFrom( startTime ).Int64()/1000;           
+        RDebug::Print(_L(">> CHuiCanvasWsPainter::ClearCache took %i ms"), timeInMs);
+#endif
+
+        }
+    }
+
+
+void CHuiCanvasWsPainter::WsBitBltL()
+    {
+    TPoint point(0,0);
+    TInt bitmapHandle = 0;
+    iWsCommandBufferReader->ReadPointL( point );
+    iWsCommandBufferReader->ReadBitmapHandleL( bitmapHandle );
+   	iCanvasWsGc->WsBitBltL(bitmapHandle,point);         
+    }
+    
+void CHuiCanvasWsPainter::WsBitBltRectL()
+    {
+    iWsCommandBufferReader->ReadL( (TUint8*)&iStructBitBlitRect, sizeof( TStructBitBlitRect ) );
+    iCanvasWsGc->WsBitBltRectL( 
+            iStructBitBlitRect.iBitmapHandle,
+            iStructBitBlitRect.iPoint,
+            iStructBitBlitRect.iRect);
+    }
+    
+void CHuiCanvasWsPainter::WsBitBltMaskedL()
+    {
+    iWsCommandBufferReader->ReadL( (TUint8*)&iStructBitBlitMasked, sizeof( TStructBitBlitMasked ) );
+	iCanvasWsGc->WsBitBltMaskedL( 
+	        iStructBitBlitMasked.iBitmapHandle,
+	        iStructBitBlitMasked.iMaskHandle,
+	        iStructBitBlitMasked.iInvertMask,
+	        iStructBitBlitMasked.iPoint,
+	        iStructBitBlitMasked.iRect);         
+    }
+
+
+void  CHuiCanvasWsPainter::WsCombinedBitBlitMaskedL()
+	{
+	TRect clipRect(0,0,0,0);
+	TRect blitRect(0,0,0,0);
+	TInt itemCount = iWsCommandBufferReader->ReadInt8L();
+	iWsCommandBufferReader->ReadL( (TUint8*)&clipRect, sizeof( TRect ) );
+	iWsCommandBufferReader->ReadL( (TUint8*)&blitRect, sizeof( TRect ) );
+	    
+	TInt index(0);
+	
+	RArray<THuiCachedCombinedImageParams> combinedBlitItems;
+	THuiCachedCombinedImageParams combinedBlitItem;
+	while( index++ < itemCount )
+		{
+		iWsCommandBufferReader->ReadL( (TUint8*)&combinedBlitItem, sizeof( THuiCachedCombinedImageParams ) );
+		combinedBlitItems.Append(combinedBlitItem);
+		}
+	// clipping rects were optimized away by renderstage. it must be set now.
+	// We use SetClippingRegion instead of SetClippingRect as they handle ws origin differently.
+	iTempRegion.Clear();
+    iTempRegion.AddRect(clipRect);
+    iCanvasWsGc->WsSetClippingRegionL(iTempRegion);  
+	iCanvasWsGc->WsCombinedBitBltMaskedL(blitRect, combinedBlitItems);
+    iCanvasWsGc->WsResetClippingRegionL();  
+	combinedBlitItems.Close();
+	}
+
+void CHuiCanvasWsPainter::WsBitBltMaskedPointL()
+    { 
+    TPoint point1(0,0);
+    TPoint point2(0,0);
+    TRect rect(0,0,0,0);
+    TInt bitmapHandle = 0;
+    TInt maskHandle = 0;
+    iWsCommandBufferReader->ReadPointL( point1 );
+    iWsCommandBufferReader->ReadBitmapHandleL( bitmapHandle );
+    iWsCommandBufferReader->ReadRectL( rect );
+    iWsCommandBufferReader->ReadBitmapHandleL( maskHandle );
+    iWsCommandBufferReader->ReadPointL( point2 );
+    iCanvasWsGc->WsBitBltMaskedPointL(bitmapHandle,maskHandle,point1,point2,rect);
+    }
+    
+void CHuiCanvasWsPainter::WsResetClippingRegionL()
+    {    
+    iCanvasWsGc->WsResetClippingRegionL();
+    }
+    
+void CHuiCanvasWsPainter::WsClearL()
+    {
+   	iCanvasWsGc->WsClearL();
+    }
+
+void CHuiCanvasWsPainter::WsClearRectL()
+    {
+    TRect tmpRect1(0,0,0,0);
+    iWsCommandBufferReader->ReadRectL( tmpRect1 );
+	iCanvasWsGc->WsClearRectL(tmpRect1);
+    }
+
+void CHuiCanvasWsPainter::WsResetBrushPatternL()
+    {
+            
+    }
+
+void CHuiCanvasWsPainter::WsResetFontL()
+    {    
+    iCanvasWsGc->WsResetFontL();
+    }
+
+void CHuiCanvasWsPainter::WsDrawArcL()
+    {
+    TPoint point1(0,0);
+    TPoint point2(0,0);
+    TRect rect(0,0,0,0);
+    iWsCommandBufferReader->ReadRectL( rect );
+    iWsCommandBufferReader->ReadPointL( point1 );
+    iWsCommandBufferReader->ReadPointL( point2 );
+   	iCanvasWsGc->WsDrawArcL(point1,point2,rect);   
+    }
+
+void CHuiCanvasWsPainter::WsDrawPieL()
+    {
+    TPoint point1(0,0);
+    TPoint point2(0,0);
+    TRect rect(0,0,0,0);
+    iWsCommandBufferReader->ReadRectL( rect );
+    iWsCommandBufferReader->ReadPointL( point1 );
+    iWsCommandBufferReader->ReadPointL( point2 );
+    iCanvasWsGc->WsDrawPieL(point1,point2,rect);
+    }
+
+void CHuiCanvasWsPainter::WsDrawBitmap1L()
+    {
+    TRect rect(0,0,0,0);
+    TInt bitmapHandle = 0;
+    iWsCommandBufferReader->ReadRectL( rect );
+    iWsCommandBufferReader->ReadBitmapHandleL( bitmapHandle );
+    iCanvasWsGc->WsDrawBitmap1L(bitmapHandle,rect);
+    }
+
+void CHuiCanvasWsPainter::WsDrawBitmap2L()
+    {
+    TRect rect1(0,0,0,0);
+    TRect rect2(0,0,0,0);
+    TInt bitmapHandle = 0;
+    iWsCommandBufferReader->ReadRectL( rect1);
+    iWsCommandBufferReader->ReadBitmapHandleL( bitmapHandle );
+    iWsCommandBufferReader->ReadRectL( rect2);
+    iCanvasWsGc->WsDrawBitmap2L(bitmapHandle,rect1,rect2);
+    }
+
+void CHuiCanvasWsPainter::WsDrawBitmap3L()
+    {
+    TPoint point(0,0);
+    TInt bitmapHandle = 0;
+    iWsCommandBufferReader->ReadPointL( point );
+    iWsCommandBufferReader->ReadBitmapHandleL( bitmapHandle );   
+	iCanvasWsGc->WsDrawBitmap3L(bitmapHandle,point);
+    }
+
+void CHuiCanvasWsPainter::WsDrawBitmapMaskedL()
+    {
+    iWsCommandBufferReader->ReadL( (TUint8*)&iStructDrawBitmapMasked, sizeof( TStructDrawBitmapMasked ) );
+    iCanvasWsGc->WsDrawBitmapMaskedL(
+            iStructDrawBitmapMasked.iBitmapHandle,
+            iStructDrawBitmapMasked.iMaskHandle,
+            iStructDrawBitmapMasked.iInvertMask,
+            iStructDrawBitmapMasked.iRect1,
+            iStructDrawBitmapMasked.iRect2);
+    }
+
+void CHuiCanvasWsPainter::WsDrawRoundRectL()
+    {
+    TPoint point(0,0);
+    TRect rect(0,0,0,0);        
+    iWsCommandBufferReader->ReadRectL( rect );
+    iWsCommandBufferReader->ReadPointL( point );    
+    iCanvasWsGc->WsDrawRoundRectL(point,rect);    
+    }
+
+void CHuiCanvasWsPainter::WsDrawPolyLineL()
+    {
+    CArrayFix<TPoint>* pointerArray = NULL;    
+    iWsCommandBufferReader->ReadPointArrayL( pointerArray );    
+    iCanvasWsGc->WsDrawPolyLineL(pointerArray);    
+    delete pointerArray;
+    }
+
+void CHuiCanvasWsPainter::WsDrawPolyLineNoEndPointL()
+    {
+    TPoint* pointerArray = NULL;
+    TInt count = 0;
+    iWsCommandBufferReader->ReadPointArrayL( pointerArray, count );
+    iCanvasWsGc->WsDrawPolyLineNoEndPointL(pointerArray,count);
+    pointerArray = NULL;
+    }
+
+void CHuiCanvasWsPainter::WsDrawPolygonL()
+    {
+    CArrayFix<TPoint>* pointerArray;
+    TInt fillRule = 0;
+    iWsCommandBufferReader->ReadPointArrayL( pointerArray );
+    iWsCommandBufferReader->ReadInt8L(); // command
+    iWsCommandBufferReader->ReadInt32L( fillRule ); 
+    iCanvasWsGc->WsDrawPolygonL(pointerArray,fillRule);    
+    delete pointerArray;
+    }
+
+void CHuiCanvasWsPainter::WsDrawEllipseL()
+    {
+    TRect rect(0,0,0,0);                        
+    iWsCommandBufferReader->ReadRectL( rect );    
+    iCanvasWsGc->WsDrawEllipseL(rect);    
+    }
+
+void CHuiCanvasWsPainter::WsDrawLineL()
+    {
+    TPoint start(0,0);
+    TPoint end(0,0);
+    iWsCommandBufferReader->ReadPointL( start );
+    iWsCommandBufferReader->ReadPointL( end );   
+    iCanvasWsGc->WsDrawLineL(start,end);    
+    }
+
+void CHuiCanvasWsPainter::WsDrawLineToL()
+    {
+    TPoint point(0,0);
+    iWsCommandBufferReader->ReadPointL( point );    
+    iCanvasWsGc->WsDrawLineToL(point);    
+    }
+
+void CHuiCanvasWsPainter::WsDrawLineByL()
+    {
+    TPoint point(0,0);
+    iWsCommandBufferReader->ReadPointL( point );    
+    iCanvasWsGc->WsDrawLineByL(point);    
+    }
+
+void CHuiCanvasWsPainter::WsDrawRectL()
+    {
+    TRect rect(0,0,0,0);                        
+    iWsCommandBufferReader->ReadRectL( rect );
+
+	// There is a bug that CScreen::DisplayMode() returns non-alpha display mode (TSW error: ??)
+	// That is why WServ clears the window with the color that is opaque (0xFF000400) instead of transparent (0x00000000) 
+	#ifdef __ALF_SYMBIAN_RWINDOW_CLEARING_BUG_WORKAROUND__
+//	RDebug::Print(_L("HV: CHuiCanvasWsPainter::WsDrawRectL(). iTestBrushColor.Internal()=%x, iTestFullDisplayRect=(%d %d %d %d), rect=(%d %d %d %d) "),
+//		iTestBrushColor.Internal(), iTestFullDisplayRect.iTl.iX, iTestFullDisplayRect.iTl.iY,iTestFullDisplayRect.iBr.iX, iTestFullDisplayRect.iBr.iY, 
+//		rect.iTl.iX, rect.iTl.iY,rect.iBr.iX, rect.iBr.iY);
+	if ( (rect ==  iTestFullDisplayRect) &&  	// Is full screen rect?
+	     (iTestBrushColor.Internal() == 0xff000400))  	// Last set color is opaque dark green?
+		{
+	//	RDebug::Print(_L("HV: CHuiCanvasWsPainter::WsDrawRectL(). Change brush color to 0x00000000. "));
+		iCanvasWsGc->WsSetBrushColorL(TRgb(0,0,0,0)); // Replace brush color with transparent black          	  	                            	
+		}
+	#endif
+    
+    iCanvasWsGc->WsDrawRectL(rect);    
+    }
+
+void CHuiCanvasWsPainter::WsDrawText1L()
+    {
+    TPtr textValue(0,0);
+    TBool success = iWsCommandBufferReader->ReadTextL( textValue, iTextParametersGeneral );
+    
+    if (textValue.Length() == 0 || !success )
+        {
+        return;   
+        }
+    
+    iCanvasWsGc->WsDrawText1L(textValue,iTextParametersGeneral);    
+    }
+    
+void CHuiCanvasWsPainter::WsDrawText2L()
+    {
+    TPoint point(0,0);
+    TPtr textValue(0,0);
+    TBool success = iWsCommandBufferReader->ReadTextL( textValue, iTextParametersGeneral );
+    iWsCommandBufferReader->ReadPointL( point );
+    
+    if (textValue.Length() == 0 ||!success)
+        {
+        return;   
+        }
+	
+    iCanvasWsGc->WsDrawText2L(textValue,point,iTextParametersGeneral);    
+    }
+
+void CHuiCanvasWsPainter::WsDrawText3L()
+    {
+    TRect rect(0,0,0,0);
+    TPtr textValue(0,0);
+    TBool success = iWsCommandBufferReader->ReadTextL( textValue, iTextParametersGeneral );
+    iWsCommandBufferReader->ReadRectL( rect );
+
+    if (textValue.Length() == 0 || !success )
+        {
+        return;   
+        }
+	
+    iCanvasWsGc->WsDrawText3L(textValue,rect,iTextParametersGeneral);    
+    }
+
+void CHuiCanvasWsPainter::WsDrawText4L()
+    {
+    TPtr textValue(0,0);
+    TBool success = iWsCommandBufferReader->ReadTextL( textValue, iTextParametersGeneral );
+    iWsCommandBufferReader->ReadL( (TUint8*)&iStructDrawTextGeneral, sizeof( TStructDrawTextGeneral ) - sizeof(TInt) );
+    
+    if (textValue.Length() == 0 || !success )
+            {
+            return;   
+            }
+
+    iCanvasWsGc->WsDrawText4L(textValue,
+            iStructDrawTextGeneral.iRect,
+            iStructDrawTextGeneral.iValue1,  // textBaselineOffset
+            iStructDrawTextGeneral.iValue2, // textAlign
+            iStructDrawTextGeneral.iValue3, // textMargin,
+            iTextParametersGeneral);    
+    }
+
+void CHuiCanvasWsPainter::WsDrawText5L()
+    {
+    TPtr textValue(0,0);
+    TBool success = iWsCommandBufferReader->ReadTextL( textValue, iTextParametersGeneral );
+    iWsCommandBufferReader->ReadL( (TUint8*)&iStructDrawTextGeneral, sizeof( TStructDrawTextGeneral ) );
+    
+    if (textValue.Length() == 0 || !success )
+        {
+        return;   
+        }
+
+	iCanvasWsGc->WsDrawText5L(textValue,
+	        iStructDrawTextGeneral.iRect,
+	        iStructDrawTextGeneral.iValue1,  // textBaselineOffset
+	        iStructDrawTextGeneral.iValue3, // textAlign
+	        iStructDrawTextGeneral.iValue4, // textMargin,
+	        iStructDrawTextGeneral.iValue2, // textWidth
+	        iTextParametersGeneral);    
+    }
+
+void CHuiCanvasWsPainter::WsDrawTextVertical1L()
+    {
+    TInt textUp = 0;
+    TPtr textValue(0,0);
+    TBool success = iWsCommandBufferReader->ReadTextL( textValue, iTextParametersGeneral );
+    iWsCommandBufferReader->ReadInt32L( textUp );  
+    
+    if (textValue.Length() == 0 || !success )
+        {
+        return;   
+        }
+
+	iCanvasWsGc->WsDrawTextVertical1L(textValue,textUp,iTextParametersGeneral);    
+    }
+
+void CHuiCanvasWsPainter::WsDrawTextVertical2L()
+    {
+    TPoint point(0,0);
+    TInt textUp = 0;
+    TPtr textValue(0,0);
+    TBool success = iWsCommandBufferReader->ReadTextL( textValue, iTextParametersGeneral );
+    iWsCommandBufferReader->ReadPointL( point );
+    iWsCommandBufferReader->ReadInt32L( textUp );  
+
+    if (textValue.Length() == 0 || !success )
+            {
+            return;   
+            }
+        
+	iCanvasWsGc->WsDrawTextVertical2L(textValue,textUp,point,iTextParametersGeneral);    
+    }
+
+
+void CHuiCanvasWsPainter::WsDrawTextVertical3L()
+    {
+    TRect rect(0,0,0,0);
+    TInt textUp = 0;
+    TPtr textValue(0,0);
+    TBool success = iWsCommandBufferReader->ReadTextL( textValue, iTextParametersGeneral);
+    iWsCommandBufferReader->ReadRectL( rect );
+    iWsCommandBufferReader->ReadInt32L( textUp ); 
+
+    if (textValue.Length() == 0 || !success )
+            {
+            return;   
+            }
+    
+    iCanvasWsGc->WsDrawTextVertical3L(textValue,textUp,rect,iTextParametersGeneral);    
+    }
+
+void CHuiCanvasWsPainter::WsDrawTextVertical4L()
+    {
+    TRect rect(0,0,0,0);
+    TInt textBaselineOffset = 0;
+    TInt textUp = 0;
+    TInt textAlign = 0;
+    TInt textMargin = 0;
+    TPtr textValue(0,0);
+    
+    TBool success = iWsCommandBufferReader->ReadTextL( textValue, iTextParametersGeneral );
+    iWsCommandBufferReader->ReadRectL( rect );
+    iWsCommandBufferReader->ReadInt32L( textBaselineOffset );
+    iWsCommandBufferReader->ReadInt32L( textUp );
+    iWsCommandBufferReader->ReadInt32L( textAlign );
+    iWsCommandBufferReader->ReadInt32L( textMargin );
+
+    if (textValue.Length() == 0 || !success )
+            {
+            return;   
+            }
+
+    iCanvasWsGc->WsDrawTextVertical4L(textValue,rect,textBaselineOffset,textUp,textAlign,textMargin,iTextParametersGeneral);    
+    }
+
+void CHuiCanvasWsPainter::WsDrawTextVertical5L()
+    {
+    TRect rect(0,0,0,0);
+    TInt textBaselineOffset = 0;
+    TInt textWidth = 0;
+    TInt textUp = 0;
+    TInt textAlign = 0;
+    TInt textMargin = 0;
+    TPtr textValue(0,0);
+    
+    iWsCommandBufferReader->ReadTextL( textValue, iTextParametersGeneral );
+    iWsCommandBufferReader->ReadRectL( rect );
+    iWsCommandBufferReader->ReadInt32L( textBaselineOffset );
+    iWsCommandBufferReader->ReadInt32L( textWidth );
+    iWsCommandBufferReader->ReadInt32L( textUp );
+    iWsCommandBufferReader->ReadInt32L( textAlign );
+    iWsCommandBufferReader->ReadInt32L( textMargin );
+
+    if (textValue.Length() == 0)
+            {
+            return;   
+            }
+
+    iCanvasWsGc->WsDrawTextVertical5L(textValue,rect,textBaselineOffset,textUp,textAlign,textMargin,textWidth,iTextParametersGeneral);    
+    }
+
+void CHuiCanvasWsPainter::WsMoveToL()
+    {
+    TPoint point(0,0);        
+    iWsCommandBufferReader->ReadPointL( point );
+    iCanvasWsGc->WsMoveToL(point);
+    }
+
+void CHuiCanvasWsPainter::WsMoveByL()
+    {
+    TPoint point(0,0);        
+    iWsCommandBufferReader->ReadPointL( point );    
+    iCanvasWsGc->WsMoveByL(point);
+    }
+
+void CHuiCanvasWsPainter::WsPlotL()
+    {
+    TPoint point(0,0);        
+    iWsCommandBufferReader->ReadPointL( point );    
+    iCanvasWsGc->WsPlotL(point);               	  	                        
+    }
+
+void CHuiCanvasWsPainter::WsResetL()
+    {
+    iCanvasWsGc->WsResetL();               	  	                            
+
+	#ifdef __ALF_SYMBIAN_RWINDOW_CLEARING_BUG_WORKAROUND__
+	iTestBrushColor.SetInternal(0);
+	#endif	
+    }
+
+void CHuiCanvasWsPainter::WsSetBrushColorL()
+    {
+    TRgb color = 0;        
+    iWsCommandBufferReader->ReadColorL( color );
+	iCanvasWsGc->WsSetBrushColorL(color);           	  	                            
+
+	#ifdef __ALF_SYMBIAN_RWINDOW_CLEARING_BUG_WORKAROUND__
+	iTestBrushColor = color;    	  	                            	
+	#endif
+    }
+
+void CHuiCanvasWsPainter::WsSetBrushOriginL()
+    {
+    TPoint point(0,0);        
+    iWsCommandBufferReader->ReadPointL( point );
+	iCanvasWsGc->WsSetBrushOriginL(point);	
+    }
+
+void CHuiCanvasWsPainter::WsSetBrushStyleL()
+    {
+    TInt style = 0;
+    iWsCommandBufferReader->ReadInt32L( style );
+	iCanvasWsGc->WsSetBrushStyleL(style);        
+    }
+
+void CHuiCanvasWsPainter::WsSetClippingRegionL()
+    {
+    iTempRegion.Clear();
+    iWsCommandBufferReader->ReadRegionL( iTempRegion );
+    iCanvasWsGc->WsSetClippingRegionL(iTempRegion);
+    }
+
+void CHuiCanvasWsPainter::WsSetDrawModeL()
+    {
+    TInt drawMode = 0;    
+    iWsCommandBufferReader->ReadInt32L( drawMode );
+	iCanvasWsGc->WsSetDrawModeL(drawMode);
+    }
+
+void CHuiCanvasWsPainter::WsSetOriginL()
+    {
+    TPoint origin(0,0);        
+    iWsCommandBufferReader->ReadPointL(origin);
+   	iCanvasWsGc->WsSetOriginL(origin);
+    }
+
+void CHuiCanvasWsPainter::WsSetPenColorL()
+    {
+    TRgb color = 0;        
+    iWsCommandBufferReader->ReadColorL( color );
+	iCanvasWsGc->WsSetPenColorL(color);    
+    }
+
+void CHuiCanvasWsPainter::WsSetPenStyleL()
+    {
+    TInt style = 0;    
+    iWsCommandBufferReader->ReadInt32L( style );
+	iCanvasWsGc->WsSetPenStyleL(style);
+    }
+
+void CHuiCanvasWsPainter::WsSetPenSizeL()
+    {
+    TInt width = 0;    
+    TInt height = 0;    
+    iWsCommandBufferReader->ReadInt32L( width ); 
+    iWsCommandBufferReader->ReadInt32L( height ); 
+    iCanvasWsGc->WsSetPenSizeL(width,height);
+    //\todo: Separate pen width and height are not yet supported 	
+    }
+
+void CHuiCanvasWsPainter::WsSetTextShadowColorL()
+    {
+    TRgb color = 0;        
+    iWsCommandBufferReader->ReadColorL( color );
+    iCanvasWsGc->WsSetTextShadowColorL(color);
+    }
+
+void CHuiCanvasWsPainter::WsSetCharJustificationL()
+    {
+    TInt excessWidth = 0;
+    TInt numGaps = 0;
+    iWsCommandBufferReader->ReadInt32L( excessWidth );
+    iWsCommandBufferReader->ReadInt32L( numGaps ); // NumChars
+	iCanvasWsGc->WsSetCharJustificationL(excessWidth,numGaps);
+    }
+
+void CHuiCanvasWsPainter::WsSetWordJustificationL()
+    {
+    TInt excessWidth = 0;
+    TInt numGaps = 0;
+    iWsCommandBufferReader->ReadInt32L( excessWidth );
+    iWsCommandBufferReader->ReadInt32L( numGaps ); // NumChars
+	iCanvasWsGc->WsSetWordJustificationL(excessWidth,numGaps);        
+    }
+
+void CHuiCanvasWsPainter::WsSetUnderlineStyleL()
+    {
+    TInt value = 0;
+    iWsCommandBufferReader->ReadInt32L( value );
+    iCanvasWsGc->WsSetUnderlineStyleL(value);
+    }
+
+void CHuiCanvasWsPainter::WsSetStrikethroughStyleL()
+    {
+    TInt value = 0;
+    iWsCommandBufferReader->ReadInt32L( value );
+    // todo: is this magic 1000 safe offset?
+    iCanvasWsGc->WsSetUnderlineStyleL(value+1000);
+    }
+
+
+void CHuiCanvasWsPainter::WsSetBrushPatternL()
+    {
+    TInt value = 0;        
+    iWsCommandBufferReader->ReadInt32L( value );
+	iCanvasWsGc->WsSetBrushPatternL(value);
+    }
+
+void CHuiCanvasWsPainter::WsSetFontL()
+    {
+    TInt fontId = 0;
+    iWsCommandBufferReader->ReadInt32L( fontId );// Font type Uid
+    iCanvasWsGc->WsSetFontL(fontId);    
+    }
+
+void CHuiCanvasWsPainter::WsContentTagL()
+    {
+    TInt tag;
+    iWsCommandBufferReader->ReadInt32L( tag );
+    }
+
+void CHuiCanvasWsPainter::WsCopyRectL()
+    {
+    TPoint point(0,0);
+    TRect rect(0,0,0,0);
+    iWsCommandBufferReader->ReadPointL( point );
+    iWsCommandBufferReader->ReadRectL( rect );
+	iCanvasWsGc->WsCopyRectL(point,rect);
+    }
+
+void CHuiCanvasWsPainter::WsUpdateJustificationL()
+    {
+    TPtr textValue(0,0);
+    iWsCommandBufferReader->ReadTextL( textValue, iTextParametersGeneral );	
+	iCanvasWsGc->WsUpdateJustificationL(textValue);
+    }
+
+void CHuiCanvasWsPainter::WsUpdateJustificationVerticalL()
+    {
+    TPtr textValue(0,0);
+    TInt value = 0;
+
+    iWsCommandBufferReader->ReadTextL( textValue, iTextParametersGeneral );
+    iWsCommandBufferReader->ReadInt32L( value );
+	iCanvasWsGc->WsUpdateJustificationVerticalL(value,textValue);
+   }
+
+void CHuiCanvasWsPainter::WsSetFontNoDuplicateL()
+    {
+    TInt tempFont = 0;
+    iWsCommandBufferReader->ReadInt32L( tempFont );
+	iCanvasWsGc->WsSetFontNoDuplicateL(tempFont);	    
+    }
+
+
+void CHuiCanvasWsPainter::WsCopySettingsL()
+    {
+    iCanvasWsGc->WsCopySettingsL();	
+    }
+
+void CHuiCanvasWsPainter::WsSetClippingRectL()
+    {
+    TRect rect(0,0,0,0);
+    iWsCommandBufferReader->ReadRectL( rect );
+	iCanvasWsGc->WsSetClippingRectL(rect);	                        
+    }
+
+void CHuiCanvasWsPainter::WsCancelClippingRectL()
+    {
+    iCanvasWsGc->WsCancelClippingRectL();
+    }
+
+void CHuiCanvasWsPainter::WsSetFadedL()
+    {
+    TInt faded = 0;
+    iWsCommandBufferReader->ReadInt32L( faded );
+	iCanvasWsGc->WsSetFadedL(faded);	                        
+    }
+
+void CHuiCanvasWsPainter::WsSetFadingParametersL()
+    {
+    TInt blackMap = 0;        
+    TInt whiteMap = 0;        
+    iWsCommandBufferReader->ReadInt32L( blackMap );
+    iWsCommandBufferReader->ReadInt32L( whiteMap );
+	iCanvasWsGc->WsSetFadingParametersL(blackMap,whiteMap);	                        
+    }
+
+void CHuiCanvasWsPainter::WsFadeAreaL()
+    {
+    iTempRegion.Clear();
+    iWsCommandBufferReader->ReadRegionL( iTempRegion );    
+	iCanvasWsGc->WsFadeAreaL(iTempRegion);	                        
+    }
+
+void CHuiCanvasWsPainter::WsMapColorsL()
+    {
+    iCanvasWsGc->WsMapColorsL();	                        
+    }
+
+void CHuiCanvasWsPainter::WsSetUserDisplayModeL()
+    {
+    TInt mode = 0;
+    iWsCommandBufferReader->ReadInt32L( mode );
+	iCanvasWsGc->WsSetUserDisplayModeL(mode);	                        
+        
+    }
+
+void CHuiCanvasWsPainter::WsUseFontL()
+    {
+	TInt tempFont = 0;
+    iWsCommandBufferReader->ReadInt32L( tempFont );
+    iCanvasWsGc->WsUseFontL(tempFont);	                                
+    }       
+
+void CHuiCanvasWsPainter::WsSetUpdateRegionL(TInt aIndex)
+    {
+    iTempRegion.Clear();                
+    iWsCommandBufferReader->ReadRegionL( iTempRegion );
+    if (aIndex==-1) return; //TP
+    // Update region is modified when new buffers are added after this buffer, 
+    // so store the region only at first read. 
+    if (iCommandBuffers[aIndex]->iChanged && iCommandBuffers[aIndex]->iUpdateRegion.Count() == 0)
+        {
+        // Check first that the coordiates are not insane (sometimes thay are)
+        TInt count = iTempRegion.Count();                    
+        TRect displayRect = iCanvasVisual->DisplayRect();
+        for (TInt i=count-1; i>=0; i--)
+            {
+            TRect rect = iTempRegion[i];
+            TRect screen = iCanvasVisual->Display()->VisibleArea();
+            if (rect.Intersects(screen) || rect == screen)
+                {
+                // - Sometimes updateregion is outiside window (WSERV...why?!) 
+                //   We clip it here to avoid ui probs.
+				// - Lets remove this for now, this seems to break scrollbars again
+				//   when window parent-child relations work..
+				// - Hmm, should we add this anyway because now the idle softkeys are lost again in landscape mode ?
+				// - Added again after WSERV fix in the window parent-child relations
+#ifndef HUI_DISABLE_CANVAS_VISUAL_CLIPPING
+                rect.Intersection(displayRect); 
+#endif                
+                iCommandBuffers[aIndex]->iUpdateRegion.AddRect(rect);    
+                iCommandBuffers[aIndex]->iOriginalUpdateRegion.AddRect(rect);    
+                }
+            else
+                {
+#ifdef _DEBUG
+                RDebug::Print(_L("CHuiCanvasWsPainter::WsSetUpdateRegionL: Incorrect update region removed from buffer, this should not happen !"));
+#endif
+                }
+            }                
+        
+        // Combine areas that are next to each others
+        iCommandBuffers[aIndex]->iUpdateRegion.Tidy();                    
+        iCommandBuffers[aIndex]->iOriginalUpdateRegion.Tidy();                    
+
+        // Subtract this buffers update area from previous buffers update areas to avoid overdraw
+
+ // TODO: Subtraction is for now commented out because it seems to cause UI problems, especially
+ //       with lists with scrollbar. Try e.g. opening image from filebrowser, then press back and
+ //       scrollbar area is often corrupted. This happens (probaply) because first command buffer contains
+ //       real background drawing under scrollbar, but partial command buffers do not contain it although 
+ //       their update region extends below scrollbar.
+ //       
+ //       This issue should be fixed because leaving subration undone causes performance to be worse.
+ //       
+        
+ /*
+        if (aIndex > 0)
+            {
+            for (TInt i=aIndex; i>0; i--)
+                {
+                TInt previous = aIndex - 1;
+                iCommandBuffers[previous]->iUpdateRegion.SubRegion(iCommandBuffers[aIndex]->iUpdateRegion);
+                iCommandBuffers[previous]->iUpdateRegion.Tidy();                            
+                }            
+            }
+*/            
+        }
+    }
+
+void CHuiCanvasWsPainter::WsSetShapeRegionL( TInt aIndex )
+    {
+    iTempRegion.Clear();                
+    iWsCommandBufferReader->ReadRegionL( iTempRegion );
+    
+	
+    // If there is a shape region, get it only from the newest buffer. 
+    // This is the case when the buffer has just been added to the canvas visual.
+    
+    if(aIndex == iCommandBuffers.Count() - 1)
+        {
+        // Note: The "set shape" command looks to be used only if it really is different from
+        // the window rect. So there is no need to check if the shape region is relevant. 
+        iShapeRegion.Copy(iTempRegion);
+
+        // note: iUpdateRegion will be updated later, set flags to indicate pending
+        iShapeRegionClearingPending = ETrue;
+        iShapeRegionClippingPending = ETrue;        
+       }
+    
+	
+    #ifdef _DEBUG
+    if (iShapeRegion.Count() == 0 && iTempRegion.Count() > 0)
+        {
+        HUI_DEBUG(_L("CHuiCanvasWsPainter::WsSetShapeRegionL. Error: iShapeRegion not set by any command buffer! However, there exists at least one command buffer that has shape region command."));
+         }
+    #endif
+    }
+
+void CHuiCanvasWsPainter::DoDigestPaddingL()
+    {
+    TUint8 padding = iWsCommandBufferReader->ReadInt8L();
+    while( padding-- )
+        {
+#ifdef _DEBUG
+        if ( iWsCommandBufferReader->ReadInt8L() != 0 )
+            {
+            RDebug::Print(_L("CHuiCanvasWsPainter::DigestPaddingL - Padding error"));
+            USER_INVARIANT();
+            }
+#else
+        iWsCommandBufferReader->ReadInt8L();
+#endif        
+        }
+    }
+
+void CHuiCanvasWsPainter::DestroyBuffer(TInt aIndex)
+    {
+    CHuiCanvasCommandBuffer* buffer = iCommandBuffers[aIndex];
+
+    TTime now;
+    now.UniversalTime();    
+    TInt lifetimeInMs =  now.MicroSecondsFrom( buffer->iCreationTime ).Int64()/1000;                               
+    if (lifetimeInMs > 0 && lifetimeInMs < KHuiCanvasDisableRenderBufferHandleInterval)
+        {
+        /* Check and disable render buffer if needed */
+        if (iCommandBuffers.Count() == 2)
+            {
+            EnableRenderBufferIfNeeded(EFalse);
+            }
+        }
+    
+    iCommandBuffers.Remove(aIndex);
+    delete buffer;
+    }
+
+
+TBool CHuiCanvasWsPainter::RemoveRedundantBuffers()
+    {
+    TBool didRemoveBuffers = EFalse;
+    TInt originalBufferCount = iCommandBuffers.Count();
+    
+    RemoveBuffersWithoutRealDrawing();
+    RemoveBuffersWithOldDisplayRect();
+    RemoveBuffersWithEmptyUpdateRegion();
+    RemoveBuffersWithOverlappingUpdateRegion();         
+    
+    didRemoveBuffers = (originalBufferCount != iCommandBuffers.Count());    
+    return didRemoveBuffers;
+    }
+
+void CHuiCanvasWsPainter::RemoveBuffersWithoutRealDrawing()
+    {
+    TInt bufferCount = iCommandBuffers.Count();
+    for (TInt cb = bufferCount - 1; cb >= 0; cb--)
+        {
+        CHuiCanvasCommandBuffer* buffer = iCommandBuffers[cb];
+        TInt flags = buffer->iStatusFlags;
+        if ((flags & EHuiCanvasBufferStatusScanned) && !(flags & EHuiCanvasBufferContainsDrawing))
+            {
+            DestroyBuffer(cb);
+            }
+        }        
+    }
+
+
+void CHuiCanvasWsPainter::RemoveBuffersWithOldDisplayRect() 
+    {
+    TInt bufferCount = iCommandBuffers.Count();
+    for (TInt cb = bufferCount - 1; cb >= 0; cb--)
+        {
+        CHuiCanvasCommandBuffer* buffer = iCommandBuffers[cb];
+        if (buffer->iOriginalDisplayRect.Round() != iCanvasVisual->DisplayRect().Round())
+            {
+            DestroyBuffer(cb);
+            }
+        }    
+    }
+
+void CHuiCanvasWsPainter::RemoveBuffersWithEmptyUpdateRegion() 
+    {
+    TInt bufferCount = iCommandBuffers.Count();
+    for (TInt cb = bufferCount - 1; cb >= 0; cb--)
+        {
+        CHuiCanvasCommandBuffer* buffer = iCommandBuffers[cb];
+        if (buffer->iOriginalUpdateRegion.Count() == 0)
+            {        
+            DestroyBuffer(cb);
+            }
+        }    
+    }
+
+void CHuiCanvasWsPainter::RemoveBuffersWithOverlappingUpdateRegion() 
+    {
+    // Check possibly overlapping update regions
+    TBool arraysChanged = ETrue;  
+    while (arraysChanged)
+        {
+        arraysChanged = EFalse;
+        iTempRegion.Clear();
+        
+        // Loop all buffers                
+        TInt bufferCount = iCommandBuffers.Count();        
+        for (TInt cb = bufferCount - 1; cb >= 0; cb--)
+            {            
+            if (arraysChanged)
+                {
+                break;    
+                }
+            
+            CHuiCanvasCommandBuffer* cmdbuffer = iCommandBuffers[cb];
+            for (TInt j=0; j < cmdbuffer->iOriginalUpdateRegion.Count();j++)
+                {
+                iTempRegion.AddRect(cmdbuffer->iOriginalUpdateRegion[j]);        
+                }
+                       
+            // Check older buffers for overlapping regions against current buffer
+            if (cb > 0)
+                {                   
+                for (TInt i = cb - 1; i >= 0; i--)
+                    {
+                    if (arraysChanged)
+                        {
+                        break;    
+                        }
+
+                    CHuiCanvasCommandBuffer* previousCommands = iCommandBuffers[i];            
+                    // Keep count how many subregions of the prevous command are contained inside current command buffer region
+                    TInt coveredRegionCount = 0;                    
+                    for (TInt k=0; k < previousCommands->iOriginalUpdateRegion.Count();k++)
+                        {
+                        iTempCurrentSubRegion.Clear();
+                        iTempIntersectingRegion.Clear();                                               
+                        iTempCurrentSubRegion.AddRect(previousCommands->iOriginalUpdateRegion[k]);                        
+                        iTempIntersectingRegion.Intersection(iTempRegion, iTempCurrentSubRegion);
+                        iTempIntersectingRegion.Tidy();
+                        
+                        if (iTempIntersectingRegion.Count() == 1)
+                            {
+                            if (iTempIntersectingRegion[0] == previousCommands->iOriginalUpdateRegion[k])
+                                {
+                                coveredRegionCount++;
+                                // If all regions were overlapping agains current buffer, we can delete this.
+                                if (coveredRegionCount == previousCommands->iOriginalUpdateRegion.Count())
+                                    {
+                                    DestroyBuffer(i);
+                                    arraysChanged = ETrue;
+                                    break;                                                                            
+                                    }
+                                }
+                            else
+                                {
+                                // There is no reason to continue with this one if even one of its subregions
+                                // is  outside overlapping region.
+                                break;                                    
+                                }
+                            }                        
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+CHuiCanvasGc& CHuiCanvasWsPainter::CanvasGc() const
+	{
+	return iCanvasWsGc->CanvasGc();
+	}
+
+TInt CHuiCanvasWsPainter::PaintedAreaCount() const
+    {
+    TInt paintedAreaCount = 0;
+    TInt bufferCount = iCommandBuffers.Count();
+    for (TInt cb = 0; cb < bufferCount; cb++)
+        {        
+        paintedAreaCount += iCommandBuffers[cb]->iUpdateRegion.Count();
+        }
+    return paintedAreaCount;
+    }
+    
+THuiCanvasPaintedArea CHuiCanvasWsPainter::PaintedArea(TInt aIndex)
+    {
+    THuiCanvasPaintedArea area;
+    area.iPaintType = EHuiCanvasPaintTypeOpaque;
+    area.iFlags = 0;    
+    
+    TInt firstIndexInCurrentBuffer = 0;
+    TInt lastIndexInCurrentBuffer = 0;
+    TInt indexCounter = 0;
+    
+    TInt bufferCount = iCommandBuffers.Count();
+    for (TInt cb = 0; cb < bufferCount; cb++)
+        {
+        TInt updateRegionCount = iCommandBuffers[cb]->iUpdateRegion.Count();
+        if (updateRegionCount)
+            {        
+            firstIndexInCurrentBuffer = indexCounter;
+            lastIndexInCurrentBuffer = firstIndexInCurrentBuffer + updateRegionCount - 1;
+            
+            if ((firstIndexInCurrentBuffer <= aIndex) && (aIndex <= lastIndexInCurrentBuffer))
+                {
+                TInt localIndex = aIndex - firstIndexInCurrentBuffer;
+                area.iPaintedRect = iCommandBuffers[cb]->iUpdateRegion[localIndex];
+                break;
+                }        
+            indexCounter += updateRegionCount;        
+            }
+       }   
+    return area;
+    }
+
+TInt CHuiCanvasWsPainter::SetCapturingBufferL(CFbsBitmap* aTarget)
+    {
+    TInt result = iCanvasWsGc->SetCapturingBufferL(aTarget);
+        
+    if ( !aTarget )
+        {
+        // We may have switched to another GC - so to ensure that 
+        // all are released, we will send this request to all.
+        CHuiCanvasWsGc* gcs[] = 
+            { 
+            iCanvasWsBitGc, 
+            iCanvasWsSwGc, 
+            iCanvasWsHwGc 
+            };
+        TInt count = sizeof(gcs) / sizeof(CHuiCanvasWsGc*);
+        for ( TInt i = count - 1; i >= 0; --i )
+            {
+            if ( gcs[i] && gcs[i] != iCanvasWsGc )
+                {
+                gcs[i]->SetCapturingBufferL(NULL);
+                }
+            }
+        }
+
+    return result;
+    }
+
+TRect CHuiCanvasWsPainter::DirtyRect() const
+    {
+    iTempRegion.Clear();                
+    TInt bufferCount = iCommandBuffers.Count();
+    for (TInt cb = 0; cb < bufferCount; cb++)
+        {        
+        const CHuiCanvasCommandBuffer& cmdbuffer = *iCommandBuffers[cb];
+        
+        // Report only changed buffers. This should be ok as long as
+        // this method is only used when scanning visual tree and
+        // thus visual (and buffer) changed flags are in correct states.
+        if (cmdbuffer.iChanged)
+            {
+            iTempRegion.Union(cmdbuffer.iUpdateRegion);
+            }
+        }
+    return iTempRegion.BoundingRect();
+    }
+
+TBool CHuiCanvasWsPainter::IsBufferCompletelyOutisideClippingRegion(const CHuiCanvasCommandBuffer& aCommandbuffer) const
+    {
+    CHuiGc* gc = iCanvasWsGc->CanvasGc().Gc();
+    if (gc && gc->ClipRegion().Count())
+        {
+        // This is a bit tricky part, gc clipregion is in transformed coordinates but our update region is not.
+        // So we must transform our update region before we can compare it to gc clipping region and
+        // know if it falls comletely outside it or not.        
+        iTempRegion.Clear();
+        for (TInt i=0; i<aCommandbuffer.iUpdateRegion.Count();i++)
+            {
+            THuiRealRect transformed = aCommandbuffer.iUpdateRegion[i];
+            gc->TransformDirtyRect(transformed);
+            iTempRegion.AddRect(transformed.Round());            
+            }
+        
+        CHuiCanvasGc::TClipRectVisibility visibility = iCanvasWsGc->CanvasGc().IsClipped(iTempRegion, gc->ClipRegion());
+        
+        if (visibility == CHuiCanvasGc::EFullyOutside)
+            {
+            return ETrue;
+            }
+        }
+
+    return EFalse;
+    }
+
+TInt CHuiCanvasWsPainter::EnableRenderBuffer(TBool aEnable)
+    {
+    if (aEnable != iCanvasWsGc->IsRenderBufferEnabled())
+        {
+        if (aEnable)
+            {
+            // Must redraw all buffers to render buffer at next frame
+            RenewAllBuffers();         
+            }        
+        return iCanvasWsGc->EnableRenderbuffer(aEnable);
+        }
+    else
+        {
+        return KErrNone;
+        }    
+    }
+
+void CHuiCanvasWsPainter::EnableRenderBufferIfNeeded(TBool aEnable)
+    {
+    if (!KHuiCanvasAutomaticRenderBufferUsage || !CHuiStatic::Renderer().Allows(EHuiRenderPluginAllowVisualPBufferSurfaces))
+        {
+        return;
+        }
+    
+    if (aEnable)
+        {
+        if (iAutomaticRenderBufferUsage && !iCanvasWsGc->IsRenderBufferEnabled() && HasOldCommandBuffers(KHuiCanvasEnableRenderBufferHandleInterval))
+            {
+            RDebug::Print(_L("CHuiCanvasWsPainter::EnableRenderBufferIfNeeded: Enabling renderbuffer"));
+            EnableRenderBuffer(ETrue);
+            iAutomaticRenderBufferUsage = ETrue;
+            }        
+        }
+    else
+        {
+        if (iCanvasWsGc->IsRenderBufferEnabled())
+            {
+            RDebug::Print(_L("CHuiCanvasWsPainter::EnableRenderBufferIfNeeded: Disabling renderbuffer"));
+            EnableRenderBuffer(EFalse);
+            iAutomaticRenderBufferUsage = ETrue;
+            }
+        }    
+    }
+
+void CHuiCanvasWsPainter::SelectGcL()
+    {
+    TBool hasUnsupportedCommands = EFalse;
+    TInt bufferCount = iCommandBuffers.Count();
+    for (TInt cb = 0; cb < bufferCount; cb++)
+        {        
+        const CHuiCanvasCommandBuffer& cmdbuffer = *iCommandBuffers[cb];
+        if (cmdbuffer.iContainsUnsupportedCommands)
+            {
+            hasUnsupportedCommands = ETrue;
+            break;
+            }
+        }
+        
+    THuiMemoryLevel memoryLevel;
+    if ( iCanvasVisual ) // in constructor, iCanvasVisual == NULL
+        {
+        memoryLevel = iCanvasVisual->Env().MemoryLevel();
+        }
+    else
+        {
+        memoryLevel = CHuiStatic::Env().MemoryLevel();
+        }
+
+    CHuiCanvasWsGc* oldGc = iCanvasWsGc;
+
+    if (memoryLevel <= EHuiMemoryLevelLowest)
+        {
+        if (!iCanvasWsGc || iCanvasWsGc != iCanvasWsBitGc)
+            {
+            // Fallback to the BIT GDI mode
+            if (!iCanvasWsBitGc)
+                {
+                iCanvasWsBitGc = CHuiCanvasWsBitGc::NewL();
+                }        
+            iCanvasWsGc = iCanvasWsBitGc;
+            // Must redraw all buffers to render buffer at next frame
+            RenewAllBuffers();             
+            }
+        }
+    else if (hasUnsupportedCommands && (!iCanvasWsGc || 
+             iCanvasWsGc != iCanvasWsSwGc))
+        {
+        // Fallback to the SW mode
+        if (!iCanvasWsSwGc)
+            {
+            iCanvasWsSwGc = CHuiCanvasWsSwGc::NewL();     
+            }        
+        iCanvasWsGc = iCanvasWsSwGc;
+        // Must redraw all buffers to render buffer at next frame
+        RenewAllBuffers();         
+        }
+    else if (!hasUnsupportedCommands && (!iCanvasWsGc || 
+             iCanvasWsGc != iCanvasWsHwGc))
+        {
+        // Return to the HW accelerated mode
+        if (!iCanvasWsHwGc)
+            {
+            iCanvasWsHwGc = CHuiCanvasWsHwGc::NewL();     
+            }                
+        iCanvasWsGc = iCanvasWsHwGc;
+        // Must redraw all buffers to render buffer at next frame
+        RenewAllBuffers();         
+        }
+    else
+        {
+        // We are good
+        }        
+        
+    // Clear caches of non-used GCs
+    if ( oldGc && oldGc != iCanvasWsGc )
+        {
+        oldGc->ClearCache();
+        }
+
+    #ifdef HUI_DEBUG_TRACK_DRAWING
+    CHuiCanvasWsGc* realGc = iCanvasWsGc;
+    iCanvasWsGc = CHuiCanvasDebugWsGc::NewL( realGc, *iCommandDebugger );
+    #endif
+    }
+
+void CHuiCanvasWsPainter::RenewAllBuffers()
+    {
+    ClearAllBufferStatusFlags(EHuiCanvasBufferStatusAll);
+    SetAllBufferStatusFlags(EHuiCanvasBufferStatusNew);                
+    
+    if (iCanvasVisual)
+        {
+        iCanvasVisual->SetChanged();
+        }    
+    }
+	
+void CHuiCanvasWsPainter::UpdateBufferUpdateRegions(TPoint aPos)
+	{
+	// iUpdateRegion is in screen coordinates. If visual moves position, iUpdateRegion 
+	// should be updated as well. Otherwise visual will encounter clipping.
+    for (TInt cb = 0; cb < iCommandBuffers.Count(); cb++)
+        {
+		if (iCommandBuffers[cb]->iPositionForUpdateRegion != aPos && !iCommandBuffers[cb]->iUpdateRegion.IsEmpty() )
+			{
+			TPoint deltaPos = aPos - iCommandBuffers[cb]->iPositionForUpdateRegion;
+			iCommandBuffers[cb]->iUpdateRegion.Offset(deltaPos);
+			iCommandBuffers[cb]->iPositionForUpdateRegion = aPos;
+			iCommandBuffers[cb]->ClearStatusFlags(EHuiCanvasBufferStatusAll);
+			iCommandBuffers[cb]->SetStatusFlags(EHuiCanvasBufferStatusNew);
+			}
+        }
+	}
+
+void CHuiCanvasWsPainter::SetMemoryLevel(THuiMemoryLevel /*aLevel*/)
+    {
+    TRAP_IGNORE(SelectGcL());
+    }
+