/*
* Copyright (c) 2008-2009 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 CHuiCanvasWsHwGc.
*
*/



#include "huicanvaswshwgc.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 "HuiRenderSurface.h"
#include "huicanvastexturecache.h"
#include "huicanvasbackground.h"
#include <graphics/wsgraphicscontext.h>
#include <e32cmn.h>
#include <AknLayoutFont.h>
#include <graphics/lookuptable.h>

//#define HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL

CHuiCanvasWsHwGc* CHuiCanvasWsHwGc::NewL()
	{
	CHuiCanvasWsHwGc* self    = new ( ELeave ) CHuiCanvasWsHwGc;
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop();

    return self;
    }

void CHuiCanvasWsHwGc::AdjustCoordinates(TPoint& aPoint, TBool aUseWsOrigin )
    {
    aPoint +=  iPosDelta;
    if ( aUseWsOrigin ) 
        {
        aPoint += iWsOrigin;
        }
    }

void CHuiCanvasWsHwGc::AdjustCoordinates(TRect& aRect, TBool aUseWsOrigin )
    {
    aRect.Move( iPosDelta );
    if ( aUseWsOrigin )
        {
        aRect.Move( iWsOrigin );
        }
    }

void CHuiCanvasWsHwGc::DrawTextBrush( THuiRealRect& aRect )
    {
    if( iWsBrushStyle == CGraphicsContext::ESolidBrush )
        {
        TRgb oldPenColor = iCanvasGc->PenColor();
        TReal32 oldOpacity = iCanvasGc->Opacity();
        THuiFillMode oldFillMode = iCanvasGc->PolygonDrawMode();
        
        iCanvasGc->SetPenColor(iWsBrushColor);
        iCanvasGc->SetOpacity(TReal32(iWsBrushColor.Alpha() / 255.f));   
        iCanvasGc->SetPolygonDrawMode(EHuiFillEvenOdd);
        
        RArray<THuiRealRect> rects;
        rects.Append(aRect);
        iCanvasGc->DrawRects(rects);
        rects.Close();
        
        iCanvasGc->SetPolygonDrawMode(oldFillMode);
        iCanvasGc->SetOpacity(oldOpacity);
        iCanvasGc->SetPenColor(oldPenColor);
        }
    }

CHuiCanvasWsHwGc::CHuiCanvasWsHwGc()
    {
    }

void CHuiCanvasWsHwGc::ConstructL()
	{
    iCanvasGc = CHuiStatic::Renderer().CreateCanvasGcL();
	
	// Set delayed clipping mode, this is supposed to reduce unnecessary
	// clipping which may cause bad performance on hw renderers 
	iCanvasGc->SetClippingMode(EHuiCanvasClipModeDelayed);
	WsResetL();
#ifdef __WINS__	
	iPushCount = 0;
#endif
	}

CHuiCanvasWsHwGc::~CHuiCanvasWsHwGc()
    {
    if (iVisual)
        {
        iVisual->Env().CanvasTextureCache().ReleaseCachedRenderBuffer(*iVisual);
        }
                
    iTempRegion.Close();
    iWsClipRegion.Close();
    delete iCanvasGc;
    iCanvasGc = NULL;
    }
    
void CHuiCanvasWsHwGc::WsBitBltL(TInt aBitmapHandle, TPoint aPoint)
	{
	THuiCachedImageParams cachedImageParams;
    cachedImageParams.iBitmapHandle = aBitmapHandle;
    cachedImageParams.iGcParams = CachedGcParams();

    if (IsRenderingEnabled())
        {           
        const CHuiCanvasGraphicImage* cachedImage = iVisual->Env().CanvasTextureCache().CreateCachedImageL(cachedImageParams,*iVisual);
        
        const CHuiTexture* texture = cachedImage->Texture();
        if (texture)
            {
            AdjustCoordinates( aPoint );
            THuiRealRect destinationRect = TRect(aPoint, texture->Size());          
    
            THuiCanvasDrawMode oldDrawMode = iCanvasGc->DrawMode();
            iCanvasGc->SetDrawMode(SelectCanvasDrawMode(iWsDrawMode));        
            // Draw            
            iCanvasGc->DrawImage(*texture, destinationRect, TRect(TPoint(0,0), texture->Size()), CHuiGc::EStretchNone);
            iCanvasGc->SetDrawMode(oldDrawMode);
            }
        }
    else
        {
        if ( IsCacheUpdateNeeded() )
            {
            iVisual->Env().CanvasTextureCache().CreateCachedImageL(cachedImageParams,*iVisual);
            }
        }
	}




void CHuiCanvasWsHwGc::WsBitBltRectL(TInt aBitmapHandle, TPoint aPoint, TRect aRect)
	{
	THuiCachedImageParams cachedImageParams;
    cachedImageParams.iBitmapHandle = aBitmapHandle;
    cachedImageParams.iGcParams = CachedGcParams();
     
    if (IsRenderingEnabled())
        {           
        const CHuiCanvasGraphicImage* cachedImage = iVisual->Env().CanvasTextureCache().CreateCachedImageL(cachedImageParams,*iVisual);
        
        const CHuiTexture* texture = cachedImage->Texture();
        if (texture)
            {
            AdjustCoordinates( aPoint );
            THuiRealRect destinationRect = TRect(aPoint, texture->Size());                

            THuiCanvasDrawMode oldDrawMode = iCanvasGc->DrawMode();
            iCanvasGc->SetDrawMode(SelectCanvasDrawMode(iWsDrawMode));        

            // Draw            
            iCanvasGc->DrawImage(*texture, destinationRect, aRect, CHuiGc::EStretchNone);
            iCanvasGc->SetDrawMode(oldDrawMode);
            }        
        }
	else
	    {
        if ( IsCacheUpdateNeeded() )
            {
            iVisual->Env().CanvasTextureCache().CreateCachedImageL(cachedImageParams,*iVisual);
            }	        
	    }
	}



void CHuiCanvasWsHwGc::WsBitBltMaskedL(TInt aBitmapHandle, TInt aMaskHandle, TInt aInvertMask, TPoint aPoint, TRect aRect)
	{
	THuiCachedImageParams cachedImageParams;
    cachedImageParams.iBitmapHandle = aBitmapHandle;
    cachedImageParams.iMaskHandle = aMaskHandle;
    cachedImageParams.iInvertedMask = aInvertMask;
    cachedImageParams.iGcParams = CachedGcParams();
     

    if (IsRenderingEnabled())
        {           
        const CHuiCanvasGraphicImage* cachedImage = iVisual->Env().CanvasTextureCache().CreateCachedImageL(cachedImageParams,*iVisual);
        
        const CHuiTexture* texture = cachedImage->Texture();
        if (texture)
            {
            AdjustCoordinates( aPoint );
            THuiRealRect destinationRect = TRect(aPoint, texture->Size());                
            
            // Draw            
            iCanvasGc->DrawImage(*texture, destinationRect, aRect, CHuiGc::EStretchNone);
            }
        }
	else
	    {
	    if (IsCacheUpdateNeeded())
	        {
	        iVisual->Env().CanvasTextureCache().CreateCachedImageL(cachedImageParams,*iVisual);
	        }
	    }
	}


void CHuiCanvasWsHwGc::WsCombinedBitBltMaskedL(TRect aDestinationRect, const RArray<THuiCachedCombinedImageParams>& aBlits )
	{
	THuiCachedCombinedImageParams cachedCombinedImageParams;	    
    THuiCachedGcParams gcParams = CachedGcParams();          
    TSize imageSize = aDestinationRect.Size();

    // Must convert points relative to the image itself
    RArray<THuiCachedCombinedImageParams> convertedBlits;   
    
    for (TInt i=0; i<aBlits.Count();i++)
        {
        THuiCachedCombinedImageParams convertedParams;
        convertedParams = aBlits[i];
        convertedParams.iCombinedBitmapPoint -= aDestinationRect.iTl;
        convertedBlits.Append(convertedParams);
        }       

    if (IsRenderingEnabled())
        {    
        const CHuiCanvasGraphicImage* cachedImage = iVisual->Env().CanvasTextureCache().CreateCombinedCachedImageL(
            convertedBlits, 
            gcParams,
            imageSize, 
            *iVisual);
       
        const CHuiTexture* texture = cachedImage->Texture();        
        if (texture)
            {
            TPoint point = aDestinationRect.iTl;
            AdjustCoordinates( point );
            
            THuiRealRect destinationRect = TRect(point, texture->Size());                        
    
            // Draw            
            iCanvasGc->DrawImage(*texture, destinationRect, TRect(TPoint(0,0), texture->Size()),  CHuiGc::EStretchNone);
            }
        }
    else
        {
        if (IsCacheUpdateNeeded())
            {
            iVisual->Env().CanvasTextureCache().CreateCombinedCachedImageL(
                convertedBlits, 
                gcParams,
                imageSize, 
                *iVisual);
            }
        }
	
	convertedBlits.Close();
	}


void CHuiCanvasWsHwGc::WsBitBltMaskedPointL(TInt aBitmapHandle, TInt aMaskHandle, TPoint aPoint1, TPoint aPoint2, TRect aRect)
	{
	THuiCachedImageParams cachedImageParams;
    cachedImageParams.iBitmapHandle = aBitmapHandle;
    cachedImageParams.iMaskHandle = aMaskHandle;
    cachedImageParams.iMaskOriginPoint = aPoint2;
    cachedImageParams.iGcParams = CachedGcParams();

    if (IsRenderingEnabled())
        {           
        const CHuiCanvasGraphicImage* cachedImage = iVisual->Env().CanvasTextureCache().CreateCachedImageL(cachedImageParams,*iVisual);
        
        const CHuiTexture* texture = cachedImage->Texture();
        if (texture)
            {
            AdjustCoordinates( aPoint1 );
            THuiRealRect destinationRect = TRect(aPoint1, texture->Size());                
            
            // Draw            
            iCanvasGc->DrawImage(*texture, destinationRect, aRect, CHuiGc::EStretchNone);
            }             
        }
    else
        {
        if (IsCacheUpdateNeeded())
            {
            iVisual->Env().CanvasTextureCache().CreateCachedImageL(cachedImageParams,*iVisual);
            }
        }
	}

void CHuiCanvasWsHwGc::WsResetClippingRegionL()
	{
    if (IsRenderingEnabled())
        {
        // Reset clip region
        iWsClipRegion.Clear();
        iCanvasGc->CancelClipping();
        }
	}

void CHuiCanvasWsHwGc::WsClearL()
	{		
    if (IsRenderingEnabled())
        {
        THuiRealRect rect(iVisual->DisplayRect());     
        DoWsClearRectL(rect);
        }
	}

void CHuiCanvasWsHwGc::WsClearRectL(TRect& aRect)
	{		
    if (IsRenderingEnabled())
        {
        AdjustCoordinates( aRect );
        DoWsClearRectL(aRect);
        }
	}


void CHuiCanvasWsHwGc::DoWsClearRectL(const THuiRealRect& aRect )
	{
    if (IsRenderingEnabled())
        {
        RArray<THuiRealRect> rects;
        rects.Append(aRect);
    
        // Store current gc params
        UseWsState();
        
        CHuiTexture* oldPolygonFillTexture = iCanvasGc->PolygonFillTexture(); 
        
        // Clear
        iCanvasGc->SetPolygonFillTexture(NULL);
        iCanvasGc->SetPolygonDrawMode(EHuiFillNonZero);
        iCanvasGc->SetPenWidth(1);           	  	        
        iCanvasGc->SetPenColor(iWsBrushColor);            
        iCanvasGc->SetOpacity(TReal32(iWsBrushColor.Alpha() / 255.f));   
        iCanvasGc->SetDrawMode(SelectCanvasDrawMode(iWsDrawMode));        
        iCanvasGc->DrawRects(rects);
    
        // Restore gc params etc.
        rects.Close();
        UseCanvasState();
        iCanvasGc->SetPolygonFillTexture(oldPolygonFillTexture);
        }
    }

