uiacceltk/hitchcock/coretoolkit/rendervg10/src/HuiVg10Gc.cpp
changeset 0 15bf7259bb7c
child 3 d8a3531bc6b8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uiacceltk/hitchcock/coretoolkit/rendervg10/src/HuiVg10Gc.cpp	Tue Feb 02 07:56:43 2010 +0200
@@ -0,0 +1,2284 @@
+/*
+* Copyright (c) 2006-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:   Implements CHuiVg10Gc, an OpenVG 1.0 version of the HUITK
+*                graphics context.
+*
+*/
+
+
+
+#include "HuiVg10Gc.h"  // Class definition
+#include "HuiVg10RenderPlugin.h"
+#include "HuiVg10Texture.h"
+#include "HuiVg10RenderSurface.h"
+#include "uiacceltk/HuiSegmentedTexture.h"
+#include "uiacceltk/HuiFont.h"
+#include "uiacceltk/HuiImage.h"
+#include "uiacceltk/HuiTextMesh.h"
+#include "uiacceltk/HuiCurvePath.h"
+#include "uiacceltk/HuiTransformation.h"
+#include "uiacceltk/HuiUtil.h"
+#include "uiacceltk/HuiPanic.h"
+#include "uiacceltk/huifixmath.h"
+#include "HuiRenderSurface.h"
+#include "../../CommonInc/uiacceltkdomaincrkeys.h"
+
+#include <e32math.h>
+#include <VG/vgu.h>
+#ifdef __NVG
+#pragma message( "NVG Defined!" )
+    #include <nvg.h>
+    #include <AknIconHeader.h>
+    #include <AknIconUtils.h>
+    #include "NVGIcon.h"
+#endif
+
+const TInt KHuiMaxVgScissorRects = 32;
+
+/** Only render colorful rectangles instead of real graphics 
+ *  content. Useful for debugging broken OpenVG drivers.
+ */
+//#define RENDER_DEBUG_RECTANGLES
+
+CHuiVg10Gc* CHuiVg10Gc::NewL()
+    {
+    CHuiVg10Gc* self = CHuiVg10Gc::NewLC();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+
+CHuiVg10Gc* CHuiVg10Gc::NewLC()
+    {
+    CHuiVg10Gc* self = new (ELeave) CHuiVg10Gc();
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    return self;
+    }
+
+
+CHuiVg10Gc::CHuiVg10Gc()
+        : CHuiGc()
+    {
+    }
+
+
+void CHuiVg10Gc::ConstructL()
+    {
+    // iMatrix stack must be allocated here because InitState() is not allowed to leave
+    
+    iMatrixStack = CHuiMatrixStack::NewL();
+#ifdef __NVG
+    CHuiVg10RenderPlugin& renderer = (CHuiVg10RenderPlugin&) CHuiStatic::Renderer();
+    iNvgEngine = &renderer.NvgEngine();
+#endif    
+    }
+
+
+CHuiVg10Gc::~CHuiVg10Gc()
+    {
+#ifdef __NVG
+    // Don't delete the iNvgEngine, it's owned by the plugin!
+    iNvgEngine = NULL;
+#endif    
+    delete iMatrixStack;
+    
+    vgDestroyPath(iPath);
+    vgDestroyPath(iImagePath);
+    vgDestroyPath(iRectPath);
+    vgDestroyPath(iRoundRectPath);
+    vgDestroyPath(iLinePath);
+    vgDestroyPath(iBorderPath);
+    vgDestroyPath(iArcPath);
+    vgDestroyPaint(iPaint);
+    vgDestroyPaint(iGradientPaint);
+    vgDestroyPath(iEllipsePath);
+    }
+    
+
+void CHuiVg10Gc::Push(THuiGcMatrix aMatrix)
+    {
+    if (aMatrix == EHuiGcMatrixModel)
+        {
+        // Replicate the current OpenVG matrix to the matrix stack
+        UpdateClientMatrix();
+        iMatrixStack->Push();
+        
+        // Save the matrix flags
+        iMatrixFlagsStack.Append(iMatrixFlags);
+        }
+    }
+
+
+void CHuiVg10Gc::Pop(THuiGcMatrix aMatrix)
+    {
+    if (aMatrix == EHuiGcMatrixModel)
+        {
+        // Replicate the current matrix to OpenVG
+        iMatrixStack->Pop();
+        CHuiMatrixStack::TMatrix& matrix = iMatrixStack->Current();
+        vgLoadMatrix((VGfloat*)matrix.iMatrix);
+        
+        // Restore the matrix flags
+        iMatrixFlags = iMatrixFlagsStack[iMatrixFlagsStack.Count() - 1];
+        iMatrixFlagsStack.Remove(iMatrixFlagsStack.Count() - 1);
+        HUI_VG_INVARIANT();
+        }
+    }
+
+
+void CHuiVg10Gc::LoadIdentity(THuiGcMatrix aMatrix)
+    {
+    if (aMatrix == EHuiGcMatrixModel)
+        {
+        vgLoadIdentity();
+        
+        TRect displayArea = DisplayArea();            
+        TInt h = displayArea.Height();
+        TInt w = displayArea.Width();
+
+        // DisplayArea is rotated if orientation is rotated, so we must "counter rotate"
+        // to avoid rotating too much.
+        if(Orientation() == EOrientationCCW90 || Orientation() == EOrientationCW90)
+            {
+            TInt tmp = w;
+            w = h;
+            h = tmp;
+            }
+        
+        // Flip the Y axis to match Hitchcock's coordinate system
+        vgTranslate(0, h); 
+        vgScale(1.0f, -1.0f);
+        
+        if(Orientation() == EOrientationCCW90)
+            {
+            // Rotate around origo and move back to displayarea
+            vgRotate(90);
+            vgTranslate(0, -w);
+            }
+        else if(Orientation() == EOrientationCW90)
+            {            
+            // Rotate around origo and move back to displayarea
+            vgRotate(-90);
+            vgTranslate(-h, 0);
+            }
+        else if (Orientation() == EOrientation180)
+            {
+            // Rotate around origo and move back to displayarea
+            vgRotate(-180);
+            vgTranslate(-w, -h);            
+            }                   
+        else
+            {
+            // Nothing to do ?
+            }
+        
+        // Reset the flags for this matrix
+        iMatrixFlags = 0;
+        
+        HUI_VG_INVARIANT();
+        }
+    }
+
+
+void CHuiVg10Gc::Multiply(THuiGcMatrix aStack, TReal32 aMatrix[16])
+    {
+    if (aStack == EHuiGcMatrixModel)
+        {
+        const VGfloat m[9] = 
+            {
+            aMatrix[0], aMatrix[1], aMatrix[2],
+            aMatrix[4], aMatrix[5], aMatrix[6],
+            aMatrix[8], aMatrix[9], aMatrix[10],
+            };
+        vgMultMatrix(m);
+        HUI_VG_INVARIANT();
+        }
+    }
+
+
+void CHuiVg10Gc::Translate(THuiGcMatrix aMatrix,
+                           TReal32 aX, TReal32 aY, TReal32 /*aZ*/) __SOFTFP
+    {
+    if (aMatrix == EHuiGcMatrixModel)
+        {
+        vgTranslate(aX, aY);
+        HUI_VG_INVARIANT();
+        }
+    }
+
+
+void CHuiVg10Gc::Scale(THuiGcMatrix aMatrix,
+                         TReal32 aX, TReal32 aY, TReal32 /*aZ*/) __SOFTFP
+    {
+    if (aMatrix == EHuiGcMatrixModel)
+        {
+        vgScale(aX, aY);
+        HUI_VG_INVARIANT();
+        }
+    }
+
+void CHuiVg10Gc::Shear(THuiGcMatrix aMatrix,
+                       TReal32 aX, TReal32 aY, TReal32 /*aZ*/) __SOFTFP
+    {
+    if (aMatrix == EHuiGcMatrixModel)
+        {
+        vgShear(aX, aY);
+        HUI_VG_INVARIANT();
+        }
+    }
+
+void CHuiVg10Gc::Rotate(THuiGcMatrix aMatrix, TReal32 aAngle,
+                        TReal32 aX, TReal32 aY, TReal32 aZ) __SOFTFP
+    {
+    if (aMatrix != EHuiGcMatrixModel)
+        {
+        return;
+        }
+
+    // Only rotation around the unit Z axis is supported
+	if (aX != 0.0f || aY != 0.0f || Abs(aZ) != 1.0f)
+	    {
+	    return;
+	    }
+		
+    if (aZ < 0)
+        {
+        aAngle = -aAngle;
+        }
+    
+    iMatrixFlags |= EMatrixFlagsRotation;
+    vgRotate(aAngle);
+    HUI_VG_INVARIANT();
+    }
+
+
+// Replicate the current OpenVG matrix to the matrix stack
+void CHuiVg10Gc::UpdateMatrix(VGMatrixMode aMatrix)
+    {
+    VGfloat m[9];
+    ASSERT(vgGeti(VG_MATRIX_MODE) == VG_MATRIX_IMAGE_USER_TO_SURFACE);
+    vgGetMatrix(m);
+    vgSeti(VG_MATRIX_MODE, aMatrix);
+    vgLoadMatrix(m);
+    vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
+        
+    HUI_VG_INVARIANT();
+    }
+
+void CHuiVg10Gc::UpdateClientMatrix()
+    {
+    // Replicate the current OpenVG matrix to the matrix stack
+    vgGetMatrix((VGfloat*)iMatrixStack->Current().iMatrix);
+    
+    // The matrix is *probably* not an identity transform
+    iMatrixStack->Current().iIsIdentity = EFalse;
+    HUI_VG_INVARIANT();
+    }
+
+void CHuiVg10Gc::CreateVgObjectsL()
+    {
+    // Make sure we have enough resources to work with
+    ASSERT(vgGeti(VG_MAX_SCISSOR_RECTS) >= 1);
+    
+    // Create the default VG objects
+    iPath = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 
+                         5, 8, VG_PATH_CAPABILITY_APPEND_TO);
+    iImagePath = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 
+                              5, 8, VG_PATH_CAPABILITY_APPEND_TO | VG_PATH_CAPABILITY_MODIFY);
+    iArcPath = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 
+                            2, 7, VG_PATH_CAPABILITY_APPEND_TO);
+    iPaint = vgCreatePaint();
+    iGradientPaint = vgCreatePaint();
+    iBlendMode = VG_BLEND_SRC_OVER;
+
+    // Initialize a rectangle path with dummy coordinates
+    iRectPath = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 
+                             5, 8, VG_PATH_CAPABILITY_APPEND_TO | VG_PATH_CAPABILITY_MODIFY);
+
+    iRoundRectPath = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 
+                                 5, 8, VG_PATH_CAPABILITY_APPEND_TO | VG_PATH_CAPABILITY_MODIFY);
+
+    iEllipsePath = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 
+                                 5, 8, VG_PATH_CAPABILITY_APPEND_TO | VG_PATH_CAPABILITY_MODIFY);
+    
+    const VGubyte rectSegments[] =
+        {
+        VG_MOVE_TO_ABS,
+        VG_LINE_TO_REL,
+        VG_LINE_TO_REL,
+        VG_LINE_TO_REL,
+        VG_CLOSE_PATH
+        };
+    const VGfloat rectCoords[] = 
+        {
+         0.0f, 0.0f,             // (x, y)
+         1.0f, 0.0f,             // (width, 0)
+         0.0f, 1.0f,             // (0, height)
+        -1.0f, 0.0f,             // (-width, 0)
+        };
+    vgAppendPathData(iRectPath, 5, rectSegments, rectCoords);
+    vgRemovePathCapabilities(iRectPath, VG_PATH_CAPABILITY_APPEND_TO);
+    vgAppendPathData(iImagePath, 5, rectSegments, rectCoords);
+    vgRemovePathCapabilities(iImagePath, VG_PATH_CAPABILITY_APPEND_TO);
+
+    // Initialize a line path with dummy coordinates
+    iLinePath = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 
+                             2, 4, VG_PATH_CAPABILITY_APPEND_TO | VG_PATH_CAPABILITY_MODIFY);
+    const VGubyte lineSegments[] =
+        {
+        VG_MOVE_TO_ABS,
+        VG_LINE_TO_ABS,
+        };
+    const VGfloat lineCoords[] = 
+        {
+        0.0f, 0.0f,             // (x, y)
+        1.0f, 1.0f,             // (x, y)
+        };
+    vgAppendPathData(iLinePath, 2, lineSegments, lineCoords);
+    vgRemovePathCapabilities(iLinePath, VG_PATH_CAPABILITY_APPEND_TO);
+    
+    // Initialize a path for drawing borders
+    iBorderPath = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 
+                               11, 10 * 2, VG_PATH_CAPABILITY_APPEND_TO | VG_PATH_CAPABILITY_MODIFY);
+
+    const VGubyte borderSegments[12] =
+        {
+        VG_MOVE_TO_ABS,
+        VG_LINE_TO_REL,
+        VG_LINE_TO_REL,
+        VG_LINE_TO_REL,
+        VG_LINE_TO_REL,
+        VG_LINE_TO_REL,
+        VG_LINE_TO_REL,
+        VG_LINE_TO_REL,
+        VG_LINE_TO_REL,
+        VG_LINE_TO_REL,
+        VG_LINE_TO_REL,
+        VG_CLOSE_PATH,
+        };
+
+    const VGfloat borderCoords[10 * 2] = 
+        {
+        0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+        0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+        0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+        0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+        };
+
+    vgAppendPathData(iBorderPath, 12, borderSegments, borderCoords);
+    vgRemovePathCapabilities(iBorderPath, VG_PATH_CAPABILITY_APPEND_TO);
+        
+    // Get hardware configuration
+    TInt hwConf = 0; // the defaulf value for everything is 0 to allow new flags to be defined
+    HuiUtil::GetValueFromCentralRepository( KUIAccelTKHWConfigurationFlags, hwConf );
+    if ( hwConf & KHuiAntialiasing )
+        {
+        SetQuality( EHuiQualityAccurate );
+        }
+    else
+        {
+        SetQuality( EHuiQualityFast );
+        }
+
+    
+    iVgObjectsCreated = ETrue;
+    }
+ 
+void CHuiVg10Gc::InitState()
+    {
+    // Clean matrix stack in case there is anything left
+    // We can't construct a new stack here because we are not allowed to leave.
+    // We keep the original stack and just delete the contents leaving one 
+    // identity matrix that is always added when a new matrix stack is created
+    TInt i = 0;
+    // One identity matrix will remain.
+    // When a new matrix stack is created, one identity matrix is added
+    // It can never be removed, the code would panic.
+    for ( i = 0; i < iMatrixStack->Count() - 2; i++ )
+        {
+        iMatrixStack->Pop(); 
+        }
+    // remove flags from stack, too.
+    iMatrixFlagsStack.Reset();
+
+    iScissorRect = TRect(0, 0, 0, 0);
+    iMatrixFlags = 0;
+    
+    if (!iVgObjectsCreated)
+        {
+        TRAP_IGNORE(CreateVgObjectsL());    
+        }
+
+    // Default paint
+    vgSetParameteri(iPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
+    vgSetPaint(iPaint, VG_FILL_PATH | VG_STROKE_PATH);
+        
+    // Gradient paint
+    vgSetParameteri(iGradientPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_LINEAR_GRADIENT);
+        
+    HUI_VG_INVARIANT();
+    
+    // Reset default state
+    
+    Enable(EFeatureBlending);
+    Disable(EFeatureDepthTest);
+	iStateScissorTest = ETrue;    
+    Disable(EFeatureClipping);
+
+    // Use the image matrix as the primary matrix
+    vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
+
+    RestoreState();
+    HUI_VG_INVARIANT();
+    }
+
+void CHuiVg10Gc::SetQuality(THuiQuality aQuality)
+    {
+    CHuiGc::SetQuality(aQuality);
+    switch (Quality())
+        {
+        case EHuiQualityAccurate:
+            vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_BETTER);
+            vgSeti(VG_IMAGE_QUALITY, VG_IMAGE_QUALITY_BETTER);
+            break;
+        case EHuiQualityFast:
+            vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_FASTER);
+            vgSeti(VG_IMAGE_QUALITY, VG_IMAGE_QUALITY_FASTER);
+            break;
+        default:
+            break;
+        }
+    HUI_VG_INVARIANT();
+    }
+
+void CHuiVg10Gc::SetFillRule( THuiFillMode aFillMode )
+    {   
+    switch (aFillMode)
+       {
+       case EHuiFillNonZero:
+           vgSeti(VG_FILL_RULE, VG_NON_ZERO);
+           break;
+       case EHuiFillEvenOdd:
+           vgSeti(VG_FILL_RULE, VG_EVEN_ODD);
+           break;
+       default:
+           break;
+       }
+    HUI_VG_INVARIANT();   
+    }
+
+void CHuiVg10Gc::RestoreState() const
+    {
+    // Restore paint
+    vgSetPaint(iPaint, VG_FILL_PATH | VG_STROKE_PATH);        
+
+    // Restore scissor test state
+    if(iStateScissorTest)
+        {
+        vgSeti(VG_SCISSORING, VG_TRUE);
+        }
+    else
+        {
+        vgSeti(VG_SCISSORING, VG_FALSE);
+        }
+    
+    // Restore scissor rects
+    // This fixes CHuiFxEffect cached draw
+    TInt count = iClipRegion.Count();
+    VGint coords[KHuiMaxVgScissorRects * 4];
+
+    if(count > KHuiMaxVgScissorRects)
+        {
+        count = KHuiMaxVgScissorRects; //only 32 scissor rects supported    
+        }
+        
+    TInt numberOfCoords = count*4;
+    for ( TInt i = 0, j=0 ; i < numberOfCoords ; j++)
+        { 
+        coords[i++] = iClipRegion[j].iTl.iX;
+        coords[i++] = iClipRegion[j].iTl.iY;
+        coords[i++] = iClipRegion[j].Width();
+        coords[i++] = iClipRegion[j].Height();      
+        }
+    
+    vgSetiv(VG_SCISSOR_RECTS, numberOfCoords, coords);          
+
+    HUI_VG_INVARIANT();
+    }
+
+void CHuiVg10Gc::RestoreFlaggedState() const
+    {
+    // Get the changed stateflags from the renderplugin
+    CHuiVg10RenderPlugin& renderer = (CHuiVg10RenderPlugin&) CHuiStatic::Renderer();
+    TInt flags = renderer.GetRestoreStateFlags();
+    
+    // First a quick check, if nothing needs to be done
+    if(!flags)
+        {
+        return;
+        }
+      
+    // Check each flag and act accrodingly!
+    if(flags & EHuiVg10GcStateFlagDirtyPaint)
+        {
+        // Restore paint
+        vgSetPaint(iPaint, VG_FILL_PATH | VG_STROKE_PATH);
+        }
+
+    if(flags & EHuiVg10GcStateFlagDirtyScissor)
+        {
+        // Restore scissor test state
+        if(iStateScissorTest)
+            {
+            vgSeti(VG_SCISSORING, VG_TRUE);
+            }
+        else
+            {
+            vgSeti(VG_SCISSORING, VG_FALSE);
+            }
+        }
+    
+    if(flags & EHuiVg10GcStateFlagDirtyScissorRects)
+        {
+        // Restore scissor rects
+        TInt count = iClipRegion.Count();
+        VGint coords[KHuiMaxVgScissorRects * 4];
+
+        if(count > KHuiMaxVgScissorRects)
+            {
+            count = KHuiMaxVgScissorRects; //only 32 scissor rects supported    
+            }
+            
+        TInt numberOfCoords = count*4;
+        for ( TInt i = 0, j=0 ; i < numberOfCoords ; j++)
+            { 
+            coords[i++] = iClipRegion[j].iTl.iX;
+            coords[i++] = iClipRegion[j].iTl.iY;
+            coords[i++] = iClipRegion[j].Width();
+            coords[i++] = iClipRegion[j].Height();      
+            }
+        
+        vgSetiv(VG_SCISSOR_RECTS, numberOfCoords, coords);
+        }
+
+    // Clear the flags!
+    renderer.ClearRestoreStateFlags();
+    
+    HUI_VG_INVARIANT();
+    }
+
+void CHuiVg10Gc::UpdateProjection()
+    {
+    // Nothing to do
+    }
+
+
+TInt CHuiVg10Gc::TextureUnits() const
+    {
+    return 1;
+    }
+
+
+void CHuiVg10Gc::SetTextureUnits(TInt /*aTextureUnitCount*/)
+    {
+    // Nothing to do
+    }
+
+
+void CHuiVg10Gc::Enable(TFeature aFeature, TBool aDoEnable)
+    {
+    HUI_VG_INVARIANT();
+
+    switch(aFeature)
+        {
+        case EFeatureDepthTest:
+            // Not supported
+            break;
+
+        case EFeatureDepthWrite:
+            // Not supported
+            break;
+
+        case EFeatureTexturing:
+            // Always enabled
+            break;
+
+        case EFeatureBlending:
+            if(aDoEnable)
+                {
+                vgSeti(VG_BLEND_MODE, iBlendMode);
+                }
+            else
+                {
+                vgSeti(VG_BLEND_MODE, VG_BLEND_SRC);
+                }
+            break;
+
+        case EFeatureClipping:
+            if(aDoEnable)
+                {
+                // enable clipping
+                //if(!iStateScissorTest)
+                	{
+                	iStateScissorTest = ETrue;
+                    vgSeti(VG_SCISSORING, VG_TRUE);
+                	}
+                }
+            else
+                {
+                // disable clipping
+                //if(iStateScissorTest)
+                	{
+                	iStateScissorTest = EFalse;
+                    vgSeti(VG_SCISSORING, VG_FALSE);
+                	}
+                
+                }
+            break;
+
+        case EFeatureAntialias:
+            if(aDoEnable)
+                {
+                vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_BETTER);
+                }
+            else
+                {
+                vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_FASTER);
+                }
+            break;
+
+        case EFeatureFog:
+            // Not supported
+            break;
+
+        default:
+            break;
+        }
+
+    HUI_VG_INVARIANT();
+    }
+
+
+void CHuiVg10Gc::SetBlendMode(TBlendMode aBlendMode)
+    {
+    switch(aBlendMode)
+        {
+        case EBlendAdd:
+            iBlendMode = VG_BLEND_ADDITIVE;
+            break;
+
+        default:
+            iBlendMode = VG_BLEND_SRC_OVER;
+            break;
+        }
+        vgSeti(VG_BLEND_MODE, iBlendMode);
+    }
+
+
+void CHuiVg10Gc::SetTextureMode(TTextureMode aTextureMode, TReal32 /*aParam*/) __SOFTFP
+    {
+    switch(aTextureMode)
+        {
+        case ETextureModeNormal:
+            break;
+
+        default:
+            break;
+        }
+
+    HUI_VG_INVARIANT();
+    }
+
+
+void CHuiVg10Gc::SetDimmingFog(const TRgb& /*aColor*/, TReal32 /*aAmount*/) __SOFTFP
+    {
+    // Fog not supported
+    }
+
+
+void CHuiVg10Gc::Clear()
+    {
+    HUI_VG_INVARIANT();
+    TInt x = ProjectionViewport().iTl.iX;
+    TInt y = ProjectionViewport().iTl.iY;
+    TInt w = ProjectionViewport().Width();
+    TInt h = ProjectionViewport().Height();
+    VGfloat scale = 1.0f / 255.0f;
+    VGfloat color[] = 
+        {
+        PenColor().Red()   * scale,
+        PenColor().Green() * scale,
+        PenColor().Blue()  * scale,
+        PenAlpha() * scale
+        };
+    vgSetfv(VG_CLEAR_COLOR, 4, color);
+    vgClear(x, y, w, h);
+    HUI_VG_INVARIANT();
+    }
+
+	
+void CHuiVg10Gc::ClearDepth()
+    {
+    Clear();
+    }
+
+
+void CHuiVg10Gc::ClearColorAndDepth()
+    {
+    Clear();
+    }
+
+// Do renderer specific initializations of the frame
+void CHuiVg10Gc::InitNewFrame()
+	{
+	LoadIdentity(EHuiGcMatrixModel);
+	}
+
+void CHuiVg10Gc::Clip(const TRect& aClipRect)
+    {
+    THuiRealRect transformed = aClipRect;
+    
+    HUI_DEBUGF4(_L("CHuiVg10Gc::Clip() - aClipRect     (%5i, %5i, %5i, %5i)"),
+                aClipRect.iTl.iX, aClipRect.iTl.iY,
+                aClipRect.iBr.iX, aClipRect.iBr.iY);
+    
+    // Transform the rectangle using our stacks
+    UpdateClientMatrix();
+    iMatrixStack->Current().Multiply(transformed.iTl);
+    iMatrixStack->Current().Multiply(transformed.iBr);
+    
+    // Normalize the rectangle
+    if (transformed.iTl.iX > transformed.iBr.iX)
+    	{
+    	TReal32 tmp = transformed.iTl.iX;
+    	transformed.iTl.iX = transformed.iBr.iX;
+    	transformed.iBr.iX = tmp;
+    	}
+    if (transformed.iTl.iY > transformed.iBr.iY)
+    	{
+    	TReal32 tmp = transformed.iTl.iY;
+    	transformed.iTl.iY = transformed.iBr.iY;
+    	transformed.iBr.iY = tmp;
+    	}
+
+    HUI_DEBUGF4(_L("CHuiVg10Gc::Clip() - Transformed = (%5.0f, %5.0f, %5.0f, %5.0f)"),
+                transformed.iTl.iX, transformed.iTl.iY,
+                transformed.iBr.iX, transformed.iBr.iY);
+
+    CHuiGc::Clip(transformed.Round());
+    HUI_VG_INVARIANT();
+    }
+
+
+void CHuiVg10Gc::SetClip(const TRect& aClipRect)
+    {
+    iScissorRect = aClipRect;
+    iScissorRect.Normalize();
+    
+    CHuiGc::SetClip(iScissorRect);
+
+    VGint coords[4] = 
+        {
+        iScissorRect.iTl.iX,  iScissorRect.iTl.iY,
+        iScissorRect.Width(), iScissorRect.Height()
+        };
+   
+    Enable(EFeatureClipping);    
+    vgSetiv(VG_SCISSOR_RECTS, 4, coords);
+    HUI_VG_INVARIANT();
+    }
+
+void CHuiVg10Gc::Clip(const TRegion& aRegion)
+    {
+    UpdateClientMatrix();
+
+    iTempRegion.Clear();
+    
+    for (TInt i=0; i<aRegion.Count(); i++)
+        {
+        THuiRealRect transformed = aRegion[i];
+        iMatrixStack->Current().Multiply(transformed.iTl);
+        iMatrixStack->Current().Multiply(transformed.iBr);
+        
+        // Normalize the rectangle
+        if (transformed.iTl.iX > transformed.iBr.iX)
+        	{
+        	TReal32 tmp = transformed.iTl.iX;
+        	transformed.iTl.iX = transformed.iBr.iX;
+        	transformed.iBr.iX = tmp;
+        	}
+        if (transformed.iTl.iY > transformed.iBr.iY)
+        	{
+        	TReal32 tmp = transformed.iTl.iY;
+        	transformed.iTl.iY = transformed.iBr.iY;
+        	transformed.iBr.iY = tmp;
+        	}            
+        
+        iTempRegion.AddRect(transformed.Round());
+        }
+	    
+	CHuiGc::Clip(iTempRegion);	    
+    
+    HUI_VG_INVARIANT();
+    }
+    
+void CHuiVg10Gc::SetClipRegion(const TRegion& aRegion)
+    {
+    TInt count = aRegion.Count();
+    VGint coords[KHuiMaxVgScissorRects * 4];
+
+    if(count > KHuiMaxVgScissorRects)
+        {
+        count = KHuiMaxVgScissorRects; //only 32 scissor rects supported    
+        }
+        
+    TInt numberOfCoords = count*4;
+    for ( TInt i = 0, j=0 ; i < numberOfCoords ; j++)
+        { 
+        coords[i++] = aRegion[j].iTl.iX;
+        coords[i++] = aRegion[j].iTl.iY;
+        coords[i++] = aRegion[j].Width();
+        coords[i++] = aRegion[j].Height();      
+        }
+    
+    CHuiGc::SetClipRegion(aRegion);     
+    
+    Enable(EFeatureClipping);    
+    vgSetiv(VG_SCISSOR_RECTS, numberOfCoords, coords);          
+    
+    HUI_VG_INVARIANT();
+    }
+
+void CHuiVg10Gc::CancelClipping()
+    {
+    Disable(EFeatureClipping);    
+    }
+
+void CHuiVg10Gc::DrawText(const CHuiTextMesh& aTextMesh,
+                          const THuiRealRect& aBounds,
+                          TReal32 aShadow) __SOFTFP
+    {
+    CHuiGc::DrawText(aTextMesh, aBounds, aShadow);
+    }
+
+
+/**
+ *  Given a THuiImage, return the corresponding VGImage or 
+ *  VG_INVALID_HANDLE if there is none.
+ */
+static VGImage GetVGImageFromTexture(const MHuiSegmentedTexture& aTexture)
+    {
+    if (aTexture.SegmentCount() == 1)
+        {
+        return (VGImage)aTexture.SegmentName(0);
+        }
+    return VG_INVALID_HANDLE;
+    }
+
+
+/**
+ *  Construct a source rectangle based on the texture coordinates
+ *  specified for an image.
+ */
+static THuiRealRect GetSourceRectangleFromImage(const THuiImage& aImage)
+    {
+    TReal32 texCoords[8];
+    aImage.GetTexCoords(texCoords);
+    THuiRealRect sourceRect;
+    
+    sourceRect.iTl.iX = texCoords[0];
+    sourceRect.iTl.iY = texCoords[1];
+    sourceRect.iBr.iX = texCoords[4];
+    sourceRect.iBr.iY = texCoords[5];
+    
+    return sourceRect;
+    }
+
+void CHuiVg10Gc::DoDrawImage(const THuiImage& aImage,
+                             const THuiRealPoint& aTopLeft,
+                             const THuiRealSize& aSize)
+    {
+    if(!aImage.HasTexture())
+        {
+        return;
+        }
+    
+    // Fetch the texture coordinates from the image
+    THuiRealRect destRect(aTopLeft, aSize);
+    THuiRealRect sourceRect(GetSourceRectangleFromImage(aImage));
+    DrawTexture(aImage.Texture(), sourceRect, destRect);
+    }
+
+
+void CHuiVg10Gc::DoDrawImages(const THuiImage& aImage,
+                                const THuiImage& aImage2,
+                                const THuiRealPoint& aTopLeft,
+                                const THuiRealSize& aSize)
+    {
+    DoDrawImage(aImage,  aTopLeft, aSize);
+    DoDrawImage(aImage2, aTopLeft, aSize);
+    }
+
+
+void CHuiVg10Gc::UpdateColor(TReal32 /*aAlphaFactor*/) __SOFTFP
+    {
+    VGuint color = (PenColor().Internal() << 8) | PenAlpha();
+    
+#if defined(RENDER_DEBUG_RECTANGLES)
+    color = Math::Random() | 0xff;
+#endif
+    
+    // Update the color of the current paint
+    vgSetColor(iPaint, color);
+    
+    // Detect white fully opaque color
+    if (color == 0xffffffff)
+        {
+        vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL);
+        }
+    else
+        {
+        vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_MULTIPLY);
+        }
+    HUI_VG_INVARIANT();
+    }
+
+void CHuiVg10Gc::DrawCroppedTexture(const MHuiSegmentedTexture& aTexture, const THuiRealRect& aSourceRect,
+                                    const THuiRealRect& aDestRect)
+    {
+    // Render state which affects what we do here (roughly decreasing order of probability):
+    // - Source cropping
+    // - Color modulation
+    // - Alpha modulation
+    // - Affine matrix transform (i.e. other than scale or translation)
+    //
+    // Difficult combinations:
+    // - Source cropping with color or alpha modulation
+    //   - Option 1: Create a child image from the cropped region
+    //     - Can't do this because the cropping region is in floating point coords.
+    //     - Performance overhead possibly non-negligible.
+    //   - Option 2: Use scissoring to do the cropping
+    //     - Does not work for rotate/skew transform.
+    //   - Option 3: Use a mask to do the cropping
+    //     - Auxiliary mask bitmap needed, possible performance hit.
+    //   - Option 4: Use a pattern paint
+    //     - Color/alpha modulation requires an offscreen image.
+    // - Resolution: Go with option 2 and option 1 if rotation/skewing is in effect.
+    TSize imageSize = aTexture.Size();
+    VGfloat srcW   = aSourceRect.Width()  * imageSize.iWidth;
+    VGfloat srcH   = aSourceRect.Height() * imageSize.iHeight;
+    VGfloat srcX   = aSourceRect.iTl.iX   * imageSize.iWidth;
+    VGfloat srcY   = aSourceRect.iTl.iY   * imageSize.iHeight;
+
+    // Make sure the source rectangle is not degenerate
+    srcW = Max(1.0f, srcW);
+    srcH = Max(1.0f, srcH);
+    
+    VGfloat scaleX = aDestRect.Width()  / srcW;
+    VGfloat scaleY = aDestRect.Height() / srcH;
+    VGImage image = VG_INVALID_HANDLE;
+    
+	// Check if OpenVg state has changed
+    RestoreFlaggedState();
+    
+#ifdef __NVG
+    const CHuiVg10Texture& texture = static_cast<const CHuiVg10Texture&>( aTexture );
+    TBool isExtended = texture.IsExtended();
+#endif
+    
+    // Getting the vgImage out of the texture
+    image = GetVGImageFromTexture( aTexture );
+    
+    if (iMatrixFlags & EMatrixFlagsRotation)
+        {
+        VGImage tmpImage = vgChildImage(image, (VGint)srcX, imageSize.iHeight - (VGint)srcY - (VGint)srcH, (VGint)srcW, (VGint)srcH);
+        
+        if (tmpImage == VG_INVALID_HANDLE)
+            {
+            HUI_DEBUG(_L("CHuiVg10Gc::DrawCroppedTexture() - Unable to create temporary child image."));
+            // We cannot leave because we are called by a non-leaving exported function
+            // If we cannot draw, we just return without doing anything.
+            return;
+            }
+        HUI_VG_INVARIANT();
+        
+        // Render the child image
+        Push(EHuiGcMatrixModel);
+#if !defined(RENDER_DEBUG_RECTANGLES)
+        vgTranslate(aDestRect.iTl.iX, aDestRect.iTl.iY);
+        vgScale(scaleX, scaleY);
+        vgDrawImage(tmpImage);
+#else
+        TRect d(aDestRect.iTl.iX, aDestRect.iTl.iY, aDestRect.iBr.iX, aDestRect.iBr.iY);
+        DrawRect(d);
+#endif
+        Pop(EHuiGcMatrixModel);
+        
+        vgDestroyImage(tmpImage);
+        HUI_VG_INVARIANT();
+        return;
+        }
+    
+    // Set a scissor rectangle that corresponds with the target rectangle
+    TBool clippingWasEnabled = iStateScissorTest;
+    
+    if (!clippingWasEnabled)
+        {
+        Enable(EFeatureClipping);    
+        }
+    
+    PushClip();
+    Clip(aDestRect);    
+    
+    // Render the image
+    Push(EHuiGcMatrixModel);
+#if !defined(RENDER_DEBUG_RECTANGLES)
+    vgTranslate(aDestRect.iTl.iX, aDestRect.iTl.iY);
+    vgScale(scaleX, scaleY);
+    vgTranslate(-srcX, -srcY);
+
+#ifdef __NVG
+    if ( isExtended && texture.IsNvgContent())
+        {
+        // Determine the size to which we want to draw the NVG icon paths
+        TSize contentSize( HUI_ROUND_FLOAT_TO_INT(aDestRect.Width()),
+                HUI_ROUND_FLOAT_TO_INT(aDestRect.Height()) );
+        UpdateMatrix(VG_MATRIX_PATH_USER_TO_SURFACE);
+        // Draw the NVG data (be it either the object cached commands or the "normal" nvg data)
+        DrawNVG(texture.GetExtendedTextureData(), texture.GetIconCommandsData(), contentSize, EFalse);
+        }
+    else
+        {
+        if (image != VG_INVALID_HANDLE)
+            {
+            //HUI_DEBUG1(_L("HuiVg10Gc::DrawCroppedTexture - drawing with vgDrawImage(%d) instead of DrawNVG"), image);
+            vgDrawImage(image);
+            }
+        else
+            {
+            HUI_DEBUG1(_L("HuiVg10Gc::DrawCroppedTexture - INVALID HANDLE, vgDrawImage() not called!"), image);
+            }
+        }
+#else
+    vgDrawImage(image);
+#endif // __NVG
+
+#else // RENDER_DEBUG_RECTANGLES
+    TRect d(aDestRect.iTl.iX, aDestRect.iTl.iY, aDestRect.iBr.iX, aDestRect.iBr.iY);
+    DrawRect(d);
+#endif
+    HUI_VG_INVARIANT();
+    Pop(EHuiGcMatrixModel);
+    
+    // Restore state
+    PopClip();
+
+    if (!clippingWasEnabled)
+        {
+        Disable(EFeatureClipping);    
+        }
+    
+    HUI_VG_INVARIANT();
+    
+#if 0
+    // Crop implementation using a paint pattern
+    // TODO: Handle color modulation + cropping
+    VGfloat srcW   = aSourceRect.Width()  * aImage.Texture().Size().iWidth;
+    VGfloat srcH   = aSourceRect.Height() * aImage.Texture().Size().iHeight;
+    VGfloat srcX   = aSourceRect.iTl.iX   * aImage.Texture().Size().iWidth;
+    VGfloat srcY   = aSourceRect.iTl.iY   * aImage.Texture().Size().iHeight;
+    VGfloat scaleX = aDestRect.Width()  / srcW;
+    VGfloat scaleY = aDestRect.Height() / srcH;
+    VGImage image  = GetVGImageFromTexture(aTexture);
+
+    vgPaintPattern(iPaint, image);
+    
+    // Transform the paint pattern to fill the destination rectangle as required
+    vgSeti(VG_MATRIX_MODE, VG_MATRIX_FILL_PAINT_TO_USER);
+    vgLoadIdentity();
+    vgTranslate(aDestRect.iTl.iX, aDestRect.iTl.iY);
+    vgScale(scaleX, scaleY);
+    vgTranslate(-srcX, -srcY);
+    vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
+    
+    // Update the path transformation matrix
+    UpdateMatrix(VG_MATRIX_PATH_USER_TO_SURFACE);
+
+    // Draw a rectangle which is filled with the image as a pattern
+    const VGfloat coords[] = 
+        {
+        aDestRect.iTl.iX, aDestRect.iTl.iY,
+        aDestRect.Width(), 0,
+        0, aDestRect.Height(),
+        -aDestRect.Width(), 0,
+        };
+    vgModifyPathCoords(iImagePath, 0, 5, coords);
+    vgDrawPath(iImagePath, VG_FILL_PATH);
+    
+    // Restore the state
+    vgPaintPattern(iPaint, VG_INVALID_HANDLE);
+    UpdateColor();
+    vgSeti(VG_MATRIX_MODE, VG_MATRIX_FILL_PAINT_TO_USER);
+    vgLoadIdentity();
+    vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
+    HUI_VG_INVARIANT();
+#endif
+    }
+
+void CHuiVg10Gc::DrawTexture(const MHuiSegmentedTexture& aTexture, 
+                             const THuiRealRect& aSourceRect, 
+                             const THuiRealRect& aDestRect)
+    {
+    // See if the image is cropped
+    const VGfloat epsilon = 1e-3;
+    if (aSourceRect.iTl.iX > epsilon || 
+        aSourceRect.iTl.iY > epsilon ||
+        aSourceRect.iBr.iX < 1.0f - epsilon ||
+        aSourceRect.iBr.iY < 1.0f - epsilon)
+        {
+        DrawCroppedTexture(aTexture, aSourceRect, aDestRect);
+        return;
+        }
+
+	// Check if OpenVg state has changed
+    RestoreFlaggedState();
+    
+    Push(EHuiGcMatrixModel);
+#if !defined(RENDER_DEBUG_RECTANGLES)
+    vgTranslate(aDestRect.iTl.iX, aDestRect.iTl.iY);
+    
+#ifdef __NVG
+    const CHuiVg10Texture& texture = static_cast<const CHuiVg10Texture&>( aTexture );
+    TBool isExtended = texture.IsExtended();
+    
+    if (isExtended && texture.IsNvgContent())
+        {
+        UpdateMatrix(VG_MATRIX_PATH_USER_TO_SURFACE);
+        TSize contentSize(0, 0);
+        contentSize.SetSize( HUI_ROUND_FLOAT_TO_INT( aDestRect.Width() ),
+            HUI_ROUND_FLOAT_TO_INT( aDestRect.Height() ) );
+        // Draw the NVG data (be it either the object cached commands or the "normal" nvg data)
+        DrawNVG(texture.GetExtendedTextureData(), texture.GetIconCommandsData(), contentSize, EFalse);
+        }
+    else
+        {
+        // "Option C" -way
+        VGfloat scaleX = aDestRect.Width()  / aTexture.Size().iWidth;
+        VGfloat scaleY = aDestRect.Height() / aTexture.Size().iHeight;
+        VGImage image = GetVGImageFromTexture( aTexture );
+
+        if (image != VG_INVALID_HANDLE)
+            {
+            vgScale(scaleX, scaleY);
+            vgDrawImage(image);
+            //HUI_DEBUG1(_L("HuiVg10Gc::DrawTexture - vgDrawImage(%d) drawn!"), image);
+            }
+        else
+            {
+            HUI_DEBUG(_L("HuiVg10Gc::DrawTexture - INVALID HANDLE, vgDrawImage() not called!"));
+            }
+        }
+#else
+    // TODO: Fast paths for unit scale and opaque blending
+    VGfloat scaleX = aDestRect.Width()  / aTexture.Size().iWidth;
+    VGfloat scaleY = aDestRect.Height() / aTexture.Size().iHeight;
+    VGImage image = GetVGImageFromTexture(aTexture);
+    
+    vgScale(scaleX, scaleY);
+    vgDrawImage(image);
+#endif // __NVG
+    
+#else
+    TRect d(aDestRect.iTl.iX, aDestRect.iTl.iY, aDestRect.iBr.iX, aDestRect.iBr.iY);
+    DrawRect(d);
+#endif
+
+    HUI_VG_INVARIANT();
+    Pop(EHuiGcMatrixModel);
+    }
+
+void CHuiVg10Gc::DrawStretchImage(TStretchMode aMode,
+                                  const THuiImage& aImage, 
+                                  const THuiRealRect& aRect,
+                                  TInt aStartWidth, 
+                                  TInt aEndWidth)
+    {
+    if (!aImage.HasTexture())
+        {
+        return;
+        }
+
+    UpdateColor();
+
+    THuiRealPoint aTopLeft(aRect.iTl);
+    THuiRealSize  aSize(aRect.iBr.iX - aRect.iTl.iX, aRect.iBr.iY - aRect.iTl.iY);
+    THuiRealRect sourceRect(GetSourceRectangleFromImage(aImage));
+    THuiRealSize imageSize = aImage.Texture().Size();
+    
+	switch(aMode) 
+		{
+	    case EStretchFull:
+			{
+			DrawTexture(aImage.Texture(), sourceRect, aRect);
+	    	break;
+			}
+				    
+	    case EStretchVertical:
+	        {
+            THuiRealRect destRect(aRect);
+            if (aStartWidth > 0)
+                {
+                THuiRealRect edgeDestRect(aRect);
+                THuiRealRect edgeSourceRect(sourceRect);
+                edgeDestRect.iBr.iY   = edgeDestRect.iTl.iY   + aStartWidth;
+                edgeSourceRect.iBr.iY = edgeSourceRect.iTl.iY + aStartWidth / imageSize.iHeight;
+                DrawTexture(aImage.Texture(), edgeSourceRect, edgeDestRect);
+                destRect.iTl.iY   += aStartWidth;
+                sourceRect.iTl.iY += aStartWidth / imageSize.iHeight;
+                }
+            if (aEndWidth > 0)
+                {
+                THuiRealRect edgeDestRect(aRect);
+                THuiRealRect edgeSourceRect(sourceRect);
+                edgeDestRect.iTl.iY   = edgeDestRect.iBr.iY   - aEndWidth;
+                edgeSourceRect.iTl.iY = edgeSourceRect.iBr.iY - aEndWidth / imageSize.iHeight;
+                DrawTexture(aImage.Texture(), edgeSourceRect, edgeDestRect);
+                destRect.iBr.iY   -= aEndWidth;
+                sourceRect.iBr.iY -= aEndWidth / imageSize.iHeight;
+                }
+            DrawTexture(aImage.Texture(), sourceRect, destRect);
+	        break;
+	        }
+	    case EStretchHorizontal:
+	        {
+            THuiRealRect destRect(aRect);
+            if (aStartWidth > 0)
+                {
+                THuiRealRect edgeDestRect(aRect);
+                THuiRealRect edgeSourceRect(sourceRect);
+                edgeDestRect.iBr.iX   = edgeDestRect.iTl.iX   + aStartWidth;
+                edgeSourceRect.iBr.iX = edgeSourceRect.iTl.iX + aStartWidth / imageSize.iWidth;
+                DrawTexture(aImage.Texture(), edgeSourceRect, edgeDestRect);
+                destRect.iTl.iX   += aStartWidth;
+                sourceRect.iTl.iX += aStartWidth / imageSize.iWidth;
+                }
+            if (aEndWidth > 0)
+                {
+                THuiRealRect edgeDestRect(aRect);
+                THuiRealRect edgeSourceRect(sourceRect);
+                edgeDestRect.iTl.iX   = edgeDestRect.iBr.iX   - aEndWidth;
+                edgeSourceRect.iTl.iX = edgeSourceRect.iBr.iX - aEndWidth / imageSize.iWidth;
+                DrawTexture(aImage.Texture(), edgeSourceRect, edgeDestRect);
+                destRect.iBr.iX   -= aEndWidth;
+                sourceRect.iBr.iX -= aEndWidth / imageSize.iWidth;
+                }
+            DrawTexture(aImage.Texture(), sourceRect, destRect);
+	        break;
+	        }
+	
+	    default:
+	        HUI_DEBUG(_L("CHuiVg10Gc::DrawStretchImage() - ERROR! Tried to use stretch mode that hasn't been implemented. Panicing."));
+		    HUI_PANIC(THuiPanic::ENotImplemented);
+	}
+    
+    HUI_VG_INVARIANT();
+    }
+
+void CHuiVg10Gc::DrawRect(const TRect& aRect)
+    {
+    if (iPaintPattern)
+        {        
+        // Add 0.5 to all coordinates to get them in the middle of pixels 
+        TRect rect = aRect;
+        rect.iTl.iX += 0.5f;
+        rect.iTl.iY += 0.5f;
+        rect.iBr.iX -= 0.5f;
+        rect.iBr.iY -= 0.5f;
+        
+        const VGfloat coords[] = {
+                rect.iTl.iX + 0.5f, rect.iTl.iY + 0.5f,
+                rect.Width(), 0.0f,
+                0.0f, rect.Height(),
+                -rect.Width(), 0.0f,
+            };
+
+        UpdateColor();
+        UpdateMatrix(VG_MATRIX_PATH_USER_TO_SURFACE);
+        
+        UsePaintPattern();
+        
+        vgModifyPathCoords(iRectPath, 0, 4, coords);
+        vgDrawPath(iRectPath, VG_FILL_PATH);
+        
+        // Restore rect path
+        const VGfloat rectCoords[] = 
+            {
+             0.0f, 0.0f,             // (x, y)
+             1.0f, 0.0f,             // (width, 0)
+             0.0f, 1.0f,             // (0, height)
+            -1.0f, 0.0f,             // (-width, 0)
+            };
+
+        vgModifyPathCoords(iRectPath, 0, 4, rectCoords);        
+
+        DiscardPaintPattern();
+        }
+    else
+        {
+        // fast path (doen not work with patterned fill)
+        UpdateColor();
+        UpdateMatrix(VG_MATRIX_PATH_USER_TO_SURFACE);
+        vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
+    
+        vgTranslate(aRect.iTl.iX, aRect.iTl.iY);
+        vgScale(aRect.Width(),aRect.Height());
+    
+        vgDrawPath(iRectPath, VG_FILL_PATH);
+    
+        vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
+        UpdateMatrix(VG_MATRIX_PATH_USER_TO_SURFACE);
+        }
+
+    HUI_VG_INVARIANT();
+    }
+
+void CHuiVg10Gc::DrawPolygon( RArray<THuiRealPoint>& aPoints )
+    {
+    
+    // use the path intended for dynamic shapes
+    // it has type float and can hold any number of segments
+       
+    TInt count = aPoints.Count();
+    VGfloat* coords = NULL;
+    coords = new VGfloat[count * 2];
+    
+    VGubyte* segments = NULL;
+    segments = new VGubyte[count + 1];
+    
+    if ( !coords || !segments )
+        {
+        // ran out of memory, must just return
+        delete[] coords;
+        delete[] segments;
+        return;
+        }
+    
+    for( TInt i = 0; i < count; i++ )
+    	{
+	    coords[2 * i] = aPoints[i].iX;
+	    coords[2 * i + 1] = aPoints[i].iY;
+	    segments[i] = VG_LINE_TO_ABS;
+    	}
+    // fix the first segment into move instead of draw	
+    segments[0] = VG_MOVE_TO_ABS;
+    // the last segment closes the path to get a solid object
+    segments[count] = VG_CLOSE_PATH;
+    
+    UpdateColor();
+    UpdateMatrix( VG_MATRIX_PATH_USER_TO_SURFACE );
+    
+    UsePaintPattern(); 
+    
+    vgAppendPathData( iPath, count + 1, segments, coords);
+
+    vgDrawPath( iPath, VG_FILL_PATH );
+    vgClearPath( iPath, VG_PATH_CAPABILITY_APPEND_TO );
+
+    DiscardPaintPattern();
+    
+    // don't leak memory
+    delete[] coords;
+    delete[] segments;
+        
+    HUI_VG_INVARIANT();
+
+    }    
+
+void CHuiVg10Gc::DrawLine(const TPoint& aStart,
+                          const TPoint& aEnd,
+                          const TInt aThickness)
+    {
+
+    // Add 0.5 to all coordinates to get them in the middle of pixels 
+    const VGfloat coords[] = {
+            aStart.iX + 0.5f, aStart.iY + 0.5f,
+            aEnd.iX + 0.5f, aEnd.iY + 0.5f,
+        };
+    
+    UpdateColor();
+    UpdateMatrix(VG_MATRIX_PATH_USER_TO_SURFACE);
+    
+    vgModifyPathCoords(iLinePath, 0, 2, coords);
+    vgSeti(VG_STROKE_CAP_STYLE, VG_CAP_SQUARE);
+    vgSeti(VG_STROKE_LINE_WIDTH, aThickness);
+    vgDrawPath(iLinePath, VG_STROKE_PATH);
+    HUI_VG_INVARIANT();
+    }
+
+void CHuiVg10Gc::DrawEllipse(const TRect& aRect, THuiFillMode aDrawMode, const TInt aThickness)
+    {
+    // Fix given destination rect to be in th middle of openvg pixels
+    THuiRealRect destinationRect = aRect;
+    destinationRect.iTl.iX += 0.5f;
+    destinationRect.iTl.iY += 0.5f;
+    destinationRect.iBr.iX -= 0.5f;
+    destinationRect.iBr.iY -= 0.5f;
+    
+    VGfloat alpha = PenAlpha();
+    vgClearPath(iEllipsePath, VG_PATH_CAPABILITY_APPEND_TO);
+    
+    VGfloat cx = (destinationRect.iTl.iX + destinationRect.iBr.iX) / 2.f; 
+    VGfloat cy  = (destinationRect.iTl.iY + destinationRect.iBr.iY) / 2.f;
+    VGfloat width = destinationRect.Width();
+    VGfloat height = destinationRect.Height();
+    
+    vguEllipse(iEllipsePath, cx, cy, width, height);
+   
+    UpdateColor();
+    UpdateMatrix(VG_MATRIX_PATH_USER_TO_SURFACE);
+    
+    TInt oldThickness = vgGeti(VG_STROKE_LINE_WIDTH);
+    if(oldThickness != aThickness)
+        {
+        vgSeti(VG_STROKE_LINE_WIDTH, aThickness);
+        }
+    VGPaint paint;
+    if (aDrawMode != EHuiNoFill)
+        {
+        paint = vgGetPaint(VG_FILL_PATH);
+        }
+     else
+        {
+        paint = vgGetPaint(VG_STROKE_PATH);
+        }
+
+    VGfloat color[4], modifiedColor[4];
+    
+    if (paint != VG_INVALID_HANDLE)
+       {
+       vgGetParameterfv(paint, VG_PAINT_COLOR, 4, color);
+       if (color[3]!=alpha)
+           {
+           modifiedColor[0] = color[0];
+           modifiedColor[1] = color[1];
+           modifiedColor[2] = color[2];
+           modifiedColor[3] = alpha;
+           vgSetParameterfv(paint, VG_PAINT_COLOR, 4, modifiedColor);
+           }
+       else
+           {
+           // no reason to set back the old color. it is the same.
+           paint = VG_INVALID_HANDLE; 
+           }
+       }
+
+    UsePaintPattern();
+    
+    if (aDrawMode != EHuiNoFill)
+        {
+        vgDrawPath(iEllipsePath, VG_FILL_PATH);
+        }
+    else
+        {
+        vgDrawPath(iEllipsePath, VG_STROKE_PATH);
+        }
+
+    DiscardPaintPattern();
+    
+    if (paint != VG_INVALID_HANDLE)
+        {
+        vgSetParameterfv(paint, VG_PAINT_COLOR, 4, color);
+        HUI_VG_INVARIANT();
+        }
+    if(oldThickness != aThickness)
+        {
+        vgSeti(VG_STROKE_LINE_WIDTH, oldThickness);
+        }
+    HUI_VG_INVARIANT();
+    
+    }
+
+void CHuiVg10Gc::DrawArc(const TRect& aRect, THuiFillMode aDrawMode, const TInt aThickness, TReal32 aStart, TReal32 aEnd, TBool aIsPie)
+    {
+    // Fix given destination rect to be in th middle of openvg pixels
+    THuiRealRect destinationRect = aRect;
+    destinationRect.iTl.iX += 0.5f;
+    destinationRect.iTl.iY += 0.5f;
+    destinationRect.iBr.iX -= 0.5f;
+    destinationRect.iBr.iY -= 0.5f;
+    
+    VGfloat alpha = PenAlpha() / 255.f;
+    vgClearPath(iArcPath, VG_PATH_CAPABILITY_APPEND_TO);
+    
+    VGfloat cx = (destinationRect.iTl.iX + destinationRect.iBr.iX) / 2.f; 
+    VGfloat cy  = (destinationRect.iTl.iY + destinationRect.iBr.iY) / 2.f;
+    VGfloat width = destinationRect.Width();
+    VGfloat height = destinationRect.Height();
+    
+    VGUArcType arcType = aIsPie ? VGU_ARC_PIE : VGU_ARC_OPEN;
+
+    // Ready to draw the arc. Note that in OpenVG, y axis points upwards. Anti-clockwise goes
+    // is towards positive direction. The method CHuiVg10CanvasGc::DoDrawPieAndArc made sure that 
+    // angleExtent is always positive.
+    TReal32 angleExtent = aEnd - aStart;
+    vguArc(iArcPath, cx, cy, width, height, aStart, angleExtent, arcType);
+   
+    UpdateColor();
+    UpdateMatrix(VG_MATRIX_PATH_USER_TO_SURFACE);
+    
+    TInt oldThickness = vgGeti(VG_STROKE_LINE_WIDTH);
+    if(oldThickness != aThickness)
+        {
+        vgSeti(VG_STROKE_LINE_WIDTH, aThickness);
+        }
+    VGPaint paint;
+    if (aDrawMode != EHuiNoFill)
+        {
+        paint = vgGetPaint(VG_FILL_PATH);
+        }
+     else
+        {
+        paint = vgGetPaint(VG_STROKE_PATH);
+        }
+
+    VGfloat color[4], modifiedColor[4];
+    
+    if (paint != VG_INVALID_HANDLE)
+       {
+       vgGetParameterfv(paint, VG_PAINT_COLOR, 4, color);
+       if (color[3]!=alpha) 
+           {
+           modifiedColor[0] = color[0];
+           modifiedColor[1] = color[1];
+           modifiedColor[2] = color[2];
+           modifiedColor[3] = alpha;
+           vgSetParameterfv(paint, VG_PAINT_COLOR, 4, modifiedColor);
+           }
+       else
+           {
+           // no reason to set back the old color. it is the same.
+           paint = VG_INVALID_HANDLE; 
+           }
+       }
+
+    UsePaintPattern();
+    
+    if (aDrawMode != EHuiNoFill)
+        {
+        vgDrawPath(iArcPath, VG_FILL_PATH);
+        }
+    else
+        {
+        vgDrawPath(iArcPath, VG_STROKE_PATH);
+        }
+
+    DiscardPaintPattern();
+    
+    // Restore old values
+    if (paint != VG_INVALID_HANDLE)
+        {
+        vgSetParameterfv(paint, VG_PAINT_COLOR, 4, color);
+        HUI_VG_INVARIANT();
+        }
+    if(oldThickness != aThickness)
+        {
+        vgSeti(VG_STROKE_LINE_WIDTH, oldThickness);
+        }
+    HUI_VG_INVARIANT();
+    
+    }
+
+void CHuiVg10Gc::DrawRoundRect(const TRect& aDestinationRect, const THuiRealSize& aSize, THuiFillMode aDrawMode, const TInt aThickness)
+    {
+    // Fix given destination rect to be in th middle of openvg pixels
+    THuiRealRect destinationRect = aDestinationRect;
+    destinationRect.iTl.iX += 0.5f;
+    destinationRect.iTl.iY += 0.5f;
+    destinationRect.iBr.iX -= 0.5f;
+    destinationRect.iBr.iY -= 0.5f;
+    
+    VGfloat alpha = PenAlpha();
+    vgClearPath(iRoundRectPath, VG_PATH_CAPABILITY_APPEND_TO);
+    vguRoundRect(iRoundRectPath, destinationRect.iTl.iX, destinationRect.iTl.iY, destinationRect.Width(), destinationRect.Height(), aSize.iWidth, aSize.iHeight);
+   
+    UpdateColor();
+    UpdateMatrix(VG_MATRIX_PATH_USER_TO_SURFACE);
+    
+    TInt oldThickness = vgGeti(VG_STROKE_LINE_WIDTH);
+    if(oldThickness != aThickness)
+        {
+        vgSeti(VG_STROKE_LINE_WIDTH, aThickness);
+        }
+    VGPaint paint;
+    if (aDrawMode != EHuiNoFill)
+        {
+        paint = vgGetPaint(VG_FILL_PATH);
+        }
+     else
+        {
+        paint = vgGetPaint(VG_STROKE_PATH);
+        }
+
+    VGfloat color[4], modifiedColor[4];
+    
+    if (paint != VG_INVALID_HANDLE)
+       {
+       vgGetParameterfv(paint, VG_PAINT_COLOR, 4, color);
+       if (color[3]!=alpha)
+           {
+           modifiedColor[0] = color[0];
+           modifiedColor[1] = color[1];
+           modifiedColor[2] = color[2];
+           modifiedColor[3] = alpha;
+           vgSetParameterfv(paint, VG_PAINT_COLOR, 4, modifiedColor);
+           }
+       else
+           {
+           // no reason to set back the old color. it is the same.
+           paint = VG_INVALID_HANDLE; 
+           }
+       }
+
+    UsePaintPattern();
+    
+    if (aDrawMode != EHuiNoFill)
+        {
+        vgDrawPath(iRoundRectPath, VG_FILL_PATH);
+        }
+    else
+        {
+        vgDrawPath(iRoundRectPath, VG_STROKE_PATH);
+        }
+
+    DiscardPaintPattern();
+    
+    if (paint != VG_INVALID_HANDLE)
+        {
+        vgSetParameterfv(paint, VG_PAINT_COLOR, 4, color);
+        HUI_VG_INVARIANT();
+        }
+    if(oldThickness != aThickness)
+        {
+        vgSeti(VG_STROKE_LINE_WIDTH, oldThickness);
+        }
+    HUI_VG_INVARIANT();
+    }
+
+void CHuiVg10Gc::DrawBorders(const TRect& aOuterRect, 
+				  TReal32 aLeftBorderWidth,
+                  TReal32 aRightBorderWidth, 
+				  TReal32 aTopBorderHeight,
+                  TReal32 aBottomBorderHeight, 
+                  TBorderMode aBorderMode,
+                  const THuiImage* aImage) __SOFTFP
+	{	
+    UpdateColor();
+    
+    if (aBorderMode == EBorderImage)
+        {
+        TReal32 avgBorderWidth     = (aLeftBorderWidth + aRightBorderWidth) * .5f;
+        TReal32 avgBorderHeight    = (aTopBorderHeight + aBottomBorderHeight) * .5f;
+        THuiRealPoint borderOffset = THuiRealPoint((aRightBorderWidth   - aLeftBorderWidth) * .5f,
+                                                   (aBottomBorderHeight - aTopBorderHeight) * .5f);
+        DrawBorderImages(aOuterRect, avgBorderWidth, avgBorderHeight, borderOffset, aImage);
+        }
+    else if (aBorderMode == EBorderFixedCorners)
+        {
+        DrawBorderFixedCorners(aOuterRect, aLeftBorderWidth, aRightBorderWidth, 
+                               aTopBorderHeight, aBottomBorderHeight, aImage);
+        }
+    else
+        {
+        // We cannot leave here because we are a non-leaving function,
+        // and we cannot return an error either. 
+        // If the caller gives us invalid parameters, we do nothing.
+        return;
+        }
+
+    HUI_VG_INVARIANT();
+	}
+
+void CHuiVg10Gc::DrawBorderImages(const TRect& aOuterRect,
+                                  TReal32 aBorderWidth,
+                                  TReal32 aBorderHeight, 
+                                  THuiRealPoint aOffset,
+                                  const THuiImage* aImage)
+    {
+    // If there is no image, draw a solid border
+    if (!aImage || !aImage->HasTexture())
+        {
+        //
+        // The border is drawn like this:
+        //
+        //      +-----------------+
+        //      |                 |
+        //      +---+---------+   |
+        //      |   |         |   |
+        //      |   |         |   |
+        //      |   |         |   |
+        //      |   |         |   |
+        //      |   +---------+   |
+        //      |                 |
+        //      +-----------------+
+        //
+        // We do not use a path with a hole, because some of the edges might become too thin.
+        //
+        TReal32 w = aOuterRect.Width();
+        TReal32 h = aOuterRect.Height();
+
+        const VGfloat borderCoords[10 * 2] = 
+            {
+            aOuterRect.iTl.iX, aOuterRect.iTl.iY,
+            w, 0.0f,
+            0.0f, h,
+            -w, 0.0f,
+            0.0f, -h + aBorderWidth,
+            aBorderWidth, 0.0f,
+            0.0f, h - aBorderHeight - aBorderHeight,
+            w - aBorderHeight - aBorderHeight, 0.0f,
+            0.0f, -h + aBorderHeight + aBorderHeight,
+            -w + aBorderWidth, 0.0f,
+            };
+
+        UpdateMatrix(VG_MATRIX_PATH_USER_TO_SURFACE);
+        vgModifyPathCoords(iBorderPath, 0, 12, borderCoords);
+        vgDrawPath(iBorderPath, VG_FILL_PATH);
+        
+        HUI_VG_INVARIANT();
+        return;
+        }
+    
+    THuiRealRect texCoords = GetSourceRectangleFromImage(*aImage);
+    THuiRealPoint midTexCoord((texCoords.iTl.iX + texCoords.iBr.iX) * .5f,
+                              (texCoords.iTl.iY + texCoords.iBr.iY) * .5f);
+
+    THuiRealRect outerRect(aOuterRect);
+    outerRect.iTl += aOffset;
+    outerRect.iBr += aOffset;
+    THuiRealRect innerRect(aOuterRect);
+    innerRect.Shrink(aBorderWidth, aBorderHeight);
+
+    // Top left segment
+    DrawCroppedTexture(aImage->Texture(), 
+                       THuiRealRect(texCoords.iTl, midTexCoord), 
+                       THuiRealRect(outerRect.iTl, innerRect.iTl));
+
+    // Top segment
+    DrawCroppedTexture(aImage->Texture(), 
+                       THuiRealRect(THuiRealPoint(midTexCoord.iX, texCoords.iTl.iY), midTexCoord),
+                       THuiRealRect(THuiRealPoint(innerRect.iTl.iX, outerRect.iTl.iY), innerRect.TopRight()));
+
+    // Top right segment
+    DrawCroppedTexture(aImage->Texture(), 
+                       THuiRealRect(THuiRealPoint(midTexCoord.iX, texCoords.iTl.iY),
+                                    THuiRealPoint(texCoords.iBr.iX, midTexCoord.iY)),
+                       THuiRealRect(THuiRealPoint(innerRect.iBr.iX, outerRect.iTl.iY),
+                                    THuiRealPoint(outerRect.iBr.iX, innerRect.iTl.iY)));
+
+    // Right segment
+    DrawCroppedTexture(aImage->Texture(), 
+                       THuiRealRect(midTexCoord, 
+                                    THuiRealPoint(texCoords.iBr.iX, midTexCoord.iY)),
+                       THuiRealRect(innerRect.TopRight(),
+                                    THuiRealPoint(outerRect.iBr.iX, innerRect.iBr.iY)));
+
+    // Bottom right segment
+    DrawCroppedTexture(aImage->Texture(), 
+                       THuiRealRect(midTexCoord, texCoords.iBr),
+                       THuiRealRect(innerRect.iBr, outerRect.iBr));
+
+    // Bottom segment
+    DrawCroppedTexture(aImage->Texture(), 
+                       THuiRealRect(midTexCoord, 
+                                    THuiRealPoint(midTexCoord.iX, texCoords.iBr.iY)),
+                       THuiRealRect(innerRect.BottomLeft(),
+                                    THuiRealPoint(innerRect.iBr.iX, outerRect.iBr.iY)));
+
+    // Bottom left segment
+    DrawCroppedTexture(aImage->Texture(), 
+                       THuiRealRect(THuiRealPoint(texCoords.iTl.iX, midTexCoord.iY),
+                                    THuiRealPoint(midTexCoord.iX, texCoords.iBr.iY)),
+                       THuiRealRect(THuiRealPoint(outerRect.iTl.iX, innerRect.iBr.iY),
+                                    THuiRealPoint(innerRect.iTl.iX, outerRect.iBr.iY)));
+
+    // Left segment
+    DrawCroppedTexture(aImage->Texture(), 
+                       THuiRealRect(THuiRealPoint(texCoords.iTl.iX, midTexCoord.iY), 
+                                    midTexCoord),
+                       THuiRealRect(THuiRealPoint(outerRect.iTl.iX, innerRect.iTl.iY),
+                                    innerRect.BottomLeft()));
+    HUI_VG_INVARIANT();
+    }
+
+void CHuiVg10Gc::DrawBorderFixedCorners(const TRect& aOuterRect, 
+                                        TReal32 aLeftBorderWidth,
+                                        TReal32 aRightBorderWidth, 
+                                        TReal32 aTopBorderHeight,
+                                        TReal32 aBottomBorderHeight, 
+                                        const THuiImage* aImage)
+    {
+    // If there is no image, draw a solid border
+    if (!aImage || !aImage->HasTexture())
+        {
+        //
+        // The border is drawn like this:
+        //
+        //      +-----------------+
+        //      |                 |
+        //      +---+---------+   |
+        //      |   |         |   |
+        //      |   |         |   |
+        //      |   |         |   |
+        //      |   |         |   |
+        //      |   +---------+   |
+        //      |                 |
+        //      +-----------------+
+        //
+        // We do not use a path with a hole, because some of the edges might become too thin.
+        //
+        TReal32 w = aOuterRect.Width();
+        TReal32 h = aOuterRect.Height();
+
+        const VGfloat borderCoords[10 * 2] = 
+            {
+            aOuterRect.iTl.iX, aOuterRect.iTl.iY,
+            w, 0.0f,
+            0.0f, h,
+            -w, 0.0f,
+            0.0f, -h + aTopBorderHeight,
+            aLeftBorderWidth, 0.0f,
+            0.0f, h - aTopBorderHeight - aBottomBorderHeight,
+            w - aLeftBorderWidth - aRightBorderWidth, 0.0f,
+            0.0f, -h + aTopBorderHeight + aBottomBorderHeight,
+            -w + aRightBorderWidth, 0.0f,
+            };
+
+        UpdateMatrix(VG_MATRIX_PATH_USER_TO_SURFACE);
+        vgModifyPathCoords(iBorderPath, 0, 12, borderCoords);
+        vgDrawPath(iBorderPath, VG_FILL_PATH);
+        
+        HUI_VG_INVARIANT();
+        return;
+        }
+    
+    THuiRealRect texCoords = GetSourceRectangleFromImage(*aImage);
+    THuiRealRect innerTexCoords(texCoords);
+    THuiRealSize texSize = aImage->Texture().Size();
+    THuiRealRect outerRect(aOuterRect);
+    THuiRealRect innerRect(aOuterRect);
+    
+    innerTexCoords.iTl.iX += aLeftBorderWidth    / texSize.iWidth;
+    innerTexCoords.iTl.iY += aTopBorderHeight    / texSize.iHeight;
+    innerTexCoords.iBr.iX -= aRightBorderWidth   / texSize.iWidth;
+    innerTexCoords.iBr.iY -= aBottomBorderHeight / texSize.iHeight;
+
+    innerRect.iTl.iX += aLeftBorderWidth;
+    innerRect.iTl.iY += aTopBorderHeight;
+    innerRect.iBr.iX -= aRightBorderWidth;
+    innerRect.iBr.iY -= aBottomBorderHeight;
+
+    // Top left segment
+    if (aTopBorderHeight > 0.0f && aLeftBorderWidth > 0.0f)
+        {
+        DrawCroppedTexture(aImage->Texture(), 
+                         THuiRealRect(texCoords.iTl, innerTexCoords.iTl), 
+                         THuiRealRect(outerRect.iTl, innerRect.iTl));
+        }
+
+    // Top segment
+    if (aTopBorderHeight > 0.0f)
+        {
+        DrawCroppedTexture(aImage->Texture(), 
+                           THuiRealRect(THuiRealPoint(innerTexCoords.iTl.iX, texCoords.iTl.iY), 
+                                        innerTexCoords.TopRight()),
+                           THuiRealRect(THuiRealPoint(innerRect.iTl.iX, outerRect.iTl.iY), 
+                                        innerRect.TopRight()));
+        }
+
+    // Top right segment
+    if (aTopBorderHeight > 0.0f && aRightBorderWidth > 0.0f)
+        {
+        DrawCroppedTexture(aImage->Texture(), 
+                           THuiRealRect(THuiRealPoint(innerTexCoords.iBr.iX, texCoords.iTl.iY),
+                                        THuiRealPoint(texCoords.iBr.iX, innerTexCoords.iTl.iY)),
+                           THuiRealRect(THuiRealPoint(innerRect.iBr.iX, outerRect.iTl.iY),
+                                        THuiRealPoint(outerRect.iBr.iX, innerRect.iTl.iY)));
+        }
+
+    // Right segment
+    if (aRightBorderWidth > 0.0f)
+        {
+        DrawCroppedTexture(aImage->Texture(), 
+                           THuiRealRect(innerTexCoords.TopRight(), 
+                                        THuiRealPoint(texCoords.iBr.iX, innerTexCoords.iBr.iY)),
+                           THuiRealRect(innerRect.TopRight(),
+                                        THuiRealPoint(outerRect.iBr.iX, innerRect.iBr.iY)));
+        }
+
+    // Bottom right segment
+    if (aBottomBorderHeight > 0.0f && aRightBorderWidth > 0.0f)
+        {
+        DrawCroppedTexture(aImage->Texture(), 
+                           THuiRealRect(innerTexCoords.iBr, texCoords.iBr),
+                           THuiRealRect(innerRect.iBr, outerRect.iBr));
+        }
+
+    // Bottom segment
+    if (aRightBorderWidth > 0.0f)
+        {
+        DrawCroppedTexture(aImage->Texture(), 
+                           THuiRealRect(innerTexCoords.BottomLeft(),
+                                        THuiRealPoint(innerTexCoords.iBr.iX, texCoords.iBr.iY)),
+                           THuiRealRect(innerRect.BottomLeft(),
+                                        THuiRealPoint(innerRect.iBr.iX, outerRect.iBr.iY)));
+        }
+
+    // Bottom left segment
+    if (aBottomBorderHeight > 0.0f && aRightBorderWidth > 0.0f)
+        {
+        DrawCroppedTexture(aImage->Texture(), 
+                           THuiRealRect(THuiRealPoint(texCoords.iTl.iX, innerTexCoords.iBr.iY),
+                                        THuiRealPoint(innerTexCoords.iTl.iX, texCoords.iBr.iY)),
+                           THuiRealRect(THuiRealPoint(outerRect.iTl.iX, innerRect.iBr.iY),
+                                        THuiRealPoint(innerRect.iTl.iX, outerRect.iBr.iY)));
+        }
+
+    // Left segment
+    if (aLeftBorderWidth > 0.0f)
+        {
+        DrawCroppedTexture(aImage->Texture(), 
+                           THuiRealRect(THuiRealPoint(texCoords.iTl.iX, innerTexCoords.iTl.iY), 
+                                        innerTexCoords.BottomLeft()),
+                           THuiRealRect(THuiRealPoint(outerRect.iTl.iX, innerRect.iTl.iY),
+                                        innerRect.BottomLeft()));
+        }
+    HUI_VG_INVARIANT();
+    }
+
+void CHuiVg10Gc::DrawPath(const CHuiCurvePath& aPath,
+                            const TPoint& aOrigin,
+                            TReal32 aStartPos,
+                            TReal32 aEndPos,
+                            MHuiMappingFunction* aAlphaFunction,
+                            MHuiMappingFunction* aWidthFunction) __SOFTFP
+    {
+    // Refresh the vertices.
+    CHuiCurvePath* nonConstCurvePath = const_cast<CHuiCurvePath*>(&aPath);
+    nonConstCurvePath->Update(aStartPos, aEndPos, PenAlpha() / 255.f,
+                              aAlphaFunction, aWidthFunction);
+
+    aPath.Draw(aOrigin, this);
+    HUI_VG_INVARIANT();
+    }
+
+
+void CHuiVg10Gc::DrawMesh(const CHuiMesh& /*aMesh*/, const THuiImage* /*aImage*/,
+                            const THuiImage* /*aSecondaryImage*/,
+                            TReal32 /*aSecondaryAlpha*/) __SOFTFP
+    {
+    HUI_DEBUGF(_L("CHuiVg10Gc::DrawMesh() - Method has not been implemented! Sorry."));     
+    }
+
+void CHuiVg10Gc::DrawArc(const TPoint& /*aOrigin*/, const TSize& /*aRadius*/,
+                           TReal32 /*aEnd*/, TReal32 /*aStart*/, TInt /*aAnglePerSegment*/,
+                           TReal32 /*aWidth*/, const THuiImage& /*aImage*/,
+                           TReal32 (aAlphaFunc)(TReal32), TBool /*aAbsoluteAngleParm*/) __SOFTFP
+    {
+	 // not supported
+	aAlphaFunc(1.0); // just to disable compiler warning
+    return;
+    }
+
+
+
+void CHuiVg10Gc::DrawGradient(TGradientType aType, const TRect& aRect,
+                              const TRgb& aStartColor, const TRgb& aEndColor,
+                              TReal32 aStartOpacity, TReal32 aEndOpacity,
+                              const THuiRealRect* aTexCoords) __SOFTFP
+    {
+    VGfloat gradientCoords[4];
+    VGfloat x1 = (VGfloat)aRect.iTl.iX;
+    VGfloat y1 = (VGfloat)aRect.iTl.iY;
+    VGfloat x2 = (VGfloat)aRect.iBr.iX;
+    VGfloat y2 = (VGfloat)aRect.iBr.iY;
+    
+    switch (aType)
+        {
+        case EGradientLinearUp:
+            gradientCoords[0] = x1;  gradientCoords[1] = y2;
+            gradientCoords[2] = x1;  gradientCoords[3] = y1;
+            break;
+        case EGradientLinearRight:
+            gradientCoords[0] = x1;  gradientCoords[1] = y1;
+            gradientCoords[2] = x2;  gradientCoords[3] = y1;
+            break;
+        case EGradientLinearDown:
+            gradientCoords[0] = x1;  gradientCoords[1] = y1;
+            gradientCoords[2] = x1;  gradientCoords[3] = y2;
+            break;
+        case EGradientLinearLeft:
+            gradientCoords[0] = x2;  gradientCoords[1] = y1;
+            gradientCoords[2] = x1;  gradientCoords[3] = y1;
+            break;
+        }
+
+    VGfloat scale = 1.0f / 255.0f;
+    const VGfloat gradientStops[] =
+        {
+        0.0f,  aStartColor.Red() * scale, aStartColor.Green() * scale, aStartColor.Blue() * scale, aStartOpacity,
+        1.0f,  aEndColor.Red()   * scale, aEndColor.Green()   * scale, aEndColor.Blue()   * scale, aEndOpacity,
+        };
+    
+    vgSetParameterfv(iGradientPaint, VG_PAINT_LINEAR_GRADIENT, 2 * 2, gradientCoords);
+    vgSetParameterfv(iGradientPaint, VG_PAINT_COLOR_RAMP_STOPS, 2 * 5, gradientStops);
+    vgSetPaint(iGradientPaint, VG_FILL_PATH);
+    HUI_VG_INVARIANT();
+
+    UpdateColor();
+    UpdateMatrix(VG_MATRIX_PATH_USER_TO_SURFACE);
+    
+    // Draw the gradient as an image if we have a texture, otherwise draw a regular rectangle
+    if (aTexCoords)
+        {
+        /*
+        CHuiDisplay* display = CHuiStatic::Env().CurrentDisplay();
+
+        if (!display)
+            {
+            THuiPanic::Panic(THuiPanic::EVg10Invariant);
+            }
+        CHuiVg10RenderSurface* surface = static_cast<CHuiVg10RenderSurface*>(&display->RenderSurface());
+		*/
+		
+        CHuiVg10RenderSurface* surface = static_cast<CHuiVg10RenderSurface*>(CHuiStatic::CurrentRenderSurface());
+
+        if (!surface)
+            {
+            THuiPanic::Panic(THuiPanic::EVg10Invariant);
+            }
+        
+        const MHuiSegmentedTexture* tex = surface->BoundTexture();
+
+        if (!tex)
+            {
+            DrawRect(aRect);
+            }
+        else
+            {
+            vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_MULTIPLY); // Will be restored by next call to UpdateColor()
+            DrawTexture(*tex, *aTexCoords, aRect);
+            }
+        }
+    else
+        {
+        DrawRect(aRect);
+        }
+    HUI_VG_INVARIANT();
+    
+    // Restore the original paint
+    vgSetPaint(iPaint, VG_FILL_PATH | VG_STROKE_PATH);
+    UpdateColor();
+    }
+
+
+void CHuiVg10Gc::SetDepthOffset(TInt /*aOffset*/)
+    {
+    // No depth offset on OpenVG
+    }
+
+
+TUint8* CHuiVg10Gc::CaptureLC(TSize& aSize) const
+    {
+    TRect displayArea = RawDisplayArea();
+
+    TUint8* buffer = new (ELeave) TUint8[displayArea.Width() *
+                                         displayArea.Height() * 4];
+    CleanupStack::PushL(buffer);
+
+    aSize = displayArea.Size();
+    vgReadPixels(buffer, displayArea.Width() * 4, VG_lARGB_8888, 0, 0, 
+                 displayArea.Width(), displayArea.Height());
+
+    return buffer;
+    }
+
+#ifdef __NVG
+void CHuiVg10Gc::DrawNVG(HBufC8* aNVGData, MNVGIcon* aIconCmds, const TSize& aImageSize, TBool aIgnoreAspectRatio)
+    {
+    HUI_VG_INVARIANT();
+    
+    if (!aNVGData)
+        return;
+    // Parse the icon header info from the extended data
+    TPtr8 IconHeaderPtr((TUint8 *)aNVGData->Des().Ptr(), KIconHeaderLength, KIconHeaderLength);
+    TAknIconHeader iconheader(IconHeaderPtr);
+
+    // The rest of the data (after the iconheader) are the OVG drawing instructions
+    TInt lengthAfterHeader = aNVGData->Length() - KIconHeaderLength;
+    TPtr8 nvgDataVoidIC((TUint8 *)aNVGData->Des().Ptr() + KIconHeaderLength, lengthAfterHeader, lengthAfterHeader);
+    
+    // Set the rotation angle
+    iNvgEngine->Rotate(iconheader.GetRotation(), aImageSize.iWidth >>1, aImageSize.iHeight >>1);
+    
+    if (aIgnoreAspectRatio == EFalse)
+    {
+        // Set preserve aspect ratio (if not ignored)
+        TNvgAlignStatusType alignTypeValue = ENvgPreserveAspectRatio_XmidYmid;
+        TNvgMeetOrSliceType meetOrSliceTypeValue = ENvgMeet;
+        
+        switch ( iconheader.GetScaleMode() )
+            {
+            case EAspectRatioPreserved:
+                {
+                // Use default
+                break;
+                }
+            // Ensures NVG content fully covers the area
+            // of the icon whilst preserving aspect ratio.
+            case EAspectRatioPreservedSlice:
+                {
+                // alignTypeValue use default
+                meetOrSliceTypeValue = ENvgSlice;
+                break;
+                }
+            // EAspectRatioPreservedAndUnusedSpaceRemoved is mapped to the same
+            // values as EAspectRatioNotPreserved because we already have a
+            // frame buffer with the dimensions that preserves the aspect ratio.
+            // This mapping ensures that NVG engine does not calculate aspect
+            // ratio twice and potentially resulting in precision loss.
+            case EAspectRatioPreservedAndUnusedSpaceRemoved:
+            case EAspectRatioNotPreserved:
+                {            
+                alignTypeValue = ENvgPreserveAspectRatio_None;
+                // meetOrSliceTypeValue use default
+                break;
+                }
+            }
+        iNvgEngine->SetPreserveAspectRatio(alignTypeValue, meetOrSliceTypeValue);
+    }
+    
+    // Draw the NVG path onto the current surface using the NVGEngine
+    if (aIconCmds)
+        {
+        aIconCmds->Draw(aImageSize, iNvgEngine);
+        }
+    else
+        {
+        // Fall back drawing directly from the nvg data
+        HUI_DEBUG(_L("CHuiVg10Gc::DrawNVG() - Fallback to draw the old way (via DrawNvg)"));
+        iNvgEngine->DrawNvg(nvgDataVoidIC, aImageSize, NULL, NULL);
+        }
+
+#ifdef _DEBUG
+    // TODO: REMOVE ONCE THE TSW ERROR IS FIXED!
+    VGErrorCode err = vgGetError();
+    if (err)
+        {
+        RDebug::Print(_L("CHuiVg10Gc::DrawNVG - Error in NVG draw: %04x"), err);
+        }
+#endif
+    
+    // The NVG draw messes up the paint, scissoring & rects, so mark them as dirty
+    TInt dirtyFlags = EHuiVg10GcStateFlagDirtyPaint |
+                    EHuiVg10GcStateFlagDirtyScissor | 
+                    EHuiVg10GcStateFlagDirtyScissorRects;
+    ((CHuiVg10RenderPlugin&)CHuiStatic::Renderer()).AddRestoreStateFlags(dirtyFlags);
+    // Restore the paint etc.
+    RestoreFlaggedState();
+
+    HUI_VG_INVARIANT();
+    }
+#endif
+
+void CHuiVg10Gc::TransformDirtyRect(THuiRealRect& aRect)
+    {
+    THuiRealRect transformed = aRect;
+    
+    // Transform the rectangle using our stacks
+    UpdateClientMatrix();
+    iMatrixStack->Current().Multiply(transformed.iTl);
+    iMatrixStack->Current().Multiply(transformed.iBr);
+    
+    // Normalize the rectangle
+    if (transformed.iTl.iX > transformed.iBr.iX)
+        {
+        TReal32 tmp = transformed.iTl.iX;
+        transformed.iTl.iX = transformed.iBr.iX;
+        transformed.iBr.iX = tmp;
+        }
+    if (transformed.iTl.iY > transformed.iBr.iY)
+        {
+        TReal32 tmp = transformed.iTl.iY;
+        transformed.iTl.iY = transformed.iBr.iY;
+        transformed.iBr.iY = tmp;
+        }    
+
+    aRect = transformed;
+    }
+
+void CHuiVg10Gc::SetPaintPattern(CHuiTexture* aTexture, const TPoint& aTextureOrigin)
+    {
+    if (aTexture)
+        {
+        // TODO: This does not work if texture has NVG data only
+        iPaintPattern = GetVGImageFromTexture( *aTexture );
+        }
+    else
+        {
+        iPaintPattern = VG_INVALID_HANDLE;
+        }
+
+    if (iPaintPattern)
+        {
+        vgSetParameteri(iPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_PATTERN);
+        vgSetParameteri(iPaint, VG_PAINT_PATTERN_TILING_MODE, VG_TILE_REPEAT);        
+        iPaintPatternOrigin = aTextureOrigin;
+        }
+    else
+        {
+        vgSetParameteri(iPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
+        vgSetParameteri(iPaint, VG_PAINT_PATTERN_TILING_MODE, VG_TILE_FILL);        
+        iPaintPatternOrigin = TPoint(0,0);
+        }
+    
+    vgPaintPattern(iPaint, iPaintPattern);
+    }
+
+void CHuiVg10Gc::UsePaintPattern()
+    {
+    if (iPaintPattern)
+        {
+        // Transform the paint pattern to fill the destination rectangle as required
+        vgSeti(VG_MATRIX_MODE, VG_MATRIX_FILL_PAINT_TO_USER);
+        vgLoadIdentity();
+        vgTranslate(iPaintPatternOrigin.iX, iPaintPatternOrigin.iY);
+        vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
+        }
+    }
+
+void CHuiVg10Gc::DiscardPaintPattern()
+    {
+    if (iPaintPattern)
+        {
+        // Restore
+        vgSeti(VG_MATRIX_MODE, VG_MATRIX_FILL_PAINT_TO_USER);
+        vgLoadIdentity();
+        vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
+        }
+    }
+
+
+// End of file
+