uiacceltk/hitchcock/coretoolkit/rendervg10/src/HuiVg10Texture.cpp
changeset 0 15bf7259bb7c
child 3 d8a3531bc6b8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uiacceltk/hitchcock/coretoolkit/rendervg10/src/HuiVg10Texture.cpp	Tue Feb 02 07:56:43 2010 +0200
@@ -0,0 +1,1656 @@
+/*
+* 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:   Implementation for CHuiVg10Texture, OpenVG 1.0 Texture.
+*
+*/
+
+
+
+#include <e32def.h>
+#include <e32math.h>
+
+#include "HuiVg10RenderPlugin.h"
+#include "HuiVg10Texture.h"
+#include "HuiVg10TextureManager.h"
+#include "uiacceltk/HuiTextureHandle.h"
+#include "uiacceltk/HuiEnv.h"
+#include "uiacceltk/HuiTextureManager.h"
+#include "uiacceltk/HuiTextureProcessor.h"
+#include "uiacceltk/HuiUtil.h"
+#include "uiacceltk/HuiPanic.h"
+
+// temporary hack until the openvg headers are fixed..
+#ifndef OPENVG_VERSION_1_0_1
+    #warning using temporary hack to define OPENVG_VERSION_1_0_1, see TSW: SKYA-7QQB8
+    #define OPENVG_VERSION_1_0_1
+#endif
+
+#ifdef __NVG
+    #include <EGL/egl.h>
+    #include <nvg.h>
+    #include <AknIconUtils.h>
+    #include "HuiRenderSurface.h"
+    #include "NVGIcon.h"
+#endif
+
+
+/**
+ *  Bitmap color mode conversion.
+ *
+ *  @param aBitmap      Source bitmap to convert.
+ *  @param aDisplayMode Target display mode.
+ *  @param aCopyMode    Desired copy behavior.
+ *  @returns a new bitmap with the desired display mode.
+ */
+static CFbsBitmap& ConvertBitmapL(const CFbsBitmap& aBitmap, TDisplayMode aDisplayMode, TBitmapCopyMode aCopyMode = EAllowDuplication, TSize aNewSize = TSize(0,0))
+    {
+    // Functionality moved to Texture Manager 
+    // (to avoid recreating the bitmaps & bmpDevices every time)
+    CHuiTextureManager& tmpMgr = CHuiStatic::Env().TextureManager();
+    CHuiVg10TextureManager& textureMgr = static_cast<CHuiVg10TextureManager&>(tmpMgr);
+    
+    return textureMgr.ConvertBitmapL(aBitmap, aDisplayMode, aCopyMode, aNewSize);
+    }
+
+/**
+ *  Replace the alpha channel of an EColor16MA bitmap (in-place).
+ * 
+ *  @param aBitmap      Destination bitmap.
+ *  @param aMaskBitmap  Alpha channel source bitmap.
+ */
+static void ReplaceAlphaChannelL(CFbsBitmap& aBitmap, const CFbsBitmap& aMaskBitmap)
+    {
+    ASSERT(aBitmap.DisplayMode() == EColor16MA);
+    ASSERT(aBitmap.SizeInPixels() == aMaskBitmap.SizeInPixels());
+    
+    CFbsBitmap& convMask = ConvertBitmapL(aMaskBitmap, EGray256);
+    
+    aBitmap.BeginDataAccess();
+    convMask.BeginDataAccess();
+    TSize size           = aBitmap.SizeInPixels();
+    TUint32* dest32      = (TUint32*)aBitmap.DataAddress();
+    const TUint8* src8   = (const TUint8*)convMask.DataAddress();
+    TInt destStride      = CFbsBitmap::ScanLineLength(size.iWidth, aBitmap.DisplayMode()) >> 2;
+    TInt srcStride       = CFbsBitmap::ScanLineLength(size.iWidth, convMask.DisplayMode());
+    
+    for (TInt y = 0; y < size.iHeight; y++)
+        {
+        TUint32* d      = dest32;
+        const TUint8* s = src8;
+
+        for (TInt x = 0; x < size.iWidth; x++)
+            {
+            *d   &= ~0xff000000;
+            *d++ |= (*s++) << 24;
+            }
+        
+        dest32 += destStride;
+        src8   += srcStride;
+        }
+
+    aBitmap.EndDataAccess();
+    convMask.EndDataAccess(ETrue);
+    }
+
+#if !defined(OPENVG_VERSION_1_0_1)
+/**
+ *  Convert a native Symbian EColor16MU/A bitmap to an OpenVG 1.0 equivalent (in-place).
+ * 
+ *  @param aBitmap      Bitmap to convert.
+ */
+static void ConvertPixelComponentOrdering(CFbsBitmap& aBitmap)
+    {
+    ASSERT(aBitmap.DisplayMode() == EColor16MA || aBitmap.DisplayMode() == EColor16MU);
+    
+    aBitmap.BeginDataAccess();
+    TSize size           = aBitmap.SizeInPixels();
+    TUint32* dest32      = (TUint32*)aBitmap.DataAddress();
+    TInt destStride      = CFbsBitmap::ScanLineLength(size.iWidth, aBitmap.DisplayMode()) >> 2;
+    
+    for (TInt y = 0; y < size.iHeight; y++)
+        {
+        TUint32* d = dest32;
+
+        for (TInt x = 0; x < size.iWidth; x++)
+            {
+            *d++ = (*d << 8) | ((*d & 0xff000000) >> 24);
+            }
+        
+        dest32 += destStride;
+        }
+    aBitmap.EndDataAccess();
+    }
+#endif
+
+/* Vg10Texture internal flags. */
+enum
+    {
+    /** Content has been uploaded. */
+    EFlagHasContent = 0x1,
+
+    /** The texture has an alpha channel. */
+    EFlagHasAlpha = 0x2
+    };
+
+
+CHuiVg10Texture* CHuiVg10Texture::NewL(CHuiVg10RenderPlugin& aRenderPlugin, const THuiTextureHandle* aExistingTexture)
+    {
+    CHuiVg10Texture* self = CHuiVg10Texture::NewLC(aRenderPlugin, aExistingTexture);
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+
+CHuiVg10Texture* CHuiVg10Texture::NewLC(CHuiVg10RenderPlugin& aRenderPlugin, const THuiTextureHandle* aExistingTexture)
+    {
+    CHuiVg10Texture* self = new (ELeave) CHuiVg10Texture(aRenderPlugin);
+    CleanupStack::PushL(self);
+    self->ConstructL(aExistingTexture);
+    return self;
+    }
+
+
+CHuiVg10Texture::CHuiVg10Texture(CHuiVg10RenderPlugin& aRenderPlugin)
+    : iRenderPlugin(aRenderPlugin),
+      iInternalFlags(0),
+      iShadowEnabled(EFalse)
+    {
+    }
+
+
+void CHuiVg10Texture::ConstructL(const THuiTextureHandle* aExistingTexture)
+    {
+    CHuiTexture::BaseConstructL();
+    
+    SetSegmentCountL(1);
+    SetSegmentName(0, 0);
+    SetSegmentSize(0, TSize(0, 0));
+    SetSegmentTextureSize(0, TSize(0, 0));
+
+    if(aExistingTexture)
+        {
+        // Take over the existing texture (single named texture object).
+        ASSERT(aExistingTexture->SegmentCount() == 1);
+        ASSERT(SegmentCount() == 1);
+        SetSegmentName(0, aExistingTexture->Name());
+        SetSegmentSize(0, aExistingTexture->SegmentSize(0));
+        SetSegmentTextureSize(0, aExistingTexture->SegmentTextureSize(0));
+        SetSize(aExistingTexture->Size());
+        
+        // Copy attributes
+        const CHuiVg10Texture* vgTex = reinterpret_cast<const CHuiVg10Texture*>(aExistingTexture);
+        iInternalFlags = vgTex->iInternalFlags;
+        // Note: shared shadows not supported
+        }
+    }
+
+
+CHuiVg10Texture::~CHuiVg10Texture()
+    {
+    Reset();
+    }
+
+
+TBool CHuiVg10Texture::HasAlpha() const
+    {
+    return (iInternalFlags & EFlagHasAlpha) != 0;
+    }
+    
+    
+TBool CHuiVg10Texture::HasContent() const
+    {
+    if(!CHuiTexture::HasContent())
+        {
+        return EFalse;
+        }
+        
+    return (iInternalFlags & EFlagHasContent) != 0;
+    }    
+
+
+TSize CHuiVg10Texture::MaxTextureSize() const
+    {
+    if (iRenderPlugin.IsReleased())
+        {
+        HUI_DEBUG(_L("CHuiVg10Texture::MaxTextureSize() - Vg10 context not available, cannot get maximum texture size, returning (0,0)."));
+        return TSize(0,0);
+        }
+    
+    int maxWidth  = vgGeti(VG_MAX_IMAGE_WIDTH)-1;
+    int maxHeight = vgGeti(VG_MAX_IMAGE_HEIGHT)-1;
+    HUI_VG_INVARIANT();
+    ASSERT(maxWidth > 0 && maxHeight > 0);
+    
+    return TSize(maxWidth, maxHeight);
+    }
+
+void CHuiVg10Texture::UploadL(const CFbsBitmap& aBitmap,
+                              const CFbsBitmap* aMaskBitmap,
+                              THuiTextureUploadFlags aTextureFlags)
+    {
+    Reset(); // Must delete old content before calling SetupSegmentsL
+    
+    TBool invalidMaskSize = (aMaskBitmap && (aBitmap.SizeInPixels() != aMaskBitmap->SizeInPixels()));
+    
+    CFbsBitmap* maskBitmap = (CFbsBitmap*)aMaskBitmap;
+
+    if (invalidMaskSize)
+        {
+        maskBitmap = &ConvertBitmapL(*aMaskBitmap, aMaskBitmap->DisplayMode(), EAlwaysCopy, aBitmap.SizeInPixels());
+        }
+    
+    SetupSegmentsL(aBitmap.SizeInPixels(), aBitmap.SizeInPixels(), aTextureFlags);
+    SegmentUploadL(0, aBitmap, maskBitmap, aTextureFlags);
+    }
+
+void CHuiVg10Texture::UploadL(THuiTextureFormat aTextureFormat,
+                              const TSize& aTextureSize,
+                              const TUint8* aTextureBuffer,
+                              THuiTextureUploadFlags aTextureFlags,
+                              TUint aTextureBufferSize)
+    {
+    Reset(); // Must delete old content before calling SetupSegmentsL
+    SetupSegmentsL(aTextureSize, aTextureSize, aTextureFlags);
+    SegmentUploadL(0, aTextureFormat, aTextureSize, aTextureBuffer, aTextureBufferSize);
+    }
+    
+
+void CHuiVg10Texture::PartialUploadL(THuiTextureFormat aFormat,
+                                     const TPoint& aOrigin,
+                                     const TSize& aSize,
+                                     const TUint8* aBuffer)
+    {
+    ASSERT(SegmentCount() == 1);
+    SegmentPartialUpload(0, aFormat, aOrigin, aSize, aBuffer);
+    }
+
+
+void CHuiVg10Texture::SegmentUploadL(TInt aSegment,
+                                     const CFbsBitmap& aBitmap,
+                                     const CFbsBitmap* aMaskBitmap,
+                                     THuiTextureUploadFlags aFlags)
+    {
+    ASSERT(aSegment >= 0 && aSegment < SegmentCount());
+    ASSERT(aBitmap.SizeInPixels() == Size());
+    ASSERT(aMaskBitmap && aBitmap.SizeInPixels() == aMaskBitmap->SizeInPixels() || !aMaskBitmap);
+
+    PushEGLContext();
+    if(aSegment < 0 || aSegment >= SegmentCount())
+        {
+        User::Leave(KErrArgument);
+        }
+    
+    // Clear any previous image data
+    ResetSegment(aSegment);
+    
+#ifdef __NVG
+    // Check if the bitmap is extended and has NVG data
+    TUid bitmaptype = aBitmap.ExtendedBitmapType();
+    TUid masktype = KNullUid;
+    if (aMaskBitmap)
+        {
+        masktype = aMaskBitmap->ExtendedBitmapType();
+        // extended bitmap and mask
+        if (bitmaptype == masktype && bitmaptype != KNullUid)
+            {
+            SegmentUploadNvgL(aBitmap, aMaskBitmap, aFlags);
+            // We now have working texture data, no need to do anything else
+            PopEGLContext();
+            return;
+            }
+        }
+    else if (bitmaptype != KNullUid)
+        {
+        SegmentUploadNvgL(aBitmap, aMaskBitmap, aFlags);
+        // We now have working texture data, no need to do anything else
+        PopEGLContext();
+        return;
+        }
+#endif
+    
+    VGImageFormat imageSourceFormat = (VGImageFormat)(-1);
+    VGImageFormat imageInternalFormat = VG_sXRGB_8888; // TODO: get the most optimal image format from the renderer
+    VGbitfield qualityFlags = VG_IMAGE_QUALITY_BETTER | VG_IMAGE_QUALITY_FASTER | VG_IMAGE_QUALITY_NONANTIALIASED;
+    TBool hasAlpha = (aMaskBitmap != NULL);
+    TBool conversionRequired = ETrue;
+    TSize size = Size();
+    TSize textureSize = MaxTextureSize();
+    textureSize.iWidth = Min(size.iWidth, textureSize.iWidth);
+    textureSize.iHeight = Min(size.iHeight, textureSize.iHeight);
+
+    // See if there is a native color mode we could use without conversion
+    switch (aBitmap.DisplayMode())
+        {
+        case EGray256:
+            imageSourceFormat = VG_A_8;
+            conversionRequired = EFalse;
+            break;
+        case EColor64K:
+            imageSourceFormat = VG_sRGB_565;
+            conversionRequired = EFalse;
+            break;
+        case EColor4K:
+            imageSourceFormat = VG_sRGB_565;
+            conversionRequired = ETrue;
+            break;    
+#if defined(OPENVG_VERSION_1_0_1)
+        case EColor16MU:
+            imageSourceFormat = VG_sXRGB_8888;
+            conversionRequired = EFalse;
+            break;
+		case EColor16M:
+            imageSourceFormat = VG_sXRGB_8888;
+            conversionRequired = ETrue;
+            break;
+        case EColor16MA:
+            imageSourceFormat = VG_sARGB_8888;
+            hasAlpha = ETrue;
+            conversionRequired = EFalse;
+            break;
+        case EColor16MAP:
+            imageSourceFormat = VG_sARGB_8888_PRE;
+            hasAlpha = ETrue;
+            conversionRequired = EFalse;
+            break;
+#else // defined(OPENVG_VERSION_1_0_1)
+        case EColor16MU:
+		case EColor16M:
+            imageSourceFormat = VG_sRGBX_8888;
+            break;
+        case EColor16MA:
+            imageSourceFormat = VG_sRGBA_8888;
+            hasAlpha = ETrue;
+            break;
+        case EColor16MAP:
+            imageSourceFormat = VG_sRGBA_8888_PRE;
+            hasAlpha = ETrue;
+            break;
+#endif // defined(OPENVG_VERSION_1_0_1)
+        default:
+#ifdef _DEBUG
+            RDebug::Printf("CHuiVg10Texture::SegmentUploadL - unknown display mode %d", aBitmap.DisplayMode());
+#endif
+            conversionRequired = ETrue;
+            imageSourceFormat = VG_sXRGB_8888;
+        }
+    
+    if (aBitmap.IsCompressedInRAM() || aMaskBitmap)
+        {
+        conversionRequired = ETrue;
+        }
+
+    if (hasAlpha)
+        {
+        imageInternalFormat = VG_sRGBA_8888_PRE;
+        }
+    else
+        {
+        imageInternalFormat = imageSourceFormat;
+        }
+
+    // Create the actual image
+    VGImage image = vgCreateImage(imageInternalFormat, textureSize.iWidth, textureSize.iHeight, qualityFlags);
+
+    if (image == VG_INVALID_HANDLE)
+        {
+        User::Leave(KErrNoMemory);
+        }
+    
+    if (!conversionRequired)
+        {
+        // No data conversion is required and we can upload the pixels as such
+        aBitmap.BeginDataAccess();
+        const void* data = aBitmap.DataAddress();
+        TInt stride      = CFbsBitmap::ScanLineLength(size.iWidth, aBitmap.DisplayMode());
+        vgImageSubData(image, data, stride, imageSourceFormat, 0, 0, textureSize.iWidth, textureSize.iHeight);
+        aBitmap.EndDataAccess( ETrue );
+        }
+    else
+        {
+        // One or more conversion steps are needed
+        if (hasAlpha)
+            {
+            // Alpha channel needs to be accounted for
+#if defined(OPENVG_VERSION_1_0_1)
+            imageSourceFormat = VG_sARGB_8888;
+            CFbsBitmap& convBitmap = ConvertBitmapL(aBitmap, EColor16MA);
+#else // defined(OPENVG_VERSION_1_0_1)
+            imageSourceFormat = VG_sRGBA_8888;
+            CFbsBitmap& convBitmap = ConvertBitmapL(aBitmap, EColor16MA);
+#endif // defined(OPENVG_VERSION_1_0_1)
+            
+            // Bake the alpha channel into the converted bitmap
+            if (aMaskBitmap)
+                {
+                if (aMaskBitmap->IsCompressedInRAM() || masktype != KNullUid)
+                    {
+                    CFbsBitmap& noncompressedMask = ConvertBitmapL(*aMaskBitmap, EGray256, EAlwaysCopy);
+                    ReplaceAlphaChannelL(convBitmap, noncompressedMask);                                                
+                    }
+                 else
+                    {
+                    ReplaceAlphaChannelL(convBitmap, *aMaskBitmap);
+                    }
+                }
+            #if !defined(OPENVG_VERSION_1_0_1)
+                    // Match the native OpenVG 1.0 pixel component ordering
+                    ASSERT(convBitmap.Handle() != aBitmap.Handle());
+                    ConvertPixelComponentOrdering(convBitmap);
+            #endif 
+            convBitmap.BeginDataAccess();
+            const void* data = convBitmap.DataAddress();
+            TInt stride      = CFbsBitmap::ScanLineLength(size.iWidth, convBitmap.DisplayMode());
+            vgImageSubData(image, data, stride, imageSourceFormat, 0, 0, textureSize.iWidth, textureSize.iHeight);
+            convBitmap.EndDataAccess( ETrue );
+            }
+        else
+            {
+            // No alpha channel -- just opaque pixel data
+#if defined(OPENVG_VERSION_1_0_1)
+            TDisplayMode mode = EColor16MU;
+            if (imageSourceFormat == VG_sRGB_565)
+                {
+                mode = EColor64K;
+                }
+            else if (imageSourceFormat == VG_A_8)
+                {
+                mode = EGray256;
+                }
+            else
+                {
+                imageSourceFormat = VG_sXRGB_8888;
+                }
+            CFbsBitmap& convBitmap = ConvertBitmapL(aBitmap, mode);
+#else // defined(OPENVG_VERSION_1_0_1)
+            imageSourceFormat = VG_sRGBX_8888;
+            CFbsBitmap& convBitmap = ConvertBitmapL(aBitmap, EColor16MU);
+            
+            // Match the native OpenVG 1.0 pixel component ordering
+            ASSERT(convBitmap.Handle() != aBitmap.Handle());
+            ConvertPixelComponentOrdering(convBitmap);
+#endif // defined(OPENVG_VERSION_1_0_1)
+            
+            convBitmap.BeginDataAccess();
+            const void* data = convBitmap.DataAddress();
+            TInt stride      = CFbsBitmap::ScanLineLength(size.iWidth, convBitmap.DisplayMode());
+            vgImageSubData(image, data, stride, imageSourceFormat, 0, 0, textureSize.iWidth, textureSize.iHeight);
+            convBitmap.EndDataAccess( ETrue );
+            }
+        }
+    
+    // Save the image handle
+    SetSegmentName(0, (TUint)image);
+    
+    // The texture now has content.
+    iInternalFlags |= EFlagHasContent;
+
+    if (hasAlpha)
+        {
+        iInternalFlags |= EFlagHasAlpha;
+        }
+    
+    // Keep the shadow in sync with the image contents
+    if (IsShadowEnabled())
+        {
+        // if this fails there is nothing we can do
+        // There will be no shadow if something goes wrong here
+        TRAP_IGNORE( GenerateShadowL() );
+        }
+    PopEGLContext();
+    // Wake up refresh. It is likely that the new texture will be visible on
+    // the screen.
+    CHuiStatic::ContinueRefresh();
+    }
+
+static void ConvertBufferRgb888TosRGBX8888(const TUint8* aSrc, TUint8* aDest, TInt aCount)
+{
+    while (aCount--)
+        {
+        *aDest++ = *aSrc++;
+        *aDest++ = *aSrc++;
+        *aDest++ = *aSrc++;
+        *aDest++ = 0xff;
+        }
+}
+
+static void ConvertBufferLa88TosRGBA8888(const TUint8* aSrc, TUint8* aDest, TInt aCount)
+{
+    while (aCount--)
+        {
+        TUint8 l = *aSrc++;
+        TUint8 a = *aSrc++;
+        *aDest++ = l;
+        *aDest++ = l;
+        *aDest++ = l;
+        *aDest++ = a;
+        }
+}
+
+#if !defined(OPENVG_VERSION_1_0_1)
+static void ConvertBufferRgba8888TosRGBA8888(const TUint8* aSrc, TUint8* aDest, TInt aCount)
+{
+    while (aCount--)
+        {
+        TUint8 r = *aSrc++;
+        TUint8 g = *aSrc++;
+        TUint8 b = *aSrc++;
+        TUint8 a = *aSrc++;
+        *aDest++ = a;
+        *aDest++ = r;
+        *aDest++ = g;
+        *aDest++ = b;
+        }
+}
+#endif
+
+void CHuiVg10Texture::SegmentClearL(TInt aSegment,
+                                    TBool aWithAlpha,
+                                    const TRgb& aColor,
+                                    TUint8 aAlpha)
+    {
+    ASSERT(aSegment >= 0 && aSegment < SegmentCount());
+
+    if(aSegment < 0 || aSegment >= SegmentCount())
+        {
+        User::Leave(KErrArgument);
+        }
+
+    // Clear any previous image data
+    TSize size = Size();
+    ResetSegment(aSegment);
+
+    // Create the actual image
+    VGImageFormat imageInternalFormat = aWithAlpha ? VG_sRGBA_8888 : VG_sRGBX_8888;
+    VGbitfield qualityFlags = VG_IMAGE_QUALITY_BETTER | VG_IMAGE_QUALITY_FASTER | VG_IMAGE_QUALITY_NONANTIALIASED;
+    VGImage image = vgCreateImage(imageInternalFormat, size.iWidth, size.iHeight, qualityFlags);
+    
+    if (image == VG_INVALID_HANDLE)
+        {
+        User::Leave(KErrNoMemory);
+        }
+
+    // Set the clear color
+    VGfloat scale = 1.0f / 255.0f;
+    VGfloat color[] = {
+        aColor.Red()   * scale,
+        aColor.Green() * scale,
+        aColor.Blue()  * scale,
+        aWithAlpha ? (aAlpha * scale) : 1.0f
+    };
+    
+    vgSetfv(VG_CLEAR_COLOR, 4, color);
+    vgClearImage(image, 0, 0, size.iWidth, size.iHeight);
+
+    // The texture now has content.
+    iInternalFlags |= EFlagHasContent;
+
+    if (aWithAlpha)
+        {
+        iInternalFlags |= EFlagHasAlpha;
+        }
+
+    // Keep the shadow in sync with the image contents
+    if (IsShadowEnabled())
+        {
+        GenerateShadowL();
+        }
+    
+    HUI_VG_INVARIANT();
+    }
+
+void CHuiVg10Texture::SegmentUploadL(TInt aSegment,
+                                     THuiTextureFormat aFormat,
+                                     const TSize& aSize,
+                                     const TUint8* aBuffer,
+                                     TUint /*aBufferSize*/)
+    {
+    ASSERT(aSegment >= 0 && aSegment < SegmentCount());
+    ASSERT(aSize == Size());
+    
+    SegmentPartialUploadInternal(aSegment, aFormat, TPoint(0, 0), aSize, aBuffer, ETrue);
+    }
+
+void CHuiVg10Texture::SegmentPartialUpload(
+        TInt aSegment,
+        THuiTextureFormat aFormat,
+        const TPoint& aOrigin,
+        const TSize& aSize,
+        const TUint8* aBuffer)
+    {
+    SegmentPartialUploadInternal(aSegment, aFormat, aOrigin, aSize, aBuffer, EFalse);
+    }
+
+void CHuiVg10Texture::SegmentPartialUploadInternal(
+        TInt aSegment,
+        THuiTextureFormat aFormat,
+        const TPoint& aOrigin,
+        const TSize& aSize,
+        const TUint8* aBuffer,
+        TBool aCreateImage)
+    {
+    ASSERT(aSegment >= 0 && aSegment < SegmentCount());
+
+    if (aSegment < 0 || aSegment >= SegmentCount())
+        {
+        // we return without doing anything because we are called by a non-leaving function
+        return;
+        }
+
+    if (aOrigin.iX < 0 || aOrigin.iY < 0)
+        {
+        // we return without doing anything because we are called by a non-leaving function
+        return;
+        }
+    
+    HUI_DEBUG4(_L("CHuiVg10Texture::SegmentPartialUploadInternal() - Uploading partial image (%ix%i pixels, offset x: %i y: %i)."),
+               aSize.iWidth, aSize.iHeight, aOrigin.iX, aOrigin.iY);
+    
+    VGImageFormat imageSourceFormat = (VGImageFormat)(-1);
+    VGImageFormat imageInternalFormat = VG_sRGBX_8888; // TODO: get the most optimal image format from the renderer
+    VGbitfield qualityFlags = VG_IMAGE_QUALITY_FASTER | VG_IMAGE_QUALITY_BETTER; // TODO: get this from hitchcock
+    TBool hasAlpha = EFalse;
+    TBool conversionRequired = ETrue;
+    TInt sourceStride = 0;
+    
+    switch (aFormat)
+        {
+        case EHuiTextureFormatRgb565:
+            imageSourceFormat = VG_sRGB_565;
+            conversionRequired = EFalse;
+            sourceStride = aSize.iWidth * 2;
+            break;
+        case EHuiTextureFormatRgb888:
+            imageSourceFormat = VG_sRGBX_8888;
+            sourceStride = aSize.iWidth * 4;
+            break;
+        case EHuiTextureFormatLa88:
+            // We have to expand this format to RGBA, since there is no luminance-alpha format in OpenVG 1.0.1
+            imageSourceFormat = VG_sRGBA_8888;
+            sourceStride = aSize.iWidth * 4;
+            hasAlpha = ETrue;
+            break;
+#if defined(OPENVG_VERSION_1_0_1)
+        case EHuiTextureFormatRgba8888:
+            imageSourceFormat = VG_sARGB_8888;
+            conversionRequired = EFalse;
+            hasAlpha = ETrue;
+            sourceStride = aSize.iWidth * 4;
+            break;
+#else // defined(OPENVG_VERSION_1_0_1)
+        case EHuiTextureFormatRgba8888:
+            imageSourceFormat = VG_sRGBA_8888;
+            sourceStride = aSize.iWidth * 4;
+            hasAlpha = ETrue;
+            break;
+#endif // defined(OPENVG_VERSION_1_0_1)
+        
+        // Compressed formats are not supported
+        default:
+            // we return without doing anything because we are called by a non-leaving function
+            return;
+        }
+    
+    // Use a matching internal format
+    imageInternalFormat = imageSourceFormat;
+
+    // Create the actual image if required
+    VGImage image = VG_INVALID_HANDLE;
+    
+    if (aCreateImage)
+        {
+        image = vgCreateImage(imageInternalFormat, aSize.iWidth, aSize.iHeight, qualityFlags);
+        }
+    else
+        {
+        image = (VGImage)SegmentName(0);
+        
+        // Verify the dimensions
+        if (aOrigin.iX + aSize.iWidth  >= Size().iWidth || 
+            aOrigin.iY + aSize.iHeight >= Size().iHeight)
+            {
+            // we return without doing anything because we are called by a non-leaving function
+            return;
+            }
+        }
+
+    if (image == VG_INVALID_HANDLE)
+        {
+        // we return without doing anything because we are called by a non-leaving function
+        return;
+        }
+    
+    if (!conversionRequired)
+        {
+        // No data conversion is required and we can upload the pixels as such
+        vgImageSubData(image, aBuffer, sourceStride, imageSourceFormat, aOrigin.iX, aOrigin.iY, aSize.iWidth, aSize.iHeight);
+        HUI_VG_INVARIANT();
+        }
+    else
+        {
+        // One or more conversion steps are needed
+        TInt pixels = aSize.iWidth * aSize.iHeight;
+        TUint8* convBuffer = NULL;
+        convBuffer = new TUint8[sourceStride * aSize.iHeight];
+        // there are no leaving functions until our buffer is deleted
+        // We cannot put convBuffer onto cleanup stack because we cannot leave.
+        
+        if ( !convBuffer )
+            {
+            // we return without doing anything because we are called by a non-leaving function
+            return;
+            }
+        
+        switch (aFormat)
+            {
+            case EHuiTextureFormatRgb888:
+                ConvertBufferRgb888TosRGBX8888(aBuffer, convBuffer, pixels);
+                break;
+            case EHuiTextureFormatLa88:
+                ConvertBufferLa88TosRGBA8888(aBuffer, convBuffer, pixels);
+                break;
+#if !defined(OPENVG_VERSION_1_0_1)
+            case EHuiTextureFormatRgba8888:
+                ConvertBufferRgba8888TosRGBA8888(aBuffer, convBuffer, pixels);
+                break;
+#endif // defined(OPENVG_VERSION_1_0_1)
+            default:
+                ASSERT(0);
+            }
+        
+        vgImageSubData(image, convBuffer, sourceStride, imageSourceFormat, aOrigin.iX, aOrigin.iY, aSize.iWidth, aSize.iHeight);
+        delete[] convBuffer;
+        HUI_VG_INVARIANT();
+        }
+
+    // Save the image handle
+    SetSegmentName(0, (TUint)image);
+    
+    // The texture now has content.
+    iInternalFlags |= EFlagHasContent;
+
+    if (hasAlpha)
+        {
+        iInternalFlags |= EFlagHasAlpha;
+        }
+    
+    // Keep the shadow in sync with the image contents
+    if (IsShadowEnabled())
+        {
+        // We cannot leave, we just try our best.
+        // If this fails, we have no shadow
+        TRAP_IGNORE( GenerateShadowL() );
+        }
+    
+    HUI_VG_INVARIANT();
+    }
+
+void CHuiVg10Texture::Reset()
+    {
+    CHuiTexture::Reset();
+    
+    if (iShadow.Name())
+        {
+        vgDestroyImage((VGImage)iShadow.Name());
+        iShadow.SetName(0);
+        }
+    
+    iShadowEnabled = EFalse;
+    
+#ifdef __NVG
+    CHuiTexture::SetNvgContent(EFalse);
+    iIsExtended = EFalse;
+    
+    delete iNVGData;
+    iNVGData = NULL;
+    delete iIconCommands;
+    iIconCommands = NULL;
+#endif
+    }
+
+void CHuiVg10Texture::ResetSegment(TInt aSegment)
+    {
+    HUI_DEBUG1(_L("CHuiVg10Texture::ResetSegment() - Trying to delete image for segment %i."), aSegment);
+    HUI_VG_INVARIANT();
+    ASSERT(aSegment>=0 && aSegment < SegmentCount());
+
+    VGImage image = (VGImage)SegmentName(aSegment);
+    if (image != VG_INVALID_HANDLE)
+        {
+        vgDestroyImage(image);
+        }
+
+    SetSegmentName(aSegment, VG_INVALID_HANDLE);
+    SetSegmentTextureSize(aSegment, TSize(0, 0));
+    SetSegmentSize(aSegment, TSize(0, 0));
+    SetSegmentOffset(aSegment, TPoint(0, 0));
+
+    // There is no content anymore
+    iInternalFlags &= ~(EFlagHasContent | EFlagHasAlpha);
+    
+    HUI_VG_INVARIANT();
+    }
+
+
+void CHuiVg10Texture::InitSegmentL(TInt /*aSegment*/)
+    {
+    // Nothing to do
+    }
+
+
+void CHuiVg10Texture::SetupSegmentsL(const TSize& aLogicalSize,
+                                     const TSize& aTextureSize,
+                                     THuiTextureUploadFlags aFlags)
+    {
+    // Assert that the sizes are valid.
+    ASSERT(aTextureSize.iWidth > 0 && aTextureSize.iHeight > 0);
+    ASSERT(aLogicalSize.iWidth > 0 && aLogicalSize.iHeight > 0);
+
+    HUI_DEBUG4(_L("CHuiVg10Texture::SetupSegments() - Configuring a single %ix%i texture segment for %ix%i bitmap."),
+               aTextureSize.iWidth, aTextureSize.iHeight,
+               aTextureSize.iWidth, aTextureSize.iHeight);
+
+    // All textures use only a single segment with OpenVG.
+    SetSegmentCountL(1);
+    
+    SetSegment(0, aLogicalSize, TPoint(0, 0), aTextureSize);
+    SetSegmentName(0, (TUint)VG_INVALID_HANDLE);
+    
+    // The logical size always matches the texture size
+    SetSize(aLogicalSize);
+    
+    // Enable shadow generation if requested
+    if (aFlags & EHuiTextureUploadFlagGenerateShadow)
+        {
+        EnableShadow(ETrue);
+        }
+    }
+    
+void CHuiVg10Texture::TextureExtension(const TUid& aExtensionUid, TAny** aExtensionParameters)
+    {
+	CHuiTexture::TextureExtension(aExtensionUid, aExtensionParameters);    	
+    }
+
+void CHuiVg10Texture::EnableShadow(TBool aEnable)
+    {
+    CHuiTexture::EnableShadow(aEnable);
+    iShadowEnabled = aEnable;
+
+    if (!aEnable && iShadow.Name())
+        {
+        vgDestroyImage((VGImage)iShadow.Name());
+        iShadow.SetName(0);
+        HUI_VG_INVARIANT();
+        }
+    
+    if (aEnable)
+        {
+        // We cannot leave, we just try our best.
+        // If this fails, we have no shadow
+        TRAP_IGNORE( GenerateShadowL() ); 
+        }
+
+    HUI_VG_INVARIANT();
+    }
+
+TBool CHuiVg10Texture::IsShadowEnabled() const
+    {
+    return iShadowEnabled;
+    }
+
+TBool CHuiVg10Texture::GetShadowTexture(THuiTextureHandle& aHandle) const
+    {
+    if (iShadowEnabled && iShadow.SegmentName(0))
+        {
+        aHandle = iShadow;
+        return ETrue;
+        }
+    return EFalse;
+    }
+
+void CHuiVg10Texture::UpdateShadowSizeL(const TSize& aSize)
+    {
+    VGImage shadow = VG_INVALID_HANDLE;
+
+    if (iShadow.Name())
+        {
+        shadow = (VGImage)(iShadow.Name());
+        TInt w = vgGetParameteri(shadow, VG_IMAGE_WIDTH);
+        TInt h = vgGetParameteri(shadow, VG_IMAGE_HEIGHT);
+        
+        if (w != aSize.iWidth || h != aSize.iHeight)
+            {
+            // Destroy the old shadow image -- a new one will be created below
+            vgDestroyImage(shadow);
+            iShadow.SetName(0);
+            }
+        else
+            {
+            return;
+            }
+        }
+    
+    ASSERT(!iShadow.Name());
+    
+    shadow = vgCreateImage(VG_sRGBA_8888_PRE, aSize.iWidth, aSize.iHeight, 
+                           VG_IMAGE_QUALITY_FASTER | VG_IMAGE_QUALITY_NONANTIALIASED);
+
+    if (shadow == VG_INVALID_HANDLE)
+        {
+        return;
+        }
+    iShadow.SetName(shadow);
+    iShadow.SetSize(aSize);
+    
+    HUI_VG_INVARIANT();
+    }
+
+void CHuiVg10Texture::GenerateShadowL()
+    {
+    if (iRenderPlugin.IsReleased())
+        {
+        HUI_DEBUG(_L("CHuiVg10Texture::GenerateShadowL - VG context not available, cannot generate texture object."));
+        return;
+        }
+    
+    if (!IsShadowEnabled() || !(iInternalFlags & EFlagHasContent))
+        {
+        return;
+        }
+
+    CHuiTextureProcessor& proc = CHuiStatic::Env().TextureManager().Processor();
+    TSize size = Size();
+
+    switch(ShadowStyle())
+        {
+        case EHuiTextureShadowStyleIcon:
+            {
+            // TODO: Allow for smaller shadow images as an optimization
+            TSize shadowSize(size.iWidth, size.iHeight);
+            UpdateShadowSizeL(shadowSize);
+            proc.BlurL(Handle(), iShadow, shadowSize, 4,
+                CHuiTextureProcessor::EBlurFlagWhite |
+                CHuiTextureProcessor::EBlurFlagAlpha |
+                CHuiTextureProcessor::EBlurFlagExpandEdges);
+            break;
+            }
+
+        case EHuiTextureShadowStyleRasterizedText:
+            {
+            TSize shadowSize(size.iWidth, size.iHeight);
+            UpdateShadowSizeL(shadowSize);
+            proc.BlurL(Handle(), iShadow, shadowSize, 4,
+                CHuiTextureProcessor::EBlurFlagWhite |
+                CHuiTextureProcessor::EBlurFlagAlpha |
+                CHuiTextureProcessor::EBlurFlagExpandEdges);
+            break;
+            }
+
+        default:
+            break;
+        }
+
+    HUI_VG_INVARIANT();
+    }
+
+#ifdef __NVG
+HBufC8* CHuiVg10Texture::ReadNVGDataL(const CFbsBitmap& aBitmap)
+    {
+    // Fetch the extended data
+    aBitmap.BeginDataAccess();
+    const TUint32* data = aBitmap.DataAddress();
+    TInt dataSize = aBitmap.DataSize();
+    TUint8* compressedData = new (ELeave) TUint8[dataSize];
+    CleanupStack::PushL(compressedData);
+    Mem::Copy(compressedData, data, dataSize);
+    aBitmap.EndDataAccess(ETrue);
+    
+    // Create a descriptor out of the extended bitmap data. The iNVGData
+    // will now contain the direct OpenVG commands
+    TPtr8 nvgDataPtr(compressedData, dataSize, dataSize);
+    HBufC8* dataBuf = nvgDataPtr.AllocL();
+    
+    CleanupStack::PopAndDestroy(compressedData);
+    return dataBuf;
+    }
+
+void CHuiVg10Texture::SegmentUploadNvgL(const CFbsBitmap& aBitmap, const CFbsBitmap* aMaskBitmap, THuiTextureUploadFlags aFlags)
+    {
+    HUI_VG_INVARIANT();
+    
+    VGImage image = VG_INVALID_HANDLE;
+    HBufC8* dataBuf = ReadNVGDataL(aBitmap);
+    CleanupStack::PushL(dataBuf);
+    HBufC8* maskDataBuf = NULL;
+    TAknIconHeader header = GetNvgIconHeader(dataBuf);
+    TAknIconHeader maskHeader(header);  // DUMMY Creation, since default constructor is missing!
+    
+    if (aMaskBitmap)
+        {
+        maskDataBuf = ReadNVGDataL(*aMaskBitmap);
+        CleanupStack::PushL(maskDataBuf);
+        maskHeader = GetNvgIconHeader(maskDataBuf);
+        }
+    
+    // The trick here is to check the texture upload flags, and determine
+    // whether we want to draw from NVG object cache directly or raster
+    // the NVG data to a PBuffer
+    if (aFlags & EHuiTextureUploadFlagUsePureNvg)
+        {
+        // Save the NVG data for future use
+        if (iNVGData)
+            {
+            delete iNVGData;
+            iNVGData = NULL;
+            }
+        iNVGData = dataBuf;
+        
+        // TODO: If the NVG ObjectCache is still up-to-date, we could possibly
+        // create the object cached NVG icon for faster drawing, and maybe
+        // discard the iNVGData completely (to save RAM?)
+        CreateObjCachedNVGIconL();  // NOTE: The OPENVG_OBJECT_CACHING has to be defined in NVG!
+        
+        // Mark the texture as an NVG texture
+        CHuiTexture::SetNvgContent(ETrue);
+        iIsExtended = ETrue;
+        }
+    else    // By default, use the "OPTION C" -way!
+        {
+        // Use the same way to create the rendered image as in OPTION_C (see below)
+        CNvgEngine& nvgEngine = iRenderPlugin.NvgEngine();
+        iIsExtended = ETrue;    // I'm an NVG texture yet..
+    
+        // Make sure we don't leak memory
+        if (iNVGData)
+            {
+            delete iNVGData;
+            iNVGData = NULL;
+            }
+        
+        // Create the real image from NVG databuf
+        iNVGData = dataBuf;
+        image = CreateRenderedImage(&nvgEngine, dataBuf, Size());
+        
+        // New functionality for checking the mask
+        if (header.GetBitmapId() != maskHeader.GetBitmapId() &&
+            CompareNvgData(dataBuf, maskDataBuf) != 0)
+            {
+            VGImage maskImg = VG_INVALID_HANDLE;
+            // The mask is from different bitmap => we have to create
+            // a separate mask image for masking the NVG icon
+            maskImg = CreateRenderedImage(&nvgEngine, maskDataBuf, Size());
+            ReplaceVGImageAlphaChannelL(image, maskImg, Size());
+            vgDestroyImage(maskImg);
+            }
+        
+        // Save the image handle
+        SetSegmentName(0, (TUint)image);
+        
+        // No need for object cached cmds, if any did exist
+        delete iIconCommands; // No effect, if iIconCommands aren't created
+        iIconCommands = NULL;
+        
+        // If the VGImage texture creation was successful, we are no longer "NVG 
+        // texture" in a sense. If not, we will use the NVG data directly for drawing
+        if (image != VG_INVALID_HANDLE)
+            {
+            CHuiTexture::SetNvgContent(EFalse);
+            iIsExtended = EFalse;
+            }
+        }
+    
+    if (aMaskBitmap)
+        {
+        CleanupStack::PopAndDestroy(maskDataBuf);
+        }
+    CleanupStack::Pop(dataBuf);
+    
+    // The texture now has content.
+    iInternalFlags |= EFlagHasContent;
+    iInternalFlags |= EFlagHasAlpha;
+    
+    HUI_VG_INVARIANT();
+    }
+
+TInt CHuiVg10Texture::CompareNvgData(HBufC8* aNVGData1, HBufC8* aNVGData2)
+    {
+    TInt lengthAfterHeader1 = aNVGData1->Length() - KIconHeaderLength;
+    TInt lengthAfterHeader2 = aNVGData2->Length() - KIconHeaderLength;
+    
+    TPtr8 firstNoHeader((TUint8 *)aNVGData1->Des().Ptr() + KIconHeaderLength, lengthAfterHeader1, lengthAfterHeader1);
+    TPtr8 secondNoHeader((TUint8 *)aNVGData2->Des().Ptr() + KIconHeaderLength, lengthAfterHeader2, lengthAfterHeader2);
+    
+    TInt returnValue = firstNoHeader.Compare(secondNoHeader);
+    return returnValue;
+    }
+
+VGImage CHuiVg10Texture::CreateRenderedImage(CNvgEngine* aNvgEngine, HBufC8* aNVGData, const TSize& aDestSize)
+    {
+    HUI_VG_INVARIANT();
+    
+    // Image placeholder
+    VGImage image = VG_INVALID_HANDLE;
+
+    if ( !iIsExtended )
+        {
+        // If called outside of the context, do nothing.
+        // Image will be VG_INVALID_HANDLE
+        HUI_DEBUG(_L("CHuiVg10Texture::CreateRenderedImage() - Texture not extended, can't create rendered image"));
+        return image;
+        }
+    
+    // Check if we already have an existing image.
+    if (SegmentCount() == 1)
+        {
+        image = (VGImage)SegmentName(0);
+        if( image != VG_INVALID_HANDLE )
+            {
+            HUI_DEBUG1(_L("CHuiVg10Texture::CreateRenderedImage() - Image already exists: %d"), image);
+            return image;
+            }
+        }
+    
+    // NVGEngine is needed to do the drawing of the extended bitmap to VGImage
+    if (!aNvgEngine || !aNVGData)
+        {
+        HUI_DEBUG(_L("CHuiVg10Texture::CreateRenderedImage() - No NvgEngine / NVGData!"));
+        return image;
+        }
+    
+    // Get the needed egl contexts & stuff for creating the proper eglSurface
+    EGLContext context = iRenderPlugin.EglSharedContext();
+    MHuiRenderSurface* oldSurface = CHuiStatic::CurrentRenderSurface();
+
+#ifndef __WINS__ // Should possibly query the supported mode instead?
+    VGImageFormat imageInternalFormat = VG_sARGB_8888_PRE;
+#else
+    VGImageFormat imageInternalFormat = VG_sARGB_8888;
+#endif
+    
+    VGbitfield qualityFlags = VG_IMAGE_QUALITY_NONANTIALIASED; // | VG_IMAGE_QUALITY_BETTER | VG_IMAGE_QUALITY_FASTER;
+    image = vgCreateImage(imageInternalFormat, aDestSize.iWidth, aDestSize.iHeight, qualityFlags);
+    
+    // Get the configs and displays etc. needed for creating the surface
+    EGLDisplay display = iRenderPlugin.EglDisplay();
+
+#if 1
+    // Returns the same config, as below!
+    // The config used with the current renderer surface has the same parameters
+    // that are needed with the PBufferSurface from vgImage
+    EGLConfig config = iRenderPlugin.EglConfig(0);
+#else
+    // This structure can be used, if surface config params have to be changed
+    // Better way though might be to change the vgImage VGImageFormat accordingly..
+    const TInt BITS_PER_CHANNEL = 8;
+    // Choose an EGL config
+    const EGLint attrs[] =
+        {
+        EGL_RENDERABLE_TYPE,    EGL_OPENVG_BIT,
+        EGL_SURFACE_TYPE,       EGL_PBUFFER_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT,
+        EGL_RED_SIZE,           BITS_PER_CHANNEL,
+        EGL_GREEN_SIZE,         BITS_PER_CHANNEL,
+        EGL_BLUE_SIZE,          BITS_PER_CHANNEL,
+        EGL_ALPHA_SIZE,         BITS_PER_CHANNEL,
+        EGL_NONE
+        };
+    TInt configCount = iRenderPlugin.EglChooseConfig(attrs);
+    ASSERT(configCount > 0);
+    EGLConfig config = iRenderPlugin.EglConfig(0);
+#endif
+    
+    // The VGImage will act as the surface, so the drawing will go directly to the VGImage
+    EGLSurface newSurface = eglCreatePbufferFromClientBuffer(
+        display, EGL_OPENVG_IMAGE,
+        static_cast<EGLClientBuffer>(image),    // Use the image as buffer
+        config, NULL);
+    
+    // Report error in debug mode, if failed creating the surface
+    if ( newSurface == EGL_NO_SURFACE )
+        {
+        HUI_DEBUG1(_L("CHuiVg10Texture::CreateRenderedImage() - EGL Surface could not be created, eglErr: %04x"), eglGetError() );
+        if ( image != VG_INVALID_HANDLE )
+            {
+            vgDestroyImage( image );
+            image = VG_INVALID_HANDLE;
+            }
+        
+        HUI_VG_INVARIANT();
+        return image;
+        }
+    
+    // Set the new VGImage related eglSurface as current, and start drawing onto it!  
+    // We use the old context, our surface should be compatible with it          
+    if ( eglMakeCurrent( display, newSurface, newSurface, context ) == EGL_FALSE )
+        {
+        // Report error in debug mode
+        HUI_DEBUG1(_L("CHuiVg10Texture::CreateRenderedImage() - EGL Surface could not be made current, eglErr: %04x"), eglGetError());
+        if ( image != VG_INVALID_HANDLE )
+            {
+            vgDestroyImage( image );
+            image = VG_INVALID_HANDLE;
+            }
+        
+        eglDestroySurface( display, newSurface );
+        HUI_VG_INVARIANT();
+        return image;
+        }
+    CHuiStatic::SetCurrentRenderSurface( NULL );
+    
+    
+    // VKN TODO: It would be better, if the GC could somehow spot that openVg
+    // state has changed, and would restore it's own state. Could use the same
+    // AddRestoreStateFlags as the paint is currently using..
+    //
+    // Get the current statematrix and store it for the duration of NVG drawing
+    TReal32 matrix[9];
+    vgGetMatrix(matrix);
+    vgLoadIdentity();
+    
+    // Render the NVGtexture into the image buffer. No transformations are done for this.
+    SetNvgParamsFromIconHeader(*aNvgEngine, aNVGData);
+    
+    if (iIconCommands)
+        {
+        //HUI_DEBUG(_L("CHuiVg10Texture::CreateRenderedImage() - Drawing iIconCommands"));
+        iIconCommands->Draw(aDestSize, aNvgEngine);
+        }
+    else
+        {
+        // If ObjectCached version failed, try to use the old way
+        //HUI_DEBUG(_L("CHuiVg10Texture::CreateRenderedImage() - Drawing with DrawNvg"));
+        VGint blendMode = vgGeti(VG_BLEND_MODE);
+        vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER);
+        aNvgEngine->DrawNvg(GetNvgDataWithoutHeader(aNVGData), aDestSize, NULL, NULL);
+        vgSeti(VG_BLEND_MODE, blendMode);
+        }
+    
+    // NVG-TLV icon margin special case check:
+    // Check, if the icon has to be margin corrected
+    TAknIconHeader iconheader = GetNvgIconHeader(aNVGData);
+    TSize size = aDestSize; // For using the correct size also later on
+    if (iconheader.IsMarginCorrection())
+        {
+        size = ApplyMargin(image, aDestSize, display, newSurface, context);
+        if( size != aDestSize)
+            {
+            // Redo the drawing, this time to the correct size
+            if (iIconCommands)
+                iIconCommands->Draw(size, aNvgEngine);
+            else
+                aNvgEngine->DrawNvg(GetNvgDataWithoutHeader(aNVGData), size, NULL, NULL);
+            }
+        }
+    
+    // The NVG draw messes up the paint, scissoring & rects, so mark them as dirty
+    TInt dirtyFlags = EHuiVg10GcStateFlagDirtyPaint |
+                    EHuiVg10GcStateFlagDirtyScissor | 
+                    EHuiVg10GcStateFlagDirtyScissorRects;
+    iRenderPlugin.AddRestoreStateFlags(dirtyFlags);
+    
+#ifdef _DEBUG
+    // TODO: There's something in the DrawNvg() code, which causes OpenVg to set
+    // error code => PANIC, if not for this temp check here. REMOVE ONCE THE TSW ERROR IS FIXED!
+    VGErrorCode err = vgGetError();
+    if (err)
+        {
+        RDebug::Print(_L("CHuiVG10Texture::CreateRenderedImage - Error in NVG draw: %04x"), err);
+        }
+#endif
+    
+    HUI_VG_INVARIANT();
+    
+    vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
+    vgLoadMatrix(matrix);
+    oldSurface->MakeCurrent();  // This will also call the SetCurrentRenderSurface
+    
+    // Now we should have a rendered image in the image variable!
+    // Release the surface, but not the context because we used a shared context
+    if ( newSurface != EGL_NO_SURFACE )
+        {
+        eglDestroySurface( display, newSurface );
+        }
+    
+    // NVG-TLV color correction special case check: If the icon has 
+    // some color specified in the icon header, set the new icon color
+    TUint32 iconColor = iconheader.GetIconColor();
+    if (iconColor & 0x00FFFFFF)
+        {
+        SetIconColor(image, size, iconColor);
+        }
+    
+    HUI_VG_INVARIANT();
+    
+    return image;
+    }
+
+TBool CHuiVg10Texture::IsExtended() const
+    {
+    return iIsExtended;
+    }
+
+HBufC8* CHuiVg10Texture::GetExtendedTextureData() const
+    {
+    return iNVGData;
+    }
+
+MNVGIcon* CHuiVg10Texture::GetIconCommandsData() const
+    {
+    return iIconCommands;
+    }
+
+void CHuiVg10Texture::CreateObjCachedNVGIconL()
+    {
+    HUI_VG_INVARIANT();
+    // Just to be sure that we don't leak memory
+    if (iIconCommands)
+        {
+        HUI_DEBUG(_L("CHuiVg10Texture::CreateObjCachedNVGIconL() - deleting old iIconCommands. Should never come here"));
+        delete iIconCommands;
+        iIconCommands = NULL;
+        }
+
+    // Fetch the NvgDecoder engine for creating the obj cached icon
+    CNvgEngine& nvgEngine = iRenderPlugin.NvgEngine();
+    
+    //Set Parameters from Icon Header
+    SetNvgParamsFromIconHeader(nvgEngine, iNVGData);
+    
+    // Parse the header info out of the nvg data 
+    TPtr8 nvgDataVoidIC = GetNvgDataWithoutHeader(iNVGData);
+    
+	iIconCommands = nvgEngine.CreateNVGIcon(nvgDataVoidIC, Size());
+	
+	HUI_VG_INVARIANT();
+    }
+
+TAknIconHeader CHuiVg10Texture::GetNvgIconHeader(HBufC8* aNVGData)
+    {
+    // Parse the icon header info from the extended data
+    TPtr8 IconHeaderPtr((TUint8*)aNVGData->Des().Ptr(), KIconHeaderLength, KIconHeaderLength);
+    TAknIconHeader iconheader(IconHeaderPtr);
+    
+    return iconheader;
+    }
+
+TPtr8 CHuiVg10Texture::GetNvgDataWithoutHeader(HBufC8* aNVGData)
+    {
+    // 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);
+    
+    return nvgDataVoidIC;
+    }
+
+void CHuiVg10Texture::SetNvgParamsFromIconHeader(CNvgEngine& aNvgEngine, HBufC8* aNVGData)
+    {
+    TAknIconHeader iconheader = GetNvgIconHeader(aNVGData);
+    
+    // Set preserve aspect ratio according to the header info
+    TNvgAlignStatusType alignTypeValue = ENvgPreserveAspectRatio_XmidYmid;
+    TNvgMeetOrSliceType meetOrSliceTypeValue = ENvgMeet;
+    
+    switch ( iconheader.GetScaleMode() )
+        {
+        case EAspectRatioPreserved: // Fall through
+            {
+            // 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 used default
+            break;
+            }
+        }
+    aNvgEngine.SetPreserveAspectRatio(alignTypeValue, meetOrSliceTypeValue);
+    aNvgEngine.Rotate(iconheader.GetRotation(),Size().iWidth >>1, Size().iHeight >>1);
+    }
+
+TSize CHuiVg10Texture::ApplyMargin(VGImage aImage, TSize aSize, EGLDisplay aDisplay, EGLSurface aSurface, EGLContext aContext)
+    {
+    HUI_VG_INVARIANT();
+    // If the icon is also a current EGL surface, the getImageSubData
+    // won't succeed and return "image in use" -error..
+    if ( eglMakeCurrent( aDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT ) == EGL_FALSE )
+        {
+        HUI_DEBUG1(_L("CHuiVg10Texture::ApplyMargin() - EGL NO_Surface could not be made current, eglErr: %04x"), eglGetError());
+        return aSize;
+        }
+    
+#ifndef __WINS__ // Should possibly query the supported mode instead?
+    VGImageFormat imageInternalFormat = VG_sARGB_8888_PRE;
+#else
+    // This doesn't work in the Emulator anyways.. => remove?
+    VGImageFormat imageInternalFormat = VG_sARGB_8888;
+#endif
+    
+    TInt stride = aSize.iWidth * 4; // VG_sARGB_8888(_PRE) is four bytes long (8888)
+    HBufC8* buf = HBufC8::New(stride);
+    if (!buf)
+        {
+        HUI_DEBUG(_L("CHuiVg10Texture::ApplyMargin() - Ran out of memory!"));
+        return aSize;        
+        }
+    TUint32* ptr = (TUint32*)(buf->Des()).Ptr();
+    
+    const TInt lValidMargin = aSize.iHeight * 12 / 100;
+    
+    const TInt Ha = aSize.iHeight;
+    TInt hTa = 0;
+    TInt hNT = 0;
+    TInt C = 0;
+    TInt hNTN = Ha - 2.0 * 0.12 * Ha;
+    TReal R = 1.0;
+    TInt HaN = Ha;
+    
+    const TInt lastColumn = aSize.iHeight - 1;
+    for (TInt curRow = 0; curRow < lValidMargin; curRow++)
+        {
+        const TInt y = (aSize.iHeight - 1) - curRow; // h - 1 is the last line
+        // Get just one stride at a time (iWidth wide, 1 pixel high)
+        vgGetImageSubData(aImage, ptr, stride, imageInternalFormat, 0, y, aSize.iWidth, 1);
+        for (TInt s = lastColumn; s >= 0; --s)
+            {
+            if (ptr[s] & 0xFF000000)
+                {
+                hTa = curRow;
+                hNT = Ha - 2 * hTa;
+                C = 2 * hTa;
+                R = ( ( (TReal)hNTN / (TReal)hNT ) > 1.0 ) ? 1 : (TReal)hNTN / (TReal)hNT;
+                HaN = Ha * R - C * R + C;
+                curRow = lValidMargin; // to exit the outer loop
+                break; // to exit the inner
+                }
+            }
+        }
+    delete buf;
+    HUI_VG_INVARIANT();
+    
+    // Make the PBuffer surface current again 
+    if ( eglMakeCurrent(aDisplay, aSurface, aSurface, aContext) == EGL_FALSE )
+        {
+        HUI_DEBUG1(_L("CHuiVg10Texture::ApplyMargin() - EGL aSurface could not be made current, eglErr: %04x"), eglGetError());
+        return aSize;
+        }
+    
+    // If icon size has to be changed, clear out old area for new DrawNVG round!
+    if(aSize.iHeight > HaN)
+        {
+        vgLoadIdentity();
+        
+        VGfloat color[4] = { 1.0f, 1.0f, 1.0f, 0.0f };
+        vgSetfv(VG_CLEAR_COLOR, 4, color);
+        vgClear(0, 0, aSize.iWidth, aSize.iHeight);
+        // Or should it be clearImage instead?
+        //vgClearImage(aImage, 0, 0, aSize.iWidth, aSize.iHeight);
+        
+        VGfloat Hr = (VGfloat)HaN/(aSize.iHeight);        
+        TInt WaN = aSize.iWidth*Hr;
+        
+        VGfloat Tx = (aSize.iHeight-HaN)/2;
+        VGfloat Ty = (aSize.iWidth-WaN)/2;
+        vgTranslate(Tx,Ty);
+        
+        HUI_VG_INVARIANT();
+        return(TSize(HaN,WaN));
+        }
+    
+    HUI_VG_INVARIANT();
+    return aSize;
+    }
+
+void CHuiVg10Texture::SetIconColor(VGImage& aSrcImage, TSize aSize, TUint32 aColor)
+    {
+    // TODO: DOESN'T WORK IN EMULATOR FOR SOME REASON! Figure out why!
+    HUI_VG_INVARIANT();
+    
+    vgSeti(VG_FILTER_FORMAT_LINEAR, VG_FALSE);
+    
+#ifndef __WINS__ // Should possibly query the supported mode instead?
+    VGImageFormat imageInternalFormat = VG_sARGB_8888_PRE;
+    // TODO: !!! SHOULD FORMAT_PREMULTIPLIED BE APPLIED?? !!!
+    //vgSeti(VG_FILTER_FORMAT_PREMULTIPLIED, VG_TRUE);
+#else
+    // This doesn't work in the Emulator anyways.. => remove?
+    VGImageFormat imageInternalFormat = VG_sARGB_8888;
+#endif
+    
+    // Rip the RGB components from the aColor param & scale to [0..1]
+    VGfloat red      = (aColor&0xff)/255.0f;
+    VGfloat green    = ((aColor>>8)&0xff)/255.0f;
+    VGfloat blue     = ((aColor>>16)&0xff)/255.0f;
+    
+    //vgSeti(VG_FILTER_CHANNEL_MASK, VG_ALPHA );
+    // This matrix will set all color components in the source image to 0,
+    // and replaces the RGB with the values from the iconheader 
+    VGfloat matrix[20] = {
+            0,0,0,0,
+            0,0,0,0,
+            0,0,0,0,
+            0,0,0,1, // <- Preserves the original alpha value
+            red, green, blue, 0};
+    
+    // Create the destination image & start modifying colors
+    VGImage dstImg = vgCreateImage(imageInternalFormat, aSize.iWidth, aSize.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED);
+    vgColorMatrix(dstImg, aSrcImage, matrix);
+    HUI_VG_INVARIANT();
+    
+    // Destroy the old source image and return the new image with changed colors
+    vgDestroyImage(aSrcImage);
+    aSrcImage = dstImg;
+    
+    HUI_VG_INVARIANT();
+    }
+
+void CHuiVg10Texture::ReplaceVGImageAlphaChannelL(VGImage aImage, VGImage aMaskImage, TSize aSize)
+    {
+    HUI_VG_INVARIANT();
+    
+#ifndef __WINS__ // Should possibly query the supported mode instead?
+    VGImageFormat imageInternalFormat = VG_sARGB_8888_PRE;
+#else
+    VGImageFormat imageInternalFormat = VG_sARGB_8888;
+#endif
+    TInt height = aSize.iHeight;
+    TInt width = aSize.iWidth;
+    const TInt colorDepth = 4;  // VG_sARGB_8888(_PRE) 4 bytes long
+    TInt stride = width * colorDepth;
+    
+    // Create the pointers to RAM in which the image data will be saved temporarily
+    HBufC8* imgBuf = HBufC8::NewL(width * height * colorDepth);
+    CleanupStack::PushL(imgBuf);
+    TUint32* imgPtr = (TUint32*)(imgBuf->Des()).Ptr();
+    const TUint32* imgSavePtr = (TUint32*)(imgBuf->Des()).Ptr(); 
+    
+    HBufC8* maskBuf = HBufC8::NewL(width * height * colorDepth);
+    CleanupStack::PushL(maskBuf);
+    TUint32* maskPtr = (TUint32*)(maskBuf->Des()).Ptr();
+    
+    // Get the image pixel data
+    vgGetImageSubData(aImage, imgPtr, stride, imageInternalFormat, 0, 0, width, height);
+    vgGetImageSubData(aMaskImage, maskPtr, stride, imageInternalFormat, 0, 0, width, height);
+    
+    // Replace destination image's alpha values with mask image
+    for (TInt y = 0; y < height; y++)
+        {
+        for (TInt x = 0; x < width; x++)
+            {
+            *maskPtr    &= 0xff000000;      // Remove other than alpha component from source pixel
+            *imgPtr     &= ~0xff000000;     // Remove alpha channel value from destination pixel
+            *imgPtr++   |= *maskPtr++;      // Bitwise OR the maskImg alpha info to destination image pixel 
+            }
+        }
+
+    // Replace the destination image with combined alpha information from src image
+    vgImageSubData(aImage, imgSavePtr, stride, imageInternalFormat, 0, 0, width, height);
+
+    CleanupStack::PopAndDestroy(maskBuf);
+    CleanupStack::PopAndDestroy(imgBuf);
+    
+    HUI_VG_INVARIANT();
+    }
+#endif
+
+
+void CHuiVg10Texture::PushEGLContext()
+    {
+    iPreviousEGLState.iContext= eglGetCurrentContext(); 
+    TEGLState& state = iRenderPlugin.GetUploadState();
+    if (state.iContext == KErrNotFound)
+        {
+		TEGLState& state = iRenderPlugin.GetUploadState();
+        // the first context used for uploading will be used for all texture uploads
+        state.iContext      = iPreviousEGLState.iContext; 
+        state.iDrawSurface  = eglGetCurrentSurface(EGL_DRAW);
+        state.iReadSurface  = eglGetCurrentSurface(EGL_READ);
+        state.iDisplay      = eglGetCurrentDisplay();
+        }
+    else
+        {
+        // change context only if necessary
+        if (iPreviousEGLState.iContext != state.iContext)
+            {
+            iPreviousEGLState.iDrawSurface  = eglGetCurrentSurface(EGL_DRAW);
+            iPreviousEGLState.iReadSurface  = eglGetCurrentSurface(EGL_READ);
+            iPreviousEGLState.iDisplay      = eglGetCurrentDisplay();
+            eglMakeCurrent(state.iDisplay, state.iDrawSurface, state.iReadSurface, state.iContext);
+            }
+        }
+    }
+
+void CHuiVg10Texture::PopEGLContext()
+    {
+    if (iPreviousEGLState.iContext != iRenderPlugin.GetUploadState().iContext)
+        {
+        eglMakeCurrent(iPreviousEGLState.iDisplay,  iPreviousEGLState.iDrawSurface, iPreviousEGLState.iReadSurface,iPreviousEGLState.iContext);
+        }
+    }
+// End of file
+