void CHuiCanvasWsHwGc::WsResetBrushPatternL()
	{
	iWsBrushPattern = 0;
	}

void CHuiCanvasWsHwGc::WsResetFontL()
	{
    iWsCurrentFont = 0;
	}

void CHuiCanvasWsHwGc::WsDrawArcL(TPoint aPoint1, TPoint aPoint2, TRect aRect)
	{
	// If penstyle is ENullPen, then nothign is drawn
    if (!iWsPenStyle)
        {
        return;    
        }

    if (IsRenderingEnabled())
        {
        UseWsState();        

        AdjustCoordinates( aRect );
        AdjustCoordinates( aPoint1 );
        AdjustCoordinates( aPoint2 );

        iCanvasGc->DrawArc( THuiRealRect(aRect), THuiRealPoint(aPoint1), THuiRealPoint(aPoint2) );
        
        UseCanvasState();
        }
    }

void CHuiCanvasWsHwGc::WsDrawPieL(TPoint aPoint1, TPoint aPoint2, TRect aRect)
	{
	// If penstyle is ENullPen, then nothign is drawn
    if (!iWsPenStyle && !iWsBrushStyle)
        {
        return;    
        }

    if (IsRenderingEnabled())
        {    
        UseWsState();

        AdjustCoordinates( aRect );
        AdjustCoordinates( aPoint1 );
        AdjustCoordinates( aPoint2 );
            
        if (iWsBrushStyle == MWsGraphicsContext::ENullBrush)
            {
            iCanvasGc->SetPolygonDrawMode( EHuiNoFill );
            iCanvasGc->SetPenColor(iWsPenColor);            
            iCanvasGc->SetOpacity(TReal32(iWsPenColor.Alpha() / 255.f));       
            iCanvasGc->DrawPie(THuiRealRect(aRect),THuiRealPoint(aPoint1),THuiRealPoint(aPoint2));  
            }    
        else if (iWsBrushStyle == MWsGraphicsContext::ESolidBrush)
            {
            iCanvasGc->SetPolygonDrawMode( EHuiFillEvenOdd );
            iCanvasGc->SetPenColor(iWsBrushColor);            
            iCanvasGc->SetOpacity(TReal32(iWsBrushColor.Alpha() / 255.f));            
            iCanvasGc->DrawPie(THuiRealRect(aRect),THuiRealPoint(aPoint1),THuiRealPoint(aPoint2));  

            // Border should be drawn if pencolor is different than solid fill
            if (IsDifferent(iWsBrushColor, iWsPenColor, ETrue) && iWsPenStyle && iWsPenSize.iHeight >= 1 && iWsPenSize.iWidth >= 1)
                {
                iCanvasGc->SetPolygonDrawMode( EHuiNoFill );
                iCanvasGc->SetPenColor(iWsPenColor);                    
                iCanvasGc->SetOpacity(TReal32(iWsPenColor.Alpha() / 255.f));       
                iCanvasGc->DrawPie(THuiRealRect(aRect),THuiRealPoint(aPoint1),THuiRealPoint(aPoint2));  
                }            
            }
        else if (iWsBrushStyle == MWsGraphicsContext::EPatternedBrush)
            {
            iCanvasGc->SetPolygonDrawMode( EHuiFillEvenOdd );
            iCanvasGc->SetPenColor(iWsPenColor);                    
            iCanvasGc->SetOpacity(TReal32(iWsPenColor.Alpha() / 255.f));       
            UseBrushPattern();
            iCanvasGc->SetDrawMode(SelectCanvasDrawMode(iWsDrawMode));        
            iCanvasGc->DrawPie(THuiRealRect(aRect),THuiRealPoint(aPoint1),THuiRealPoint(aPoint2));  
            DiscardBrushPattern();

            if (iWsPenStyle && iWsPenSize.iHeight >= 1 && iWsPenSize.iWidth >= 1)
                {
                iCanvasGc->SetPolygonDrawMode( EHuiNoFill );
                iCanvasGc->SetPenColor(iWsPenColor);                    
                iCanvasGc->SetOpacity(TReal32(iWsPenColor.Alpha() / 255.f));       
                iCanvasGc->DrawPie(THuiRealRect(aRect),THuiRealPoint(aPoint1),THuiRealPoint(aPoint2));  
                }
            }
        else
            {
            // We should never get here because fallbackmode should be used in this case !
            RDebug::Print(_L("CHuiCanvasWsHwGc::WsDrawPieL - Unsupported brush mode %i"), iWsBrushStyle);
            }
                
        UseCanvasState();
        }
	}

void CHuiCanvasWsHwGc::WsDrawBitmap1L(TInt aBitmapHandle, TRect aRect)
	{
	THuiCachedImageParams cachedImageParams;
    cachedImageParams.iBitmapHandle = aBitmapHandle;
    cachedImageParams.iGcParams = CachedGcParams();

    if (IsRenderingEnabled())
        {           
        const CHuiCanvasGraphicImage* cachedImage = iVisual->Env().CanvasTextureCache().CreateCachedImageL(cachedImageParams,*iVisual);
        const CHuiTexture* texture = cachedImage->Texture();
        if (texture)
            {
            AdjustCoordinates( aRect );
            THuiRealRect destinationRect = aRect;                
            
            // Draw            
            // This should stretch !
            iCanvasGc->DrawImage(*texture, destinationRect, TRect(TPoint(0,0), texture->Size()), CHuiGc::EStretchFull); 
            }        	
        }
    else
        {
        if (IsCacheUpdateNeeded())
            {
            iVisual->Env().CanvasTextureCache().CreateCachedImageL(cachedImageParams,*iVisual);
            }
        }
	}

void CHuiCanvasWsHwGc::WsDrawBitmap2L(TInt aBitmapHandle, TRect aRect1, TRect aRect2)
	{
	THuiCachedImageParams cachedImageParams;
    cachedImageParams.iBitmapHandle = aBitmapHandle;
    cachedImageParams.iGcParams = CachedGcParams();

    if (IsRenderingEnabled())
        {           
        const CHuiCanvasGraphicImage* cachedImage = iVisual->Env().CanvasTextureCache().CreateCachedImageL(cachedImageParams,*iVisual);
        
        const CHuiTexture* texture = cachedImage->Texture();
        if (texture)
            {
            AdjustCoordinates( aRect1 );
            THuiRealRect destinationRect = aRect1;                
            
            // Draw            
            iCanvasGc->DrawImage(*texture, destinationRect, aRect2, CHuiGc::EStretchFull); 
            }        
        }
    else
        {
        if (IsCacheUpdateNeeded())
            {
            iVisual->Env().CanvasTextureCache().CreateCachedImageL(cachedImageParams,*iVisual);
            }
        }
	}

void CHuiCanvasWsHwGc::WsDrawBitmap3L(TInt aBitmapHandle, TPoint aPoint)
	{
	 THuiCachedImageParams cachedImageParams;
    cachedImageParams.iBitmapHandle = aBitmapHandle;
    cachedImageParams.iGcParams = CachedGcParams();

    if (IsRenderingEnabled())
        {           
        const CHuiCanvasGraphicImage* cachedImage = iVisual->Env().CanvasTextureCache().CreateCachedImageL(cachedImageParams,*iVisual);
        
        const CHuiTexture* texture = cachedImage->Texture();
        if (texture)
            {
            AdjustCoordinates( aPoint );
            THuiRealRect destinationRect = TRect(aPoint, texture->Size());                
       
            // Draw
            // TODO: Actually we should check the bitmap size in twips here are decide destinationRect based on that !            
            iCanvasGc->DrawImage(*texture, destinationRect, TRect(TPoint(0,0), texture->Size()), CHuiGc::EStretchNone);
            }        
        }
	else
	    {
	    if (IsCacheUpdateNeeded())
	        {
	        iVisual->Env().CanvasTextureCache().CreateCachedImageL(cachedImageParams,*iVisual);
	        }
	    }
	}

void CHuiCanvasWsHwGc::WsDrawBitmapMaskedL(TInt aBitmapHandle, TInt aMaskHandle, TInt aInvertMask, TRect& aRect1, TRect& aRect2)
	{
    THuiCachedImageParams cachedImageParams;
    cachedImageParams.iBitmapHandle = aBitmapHandle;
    cachedImageParams.iMaskHandle = aMaskHandle;
    cachedImageParams.iInvertedMask = aInvertMask;
    cachedImageParams.iGcParams = CachedGcParams();
        
    if (IsRenderingEnabled())
        {           
        const CHuiCanvasGraphicImage* cachedImage = iVisual->Env().CanvasTextureCache().CreateCachedImageL(cachedImageParams,*iVisual);
        
        const CHuiTexture* texture = cachedImage->Texture();
        if (texture)
            {
            AdjustCoordinates( aRect1 );
            THuiRealRect destinationRect = aRect1;              
    
            // Draw            
            iCanvasGc->DrawImage(*texture, destinationRect, aRect2, CHuiGc::EStretchFull);
            }        
        }
    else
        {
        if (IsCacheUpdateNeeded())
            {
            iVisual->Env().CanvasTextureCache().CreateCachedImageL(cachedImageParams,*iVisual);
            }
        }
	}

void CHuiCanvasWsHwGc::WsDrawRoundRectL(TPoint aPoint, TRect& aRect)
	{
	// If penstyle is ENullPen, then nothign is drawn
    if (!iWsPenStyle && !iWsBrushStyle)
        {
        return;    
        }

    if (IsRenderingEnabled())
        {    
        UseWsState();
        
        AdjustCoordinates( aRect );
        iCanvasGc->SetDrawMode(SelectCanvasDrawMode(iWsDrawMode));        
        
        if (iWsBrushStyle == MWsGraphicsContext::ENullBrush)
            {
            iCanvasGc->SetPolygonDrawMode( EHuiNoFill );
            iCanvasGc->SetPenColor(iWsPenColor);            
            iCanvasGc->SetOpacity(TReal32(iWsPenColor.Alpha() / 255.f));       
            iCanvasGc->DrawRoundRect( THuiRealRect(aRect), THuiRealSize( aPoint.iX*2, aPoint.iY*2 ));
            }    
        else if (iWsBrushStyle == MWsGraphicsContext::ESolidBrush)
            {
            iCanvasGc->SetPolygonDrawMode( EHuiFillEvenOdd );
            iCanvasGc->SetPenColor(iWsBrushColor);            
            iCanvasGc->SetOpacity(TReal32(iWsBrushColor.Alpha() / 255.f));            
            iCanvasGc->DrawRoundRect( THuiRealRect(aRect), THuiRealSize( aPoint.iX*2, aPoint.iY*2 ));

            // Border should be drawn if pencolor is different than solid fill
            if (IsDifferent(iWsBrushColor,iWsPenColor, ETrue) && iWsPenStyle && iWsPenSize.iHeight >= 1 && iWsPenSize.iWidth >= 1)
                {
                iCanvasGc->SetPolygonDrawMode( EHuiNoFill );
                iCanvasGc->SetPenColor(iWsPenColor);                    
                iCanvasGc->SetOpacity(TReal32(iWsPenColor.Alpha() / 255.f));       
                iCanvasGc->DrawRoundRect( THuiRealRect(aRect), THuiRealSize( aPoint.iX*2, aPoint.iY*2 ));
                }            
            }
        else if (iWsBrushStyle == MWsGraphicsContext::EPatternedBrush)
            {
            iCanvasGc->SetPolygonDrawMode( EHuiFillEvenOdd );
            iCanvasGc->SetPenColor(iWsBrushColor);                    
            iCanvasGc->SetOpacity(TReal32(iWsBrushColor.Alpha() / 255.f));       
            UseBrushPattern();
            iCanvasGc->SetDrawMode(SelectCanvasDrawMode(iWsDrawMode));        
            iCanvasGc->DrawRoundRect( THuiRealRect(aRect), THuiRealSize( aPoint.iX*2, aPoint.iY*2 ));
            DiscardBrushPattern();

            if (iWsPenStyle && iWsPenSize.iHeight >= 1 && iWsPenSize.iWidth >= 1)
                {
                iCanvasGc->SetPolygonDrawMode( EHuiNoFill );
                iCanvasGc->SetPenColor(iWsPenColor);                    
                iCanvasGc->SetOpacity(TReal32(iWsPenColor.Alpha() / 255.f));       
                iCanvasGc->DrawRoundRect( THuiRealRect(aRect), THuiRealSize( aPoint.iX*2, aPoint.iY*2 ));
                }
            }
        else
            {
            // We should never get here because fallbackmode should be used in this case !
            RDebug::Print(_L("CHuiCanvasWsHwGc::WsDrawRoundRectL - Unsupported brush mode %i"), iWsBrushStyle);
            }
        UseCanvasState();        
        }
    }

void CHuiCanvasWsHwGc::WsDrawPolyLineL(CArrayFix<TPoint>* aPointerArray)
	{
	// If penstyle is ENullPen, then nothign is drawn
    if (!iWsPenStyle)
        {
        return;    
        }
    
    if (IsRenderingEnabled())
        {    
        if ( aPointerArray )
            {
            UseWsState();
                
            RArray<THuiRealLine> lines;
            TPoint finalDeltaPos = iWsOrigin + iPosDelta; 
            for(TInt j=0; j<aPointerArray->Count()-1; j++)
                {    
                THuiRealLine line(aPointerArray->At(j) + finalDeltaPos, aPointerArray->At(j+1) + finalDeltaPos);
                lines.Append(line);        
                }
            iCanvasGc->DrawLines(lines);
            lines.Close();  
            
            UseCanvasState();
            }
        }
    }

void CHuiCanvasWsHwGc::WsDrawPolyLineNoEndPointL(TPoint* aPointerArray, TInt aCount)
	{
	// If penstyle is ENullPen, then nothign is drawn
    if (!iWsPenStyle)
        {
        return;    
        }
	
    if (IsRenderingEnabled())
        {    
        if ( aPointerArray )
           {
           UseWsState();
           
           RArray<THuiRealLine> lines;
           TPoint finalDeltaPos = iWsOrigin + iPosDelta; 
           for(TInt j=0; j< aCount-1; j++)
               {          
               THuiRealLine line(aPointerArray[j] + finalDeltaPos, aPointerArray[j+1] + finalDeltaPos );// TODO: TEST
               lines.Append(line);         
               }
           iCanvasGc->DrawLines(lines);
    
           RArray<THuiRealRect> rects;
           THuiRealRect pointRect = THuiRealRect(aPointerArray[aCount],aPointerArray[aCount]);
           rects.AppendL(pointRect);
           iCanvasGc->SetPenWidth(0);
           iCanvasGc->DrawRects(rects);
           rects.Close();
           lines.Close();       
           
           UseCanvasState();
           }
       }      
    }

void CHuiCanvasWsHwGc::WsDrawPolygonL(CArrayFix<TPoint>* aPointerArray, TInt aFillRule)
	{
    if (IsRenderingEnabled())
        {    	
        RArray<THuiRealPoint> points;
        for(TInt j=0; j<aPointerArray->Count(); j++)
           {      
           points.Append( THuiRealPoint( aPointerArray->At(j) + iWsOrigin + iPosDelta) );        
           }
        UseWsState();
        
        if (iWsBrushStyle == MWsGraphicsContext::ENullBrush)
            {
            // nullbrush, but pen style set
            // -> draw non filled polygon and 
            // use pencolor
            iCanvasGc->SetPolygonDrawMode( EHuiNoFill );
            iCanvasGc->SetPenColor(iWsPenColor);            
            iCanvasGc->SetOpacity(TReal32(iWsPenColor.Alpha() / 255.f));       

            }
        else
            {
            if ( aFillRule == MWsGraphicsContext::EAlternate )
                {
                iCanvasGc->SetPolygonDrawMode( EHuiFillEvenOdd );
                }
            if ( aFillRule == MWsGraphicsContext::EWinding )
                {        
                iCanvasGc->SetPolygonDrawMode( EHuiFillNonZero );
                }
            iCanvasGc->SetPenColor(iWsBrushColor);            
            iCanvasGc->SetOpacity(TReal32(iWsBrushColor.Alpha() / 255.f));       
            }
            
        iCanvasGc->SetDrawMode(SelectCanvasDrawMode(iWsDrawMode));        
            
        iCanvasGc->DrawPolygon( points );
    
        UseCanvasState();
    
        points.Close();        
        }	
	}

void CHuiCanvasWsHwGc::WsDrawEllipseL(TRect& aRect)
	{
	// If penstyle is ENullPen, then nothign is drawn
    if (!iWsPenStyle && !iWsBrushStyle)
        {
        return;    
        }

    if (IsRenderingEnabled())
        {        
        AdjustCoordinates( aRect );
        THuiRealRect destRect = aRect;
        UseWsState();
        
        if (iWsBrushStyle == MWsGraphicsContext::ENullBrush)
            {
            iCanvasGc->SetPolygonDrawMode( EHuiNoFill );
            iCanvasGc->SetPenColor(iWsPenColor);            
            iCanvasGc->SetOpacity(TReal32(iWsPenColor.Alpha() / 255.f));       
            iCanvasGc->DrawEllipse(destRect);
            }    
        else if (iWsBrushStyle == MWsGraphicsContext::ESolidBrush)
            {
            iCanvasGc->SetPolygonDrawMode( EHuiFillEvenOdd );
            iCanvasGc->SetPenColor(iWsBrushColor);            
            iCanvasGc->SetOpacity(TReal32(iWsBrushColor.Alpha() / 255.f));            
            iCanvasGc->DrawEllipse(destRect);

            // Border should be drawn if pencolor is different than solid fill
            if (IsDifferent(iWsBrushColor,iWsPenColor, ETrue) && iWsPenStyle && iWsPenSize.iHeight >= 1 && iWsPenSize.iWidth >= 1)
                {
                iCanvasGc->SetPolygonDrawMode( EHuiNoFill );
                iCanvasGc->SetPenColor(iWsPenColor);                    
                iCanvasGc->SetOpacity(TReal32(iWsPenColor.Alpha() / 255.f));       
                iCanvasGc->DrawEllipse(destRect);
                }            
            }
        else if (iWsBrushStyle == MWsGraphicsContext::EPatternedBrush)
            {
            iCanvasGc->SetPolygonDrawMode( EHuiFillEvenOdd );
            iCanvasGc->SetPenColor(iWsBrushColor);                    
            iCanvasGc->SetOpacity(TReal32(iWsBrushColor.Alpha() / 255.f));       
            UseBrushPattern();
            iCanvasGc->SetDrawMode(SelectCanvasDrawMode(iWsDrawMode));        
            iCanvasGc->DrawEllipse(destRect);
            DiscardBrushPattern();

            if (iWsPenStyle && iWsPenSize.iHeight >= 1 && iWsPenSize.iWidth >= 1)
                {
                iCanvasGc->SetPolygonDrawMode( EHuiNoFill );
                iCanvasGc->SetPenColor(iWsPenColor);                    
                iCanvasGc->SetOpacity(TReal32(iWsPenColor.Alpha() / 255.f));       
                iCanvasGc->DrawEllipse(destRect);
                }
            }
        else
            {
            // We should never get here because fallbackmode should be used in this case !
            RDebug::Print(_L("CHuiCanvasWsHwGc::WsDrawEllipseL - Unsupported brush mode %i"), iWsBrushStyle);
            }
    
        UseCanvasState();
        }
	}

void CHuiCanvasWsHwGc::WsDrawLineL(TPoint& aStart, TPoint& aEnd)
	{
	// If penstyle is ENullPen, then nothign is drawn
    if (!iWsPenStyle)
        {
        return;    
        }

    if (IsRenderingEnabled())
        {            
        AdjustCoordinates( aStart );
        AdjustCoordinates( aEnd );
        
        THuiRealLine line(aStart, aEnd);
        RArray<THuiRealLine> lines;
        lines.Append(line);        
    
        UseWsState();
    
        iCanvasGc->DrawLines( lines );
        lines.Close();
    
        UseCanvasState();
        }
    }

void CHuiCanvasWsHwGc::WsDrawLineToL(TPoint& aPoint)
	{
	// If penstyle is ENullPen, then nothign is drawn
    if (!iWsPenStyle)
        {
        return;    
        }
	
    if (IsRenderingEnabled())
        {            
        AdjustCoordinates( aPoint );
        TPoint currentPosition = iWsPenPosition;	
        THuiRealLine line(currentPosition, aPoint);
        RArray<THuiRealLine> lines;
        lines.Append(line);        
    
        UseWsState();
    
        iCanvasGc->DrawLines( lines );
            
        iWsPenPosition = aPoint;       
        lines.Close();        
    
        UseCanvasState();
        }
	}
    
void CHuiCanvasWsHwGc::WsDrawLineByL(TPoint& aPoint)
	{
	// If penstyle is ENullPen, then nothign is drawn
    if (!iWsPenStyle)
        {
        return;    
        }
	
    if (IsRenderingEnabled())
        {            
        AdjustCoordinates( aPoint );
        TPoint currentPosition = iWsPenPosition;
        TPoint endPoint = currentPosition + aPoint;
        THuiRealLine line(currentPosition, endPoint);    
        RArray<THuiRealLine> lines;
        lines.Append(line);        
    
        UseWsState();
    
        iCanvasGc->DrawLines( lines );
    
        iWsPenPosition = endPoint;
        lines.Close();    
    
        UseCanvasState();
        }
	}
    
void CHuiCanvasWsHwGc::WsDrawRectL(TRect& aRect)
	{
	// If penstyle is ENullPen, then nothign is drawn
    if (!iWsPenStyle && !iWsBrushStyle)
        {
        return;    
        }

    if (IsRenderingEnabled())
        {                
        AdjustCoordinates( aRect );
        RArray<THuiRealRect> rects;
        rects.AppendL(aRect);        
        
        UseWsState();
   
        if (iWsBrushStyle == MWsGraphicsContext::ENullBrush)
            {
            iCanvasGc->SetPenColor(iWsPenColor);                    
            iCanvasGc->SetOpacity(TReal32(iWsPenColor.Alpha() / 255.f));       
            iCanvasGc->SetDrawMode(SelectCanvasDrawMode(iWsDrawMode));        
            iCanvasGc->DrawRects(rects);
            }    
        else if (iWsBrushStyle == MWsGraphicsContext::ESolidBrush)
            {
            iCanvasGc->SetPolygonDrawMode( EHuiFillEvenOdd );
            iCanvasGc->SetPenColor(iWsBrushColor);            
            iCanvasGc->SetOpacity(TReal32(iWsBrushColor.Alpha() / 255.f));            
            iCanvasGc->SetDrawMode(SelectCanvasDrawMode(iWsDrawMode));        
            iCanvasGc->DrawRects(rects);

            
            // Border should be drawn if pencolor is different than solid fill
            if (IsDifferent(iWsBrushColor,iWsPenColor, ETrue) && iWsPenStyle && iWsPenSize.iHeight >= 1 && iWsPenSize.iWidth >= 1)
                {
                iCanvasGc->SetPolygonDrawMode( EHuiNoFill );
                iCanvasGc->SetPenColor(iWsPenColor);                    
                iCanvasGc->SetOpacity(TReal32(iWsPenColor.Alpha() / 255.f));       
                iCanvasGc->DrawRects(rects);                
                }            
            }
        else if (iWsBrushStyle == MWsGraphicsContext::EPatternedBrush)
            {
            iCanvasGc->SetPolygonDrawMode( EHuiFillEvenOdd );
            iCanvasGc->SetPenColor(iWsBrushColor);                    
            iCanvasGc->SetOpacity(TReal32(iWsBrushColor.Alpha() / 255.f));       
            UseBrushPattern();
            iCanvasGc->SetDrawMode(SelectCanvasDrawMode(iWsDrawMode));        
            iCanvasGc->DrawRects(rects);
            DiscardBrushPattern();

            if (iWsPenStyle && iWsPenSize.iHeight >= 1 && iWsPenSize.iWidth >= 1)
                {
                iCanvasGc->SetPolygonDrawMode( EHuiNoFill );
                iCanvasGc->SetPenColor(iWsPenColor);                    
                iCanvasGc->SetOpacity(TReal32(iWsPenColor.Alpha() / 255.f));       
                iCanvasGc->DrawRects(rects);                                
                }
            }
        else
            {
            // We should never get here because fallbackmode should be used in this case !
            RDebug::Print(_L("CHuiCanvasWsHwGc::WsDrawRectL - Unsupported brush mode %i"), iWsBrushStyle);
            }
        
        rects.Close();
        
        UseCanvasState();
        }
    }
	
const TUint8 color_s_to_lin[256] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
   0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
   0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
   0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04,
   0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
   0x05, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07,
   0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0a,
   0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0c, 0x0c, 0x0d,
   0x0d, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x10, 0x10,
   0x11, 0x11, 0x12, 0x12, 0x12, 0x13, 0x13, 0x14,
   0x15, 0x15, 0x16, 0x16, 0x17, 0x17, 0x18, 0x18,
   0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1d, 0x1d,
   0x1e, 0x1f, 0x1f, 0x20, 0x21, 0x21, 0x22, 0x23,
   0x23, 0x24, 0x25, 0x26, 0x26, 0x27, 0x28, 0x29,
   0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2d, 0x2e, 0x2f,
   0x30, 0x31, 0x32, 0x33, 0x33, 0x34, 0x35, 0x36,
   0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
   0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
   0x47, 0x48, 0x49, 0x4a, 0x4c, 0x4d, 0x4e, 0x4f,
   0x50, 0x51, 0x52, 0x54, 0x55, 0x56, 0x57, 0x58,
   0x5a, 0x5b, 0x5c, 0x5d, 0x5f, 0x60, 0x61, 0x63,
   0x64, 0x65, 0x67, 0x68, 0x69, 0x6b, 0x6c, 0x6d,
   0x6f, 0x70, 0x72, 0x73, 0x74, 0x76, 0x77, 0x79,
   0x7a, 0x7c, 0x7d, 0x7f, 0x80, 0x82, 0x83, 0x85,
   0x86, 0x88, 0x8a, 0x8b, 0x8d, 0x8e, 0x90, 0x92,
   0x93, 0x95, 0x97, 0x98, 0x9a, 0x9c, 0x9d, 0x9f,
   0xa1, 0xa3, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xad,
   0xaf, 0xb1, 0xb3, 0xb5, 0xb7, 0xb8, 0xba, 0xbc,
   0xbe, 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc,
   0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc,
   0xde, 0xe0, 0xe2, 0xe5, 0xe7, 0xe9, 0xeb, 0xed,
   0xef, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfd, 0xff };

inline TRgb ConvertToLinear(TRgb aColor)
    {
    // perform sRGB->linear color conversion if the renderer is
    // openvg
    // NOTE: For emulator depending on the OpenVG SW version mapping may
    // be needed or not. Use/unuse ifdefs below if text colors are too dark/light.
//#ifndef __WINSCW__
    if (CHuiStatic::Env().Renderer() == EHuiRendererVg10)
        {
        TUint32 color = aColor.Internal();
        return
            ((TUint32)color_s_to_lin[(color >> 0) & 0xff] << 16) |
            ((TUint32)color_s_to_lin[(color >> 8) & 0xff] << 8) |
            ((TUint32)color_s_to_lin[(color >> 16) & 0xff] << 0) |
            (color & 0xff000000);
        }
//#endif    
    return aColor;
    }

void CHuiCanvasWsHwGc::WsDrawText1L(TPtr& aTextValue, THuiCanvasTextParameters& aTextParameters)
	{		
	TPoint point = iWsPenPosition;
    AdjustCoordinates( point );
	THuiCachedTextParams cachedtextParams;
    cachedtextParams.iFindTextPtr = &aTextValue;
    cachedtextParams.iFontHandle = iWsCurrentFont;
    cachedtextParams.iTextParams = aTextParameters;
    cachedtextParams.iGcParams = CachedGcParams();

    if (IsRenderingEnabled())
        {           
        const CHuiCanvasTextImage* cachedImage = iVisual->Env().CanvasTextureCache().CreateCachedTextL(cachedtextParams,*iVisual); 
        
        const CHuiTexture* texture = cachedImage->Texture();
        if (texture)
            {
            THuiRealRect destinationRect = TRect(point, texture->Size());                
            
            // Adjust destination rect according to the point where text was rasterised in the image
            TInt dx = cachedImage->iRasterizationOffset.iX;
            TInt dy = cachedImage->iRasterizationOffset.iY;        
            destinationRect.Move(-dx,-dy);
            
            TRgb oldPenColor = iCanvasGc->PenColor();
            TReal32 oldOpacity = iCanvasGc->Opacity();
            if (cachedImage->iUseColorModulation)
                {
                iCanvasGc->SetPenColor(ConvertToLinear(iWsPenColor));    
                iCanvasGc->SetOpacity(TReal32(iWsPenColor.Alpha() / 255.f));
                }
            
            // Draw            
            iCanvasGc->DrawImage(*texture, destinationRect, TRect(TPoint(0,0), texture->Size()), CHuiGc::EStretchNone);
    
            if (cachedImage->iUseColorModulation)
                {
                iCanvasGc->SetPenColor(oldPenColor);                        
                iCanvasGc->SetOpacity(oldOpacity);
                }
            }        
        }
	else
	    {
	    if (IsCacheUpdateNeeded())
	        {
	        iVisual->Env().CanvasTextureCache().CreateCachedTextL(cachedtextParams,*iVisual); 
	        }
	    }
	}

void CHuiCanvasWsHwGc::WsDrawText2L(TPtr& aTextValue, TPoint& aPoint,THuiCanvasTextParameters& aTextParameters)
	{
	THuiCachedTextParams cachedtextParams;
    cachedtextParams.iFindTextPtr = &aTextValue;
    cachedtextParams.iFontHandle = iWsCurrentFont;
    cachedtextParams.iTextParams = aTextParameters;
    cachedtextParams.iGcParams = CachedGcParams();


    if (IsRenderingEnabled())
        {           
        const CHuiCanvasTextImage* cachedImage = iVisual->Env().CanvasTextureCache().CreateCachedTextL(cachedtextParams,*iVisual); 
        
        const CHuiTexture* texture = cachedImage->Texture();
        if (texture)
            {
            AdjustCoordinates( aPoint );
            THuiRealRect destinationRect = TRect(aPoint, texture->Size());                
            
            // Adjust destination rect according to the point where text was rasterised in the image
            TInt dx = cachedImage->iRasterizationOffset.iX;
            TInt dy = cachedImage->iRasterizationOffset.iY;        
            destinationRect.Move(-dx,-dy);
            
            TRgb oldPenColor = iCanvasGc->PenColor();
            TReal32 oldOpacity = iCanvasGc->Opacity();
            if (cachedImage->iUseColorModulation)
                {
                iCanvasGc->SetPenColor(ConvertToLinear(iWsPenColor));
                iCanvasGc->SetOpacity(TReal32(iWsPenColor.Alpha() / 255.f));    
                }
            
            // Draw            
            iCanvasGc->DrawImage(*texture, destinationRect, TRect(TPoint(0,0), texture->Size()), CHuiGc::EStretchNone);
    
            if (cachedImage->iUseColorModulation)
                {
                iCanvasGc->SetPenColor(oldPenColor);                        
                iCanvasGc->SetOpacity(oldOpacity);
                }
            }
        }
    else
        {
        if (IsCacheUpdateNeeded())
            {
            iVisual->Env().CanvasTextureCache().CreateCachedTextL(cachedtextParams,*iVisual); 
            }
        }
	}

void CHuiCanvasWsHwGc::WsDrawText3L(TPtr& aTextValue, TRect& aRect, THuiCanvasTextParameters& aTextParameters)
	{
	THuiCachedTextParams cachedtextParams;
	cachedtextParams.iFindTextPtr = &aTextValue;
	cachedtextParams.iFontHandle = iWsCurrentFont;
    cachedtextParams.iTextParams = aTextParameters;
    cachedtextParams.iTextBoxMaxSize = aRect.Size();
    cachedtextParams.iGcParams = CachedGcParams();


    if (IsRenderingEnabled())
        {           
        const CHuiCanvasTextImage* cachedImage = iVisual->Env().CanvasTextureCache().CreateCachedTextL(cachedtextParams,*iVisual); 
        
        const CHuiTexture* texture = cachedImage->Texture();
        if (texture)
            {
            AdjustCoordinates( aRect );
            THuiRealRect destinationRect = aRect;                
            
            // Adjust destination rect according to the point where text was rasterised in the image
            TInt dx = cachedImage->iRasterizationOffset.iX;
            TInt dy = cachedImage->iRasterizationOffset.iY;        
            destinationRect.Move(-dx,-dy);
            
            TRgb oldPenColor = iCanvasGc->PenColor();
            TReal32 oldOpacity = iCanvasGc->Opacity();
            if (cachedImage->iUseColorModulation)
                {
                DrawTextBrush( destinationRect );
                iCanvasGc->SetPenColor(ConvertToLinear(iWsPenColor));
                iCanvasGc->SetOpacity(TReal32(iWsPenColor.Alpha() / 255.f));    
                }
    
            // Draw            
            iCanvasGc->DrawImage(*texture, destinationRect, TRect(TPoint(0,0), texture->Size()), CHuiGc::EStretchNone);
    
            if (cachedImage->iUseColorModulation)
                {
                iCanvasGc->SetPenColor(oldPenColor);
                iCanvasGc->SetOpacity(oldOpacity);                        
                }
            }
        }
    else
        {
        if (IsCacheUpdateNeeded())
            {
            iVisual->Env().CanvasTextureCache().CreateCachedTextL(cachedtextParams,*iVisual); 
            }
        }
	}


void CHuiCanvasWsHwGc::WsDrawText4L(TPtr& aTextValue, TRect& aRect, TInt aBaselineOffset, TInt aTextAlign, TInt aTextMargin,THuiCanvasTextParameters& aTextParameters)
    {
	THuiCachedTextParams cachedtextParams;
	cachedtextParams.iFindTextPtr = &aTextValue;
    cachedtextParams.iFontHandle = iWsCurrentFont;
    cachedtextParams.iTextParams = aTextParameters;
    cachedtextParams.iTextBoxMaxSize = aRect.Size();
    cachedtextParams.iBaseLineOffset = aBaselineOffset;
    cachedtextParams.iTextAlign = aTextAlign;
    cachedtextParams.iMargin = aTextMargin;
    cachedtextParams.iGcParams = CachedGcParams();
    
    if (IsRenderingEnabled())
        {           
        const CHuiCanvasTextImage* cachedImage = iVisual->Env().CanvasTextureCache().CreateCachedTextL(cachedtextParams,*iVisual); 
        
        const CHuiTexture* texture = cachedImage->Texture();
        if (texture)
            {
            AdjustCoordinates( aRect );
            THuiRealRect destinationRect = aRect;                
            
            // Adjust destination rect according to the point where text was rasterised in the image
            TInt dx = cachedImage->iRasterizationOffset.iX;
            TInt dy = cachedImage->iRasterizationOffset.iY;        
            destinationRect.Move(-dx,-dy);
            
            TRgb oldPenColor = iCanvasGc->PenColor();
            TReal32 oldOpacity = iCanvasGc->Opacity();
            if (cachedImage->iUseColorModulation)
                {
                DrawTextBrush( destinationRect );
                iCanvasGc->SetPenColor(ConvertToLinear(iWsPenColor));
                iCanvasGc->SetOpacity(TReal32(iWsPenColor.Alpha() / 255.f));    
                }
    
            // Draw            
            iCanvasGc->DrawImage(*texture, destinationRect, TRect(TPoint(0,0), texture->Size()), CHuiGc::EStretchNone);
    
            if (cachedImage->iUseColorModulation)
                {
                iCanvasGc->SetPenColor(oldPenColor);
                iCanvasGc->SetOpacity(oldOpacity);                        
                }
            }    
        }
    else
        {
        if (IsCacheUpdateNeeded())
            {
            iVisual->Env().CanvasTextureCache().CreateCachedTextL(cachedtextParams,*iVisual); 
            }
        }
    }

void CHuiCanvasWsHwGc::WsDrawText5L( TPtr& aTextValue, TRect& aRect, TInt aBaselineOffset, TInt aTextAlign, TInt aTextMargin,TInt aTextWidth, THuiCanvasTextParameters& aTextParameters)
	{	
	THuiCachedTextParams cachedtextParams;
	cachedtextParams.iFindTextPtr = &aTextValue;
    cachedtextParams.iFontHandle = iWsCurrentFont;
    cachedtextParams.iTextParams = aTextParameters;
    cachedtextParams.iTextBoxMaxSize = aRect.Size();
    cachedtextParams.iBaseLineOffset = aBaselineOffset;
    cachedtextParams.iTextAlign = aTextAlign;
    cachedtextParams.iMargin = aTextMargin;
    cachedtextParams.iTextWidth = aTextWidth;
    cachedtextParams.iGcParams = CachedGcParams();
    
    
    if (IsRenderingEnabled())
        {           
        const CHuiCanvasTextImage* cachedImage = iVisual->Env().CanvasTextureCache().CreateCachedTextL(cachedtextParams,*iVisual); 
        
        const CHuiTexture* texture = cachedImage->Texture();
        if (texture)
            {
            AdjustCoordinates( aRect );
            THuiRealRect destinationRect = aRect;                
            
            // Adjust destination rect according to the point where text was rasterised in the image
            TInt dx = cachedImage->iRasterizationOffset.iX;
            TInt dy = cachedImage->iRasterizationOffset.iY;        
            destinationRect.Move(-dx,-dy);
            
            TRgb oldPenColor = iCanvasGc->PenColor();
            TReal32 oldOpacity = iCanvasGc->Opacity();
            if (cachedImage->iUseColorModulation)
                {
                DrawTextBrush( destinationRect );
                iCanvasGc->SetPenColor(ConvertToLinear(iWsPenColor));
                iCanvasGc->SetOpacity(TReal32(iWsPenColor.Alpha() / 255.f));    
                }
    
            // Draw            
            iCanvasGc->DrawImage(*texture, destinationRect, TRect(TPoint(0,0), texture->Size()), CHuiGc::EStretchNone);
    
            if (cachedImage->iUseColorModulation)
                {
                iCanvasGc->SetPenColor(oldPenColor);
                iCanvasGc->SetOpacity(oldOpacity);                        
                }
            }    
        }
    else
        {
        if (IsCacheUpdateNeeded())
            {
            iVisual->Env().CanvasTextureCache().CreateCachedTextL(cachedtextParams,*iVisual); 
            }
        }
	}
	
void CHuiCanvasWsHwGc::WsDrawTextVertical1L(TPtr& aTextValue, TInt aTextUp, THuiCanvasTextParameters& aTextParameters)	
    {
	TPoint point = iWsPenPosition;
    TInt angle = aTextUp ? -90 : 90;

    THuiCachedTextParams cachedtextParams;
    cachedtextParams.iFindTextPtr = &aTextValue;
    cachedtextParams.iFontHandle = iWsCurrentFont;
    cachedtextParams.iTextParams = aTextParameters;
    cachedtextParams.iAngle = angle;
    cachedtextParams.iGcParams = CachedGcParams();
 

    if (IsRenderingEnabled())
        {           
        const CHuiCanvasTextImage* cachedImage = iVisual->Env().CanvasTextureCache().CreateCachedTextL(cachedtextParams,*iVisual);
        
        const CHuiTexture* texture = cachedImage->Texture();
        if (texture)
            {
            AdjustCoordinates( point );
            THuiRealRect destinationRect = TRect(point, texture->Size());                
            
            // Adjust destination rect according to the point where text was rasterised in the image
            TInt dx = cachedImage->iRasterizationOffset.iX;
            TInt dy = cachedImage->iRasterizationOffset.iY;        
            destinationRect.Move(-dx,-dy);
            
            TRgb oldPenColor = iCanvasGc->PenColor();
            TReal32 oldOpacity = iCanvasGc->Opacity();
            if (cachedImage->iUseColorModulation)
                {
                iCanvasGc->SetPenColor(ConvertToLinear(iWsPenColor));    
                iCanvasGc->SetOpacity(TReal32(iWsPenColor.Alpha() / 255.f));
                }
    
            // Draw            
            iCanvasGc->DrawImage(*texture, destinationRect, TRect(TPoint(0,0), texture->Size()), CHuiGc::EStretchNone);
    
            if (cachedImage->iUseColorModulation)
                {
                iCanvasGc->SetPenColor(oldPenColor);
                iCanvasGc->SetOpacity(oldOpacity);                        
                }
            }    
        }
    else
        {
        if (IsCacheUpdateNeeded())
            {
            iVisual->Env().CanvasTextureCache().CreateCachedTextL(cachedtextParams,*iVisual);
            }
        }
    }

void CHuiCanvasWsHwGc::WsDrawTextVertical2L(TPtr& aTextValue, TInt aTextUp,TPoint& aPoint, THuiCanvasTextParameters& aTextParameters)	
    {	 	                                       	
    TInt angle = aTextUp ? -90 : 90;

    THuiCachedTextParams cachedtextParams;
    cachedtextParams.iFindTextPtr = &aTextValue;
    cachedtextParams.iFontHandle = iWsCurrentFont;
    cachedtextParams.iTextParams = aTextParameters;
    cachedtextParams.iAngle = angle;
    cachedtextParams.iGcParams = CachedGcParams();
	 

    if (IsRenderingEnabled())
        {           
        const CHuiCanvasTextImage* cachedImage = iVisual->Env().CanvasTextureCache().CreateCachedTextL(cachedtextParams,*iVisual);
        
        const CHuiTexture* texture = cachedImage->Texture();
        if (texture)
            {
            AdjustCoordinates( aPoint );
            THuiRealRect destinationRect = TRect(aPoint, texture->Size());                
            
            // Adjust destination rect according to the point where text was rasterised in the image
            TInt dx = cachedImage->iRasterizationOffset.iX;
            TInt dy = cachedImage->iRasterizationOffset.iY;        
            destinationRect.Move(-dx,-dy);
            
            TRgb oldPenColor = iCanvasGc->PenColor();
            TReal32 oldOpacity = iCanvasGc->Opacity();
            if (cachedImage->iUseColorModulation)
                {
                iCanvasGc->SetPenColor(ConvertToLinear(iWsPenColor));
                iCanvasGc->SetOpacity(TReal32(iWsPenColor.Alpha() / 255.f));    
                }
    
            // Draw            
            iCanvasGc->DrawImage(*texture, destinationRect, TRect(TPoint(0,0), texture->Size()), CHuiGc::EStretchNone);
    
            if (cachedImage->iUseColorModulation)
                {
                iCanvasGc->SetPenColor(oldPenColor); 
                iCanvasGc->SetOpacity(oldOpacity);                       
                }
            }
        }
    else
        {
        if (IsCacheUpdateNeeded())
            {
            iVisual->Env().CanvasTextureCache().CreateCachedTextL(cachedtextParams,*iVisual);
            }
        }
    }

void CHuiCanvasWsHwGc::WsDrawTextVertical3L(TPtr& aTextValue, TInt aTextUp, TRect& aRect, THuiCanvasTextParameters& aTextParameters)	
    {
	TInt angle = aTextUp ? -90 : 90;

    THuiCachedTextParams cachedtextParams;
    cachedtextParams.iFindTextPtr = &aTextValue;
    cachedtextParams.iFontHandle = iWsCurrentFont;
    cachedtextParams.iTextParams = aTextParameters;
    cachedtextParams.iTextBoxMaxSize = aRect.Size();
    cachedtextParams.iAngle = angle;
    cachedtextParams.iGcParams = CachedGcParams();


    if (IsRenderingEnabled())
        {           
        const CHuiCanvasTextImage* cachedImage = iVisual->Env().CanvasTextureCache().CreateCachedTextL(cachedtextParams,*iVisual); 
        
        const CHuiTexture* texture = cachedImage->Texture();
        if (texture)
            {
            AdjustCoordinates( aRect );
            THuiRealRect destinationRect = aRect;                
            
            // Adjust destination rect according to the point where text was rasterised in the image
            TInt dx = cachedImage->iRasterizationOffset.iX;
            TInt dy = cachedImage->iRasterizationOffset.iY;        
            destinationRect.Move(-dx,-dy);
            
            TRgb oldPenColor = iCanvasGc->PenColor();
            TReal32 oldOpacity = iCanvasGc->Opacity();
            if (cachedImage->iUseColorModulation)
                {
                DrawTextBrush( destinationRect );
                iCanvasGc->SetPenColor(ConvertToLinear(iWsPenColor));  
                iCanvasGc->SetOpacity(TReal32(iWsPenColor.Alpha() / 255.f));  
                }
    
            // Draw            
            iCanvasGc->DrawImage(*texture, destinationRect, TRect(TPoint(0,0), texture->Size()), CHuiGc::EStretchNone);
    
            if (cachedImage->iUseColorModulation)
                {
                iCanvasGc->SetPenColor(oldPenColor); 
                iCanvasGc->SetOpacity(oldOpacity);                       
                }
            }
        }
    else
        {
        if (IsCacheUpdateNeeded())
            {
            iVisual->Env().CanvasTextureCache().CreateCachedTextL(cachedtextParams,*iVisual); 
            }
        }
    }

void CHuiCanvasWsHwGc::WsDrawTextVertical4L(TPtr& aTextValue, TRect& aRect, TInt aBaselineOffset, TInt aTextUp, TInt aTextAlign, TInt aTextMargin,THuiCanvasTextParameters& aTextParameters)
    {
    TInt angle = aTextUp ? -90 : 90;

    THuiCachedTextParams cachedtextParams;
    cachedtextParams.iFindTextPtr = &aTextValue;
    cachedtextParams.iFontHandle = iWsCurrentFont;
    cachedtextParams.iTextParams = aTextParameters;
    cachedtextParams.iTextBoxMaxSize = aRect.Size();
    cachedtextParams.iAngle = angle;
    cachedtextParams.iBaseLineOffset = aBaselineOffset;
    cachedtextParams.iTextAlign = aTextAlign;
    cachedtextParams.iMargin = aTextMargin;
    cachedtextParams.iGcParams = CachedGcParams();


    if (IsRenderingEnabled())
        {           
        const CHuiCanvasTextImage* cachedImage = iVisual->Env().CanvasTextureCache().CreateCachedTextL(cachedtextParams,*iVisual); 

        const CHuiTexture* texture = cachedImage->Texture();
        if (texture)
            {
            AdjustCoordinates( aRect );
            THuiRealRect destinationRect = aRect;                
            
            // Adjust destination rect according to the point where text was rasterised in the image
            TInt dx = cachedImage->iRasterizationOffset.iX;
            TInt dy = cachedImage->iRasterizationOffset.iY;        
            destinationRect.Move(-dx,-dy);
            
            TRgb oldPenColor = iCanvasGc->PenColor();
            TReal32 oldOpacity = iCanvasGc->Opacity();
            if (cachedImage->iUseColorModulation)
                {
                DrawTextBrush( destinationRect );
                iCanvasGc->SetPenColor(ConvertToLinear(iWsPenColor)); 
                iCanvasGc->SetOpacity(TReal32(iWsPenColor.Alpha() / 255.f));   
                }
    
            // Draw            
            iCanvasGc->DrawImage(*texture, destinationRect, TRect(TPoint(0,0), texture->Size()), CHuiGc::EStretchNone);
    
            if (cachedImage->iUseColorModulation)
                {
                iCanvasGc->SetPenColor(oldPenColor);
                iCanvasGc->SetOpacity(oldOpacity);                        
                }
            }
        }
    else
        {
        if (IsCacheUpdateNeeded())
            {
            iVisual->Env().CanvasTextureCache().CreateCachedTextL(cachedtextParams,*iVisual); 
            }
        }
    }

void CHuiCanvasWsHwGc::WsDrawTextVertical5L(TPtr& aTextValue, TRect& aRect, TInt aBaselineOffset, TInt aTextUp, TInt aTextAlign, TInt aTextMargin, TInt aTextWidth, THuiCanvasTextParameters& aTextParameters)
    {
	TInt angle = aTextUp ? -90 : 90;

    THuiCachedTextParams cachedtextParams;
    cachedtextParams.iFindTextPtr = &aTextValue;
    cachedtextParams.iFontHandle = iWsCurrentFont;
    cachedtextParams.iTextParams = aTextParameters;
    cachedtextParams.iTextBoxMaxSize = aRect.Size();
    cachedtextParams.iAngle = angle;
    cachedtextParams.iTextWidth = aTextWidth;
    cachedtextParams.iBaseLineOffset = aBaselineOffset;
    cachedtextParams.iTextAlign = aTextAlign;
    cachedtextParams.iMargin = aTextMargin;
    cachedtextParams.iGcParams = CachedGcParams();


    if (IsRenderingEnabled())
        {           
        const CHuiCanvasTextImage* cachedImage = iVisual->Env().CanvasTextureCache().CreateCachedTextL(cachedtextParams,*iVisual); 
        
        const CHuiTexture* texture = cachedImage->Texture();
        if (texture)
            {
            AdjustCoordinates( aRect );
            THuiRealRect destinationRect = aRect;                
            
            // Adjust destination rect according to the point where text was rasterised in the image
            TInt dx = cachedImage->iRasterizationOffset.iX;
            TInt dy = cachedImage->iRasterizationOffset.iY;        
            destinationRect.Move(-dx,-dy);
            
            TRgb oldPenColor = iCanvasGc->PenColor();
            TReal32 oldOpacity = iCanvasGc->Opacity();
            if (cachedImage->iUseColorModulation)
                {
                DrawTextBrush( destinationRect );
                iCanvasGc->SetPenColor(ConvertToLinear(iWsPenColor));  
                iCanvasGc->SetOpacity(TReal32(iWsPenColor.Alpha() / 255.f));  
                }
    
            // Draw            
            iCanvasGc->DrawImage(*texture, destinationRect, TRect(TPoint(0,0), texture->Size()), CHuiGc::EStretchNone);
    
            if (cachedImage->iUseColorModulation)
                {
                iCanvasGc->SetPenColor(oldPenColor);
                iCanvasGc->SetOpacity(oldOpacity);                        
                }
            }
        }
    else
        {
        if (IsCacheUpdateNeeded())
            {
            iVisual->Env().CanvasTextureCache().CreateCachedTextL(cachedtextParams,*iVisual); 
            }
        }
    }

void CHuiCanvasWsHwGc::WsMoveToL( TPoint& aPoint)
    {
    iWsPenPosition = aPoint;
    }

void CHuiCanvasWsHwGc::WsMoveByL( TPoint& aPoint)
    {
    iWsPenPosition += aPoint;
    }
    
void CHuiCanvasWsHwGc::WsPlotL(TPoint& aPoint)
	{
    if (IsRenderingEnabled())
    	{
        AdjustCoordinates( aPoint );
	    UseWsState();        
        // Draw  
        RArray<THuiRealPoint> points;
        CleanupClosePushL(points);  
        points.AppendL(THuiRealPoint(aPoint));       
        iCanvasGc->DrawPoints(points);
        CleanupStack::PopAndDestroy();
        UseCanvasState();
        }
    }

void CHuiCanvasWsHwGc::WsResetL()
	{
	iWsClipRegion.Clear();
	iWsCurrentFont = 0;
	iWsOrigin = KHuiWsDefaultOrigin;
    iWsPenSize = KHuiWsDefaultPenSize;

	iWsPenPosition = TPoint(0,0);
	iWsFadeColor = KHuiWsDefaultFadeColor;

    iWsPenColor = KHuiWsDefaultPenColor;
    iWsBrushColor = KHuiWsDefaultBrushColor;
    iWsPenStyle = KHuiWsDefaultPenStyle;
    iWsDrawMode = KHuiWsDefaultDrawMode;
    iWsBrushStyle = KHuiWsDefaultBrushStyle;
    iWsShadowMode = KHuiWsDefaultShadowMode;
    iWsStrikethrough = KHuiWsDefaultStrikethrough;
    iWsUnderline = KHuiWsDefaultUnderline; 
    iWsUserDisplayMode = KHuiWsDefaultUserDisplayMode;
    iWsShadowColor = KHuiWsDefaultShadowColor;
    iWsBrushPattern = 0;
    iWsBrushOrigin = TPoint(0,0);


  	iCanvasGc->CancelClipping();
  	iCanvasGc->SetPenColor(KRgbWhite); 
    iCanvasGc->SetOpacity(1.0);
	iCanvasGc->SetPenWidth(1); 
	}



void CHuiCanvasWsHwGc::WsSetBrushColorL( TRgb aColor)
    {
    iWsBrushColor = aColor;
    }

void CHuiCanvasWsHwGc::WsSetBrushOriginL( TPoint& aPoint)
    {
    iWsBrushOrigin = aPoint;
    }

void CHuiCanvasWsHwGc::WsSetBrushStyleL( TInt aStyle)
    {
    iWsBrushStyle = aStyle;        
    }

void CHuiCanvasWsHwGc::WsSetClippingRegionL( RRegion& aRegion)
    {
    if (IsRenderingEnabled())
        {
        iWsClipRegion.Clear();    
        for (TInt i=0;i<aRegion.Count();i++)
            {
            TRect rect = aRegion[i];
            AdjustCoordinates( rect, EFalse );
            iWsClipRegion.AddRect(rect);
            }    
        
        iCanvasGc->ClipRegion(iWsClipRegion);                
        }
    }
    
void CHuiCanvasWsHwGc::WsSetDrawModeL( TInt aDrawMode)
	{
	iWsDrawMode = aDrawMode;	
	}

void CHuiCanvasWsHwGc::WsSetOriginL( TPoint& aOrigin)
	{
 	iWsOrigin = aOrigin;
	}

void CHuiCanvasWsHwGc::WsSetPenColorL( TRgb aColor)
	{
	iWsPenColor = aColor;
	}

void CHuiCanvasWsHwGc::WsSetPenStyleL( TInt aStyle)
	{
    iWsPenStyle = aStyle;
	}

void CHuiCanvasWsHwGc::WsSetPenSizeL( TInt aWidth, TInt aHeight)
	{
    iWsPenSize.iWidth = aWidth;
    // Note, that only width is supported by HW renderer. Canvas should be draw in fallback mode, if width and height are not the same
    iWsPenSize.iHeight = aHeight; 
	}

void CHuiCanvasWsHwGc::WsSetTextShadowColorL( TRgb aColor)
	{
 	iWsShadowColor = aColor;
	}

void CHuiCanvasWsHwGc::WsSetCharJustificationL( TInt /*aExcessiveWidth*/, TInt /*aNumGap*/)
	{
    // This is not supported by this CHuiCanvasWsGc implementation
	iAllCommandsSupported = EFalse;
	}

void CHuiCanvasWsHwGc::WsSetWordJustificationL( TInt /*aExcessiveWidth*/, TInt /*aNumGap*/)
	{
    // This is not supported by this CHuiCanvasWsGc implementation
	iAllCommandsSupported = EFalse;
	}

void CHuiCanvasWsHwGc::WsSetUnderlineStyleL( TInt aValue )
	{
    if (aValue < 1000) // magic, we recycle the same function for both underline and strike through
        {
        iWsUnderline = aValue;
        }
    else
        {
        iWsStrikethrough=aValue-1000;
        }
	}

void CHuiCanvasWsHwGc::WsSetBrushPatternL( TInt aValue )
	{
	iWsBrushPattern = aValue;
	}

void CHuiCanvasWsHwGc::WsSetFontL( TInt aFontId)
	{
	iWsCurrentFont = aFontId;
	}

void CHuiCanvasWsHwGc::WsCopyRectL( TPoint& /*aPoint*/, TRect& /*aRect*/)
	{
    // This is not supported by this CHuiCanvasWsGc implementation
	iAllCommandsSupported = EFalse;
	}

void CHuiCanvasWsHwGc::WsUpdateJustificationL( TPtr& /*aTextValue*/)
	{
    // This is not supported by this CHuiCanvasWsGc implementation
	iAllCommandsSupported = EFalse;
	}

void CHuiCanvasWsHwGc::WsUpdateJustificationVerticalL( TInt /*aValue*/, TPtr& /*aTextValue*/)
	{
    // This is not supported by this CHuiCanvasWsGc implementation
	iAllCommandsSupported = EFalse;
	}

void CHuiCanvasWsHwGc::WsSetFontNoDuplicateL( TInt aCurrentFont)
	{
	iWsCurrentFont = aCurrentFont;
	}

void CHuiCanvasWsHwGc::WsCopySettingsL()
	{
    // This is not supported by this CHuiCanvasWsGc implementation
	iAllCommandsSupported = EFalse;
	}

void CHuiCanvasWsHwGc::WsSetClippingRectL( TRect& aRect)
    {    
    if (IsRenderingEnabled())
        {
        // Symbian SetClippingRect takes ws origin into account, 
        // but setClippingRegion does not.
        AdjustCoordinates( aRect, ETrue );
        iTempRegion.Clear();
        iTempRegion.AddRect( aRect );
        iCanvasGc->ClipRegion( iTempRegion );
        }
    }

void CHuiCanvasWsHwGc::WsCancelClippingRectL()
    {
    if (IsRenderingEnabled())
        {
        WsResetClippingRegionL();
        iCanvasGc->CancelClipping();
        }
    }

void CHuiCanvasWsHwGc::WsSetFadedL( TInt& /*aFaded*/)
    {
	// Nothing to do, we should get FadeArea commands if window is faded.
    }

void CHuiCanvasWsHwGc::WsSetFadingParametersL( TInt aBlackMap, TInt aWhiteMap)
    {
    if (IsRenderingEnabled())
        {
		if (aBlackMap > aWhiteMap)
            {
            TInt oldMap = aBlackMap;
            aBlackMap = aWhiteMap;
            aWhiteMap = oldMap;
            }

        const TUint16* lut = PtrTo16BitNormalisationTable();
        
        //CFbsBitGc::FadeArea() does the following per color component:
        //   dst = dst * (aWhiteMap - aBlackMap) + aBlackMap;
    
        //To achieve the same effect using MWsGraphicsContext we draw a rectangle
        //with specific intensity and alpha values:
        //   dst = dst * (1 - alpha) + intensity * alpha;
        //Thus:
        //   alpha = 1 - aWhiteMap + aBlackMap;
        //   intensity = aBlackMap / alpha;
    
        // alpha = 1 - aWhiteMap + aBlackMap;
        TInt alpha = 255 - aWhiteMap + aBlackMap;
        // intensity = aBlackMap / alpha;
        TInt i = (aBlackMap * lut[alpha]) >> 8;
    
        iWsFadeColor.SetInternal(i << 16 | i << 8 | i | alpha << 24); 
        }
    }

void CHuiCanvasWsHwGc::WsFadeAreaL( RRegion& aRegion)
    {
    if (IsRenderingEnabled())
        {
        RArray<THuiRealRect> realRects;
        for (TInt i=0; i<aRegion.Count();i++)
            {
            realRects.Append(aRegion[i]);
            }
        UseWsState();
        // Get real color & opacity from fading params
        TRgb fadeColor = iWsFadeColor;
        // Opacity is given separately, so set alpha of the color to 255.   
        fadeColor.SetAlpha(255); 
        TReal32 opacity = TReal32(TReal32(iWsFadeColor.Alpha() / 255.f));
        
        // Draw semi transparent rect(s) over the visual faded areas
        iCanvasGc->SetPenColor(fadeColor);
        iCanvasGc->SetOpacity(opacity);    
        iCanvasGc->SetPolygonDrawMode(EHuiFillNonZero);    
        iCanvasGc->SetDrawMode(SelectCanvasDrawMode(iWsDrawMode));        

        iCanvasGc->DrawRects(realRects);
        
        UseCanvasState();
            
        realRects.Close();    
        aRegion.Close();    
        }
    }

void CHuiCanvasWsHwGc::WsMapColorsL()
    {
    // This is not supported by this CHuiCanvasWsGc implementation
	iAllCommandsSupported = EFalse;
    }

void CHuiCanvasWsHwGc::WsSetUserDisplayModeL( TInt aMode )
    {
    iWsUserDisplayMode = aMode;
    }

void CHuiCanvasWsHwGc::WsUseFontL(TInt aCurrentFont)
    {
    iWsCurrentFont = aCurrentFont;
    }       

void CHuiCanvasWsHwGc::BeginActionL(TInt aAction, TRect aDisplayRect, const CHuiCanvasVisual& aUser, TBool aIsCachePrepared, const TRegion& aUpdateRegion)
	{
    iAction = aAction;
    iVisual = (CHuiCanvasVisual*)&aUser;
    iAllCommandsSupported = ETrue;

    if (aAction == EDrawBuffer)
	    {
	    BeginDrawL(aDisplayRect, aUser, aIsCachePrepared, aUpdateRegion);
	    }
	else if (aAction == EScanBuffer)
	    {
        BeginScanL(aDisplayRect, aUser, aIsCachePrepared, aUpdateRegion);	    
	    }
	else
	    {
	    // Should not happen
	    }
	}

void CHuiCanvasWsHwGc::EndActionL(const TRegion& aUpdateRegion, TBool aUpdateDisplay)
	{
    if (iAction == EDrawBuffer)
        {
        EndDrawL(aUpdateRegion, aUpdateDisplay);
        }
    else if (iAction == EScanBuffer)
        {
        EndScanL(aUpdateRegion, aUpdateDisplay);
        }
    else
        {
        // Should not happen
        }
	}

void CHuiCanvasWsHwGc::BeginDrawL(TRect aDisplayRect,const CHuiCanvasVisual& aUser, TBool aIsCachePrepared, const TRegion& aUpdateRegion)
    {
    CHuiCanvasRenderBuffer* renderbuffer = NULL;
    TRect updatedRect = aUpdateRegion.BoundingRect();
    TBool renderBufferCreated = EFalse;
    
    // Try to get render buffer if it has been enabled
    if (iRenderBufferEnabled && updatedRect.Size() != TSize(0,0))
        {
        renderbuffer = iVisual->Env().CanvasTextureCache().FindCachedRenderBuffer(aUser);
        if (!renderbuffer)
            {        
            renderbuffer = iVisual->Env().CanvasTextureCache().CreateCachedRenderBufferL(aUser, updatedRect.Size());
            renderBufferCreated = ETrue;
            }
        }
    
    if (renderbuffer)
        {
        // If renderbuffer is not initialized, set the internal flag to EFalse. It will be set
        // to ETrue after drawing has been done.
        if (!renderbuffer->IsInitialized() || renderbuffer->Size() != updatedRect.Size() || renderBufferCreated)
            {
            iRenderBufferInitialized = EFalse;
            }
        
        // We can access render buffer, mark it to be available.
        iRenderBufferAvailable = ETrue;
        
        // Render buffer is prepared if caller says that cache is prepared and renderbuffer has been initialized.
        iRenderBufferPrepared = aIsCachePrepared && iRenderBufferInitialized;
        }
    else
        {
        // We could not access render buffer, mark it to be unavailable.
        iRenderBufferAvailable = EFalse;
        }
        
    // If render buffer is not prepared, we must prepare it. We will set the flag at EndActionL when
    // we really have prepared it.
    if (IsRenderBufferUpdateOngoing())
        {        
        // Init render buffer (it only really initializes if needed)
        renderbuffer->InitializeL(updatedRect.Size());

        // Bind render buffer
        BindRenderBuffer(renderbuffer, aUpdateRegion);
        }
    iCanvasGc->RestoreFlaggedState();
    }

void CHuiCanvasWsHwGc::BeginScanL(TRect aDisplayRect,const CHuiCanvasVisual& aUser, TBool aIsCachePrepared, const TRegion& aUpdateRegion)
    {
    CHuiCanvasRenderBuffer* renderbuffer = NULL;
    TRect updatedRect = aUpdateRegion.BoundingRect();
    TBool renderBufferCreated = EFalse;
    
    // Try to get render buffer if it has been enabled
    if (iRenderBufferEnabled && updatedRect.Size() != TSize(0,0))
        {
        renderbuffer = iVisual->Env().CanvasTextureCache().FindCachedRenderBuffer(aUser);
        if (!renderbuffer)
            {        
            renderbuffer = iVisual->Env().CanvasTextureCache().CreateCachedRenderBufferL(aUser, updatedRect.Size());
            renderBufferCreated = ETrue;
            }
        }
    
    if (renderbuffer)
        {
        // If renderbuffer is not initialized, set the internal flag to EFalse. It will be set
        // to ETrue after drawing has been done.
        if (!renderbuffer->IsInitialized() || renderbuffer->Size() != updatedRect.Size() || renderBufferCreated)
            {
            iRenderBufferInitialized = EFalse;
            }
        
        // We can access render buffer, mark it to be available.
        iRenderBufferAvailable = ETrue;
        
        // Render buffer is prepared if caller says that cache is prepared and renderbuffer has been initialized.
        iRenderBufferPrepared = aIsCachePrepared && iRenderBufferInitialized;
        }
    else
        {
        // We could not access render buffer, mark it to be unavailable.
        iRenderBufferAvailable = EFalse;
        }
        
    // If render buffer is not prepared, we must prepare it. We will set the flag at EndActionL when
    // we really have prepared it.
    if (IsRenderBufferUpdateOngoing())
        {        
        // Init render buffer (it only really initializes if needed)
        renderbuffer->InitializeL(updatedRect.Size());
        }

    iCanvasGc->RestoreFlaggedState();
	}

void CHuiCanvasWsHwGc::EndDrawL(const TRegion& aUpdateRegion, TBool aUpdateDisplay)
    {
    CHuiCanvasRenderBuffer* renderbuffer = NULL;

    // Check if we have cached render buffer available
    if (IsRenderBufferEnabled())
        {
        renderbuffer = iVisual->Env().CanvasTextureCache().FindCachedRenderBuffer(*iVisual);
        }
    
    if (renderbuffer)
        {
        // We can access render buffer, mark it to be available.
        iRenderBufferAvailable = ETrue;
        }
    else
        {
        // We could not access render buffer, mark it to be unavailable.
        iRenderBufferAvailable = EFalse;        
        }

    // Are we updating into render buffer
    if (IsRenderBufferUpdateOngoing())
        {            
        // Are we rendering
        UnBindRenderBuffer(renderbuffer);
        // If we really did draw to the renderbuffer, then set it "prepared".
        if (iCanvasGc->Gc())
            {
            iRenderBufferInitialized = ETrue;
            iRenderBufferPrepared = ETrue;
            }    
        }

    iCanvasGc->RestoreFlaggedState();
    
    // Cancel clipping if still active etc...
    iCanvasGc->SetDefaults();    

    // If render buffer is used, draw its content to display here
    if (aUpdateDisplay && renderbuffer && iCanvasGc->Gc())
        {
        THuiRealRect updatedRect = aUpdateRegion.BoundingRect();
        TInt w = 0; 
		TInt h = 0;
        // Handle relative rotation
        if (iVisual->Display())
            {
            TRect displayArea = iVisual->Display()->VisibleArea();
            w = displayArea.Width();
            h = displayArea.Height();
            }
        // ...select right rotation...
        if (iRelativeOrientation == CHuiGc::EOrientationCW90)
            {
            // Rotate around origo and move back to displayarea
            iCanvasGc->Rotate(-90, 0, 0, 1.f);
            iCanvasGc->Translate(-h, 0, 0);
            }
        else if (iRelativeOrientation == CHuiGc::EOrientationCCW90)
            {
            // Rotate around origo and move back to displayarea
            iCanvasGc->Rotate(90, 0, 0, 1.f);
            iCanvasGc->Translate(0, -w, 0);
            }
        else if (iRelativeOrientation == CHuiGc::EOrientation180)
            {
            // Rotate around origo and move back to displayarea
            iCanvasGc->Rotate(180, 0, 0, 1.f);
            iCanvasGc->Translate(-w, -h, 0);            
            }
        else
            {
            // Nothing
            }            
        
        iCanvasGc->ClipRegion(aUpdateRegion);
        THuiCanvasDrawMode dmode = iCanvasGc->DrawMode();
        // blend only transparent windows
        if ((iVisual->Flags() & EHuiVisualFlagOpaqueHint) && !(iVisual->EffectiveOpacity() < 1.0f))
            {
            iCanvasGc->SetDrawMode(EHuiCanvasDrawModeNormal);
            }
        else
            {
            iCanvasGc->SetDrawMode(EHuiCanvasDrawModeBlend);
            }
        
        iCanvasGc->DrawImage(*renderbuffer, updatedRect.iTl);
        iCanvasGc->CancelClipping();
        iCanvasGc->SetDrawMode(dmode);
        }    
    }

void CHuiCanvasWsHwGc::EndScanL(const TRegion& aUpdateRegion, TBool aUpdateDisplay)
    {
    CHuiCanvasRenderBuffer* renderbuffer = NULL;

    // Check if we have cached render buffer available
    if (IsRenderBufferEnabled())
        {
        renderbuffer = iVisual->Env().CanvasTextureCache().FindCachedRenderBuffer(*iVisual);
        }
    
    if (renderbuffer)
        {
        // We can access render buffer, mark it to be available.
        iRenderBufferAvailable = ETrue;
        }
    else
        {
        // We could not access render buffer, mark it to be unavailable.
        iRenderBufferAvailable = EFalse;        
        }
    
    // Cancel clipping if still active etc...
    iCanvasGc->RestoreFlaggedState();
    iCanvasGc->SetDefaults();    
    }


CHuiCanvasGc& CHuiCanvasWsHwGc::CanvasGc() const
	{
	return *iCanvasGc;	
	}
	
THuiCachedGcParams CHuiCanvasWsHwGc::CachedGcParams()
    {
    THuiCachedGcParams params;
    params.iPenColor = iWsPenColor;    
    params.iBrushColor = iWsBrushColor;
    params.iPenStyle = iWsPenStyle;
    params.iDrawMode = iWsDrawMode;
    params.iBrushColor = iWsBrushColor;
    params.iBrushStyle = iWsBrushStyle;
    params.iShadowMode = iWsShadowMode;
    params.iStrikethrough = iWsStrikethrough;
    params.iUnderline = iWsUnderline;
    params.iUserDisplayMode = iWsUserDisplayMode;
    params.iShadowColor = iWsShadowColor;
    return params;        
    }

TInt CHuiCanvasWsHwGc::SetCapturingBufferL(CFbsBitmap* /*aTarget*/)
    {
    // This implementation does not support capturing
    return KErrNotSupported;    
    }

void CHuiCanvasWsHwGc::SetPositionDelta( TPoint& aPoint )
    {
    iPosDelta = aPoint;
    }

TRect CHuiCanvasWsHwGc::RoundedDisplayRect()
    {
    if (iVisual)
        {
        return iVisual->DisplayRect().Round();    
        }
    else
        {
        return TRect(0,0,0,0);    
        }            
    }

void CHuiCanvasWsHwGc::ClearCache()
    {
    if (iVisual)
        {
        iVisual->Env().CanvasTextureCache().ReleaseCachedRenderBuffer(*iVisual);
        }
    }    

TBool CHuiCanvasWsHwGc::IsRenderBufferEnabled() const
    {
    return iRenderBufferEnabled && iRenderBufferAvailable;
    }

TBool CHuiCanvasWsHwGc::IsRenderBufferPrepared() const
    {
    return iRenderBufferEnabled && iRenderBufferAvailable && iRenderBufferPrepared;    
    }

TBool CHuiCanvasWsHwGc::IsRenderBufferInitialized() const
    {
    return iRenderBufferEnabled && iRenderBufferAvailable && iRenderBufferInitialized;    
    }


TBool CHuiCanvasWsHwGc::IsRenderingEnabled() const
    {
    if (iAction == EDrawBuffer)
        {
        return ETrue;
        }
    else if (iAction == EScanBuffer)
        {
        return EFalse;
        }
    else
        {
        return EFalse;
        }
    }

TBool CHuiCanvasWsHwGc::IsRenderBufferUpdateOngoing() const
    {
    return iRenderBufferEnabled && iRenderBufferAvailable && !iRenderBufferPrepared;
    }


TInt CHuiCanvasWsHwGc::EnableRenderbuffer(TBool aEnable)
    {
    // TODO: Some renderers should return KErrNotSupported
    TInt retVal = KErrNone;
    iRenderBufferEnabled = aEnable;
    return retVal;
    }

THuiCanvasWsGcType CHuiCanvasWsHwGc::Type() const
    {
    return EHuiCanvasWsHw;
    }

void CHuiCanvasWsHwGc::ClearCapturingBufferArea(const TRect& /*aRect*/)
    {
    // Not supported by HW GC.
    }

THuiCanvasDrawMode CHuiCanvasWsHwGc::SelectCanvasDrawMode(TInt aWsDrawMode)
    {
    if (aWsDrawMode == MWsGraphicsContext::EDrawModeWriteAlpha)
        {
        return EHuiCanvasDrawModeNormal;            
        }
    else
        {
         return EHuiCanvasDrawModeBlend;
        }    
    }

void CHuiCanvasWsHwGc::EnableUpdateRegion(const TRegion& aUpdateRegion, TBool aClear)
    {
    CHuiGc* gc = iCanvasGc->Gc(); 
    if (gc && IsRenderingEnabled())
        {
        gc->Enable(CHuiGc::EFeatureClipping);
        gc->PushClip();
        gc->Clip(aUpdateRegion);
        if (aClear)
            {
            TInt oldAlpha = gc->PenAlpha();
            TRgb oldColor = gc->PenColor();            
            gc->SetPenAlpha(0);
            gc->SetPenColor(KRgbBlue);
            TRect rect = aUpdateRegion.BoundingRect();
            gc->Clear(rect); 
            gc->SetPenAlpha(oldAlpha);
            gc->SetPenColor(oldColor);
            }
        }
    }

void CHuiCanvasWsHwGc::DisableUpdateRegion()
    {
    CHuiGc* gc = iCanvasGc->Gc(); 
    if (gc && IsRenderingEnabled())
        {    
        gc->PopClip();
        }
    }

static TRect CalculateClipRect(CHuiCanvasRenderBuffer* aRenderbuffer)
    {
    const TInt KHuiDefaultSize = 2048;
    return 
        aRenderbuffer && aRenderbuffer->IsInitialized() ? 
        TRect( aRenderbuffer->Size() ) :
        TRect( TSize( KHuiDefaultSize, KHuiDefaultSize ) );
    }

void CHuiCanvasWsHwGc::BindRenderBuffer(CHuiCanvasRenderBuffer* aRenderbuffer, const TRegion& aUpdateRegion)
    {
    // Disable effective opacity when rendering to a buffer
    iCanvasGc->EnableEffectiveOpacity(EFalse);
    
    THuiRealRect updatedRect = aUpdateRegion.BoundingRect();

    // Bind render buffer as rendering target (further drawing will be redirected to render buffer)
    aRenderbuffer->Bind();

    // Restore gc state after render target bind/unbind ops
    iCanvasGc->RestoreState();

    // Translation values
    TReal32 x = -updatedRect.iTl.iX;
    TReal32 y = -updatedRect.iTl.iY;  
    
    // Push clipping so that we can restore it after we have done drawing into render buffer.
    iCanvasGc->Gc()->PushClip();
    
    // Set new clipping region which does not clip anything. 
    // We want always draw aUpdateRegion fully to the aRenderbuffer. 
            
    iCanvasGc->Gc()->SetClip(CalculateClipRect(aRenderbuffer)); // this call does not transform region anymore
    
    // We use translation to get screen coordinates to match render buffer coordinates
    iCanvasGc->PushTransformationMatrix();
    iCanvasGc->Translate(x, y, 0.f);
        
    // Handle relative rotation
    TRect displayArea = iCanvasGc->Gc()->DisplayArea();
    TInt w = displayArea.Width();
    TInt h = displayArea.Height();
    
    // ...select right rotation...
    if (iRelativeOrientation == CHuiGc::EOrientationCW90)
        {
        // Rotate around origo and move back to displayarea
        iCanvasGc->Rotate(-90, 0, 0, 1.f);
        iCanvasGc->Translate(-h, 0, 0);
        }
    else if (iRelativeOrientation == CHuiGc::EOrientationCCW90)
        {
        // Rotate around origo and move back to displayarea
        iCanvasGc->Rotate(90, 0, 0, 1.f);
        iCanvasGc->Translate(0, -w, 0);
        }
    else if (iRelativeOrientation == CHuiGc::EOrientation180)
        {
        // Rotate around origo and move back to displayarea
        iCanvasGc->Rotate(180, 0, 0, 1.f);
        iCanvasGc->Translate(-w, -h, 0);            
        }
    else
        {
        // Nothing
        }            
        
    // Set needed clip region
    iCanvasGc->Gc()->Clip(aUpdateRegion);
    }

void CHuiCanvasWsHwGc::UnBindRenderBuffer(CHuiCanvasRenderBuffer* aRenderbuffer)
    {
    // Enable effective opacity again when no more rendering to buffer
    iCanvasGc->EnableEffectiveOpacity(ETrue);

    // Restore translation (screen coordinates to match render buffer coordinates)
    iCanvasGc->PopTransformationMatrix();

    // Restore clipping 
    iCanvasGc->Gc()->PopClip();
            
    // Unbind render buffer as rendering target (further drawing will be done to display normally) 
    aRenderbuffer->UnBind();
    
    // Restore gc state after render target bind/unbind ops
    iCanvasGc->RestoreState();
    }

void CHuiCanvasWsHwGc::SetRelativeOrientation(CHuiGc::TOrientation aOrientation)
    {
    iRelativeOrientation = aOrientation;
    }


void CHuiCanvasWsHwGc::UseBrushPattern()
    {
    THuiCachedImageParams cachedImageParams;
    cachedImageParams.iBitmapHandle = iWsBrushPattern;
    cachedImageParams.iGcParams = CachedGcParams();    

    const CHuiCanvasGraphicImage* cachedImage = iVisual->Env().CanvasTextureCache().CreateCachedImageL(cachedImageParams,*iVisual);    
    if (IsRenderingEnabled())
        {
        iCanvasGc->SetPolygonFillTexture(cachedImage->Texture());
        // Symbian implementation for CWindowGc is different from CFbsBitGc. Latter
        // adds iWsOrigin to iWsBrushOrigin, but because we are implementing
        // CWindowGc, we do not take iWsOrigin into account here.
        iCanvasGc->SetPolygonFillTextureOrigin(iWsBrushOrigin); 
        }
    }

void CHuiCanvasWsHwGc::DiscardBrushPattern()
    {
    if (IsRenderingEnabled())
        {
        iCanvasGc->SetPolygonFillTexture(NULL);
        iCanvasGc->SetPolygonFillTextureOrigin(TPoint(0,0));
        }
    }

TBool CHuiCanvasWsHwGc::IsDifferent(const TRgb& aFirst, const TRgb& aSecond, TBool aIgnoreAlpha)
    {
    if (aIgnoreAlpha)
        {
        const TUint32 mask = 0x00FFFFFF;
        return ((aFirst.Internal() & mask) != (aSecond.Internal() & mask));
        }
    else
        {
        return (aFirst.Internal() != aSecond.Internal());
        }    
    }

void CHuiCanvasWsHwGc::UseWsState()
    {
#ifdef __WINS__
    iPushCount++;
    if(iPushCount>1)
        {
        // This function cannot be called recursively. Fix your code.
        USER_INVARIANT();
        }
#endif    
    iOldColor = iCanvasGc->PenColor();            
    iOldOpacity = iCanvasGc->Opacity();
    iOldDrawMode = iCanvasGc->DrawMode();
    iOldPenWidth = iCanvasGc->PenWidth(); 
    iOldPolygonDrawMode = iCanvasGc->PolygonDrawMode();
    
    iCanvasGc->SetPenColor(iWsPenColor);
    iCanvasGc->SetOpacity(TReal32(iWsPenColor.Alpha() / 255.f));
    iCanvasGc->SetDrawMode(SelectCanvasDrawMode(iWsDrawMode));
    iCanvasGc->SetPenWidth(iWsPenSize.iWidth);
    iCanvasGc->PolygonDrawMode();
    }

void CHuiCanvasWsHwGc::UseCanvasState()
    {
#ifdef __WINS__
    iPushCount--;
    if(iPushCount!=0)
        {
        // This function cannot be called recursively. Fix your code.
        USER_INVARIANT();
        }
#endif
    iCanvasGc->SetPenColor(iOldColor);            
    iCanvasGc->SetOpacity(iOldOpacity);
    iCanvasGc->SetDrawMode(iOldDrawMode);
    iCanvasGc->SetPenWidth(iOldPenWidth);
    iCanvasGc->SetPolygonDrawMode(iOldPolygonDrawMode);
    }

TBool CHuiCanvasWsHwGc::IsCacheUpdateNeeded() const
    {
    TBool result = ETrue;
    if ( iVisual )
        {
        result = IsRenderingEnabled() || iVisual->KeepCache();
        }
    return result;
    }

