--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/svgtopt/nvgdecoder/src/nvg.cpp Thu Jan 07 16:19:02 2010 +0200
@@ -0,0 +1,1717 @@
+/*
+* Copyright (c) 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: NVG Decoder source file
+*
+*/
+
+
+#include <s32mem.h>
+#include <libc/math.h>
+#include <e32math.h>
+
+#include "nvg.h"
+#include "nvgfittoviewbox.h"
+#include "NVGUtil.h"
+
+#include "NVGCSIcon.h"
+#include "NVGTLVIcon.h"
+#include "FloatFixPt.h"
+
+#include "NVGIconData.h"
+
+/*
+ * may be we should use dynamic_cast?
+ */
+#define CSICON(icon) ((CNVGCSIcon *)icon)
+#define TLVICON(icon) ((CNVGTLVIcon *)icon)
+
+enum TNVGFormats
+ {
+ ENVGCS,
+ ENVGTLV
+ };
+
+/*
+ * NVG-CS version
+ */
+//const TInt KVersion1 = 1;
+const TInt KVersion2 = 2;
+
+/*
+ * constants for nvg file header offsets
+ */
+const TUint8 KNVG_SIGNATURE[] = "nvg";
+const TInt KNVG_SIGNATURE_LENGTH = sizeof(KNVG_SIGNATURE) - sizeof('\0');
+const TInt KNVG_COMMANDSECTION_OFS = 2;
+const TInt KNVG_VERSION_OFS = 3;
+const TInt KNVG_RGBA_OFS = 4;
+const TInt KNVG_HEADERSIZE_OFS = 4;
+const TInt KNVG_PATHDATATYPE_OFS = 26;
+const TInt KNVG_SCALE_OFS = 28;
+const TInt KNVG_BIAS_OFS = 32;
+const TInt KNVG_VIEWBOX_X_OFS = 36;
+const TInt KNVG_VIEWBOX_Y_OFS = 40;
+const TInt KNVG_VIEWBOX_WIDTH_OFS = 44;
+const TInt KNVG_VIEWBOX_HEIGHT_OFS = 48;
+
+const TInt KNVG_PAINTSECTION_LINEARGRAD_TRANSFORM_OFFSET = 20;
+const TInt KNVG_PAINTSECTION_RADIALGRAD_TRANSFORM_OFFSET = 24;
+
+/*
+ * nvg-cs commands
+ */
+const TInt KCMD_SET_FILL_PAINT = 4 << 24;
+const TInt KCMD_SET_COLOR_RAMP = 6 << 24;
+const TInt KCMD_DRAW_PATH = 7 << 24;
+const TInt KCMD_SET_TRANSFORMATION = 8 << 24;
+const TInt KCMD_SET_STROKE_PAINT = 5 << 24;
+const TInt KCMD_SET_STROKE_WIDTH = 9 << 24;
+const TInt KCMD_SET_STROKE_LINE_JOIN_CAP = 10 << 24;
+const TInt KCMD_SET_STROKE_MITER_LIMIT = 11 << 24;
+
+/*
+ * stroke cap style
+ */
+const TInt KCAP_BUTT = 1;
+const TInt KCAP_SQUARE = 2;
+const TInt KCAP_ROUND = 3;
+
+/*
+ * stroke join style
+ */
+const TInt KLINE_JOIN_BEVEL = 1;
+const TInt KLINE_JOIN_MITER = 2;
+const TInt KLINE_JOIN_ROUND = 3;
+
+/*
+ * fill paint type
+ */
+const TInt KPAINT_FLAT = 1;
+const TInt KPAINT_LGRAD = 2;
+const TInt KPAINT_RGRAD = 3;
+
+/*
+ * stroke paint type
+ */
+const TInt KSTROKE_LGRAD = 2;
+const TInt KSTROKE_RGRAD = 3;
+const TInt KSTROKE_COLOR_RAMP = 4;
+
+/*
+ * nvg offset
+ */
+const TInt KOffsetReserved1 = 6;
+
+/*
+ * transform encoding values
+ */
+const TInt KTRANSFORM_COMPLETE = 0;
+const TInt KTRANSFORM_SCALING = 2;
+const TInt KTRANSFORM_SHEARING = 4;
+const TInt KTRANSFORM_ROTATION = 8;
+const TInt KTRANSFORM_TRANSLATION = 16;
+
+#ifdef OPENVG_OBJECT_CACHING
+const VGfloat KIdentityMatrix[] =
+ {
+ 1.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f ,1.0f
+ };
+#endif
+
+/*
+ * function to delete array, for basic types
+ */
+GLDEF_C void CleanupArray( TAny * aObj )
+ {
+ delete [] aObj;
+ }
+
+/*
+ * function to delete array of TFloatFixArray
+ */
+GLDEF_C void CleanupTFloatFixArray( TAny * aObj )
+ {
+ TFloatFixPt * ff = (TFloatFixPt *)aObj;
+ delete [] ff;
+ }
+
+/**
+ * @class TNVGEngineInternal
+ * This class is added to maintain BC.
+ * If you want to add new member variable you can add in this class, without breaking BC.
+ * It is better to add members which are depend on macro's in this class.
+ */
+class TNVGEngineInternal
+ {
+public:
+ TNVGEngineInternal()
+ {
+#ifdef OPENVG_OBJECT_CACHING
+ iCreatingNVGIcon = 0;
+ iCurrentNVGIcon = 0;
+#endif
+ }
+
+#ifdef OPENVG_OBJECT_CACHING
+ TInt iCreatingNVGIcon;
+ MNVGIcon * iCurrentNVGIcon;
+#endif
+ };
+
+CNvgEngine::CNvgEngine()
+ : iCurrentBufferSize(1, 1),
+ iPath(VG_INVALID_HANDLE),
+ iPaintFill(VG_INVALID_HANDLE),
+ iPaintStroke( VG_INVALID_HANDLE),
+ iUserStrokePaintColor(0xFFFFFFFF),
+ iRotateApplied(EFalse),
+ iLastPathDataType(0),
+ iPreserveAspectSetting(ENvgPreserveAspectRatio_XmidYmid),
+ iSmilFitSetting(ENvgMeet),
+ iVGImageBinder(0)
+ {
+ }
+
+EXPORT_C CNvgEngine* CNvgEngine::NewL()
+ {
+ CNvgEngine* self = new (ELeave) CNvgEngine;
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+void CNvgEngine::ConstructL()
+ {
+ vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_BETTER);
+ vgSeti(VG_FILL_RULE, VG_NON_ZERO);
+
+ iInternal = new (ELeave) TNVGEngineInternal;
+ iPaintFill = vgCreatePaint();
+ }
+
+EXPORT_C CNvgEngine::~CNvgEngine()
+ {
+ if (iPath != VG_INVALID_HANDLE)
+ {
+ vgDestroyPath(iPath);
+ }
+
+ if (iPaintFill != VG_INVALID_HANDLE)
+ {
+ vgSetPaint(VG_INVALID_HANDLE, VG_FILL_PATH);
+ vgDestroyPaint(iPaintFill);
+ }
+
+ if (iPaintStroke != VG_INVALID_HANDLE)
+ {
+ vgSetPaint(VG_INVALID_HANDLE, VG_STROKE_PATH);
+ vgDestroyPaint(iPaintStroke);
+ }
+
+
+#ifdef OPENVG_OBJECT_CACHING
+ if (iInternal)
+ {
+ delete iInternal->iCurrentNVGIcon;
+ }
+#endif
+
+ delete iInternal;
+ }
+
+/**
+ * @brief Set the angle for rotation of the NVG graphic
+ * @version
+ * @param aAngle counter-clockwise rotation by a given angle (expressed in degrees)
+ * aX, aY point around which the rotation must take place
+ * @return None
+ */
+EXPORT_C void CNvgEngine::Rotate(TReal32 aAngle, TReal32 aCentreX, TReal32 aCentreY) __SOFTFP
+ {
+ if(aAngle)
+ {
+ iRotateApplied = ETrue;
+ iCentreX = aCentreX;
+ iCentreY = aCentreY;
+ iRotateAngle = aAngle;
+ }
+ else
+ {
+ iRotateApplied = EFalse;
+ iCentreX = 0;
+ iCentreY = 0;
+ iRotateAngle = 0;
+ }
+ }
+
+/**
+ * @brief Gets the viewbox width and height from the NVG bytedata
+ * @version
+ * @param aBuf NVG byte data of the file
+ * @return content dimension
+ */
+EXPORT_C TSize CNvgEngine::ContentDimensions(const TDesC8& aBuf)
+ {
+ if (aBuf.Length() < KNVG_VIEWBOX_HEIGHT_OFS + sizeof (TReal32))
+ {
+ return TSize(0, 0);
+ }
+
+ const TUint8* lBuf = aBuf.Ptr();
+ TReal32 lViewboxWidth = * (TReal32*)(lBuf + KNVG_VIEWBOX_WIDTH_OFS);
+ TReal32 lViewboxHeight = * (TReal32*)(lBuf + KNVG_VIEWBOX_HEIGHT_OFS);
+
+ if (lViewboxWidth > 0 && lViewboxHeight > 0)
+ {
+ return TSize(lViewboxWidth, lViewboxHeight);
+ }
+ else
+ {
+ return TSize(0, 0);
+ }
+ }
+
+TInt CNvgEngine::InitializeGC()
+ {
+ if (iPaintFill == VG_INVALID_HANDLE)
+ {
+ iPaintFill = vgCreatePaint();
+ if (iPaintFill == VG_INVALID_HANDLE)
+ {
+ return OpenVGErrorToSymbianError(vgGetError());
+ }
+ }
+
+ vgSetPaint(iPaintFill, VG_FILL_PATH);
+ if (iPaintStroke == VG_INVALID_HANDLE)
+ {
+ iPaintStroke = vgCreatePaint();
+ if (iPaintStroke == VG_INVALID_HANDLE)
+ {
+ return OpenVGErrorToSymbianError(vgGetError());
+ }
+ }
+
+ vgSetPaint( iPaintStroke, VG_STROKE_PATH);
+
+ return KErrNone;
+ }
+
+EXPORT_C void CNvgEngine::ResetNvgState()
+ {
+ if (iPath != VG_INVALID_HANDLE)
+ {
+ vgDestroyPath(iPath);
+ iPath = VG_INVALID_HANDLE;
+ }
+
+ if (iPaintFill != VG_INVALID_HANDLE)
+ {
+ vgSetPaint(VG_INVALID_HANDLE, VG_FILL_PATH);
+ vgDestroyPaint(iPaintFill);
+ iPaintFill = VG_INVALID_HANDLE;
+ }
+
+ if (iPaintStroke != VG_INVALID_HANDLE)
+ {
+ vgSetPaint(VG_INVALID_HANDLE, VG_STROKE_PATH);
+ vgDestroyPaint(iPaintStroke);
+ iPaintStroke = VG_INVALID_HANDLE;
+ }
+ }
+
+EXPORT_C TInt CNvgEngine::DrawNvg(const TDesC8& aBuf, const TSize& aSize, CFbsBitmap* aDstBitmap, CFbsBitmap* aMask)
+ {
+ TInt error = KErrNone;
+
+ /*
+ * Get Matrix modes and all caller matrices (must be restored afterwards)
+ */
+ UpdateClientMatrices();
+
+ TRAP(error, DoDrawNVGL(aBuf, aSize, aDstBitmap, aMask));
+
+ /*
+ * restore everything as we may have changed matrix mode
+ */
+ RestoreClientMatrices();
+ vgSeti(VG_SCISSORING, VG_FALSE);
+
+ if (error)
+ {
+ NVG_DEBUGP2("Error in NVG rendering %d", error);
+ }
+ return error;
+ }
+
+EXPORT_C MNVGIcon * CNvgEngine::CreateNVGIcon(const TDesC8& aBuf, const TSize& aSize)
+ {
+ NVG_DEBUGP1("Creating NVGCSIcon");
+
+ MNVGIcon * nvgIcon = 0;
+
+ /*
+ * this is bit unreadable,
+ * need to find a better design to separate the object caching solution from normal rendering,
+ * but anyway I guess its better than those ifdef's, in that code scanner won't give any warnings
+ */
+ COND_COM_OC_NOC(
+ {
+ if (iInternal->iCurrentNVGIcon)
+ {
+ delete iInternal->iCurrentNVGIcon;
+ }
+
+ iInternal->iCurrentNVGIcon = 0;
+ iInternal->iCreatingNVGIcon = 1;
+
+ if (DrawNvg(aBuf, aSize, 0, 0) != KErrNone)
+ {
+ delete iInternal->iCurrentNVGIcon;
+ iInternal->iCurrentNVGIcon = 0;
+ }
+
+ iInternal->iCreatingNVGIcon = 0;
+ nvgIcon = iInternal->iCurrentNVGIcon;
+ iInternal->iCurrentNVGIcon = 0;
+ },
+ {
+ (void)aBuf;
+ (void)aSize;
+ });
+
+ return nvgIcon;
+ }
+
+void CNvgEngine::DoDrawNVGL(const TDesC8& aBuffer, const TSize& aSize, CFbsBitmap* aDstBitmap, CFbsBitmap* aMask)
+ {
+ TInt drawStatus = KErrNone;
+
+ if (iCurrentBufferSize != aSize)
+ {
+ iCurrentBufferSize = aSize;
+ }
+
+ iDstBimtap = aDstBitmap;
+
+ TDereferencer nvgIconData(aBuffer);
+
+ TUint8 * signature = nvgIconData.DerefInt8ArrayL(KNVG_SIGNATURE_LENGTH);
+
+ // checking the 'nvg' signature
+ if (Mem::Compare(signature, KNVG_SIGNATURE_LENGTH, KNVG_SIGNATURE, KNVG_SIGNATURE_LENGTH) != 0)
+ {
+ NVG_DEBUGP1("Not an NVG icon");
+ User::Leave(KErrNotSupported);
+ }
+
+ // last two bits are for identifying the nvg type. currently nvg-cs or nvg-tlv
+ TUint16 nvgType = nvgIconData.DerefInt16L(KOffsetReserved1) & 0x03;
+
+ switch (nvgType)
+ {
+ case ENVGCS:
+ {
+ drawStatus = DrawCommandSectionL(&nvgIconData, aSize, aDstBitmap, aMask);
+ break;
+ }
+ case ENVGTLV:
+ {
+ drawStatus = DrawTLVL(aBuffer, aSize, aDstBitmap, aMask);
+ break;
+ }
+ default:
+ drawStatus = KErrNotSupported;
+ break;
+ }
+
+ User::LeaveIfError(drawStatus);
+ }
+
+TInt CNvgEngine::DrawTLVL(const TDesC8& aBuf, const TSize& aTargetSize, CFbsBitmap* /*aDstBitmap*/, CFbsBitmap * /*aMask*/)
+ {
+ TInt ret = KErrNone;
+
+ // Try to set user's matrix to path matrix
+ VGfloat origMatrix[9];
+ vgGetMatrix(origMatrix);
+
+ vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
+ vgLoadMatrix(origMatrix);
+
+#ifndef __MIRROR_
+ vgScale(1.0f, -1.0f);
+ vgTranslate(0, (VGfloat)(-iCurrentBufferSize.iHeight));
+#endif
+
+ /*
+ * this is bit unreadable,
+ * need to find a better design to separate the object caching solution from normal rendering,
+ * but anyway I guess its better than those ifdef's, in that code scanner won't give any warnings
+ */
+ COND_COM_OC_NOC(
+ {
+ if (iInternal->iCreatingNVGIcon)
+ {
+ iInternal->iCurrentNVGIcon = CNVGTLVIcon::NewL();
+ TLVICON(iInternal->iCurrentNVGIcon)->SetVGImageBinder(iVGImageBinder);
+ TLVICON(iInternal->iCurrentNVGIcon)->CreateL(aBuf, aTargetSize);
+ }
+ else
+ {
+ CNVGTLVIcon * tlvIcon = CNVGTLVIcon::NewL();
+ CleanupStack::PushL(tlvIcon);
+ tlvIcon->SetVGImageBinder(iVGImageBinder);
+ tlvIcon->DirectDrawL(aBuf, aTargetSize);
+ CleanupStack::PopAndDestroy(tlvIcon);
+ }
+
+ },
+ {
+ CNVGTLVIcon * tlvIcon = CNVGTLVIcon::NewL();
+ CleanupStack::PushL(tlvIcon);
+ TLVICON(tlvIcon)->SetVGImageBinder(iVGImageBinder);
+ TLVICON(tlvIcon)->DirectDrawL(aBuf, aTargetSize);
+ CleanupStack::PopAndDestroy(tlvIcon);
+ });
+
+ vgSeti(VG_SCISSORING, VG_FALSE);
+
+ return ret;
+ }
+
+TInt CNvgEngine::CreatePathHandle(TInt16 aPathDataType, TReal32 aScale, TReal32 aBias)
+ {
+ (void) aScale;
+ (void) aBias;
+
+ TInt error = KErrNone;
+
+ if (iLastPathDataType != aPathDataType)
+ {
+ if (iPath != VG_INVALID_HANDLE)
+ {
+ vgDestroyPath(iPath);
+ iPath = VG_INVALID_HANDLE;
+ }
+ }
+
+ if (iPath == VG_INVALID_HANDLE)
+ {
+ switch (aPathDataType)
+ {
+ case EEightBitEncoding:
+ {
+ iPath = vgCreatePath(VG_PATH_FORMAT_STANDARD,
+ VG_PATH_DATATYPE_S_16, 1.0f/2.0f, 0.0f, 0, 0,
+ VG_PATH_CAPABILITY_APPEND_TO);
+ }
+ break;
+
+ case ESixteenBitEncoding:
+ {
+ iPath = vgCreatePath(VG_PATH_FORMAT_STANDARD,
+ VG_PATH_DATATYPE_S_16, 1.0f/16.0f, 0.0f, 0, 0,
+ VG_PATH_CAPABILITY_APPEND_TO);
+ }
+ break;
+
+ case EThirtyTwoBitEncoding:
+ {
+ iPath = vgCreatePath(VG_PATH_FORMAT_STANDARD,
+ VG_PATH_DATATYPE_S_32, 1.0f/65536.0f, 0.0f, 0, 0,
+ VG_PATH_CAPABILITY_APPEND_TO);
+ }
+ break;
+
+ default:
+ {
+ return KErrCorrupt;
+ }
+ }
+ }
+
+ if( iPath == VG_INVALID_HANDLE )
+ {
+ // get the symbian error code
+ error = OpenVGErrorToSymbianError(vgGetError());
+
+ if (error == KErrNoMemory)
+ {
+ NVG_DEBUGP1("NVG Error OOM");
+ ResetNvgState();
+ }
+ return error;
+ }
+
+ iLastPathDataType = aPathDataType;
+
+ return error;
+ }
+
+TInt CNvgEngine::DrawCommandSectionL(TDereferencer * aIconData, const TSize& aTargetSize, CFbsBitmap * /*aDstBitmap*/, CFbsBitmap * /*aMask*/)
+ {
+ TInt16 lHeaderSize = aIconData->DerefInt16L(KNVG_HEADERSIZE_OFS);
+ TInt8 NVGVersion = aIconData->DerefInt8L(KNVG_VERSION_OFS);
+
+ User::LeaveIfError(InitializeGC());
+
+ TInt16 lPathDataType = aIconData->DerefInt16L(KNVG_PATHDATATYPE_OFS);
+ TReal32 lScale = aIconData->DerefReal32L(KNVG_SCALE_OFS);
+ TReal32 lBias = aIconData->DerefReal32L(KNVG_BIAS_OFS);
+
+ User::LeaveIfError(CreatePathHandle(lPathDataType, lScale, lBias));
+
+ vgSetPaint(iPaintFill, VG_FILL_PATH);
+
+ COND_COM_OC_OOC(
+ if (iInternal->iCreatingNVGIcon)
+ {
+ iInternal->iCurrentNVGIcon = CNVGCSIcon::NewL(aIconData->GetPtr());
+ });
+
+ VGfloat lCurrentPathMatrix[9];
+ vgGetMatrix(lCurrentPathMatrix);
+
+ vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
+
+ /*
+ * We use the caller's base batrix regardless of which mode the caller was.
+ * The caller may have set the matrix in VG_MATRIX_IMAGE_USER_TO_SURFACE mode
+ * as it thinks it is drawing images (textures).
+ * But even though the texture gets stroked instead, we must use the caller's
+ * transformation matrix.
+ * Everything gets restored to the original values before we return.
+ */
+ vgLoadMatrix(lCurrentPathMatrix);
+
+ ApplyScissoring(lCurrentPathMatrix, aTargetSize);
+
+ /*
+ * set the rotation angle if available
+ */
+ if (iRotateApplied)
+ {
+ ApplyRotation();
+ }
+
+#ifdef __MIRROR_
+ vgScale(1.0f, -1.0f);
+ vgTranslate(0, (VGfloat)(-iCurrentBufferSize.iHeight) );
+#endif
+
+ TReal32 lViewboxX = aIconData->DerefReal32L(KNVG_VIEWBOX_X_OFS);
+ TReal32 lViewboxY = aIconData->DerefReal32L(KNVG_VIEWBOX_Y_OFS);
+ TReal32 lViewboxW = aIconData->DerefReal32L(KNVG_VIEWBOX_WIDTH_OFS);
+ TReal32 lViewboxH = aIconData->DerefReal32L(KNVG_VIEWBOX_HEIGHT_OFS);
+
+ ApplyViewboxToViewPortTransformationL(aTargetSize, lViewboxX, lViewboxY, lViewboxW, lViewboxH);
+
+ TPtr8 ptr = aIconData->GetPtr();
+
+ TInt offsetSectionLength = aIconData->GetLength() - lHeaderSize;
+ TUint8 * offsetPtr = aIconData->DerefInt8ArrayL(offsetSectionLength, lHeaderSize);
+
+ TDereferencer offsetSection(offsetPtr, offsetSectionLength);
+
+ TUint16 lOffsetVectorCount = offsetSection.DerefInt16L();
+
+ offsetPtr = aIconData->DerefInt8ArrayL(offsetSectionLength - sizeof(TUint16), lHeaderSize + sizeof(TUint16));
+ TDereferencer offsetVector(offsetPtr, offsetSectionLength - sizeof(TUint16));
+
+ idoFill = VG_FALSE;
+ idoStroke = VG_FALSE;
+
+ TPtr8 offsetTPtr = offsetVector.GetPtr();
+
+ TInt commandSectionOffset = lOffsetVectorCount * sizeof(TUint16);
+ TDereferencer commandSection((unsigned char*)(offsetTPtr.Ptr() + commandSectionOffset),
+ aIconData->GetLength() - commandSectionOffset - lHeaderSize - sizeof(TUint16));
+
+ // from version 2 onwards command section will start on word boundary
+ if (NVGVersion >= KVersion2 && ((lOffsetVectorCount & 0x01) == 0))
+ {
+ commandSection.SkipL(2);
+ }
+
+ TUint16 lCmdCount = commandSection.DerefInt16L();
+
+ commandSection.SkipL(KNVG_COMMANDSECTION_OFS);
+
+ /*
+ * from version 2 onwards there will be a padding added
+ * after the command count to make it word aligned
+ */
+ if (NVGVersion >= KVersion2)
+ {
+ commandSection.SkipL(2);
+ }
+
+ ExecuteNVGCSCommandLoopL(lCmdCount, aIconData, &offsetVector, &commandSection, NVGVersion);
+
+ return KErrNone;
+ }
+
+void CNvgEngine::ApplyRotation()
+ {
+ vgTranslate(iCentreX, iCentreY);
+ vgRotate(iRotateAngle);
+ vgTranslate(-iCentreX, -iCentreY);
+ }
+
+void CNvgEngine::ApplyScissoring(VGfloat aMatrix[], const TSize& aTargetSize)
+ {
+ /*
+ * calculate the rectangle with respect to the transformation applied
+ * and set the scissoring rect
+ */
+ TPoint leftBottom = GetTranslatedPoint(aMatrix, TPoint(0, 0));
+ TPoint leftTop = GetTranslatedPoint(aMatrix, TPoint(0, aTargetSize.iHeight));
+ TPoint rightBottom = GetTranslatedPoint(aMatrix, TPoint(aTargetSize.iWidth, 0));
+ TPoint rightTop = GetTranslatedPoint(aMatrix, TPoint(aTargetSize.iWidth,aTargetSize.iHeight));
+
+ VGfloat minX = leftBottom.iX;
+ VGfloat minY = leftBottom.iY;
+ VGfloat maxX = leftBottom.iX;
+ VGfloat maxY = leftBottom.iY;
+
+ minX = MinVal4(leftBottom.iX, leftTop.iX, rightBottom.iX, rightTop.iX);
+ minY = MinVal4(leftBottom.iY, leftTop.iY, rightBottom.iY, rightTop.iY);
+
+ maxX = MaxVal4(leftBottom.iX, leftTop.iX, rightBottom.iX, rightTop.iX);
+ maxY = MaxVal4(leftBottom.iY, leftTop.iY, rightBottom.iY, rightTop.iY);
+
+ VGfloat newW = maxX - minX;
+ VGfloat newH = maxY - minY;
+
+ VGint clipRect[] = {minX, minY, newW, newH};
+
+ vgSeti(VG_SCISSORING, VG_TRUE);
+ vgSetiv(VG_SCISSOR_RECTS, 4,(const TInt32*) clipRect);
+ }
+
+void CNvgEngine::ApplyViewboxToViewPortTransformationL(const TSize& aTargetSize, TReal32 aViewboxX, TReal32 aViewboxY, TReal32 aViewboxW, TReal32 aViewboxH)
+ {
+ CNvgFitToViewBoxImpl * viewboxTrnsfr = CNvgFitToViewBoxImpl::NewL();
+ CleanupStack::PushL(viewboxTrnsfr);
+ /*
+ * this is bit unreadable,
+ * need to find a better design to separate the object caching solution from normal rendering,
+ * but anyway I guess its better than those ifdef's, in that code scanner won't give any warnings
+ */
+ COND_COM_OC_NOC(
+ {
+ if (iInternal->iCreatingNVGIcon)
+ {
+ CSICON(iInternal->iCurrentNVGIcon)->SetViewBox(aViewboxX, aViewboxY, aViewboxW, aViewboxH);
+ CSICON(iInternal->iCurrentNVGIcon)->SetPreserveAspectRatio(iPreserveAspectSetting, iSmilFitSetting);
+ CSICON(iInternal->iCurrentNVGIcon)->Rotate(iRotateAngle, iCentreX, iCentreY);
+ }
+ else
+ {
+ viewboxTrnsfr->SetAlign(iPreserveAspectSetting);
+ viewboxTrnsfr->SetScaling(iSmilFitSetting);
+
+ if (aViewboxW > 0 && aViewboxH > 0)
+ {
+ viewboxTrnsfr->SetViewBox(aViewboxX, aViewboxY, aViewboxW, aViewboxH);
+ }
+
+ TInt lWidth = aTargetSize.iWidth;
+ TInt lHeight = aTargetSize.iHeight;
+
+ viewboxTrnsfr->SetWindowViewportTrans(TRect(0, 0, lWidth, lHeight), TSize(0, 0));
+
+ }
+ },
+ {
+ viewboxTrnsfr->SetAlign(iPreserveAspectSetting);
+ viewboxTrnsfr->SetScaling(iSmilFitSetting);
+
+ if (aViewboxW > 0 && aViewboxH > 0)
+ {
+ viewboxTrnsfr->SetViewBox(aViewboxX, aViewboxY, aViewboxW, aViewboxH);
+ }
+
+ TInt lWidth = aTargetSize.iWidth;
+ TInt lHeight = aTargetSize.iHeight;
+
+ viewboxTrnsfr->SetWindowViewportTrans(TRect(0, 0, lWidth, lHeight), TSize(0, 0));
+ });
+
+ CleanupStack::PopAndDestroy(viewboxTrnsfr);
+ }
+
+TDereferencer GetCommandSectionL(TUint16 aOffset, TDereferencer * aIconData, TInt aNVGVersion)
+ {
+ // the max length that the command section can have
+ TInt commandSectionLength = aIconData->GetLength() - aOffset;
+
+ if (commandSectionLength <= 0)
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ TDereferencer section(aIconData->DerefInt8ArrayL(commandSectionLength, aOffset), commandSectionLength);
+
+ /*
+ * all the section are expected to be word aligned
+ * all of the nvg-cs icon will be version 2 or above
+ * the else won't be there as nvg version will always be greater than 2
+ */
+ if (aNVGVersion >= KVersion2)
+ {
+ if (!IsAligned4(aOffset))
+ {
+ User::Leave(KErrCorrupt);
+ }
+ }
+ else
+ {
+ /*
+ * no need to do anything here as once the nvgdecoder release
+ * its version will be always greater than 2
+ * infact the check for version will be removed
+ */
+ }
+
+ return section;
+ }
+
+void CNvgEngine::ExecuteNVGCSCommandLoopL(TUint16 aCommandCount, TDereferencer * aIconData, TDereferencer * aOffsetVector,
+ TDereferencer * aCommandSection, TInt aNVGVersion)
+ {
+ TUint32 transVal;
+
+ VGfloat lCurrentPathMatrix[9];
+
+ vgGetMatrix(lCurrentPathMatrix);
+
+ TInt32 lOffsetIx = 0;
+ for (TInt i=0; i < aCommandCount; i++)
+ {
+ TUint32 currentCommand = aCommandSection->DerefInt32L();
+ lOffsetIx = currentCommand & 0x0000ffff;
+
+ switch (currentCommand & 0xff000000)
+ {
+ case KCMD_SET_FILL_PAINT:
+ {
+ iFillAlpha = (currentCommand & 0x00ff0000) >> 16;
+ TUint16 offset = aOffsetVector->DerefInt16L(lOffsetIx * sizeof(TUint16));
+
+ TDereferencer section = GetCommandSectionL(offset, aIconData, aNVGVersion);
+
+ SetFillPaintL(§ion);
+
+ break;
+ }
+
+ case KCMD_SET_COLOR_RAMP:
+ {
+ TUint16 offset = aOffsetVector->DerefInt16L(lOffsetIx * sizeof(TUint16));
+
+ TDereferencer section = GetCommandSectionL(offset, aIconData, aNVGVersion);
+
+ SetColorRampL(§ion);
+
+ break;
+ }
+
+ case KCMD_DRAW_PATH:
+ {
+ if ((currentCommand & 0x00010000))
+ {
+ idoStroke = VG_TRUE;
+ }
+
+ if ((currentCommand & 0x00020000))
+ {
+ idoFill = VG_TRUE;
+ }
+ TUint16 offset = aOffsetVector->DerefInt16L(lOffsetIx * sizeof(TUint16));
+
+ TDereferencer section = GetCommandSectionL(offset, aIconData, aNVGVersion);
+
+ DrawPathL(§ion);
+
+ break;
+ }
+
+ case KCMD_SET_TRANSFORMATION:
+ {
+ SetTransformL(aCommandSection, transVal, lCurrentPathMatrix);
+ aCommandSection->SkipL(transVal * sizeof(TUint32));
+ break;
+ }
+
+ case KCMD_SET_STROKE_PAINT:
+ {
+ iStrokeAlpha = (currentCommand & 0x00ff0000) >> 16;
+ TUint16 offset = aOffsetVector->DerefInt16L(lOffsetIx * sizeof(TUint16));
+
+ TDereferencer section = GetCommandSectionL(offset, aIconData, aNVGVersion);
+
+ SetStrokePaintL(§ion);
+
+ break;
+ }
+
+ case KCMD_SET_STROKE_WIDTH:
+ {
+ TReal32 lStrokeWidth;
+ aCommandSection->SkipL(sizeof(TUint32));
+
+ /*
+ * check for alignment and copy data if not aligned, else directly convert
+ * version 2 or above guarantees that is always word aligned
+ */
+ TUint8 * cptr = aCommandSection->DerefInt8ArrayL(sizeof(TReal32), 0);
+ if (aNVGVersion < KVersion2 && !IsAligned4(cptr))
+ {
+
+ Mem::Copy(reinterpret_cast<void *>(&lStrokeWidth),
+ reinterpret_cast<void *>(cptr), sizeof(lStrokeWidth));
+ }
+ else
+ {
+ lStrokeWidth = aCommandSection->DerefReal32L();
+ }
+
+ COND_COM_OC(iInternal->iCreatingNVGIcon,
+ CSICON(iInternal->iCurrentNVGIcon)->AddSetStrokeWidthCommandL(lStrokeWidth),
+ vgSetf(VG_STROKE_LINE_WIDTH, lStrokeWidth));
+ break;
+ }
+
+ case KCMD_SET_STROKE_MITER_LIMIT:
+ {
+ TReal32 lMiterLimit;
+ aCommandSection->SkipL(sizeof(TUint32));
+
+ /*
+ * check for alignment and copy data if not aligned, else directly convert
+ * version 2 or above guarantees that is always word aligned
+ */
+ TUint8 * cptr = aCommandSection->DerefInt8ArrayL(sizeof(TReal32), 0);
+
+ if (aNVGVersion < KVersion2 && !IsAligned4(cptr))
+ {
+ Mem::Copy(reinterpret_cast<void *>(&lMiterLimit),
+ reinterpret_cast<void *>(cptr), sizeof(lMiterLimit));
+ }
+ else
+ {
+ lMiterLimit = aCommandSection->DerefReal32L();
+ }
+
+ COND_COM_OC(iInternal->iCreatingNVGIcon,
+ CSICON(iInternal->iCurrentNVGIcon)->AddSetStrokeMiterLimitCommandL(lMiterLimit),
+ vgSetf(VG_STROKE_MITER_LIMIT, lMiterLimit));
+
+ break;
+ }
+
+ case KCMD_SET_STROKE_LINE_JOIN_CAP:
+ {
+ TUint8 lJoinType =(currentCommand & 0x0000ff00)>>8;
+ TUint8 lCapType = (currentCommand & 0x000000ff);
+
+ VGCapStyle capStyle;
+ switch(lCapType)
+ {
+ case KCAP_SQUARE:
+ capStyle = VG_CAP_SQUARE;
+ break;
+ case KCAP_ROUND:
+ capStyle = VG_CAP_ROUND;
+ break;
+ case KCAP_BUTT:
+ default:
+ capStyle = VG_CAP_BUTT;
+ break;
+ }
+
+ VGJoinStyle lineJoinStyle;
+ switch(lJoinType)
+ {
+ case KLINE_JOIN_BEVEL:
+ lineJoinStyle = VG_JOIN_BEVEL;
+ break;
+ case KLINE_JOIN_ROUND:
+ lineJoinStyle = VG_JOIN_ROUND;
+ break;
+ case KLINE_JOIN_MITER:
+ default:
+ lineJoinStyle = VG_JOIN_MITER;
+ break;
+ }
+
+ COND_COM_OC(iInternal->iCreatingNVGIcon,
+ CSICON(iInternal->iCurrentNVGIcon)->AddStrokeLineJoinCapCommandL(capStyle, lineJoinStyle),
+ vgSeti(VG_STROKE_CAP_STYLE, capStyle);
+ vgSeti(VG_STROKE_JOIN_STYLE, lineJoinStyle););
+ break;
+ }
+
+ default:
+ {
+ User::Leave(KErrCorrupt);
+ break;
+ }
+ }
+
+ // go to the next command
+ aCommandSection->SkipL(sizeof(TUint32));
+ }
+ }
+
+EXPORT_C void CNvgEngine::SetPreserveAspectRatio(
+ TNvgAlignStatusType aPreserveAspectSetting,
+ TNvgMeetOrSliceType aSmilFitSetting)
+ {
+ iPreserveAspectSetting = aPreserveAspectSetting;
+ iSmilFitSetting = aSmilFitSetting;
+ }
+
+EXPORT_C void CNvgEngine::SetBackgroundColor(TUint32 aRGBA8888Color)
+ {
+ iBackgroundColor = aRGBA8888Color;
+ }
+
+TInt CNvgEngine::SetFillPaintL(TDereferencer * aIconData)
+ {
+ COND_COM_OC_OOC(register int drawingMode = iInternal->iCreatingNVGIcon);
+
+ TUint32 lCommonData = aIconData->DerefInt32L();
+ TUint lPaintType = lCommonData & 0x07;
+ TUint16 lSpecifcData = (lCommonData >> 16) & 0xff;
+
+ switch (lPaintType)
+ {
+ case KPAINT_LGRAD:
+ {
+ iGradPaintFill = iPaintFill;
+
+ COND_COM_OC_OOC(
+ if (iInternal->iCreatingNVGIcon)
+ {
+ // CNVGCSIcon will destroy the paint handle
+ iGradPaintFill = vgCreatePaint();
+ if (iGradPaintFill == VG_INVALID_HANDLE)
+ {
+ User::LeaveIfError(CNvgEngine::OpenVGErrorToSymbianError(vgGetError()));
+ }
+ });
+
+ // gradient data, the data will be word aligned
+ TReal32* lGradData = (TReal32*)aIconData->DerefInt8ArrayL(4 * sizeof(VGfloat), sizeof(TUint32));
+
+ vgSetParameteri(iGradPaintFill, VG_PAINT_TYPE, VG_PAINT_TYPE_LINEAR_GRADIENT);
+ vgSetParameterfv(iGradPaintFill, VG_PAINT_LINEAR_GRADIENT, 4, lGradData);
+ vgSeti(VG_MATRIX_MODE, VG_MATRIX_FILL_PAINT_TO_USER);
+
+ if (lSpecifcData & 0x1)
+ {
+ TReal32* lGradMatrix1 = (TReal32*) aIconData->DerefInt8ArrayL(6 * sizeof (VGfloat),
+ KNVG_PAINTSECTION_LINEARGRAD_TRANSFORM_OFFSET);
+
+ TReal32 lGradMatrix[9] = {lGradMatrix1[0], lGradMatrix1[3], 0.0f,
+ lGradMatrix1[1], lGradMatrix1[4], 0.0f,
+ lGradMatrix1[2], lGradMatrix1[5], 1.0f};
+
+ COND_COM_OC(drawingMode,
+ CSICON(iInternal->iCurrentNVGIcon)->AddLinearGradientCommandL(4, lGradData, lGradMatrix, iGradPaintFill),
+ vgLoadMatrix(lGradMatrix););
+ }
+ else
+ {
+ COND_COM_OC(drawingMode,
+ CSICON(iInternal->iCurrentNVGIcon)->AddLinearGradientCommandL(4, lGradData, (VGfloat*)KIdentityMatrix, iGradPaintFill),
+ vgLoadIdentity());
+ }
+
+ COND_COM_OC(drawingMode, ;,
+ vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE));
+
+ break;
+ }
+
+ case KPAINT_RGRAD:
+ {
+ // gradient data, the data will be word aligned
+ TReal32* lGradData = (TReal32*)aIconData->DerefInt8ArrayL(5 * sizeof(VGfloat), sizeof(TUint32));
+ iGradPaintFill = iPaintFill;
+
+ COND_COM_OC_OOC(
+ if (iInternal->iCreatingNVGIcon)
+ {
+ iGradPaintFill = vgCreatePaint();
+ if (iGradPaintFill == VG_INVALID_HANDLE)
+ {
+ User::LeaveIfError(CNvgEngine::OpenVGErrorToSymbianError(vgGetError()));
+ }
+ });
+
+ vgSetParameteri(iGradPaintFill, VG_PAINT_TYPE, VG_PAINT_TYPE_RADIAL_GRADIENT);
+ vgSetParameterfv(iGradPaintFill, VG_PAINT_RADIAL_GRADIENT, 5, lGradData);
+ vgSeti(VG_MATRIX_MODE, VG_MATRIX_FILL_PAINT_TO_USER);
+
+
+ if (lSpecifcData & 0x1)
+ {
+ TReal32* lGradMatrix1 = (TReal32*)aIconData->DerefInt8ArrayL(6 * sizeof (VGfloat),
+ KNVG_PAINTSECTION_RADIALGRAD_TRANSFORM_OFFSET);
+
+ TReal32 lGradMatrix[9] = {lGradMatrix1[0], lGradMatrix1[3], 0.0f,
+ lGradMatrix1[1], lGradMatrix1[4], 0.0f,
+ lGradMatrix1[2], lGradMatrix1[5], 1.0f};
+
+ COND_COM_OC(drawingMode,
+ CSICON(iInternal->iCurrentNVGIcon)->AddRadialGradientCommandL(5, lGradData, lGradMatrix, iGradPaintFill),
+ vgLoadMatrix(lGradMatrix));
+ }
+ else
+ {
+ COND_COM_OC(drawingMode,
+ CSICON(iInternal->iCurrentNVGIcon)->AddRadialGradientCommandL(5, lGradData, (VGfloat*)KIdentityMatrix, iGradPaintFill),
+ vgLoadIdentity());
+ }
+
+ COND_COM_OC(drawingMode, ;,
+ vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE));
+ break;
+ }
+
+ case KPAINT_FLAT:
+ {
+ TUint32 lRgba = aIconData->DerefInt32L(KNVG_RGBA_OFS);
+
+ lRgba = (lRgba & 0xffffff00) | iFillAlpha;
+
+ COND_COM_OC(drawingMode,
+ CSICON(iInternal->iCurrentNVGIcon)->AddSetColorCommandL(lRgba),
+ vgSetParameteri(iPaintFill, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
+ vgSetColor(iPaintFill, lRgba));
+ break;
+ }
+
+ default:
+ {
+ User::Leave(KErrCorrupt);
+ break;
+ }
+ }
+ return KErrNone;
+ }
+
+TInt CNvgEngine::SetColorRampL(TDereferencer * aIconData)
+ {
+ TUint32 lCommonData = aIconData->DerefInt32L();
+
+ TInt lStopCount = (lCommonData >> 16) & 0x00ff;
+ TReal32* lStopData = (TReal32*)aIconData->DerefInt8ArrayL(lStopCount * 5 * sizeof(TReal32), sizeof(TUint32));
+
+ VGfloat * colorRamps = new (ELeave) VGfloat[lStopCount * 5];
+ CleanupStack::PushL(TCleanupItem(CleanupArray, colorRamps));
+
+ if (iFillAlpha == 0xff)
+ {
+ vgSetParameteri(iGradPaintFill, VG_PAINT_COLOR_RAMP_SPREAD_MODE, VG_COLOR_RAMP_SPREAD_PAD);
+ vgSetParameterfv(iGradPaintFill, VG_PAINT_COLOR_RAMP_STOPS, lStopCount * 5, lStopData);
+ }
+ else
+ {
+ // Copy color ramps and modify alpha
+ memcpy(colorRamps, lStopData, lStopCount * 5 * sizeof(VGfloat));
+
+ VGfloat lAlphaInFloat = iFillAlpha * (1.0f/255.0f);
+ VGfloat* lAlphaValue = &colorRamps[4];
+
+ for (int i=0; i<lStopCount; i++)
+ {
+ *lAlphaValue *= lAlphaInFloat;
+ lAlphaValue += 5;
+ }
+
+ vgSetParameteri(iGradPaintFill, VG_PAINT_COLOR_RAMP_SPREAD_MODE, VG_COLOR_RAMP_SPREAD_PAD);
+ vgSetParameterfv(iGradPaintFill, VG_PAINT_COLOR_RAMP_STOPS, lStopCount * 5, colorRamps);
+ }
+
+ CleanupStack::PopAndDestroy();
+ return KErrNone;
+ }
+
+void CNvgEngine::SetStrokePaintL(TDereferencer * aIconData)
+ {
+ COND_COM_OC_OOC(register int drawingMode = iInternal->iCreatingNVGIcon;);
+
+ TUint32 lCommonData = aIconData->DerefInt32L();
+ TUint lStrokeType = lCommonData & 0x07;
+ TUint16 lSpecifcData = (lCommonData >> 16) & 0xff;
+
+ switch (lStrokeType)
+ {
+ case KSTROKE_LGRAD:
+ {
+ iGradPaintStroke = iPaintStroke;
+
+ COND_COM_OC_OOC(
+ if (iInternal->iCreatingNVGIcon)
+ {
+ iGradPaintStroke = vgCreatePaint();
+ User::LeaveIfNull((TAny *)iGradPaintStroke);
+ });
+
+ // gradient data, the data will be word aligned
+ TReal32* lGradData = (TReal32*)aIconData->DerefInt8ArrayL(4 * sizeof(VGfloat), sizeof(TUint32));
+
+ COND_COM_OC(drawingMode, ;,
+ vgSetParameteri( iGradPaintStroke, VG_PAINT_TYPE, VG_PAINT_TYPE_LINEAR_GRADIENT );
+ vgSetParameterfv( iGradPaintStroke, VG_PAINT_LINEAR_GRADIENT, 4, lGradData);
+ vgSeti(VG_MATRIX_MODE, VG_MATRIX_STROKE_PAINT_TO_USER));
+
+ if (lSpecifcData & 0x1)
+ {
+ TReal32* lGradMatrix1 = (TReal32*)aIconData->DerefInt8ArrayL(6 * sizeof(VGfloat),
+ 4 + 4 * sizeof(VGfloat));
+ TReal32 lGradMatrix[9] = {lGradMatrix1[0], lGradMatrix1[3], 0.0f,
+ lGradMatrix1[1], lGradMatrix1[4], 0.0f,
+ lGradMatrix1[2], lGradMatrix1[5], 1.0f};
+
+ COND_COM_OC(drawingMode,
+ CSICON(iInternal->iCurrentNVGIcon)->AddStrokeLinearGradientCommandL(4, lGradData, lGradMatrix, iGradPaintStroke),
+ vgLoadMatrix(lGradMatrix));
+ }
+ else
+ {
+ COND_COM_OC(drawingMode,
+ CSICON(iInternal->iCurrentNVGIcon)->AddStrokeLinearGradientCommandL(4, lGradData, (VGfloat*)KIdentityMatrix, iGradPaintStroke),
+ vgLoadIdentity());
+ }
+ vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
+ break;
+ }
+
+ case KSTROKE_RGRAD:
+ {
+ iGradPaintStroke = iPaintStroke;
+
+ COND_COM_OC_OOC(
+ if (iInternal->iCreatingNVGIcon)
+ {
+ iGradPaintStroke = vgCreatePaint();
+ User::LeaveIfNull((TAny *)iGradPaintStroke);
+ });
+
+ // gradient data, the data will be word aligned
+ TReal32* lGradData = (TReal32*)aIconData->DerefInt8ArrayL(5 * sizeof(VGfloat), sizeof(TUint32));
+
+ COND_COM_OC(drawingMode, ;,
+ vgSetParameteri( iGradPaintStroke, VG_PAINT_TYPE, VG_PAINT_TYPE_RADIAL_GRADIENT );
+ vgSetParameterfv( iGradPaintStroke, VG_PAINT_RADIAL_GRADIENT, 5, lGradData);
+ vgSeti(VG_MATRIX_MODE, VG_MATRIX_STROKE_PAINT_TO_USER));
+
+ if (lSpecifcData & 0x1)
+ {
+ TReal32* lGradMatrix1 = (TReal32*)aIconData->DerefInt8ArrayL(6 * sizeof(VGfloat),
+ 4 + 5 * sizeof(VGfloat));
+ TReal32 lGradMatrix[9] = {lGradMatrix1[0], lGradMatrix1[3], 0.0f,
+ lGradMatrix1[1], lGradMatrix1[4], 0.0f,
+ lGradMatrix1[2], lGradMatrix1[5], 1.0f};
+
+ COND_COM_OC(drawingMode,
+ CSICON(iInternal->iCurrentNVGIcon)->AddStrokeRadialGradientCommandL(4, lGradData, lGradMatrix, iGradPaintStroke),
+ vgLoadMatrix(lGradMatrix));
+ }
+ else
+ {
+ COND_COM_OC(drawingMode,
+ CSICON(iInternal->iCurrentNVGIcon)->AddStrokeRadialGradientCommandL(4, lGradData, (VGfloat*)KIdentityMatrix, iGradPaintStroke),
+ vgLoadIdentity());
+ }
+ vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
+ break;
+ }
+
+ case KSTROKE_COLOR_RAMP:
+ {
+ TInt lStopCount = lSpecifcData;
+ TReal32* lStopData = (TReal32*) aIconData->DerefInt8ArrayL(lStopCount * 5 * sizeof(VGfloat), 4);
+
+ if (iStrokeAlpha == 0xff)
+ {
+ vgSetParameteri(iGradPaintStroke, VG_PAINT_COLOR_RAMP_SPREAD_MODE, VG_COLOR_RAMP_SPREAD_PAD);
+ vgSetParameterfv(iGradPaintStroke, VG_PAINT_COLOR_RAMP_STOPS, lStopCount*5, lStopData);
+ }
+ else
+ {
+ VGfloat * colorRamps = new (ELeave) VGfloat[lStopCount * 5];
+ CleanupStack::PushL(TCleanupItem(CleanupArray, colorRamps));
+
+ memcpy(colorRamps, lStopData, lStopCount * 5 * sizeof(VGfloat));
+
+ VGfloat lAlphaInFloat = iStrokeAlpha * (1.0f/255.0f);
+ VGfloat* lAlphaValue = &colorRamps[4];
+
+ for (int i=0; i<lStopCount; i++)
+ {
+ *lAlphaValue *= lAlphaInFloat;
+ lAlphaValue += 5;
+ }
+
+ vgSetParameteri(iGradPaintStroke, VG_PAINT_COLOR_RAMP_SPREAD_MODE, VG_COLOR_RAMP_SPREAD_PAD);
+ vgSetParameterfv(iGradPaintStroke, VG_PAINT_COLOR_RAMP_STOPS, lStopCount * 5, colorRamps);
+ CleanupStack::PopAndDestroy();
+ }
+ break;
+ }
+
+ default:
+ {
+ TUint32 lRgba = aIconData->DerefInt32L(KNVG_RGBA_OFS);
+ lRgba = (lRgba & 0xffffff00)|iStrokeAlpha; // replace alpha
+
+ COND_COM_OC(drawingMode,
+ CSICON(iInternal->iCurrentNVGIcon)->AddStrokeSetColorCommandL(lRgba),
+ vgSetParameteri( iPaintStroke, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR );
+ vgSetColor(iPaintStroke, lRgba));
+ break;
+ }
+ }
+ }
+
+void CNvgEngine::DrawPathL(TDereferencer * aIconData)
+ {
+ TInt numSegments = aIconData->DerefInt16L();
+ const VGubyte * pathSegments = aIconData->DerefInt8ArrayL(numSegments, sizeof(TUint16));
+
+ /*
+ * verify that what we got is proper data
+ * for that calculate the path co-ordinate length
+ * and check that the path data does not overflow
+ */
+ TInt coordinateCount = 0;
+ for (TInt i = 0; i < numSegments; ++i)
+ {
+ switch (pathSegments[i])
+ {
+ case VG_HLINE_TO:
+ case VG_VLINE_TO:
+ coordinateCount += 1;
+ break;
+ case VG_MOVE_TO:
+ case VG_LINE_TO:
+ case VG_SQUAD_TO:
+ coordinateCount += 2;
+ break;
+ case VG_QUAD_TO:
+ case VG_SCUBIC_TO:
+ coordinateCount += 4;
+ break;
+ case VG_SCCWARC_TO:
+ case VG_SCWARC_TO:
+ case VG_LCCWARC_TO:
+ case VG_LCWARC_TO:
+ coordinateCount += 5;
+ break;
+ case VG_CUBIC_TO:
+ coordinateCount += 6;
+ break;
+ default:
+ break;
+ }
+ }
+
+ // this one is just to check the alignment
+ TUint8* pathData = aIconData->DerefInt8ArrayL(sizeof(TUint32), sizeof(TUint16) + numSegments);
+
+ /*
+ * path data need to be word aligned
+ * alignment are done according to the path format
+ */
+ TUint sizeofpathdata = sizeof(TUint32);
+ TUint alignSkip = 0;
+ TUint8 * alignedPtr = 0;
+ if (iLastPathDataType == ESixteenBitEncoding)
+ {
+ alignedPtr = Align2(pathData);
+ sizeofpathdata = sizeof(TUint16);
+ }
+ else if (iLastPathDataType == EThirtyTwoBitEncoding)
+ {
+ alignedPtr = Align4(pathData);
+ }
+ else
+ {
+ User::Leave(KErrCorrupt); // no other path data type is supported
+ }
+
+ alignSkip = alignedPtr - pathData;
+
+ /*
+ * check to see whether we have enough path data
+ */
+ aIconData->IsSafeL(coordinateCount * sizeofpathdata + alignSkip, sizeof(TUint16) + numSegments);
+
+ pathData = alignedPtr;
+
+ VGint paintMode = (idoFill ? VG_FILL_PATH : 0)|(idoStroke ? VG_STROKE_PATH : 0);
+ if (paintMode == 0)
+ {
+ paintMode = VG_FILL_PATH;
+ }
+
+ COND_COM_OC(iInternal->iCreatingNVGIcon,
+ {
+ VGPath path = CreatePath();
+
+ if (path != VG_INVALID_HANDLE)
+ {
+ vgAppendPathData(path, numSegments, pathSegments, pathData);
+ }
+ else
+ {
+ CSICON(iInternal->iCurrentNVGIcon)->AddPathDataL(numSegments, pathSegments, pathData);
+ }
+ CSICON(iInternal->iCurrentNVGIcon)->AddDrawPathCommandL(path, paintMode);
+ },
+ {
+ vgClearPath(iPath, VG_PATH_CAPABILITY_APPEND_TO);
+
+ vgAppendPathData(iPath, numSegments, pathSegments, pathData);
+ vgDrawPath(iPath, paintMode);
+ });
+
+ idoStroke = VG_FALSE;
+ idoFill = VG_FALSE;
+ }
+
+#ifdef OPENVG_OBJECT_CACHING
+VGPath CNvgEngine::CreatePath()
+ {
+ VGPath path = VG_INVALID_HANDLE;
+ switch (iLastPathDataType)
+ {
+ case EEightBitEncoding:
+ {
+ path = vgCreatePath(VG_PATH_FORMAT_STANDARD,
+ VG_PATH_DATATYPE_S_16, 1.0f/2.0f, 0.0f, 0, 0,
+ VG_PATH_CAPABILITY_APPEND_TO);
+ }
+ break;
+
+ case ESixteenBitEncoding:
+ {
+ path = vgCreatePath(VG_PATH_FORMAT_STANDARD,
+ VG_PATH_DATATYPE_S_16, 1.0f/16.0f, 0.0f, 0, 0,
+ VG_PATH_CAPABILITY_APPEND_TO);
+ }
+ break;
+
+ case EThirtyTwoBitEncoding:
+ {
+ path = vgCreatePath(VG_PATH_FORMAT_STANDARD,
+ VG_PATH_DATATYPE_S_32, 1.0f/65536.0f, 0.0f, 0, 0,
+ VG_PATH_CAPABILITY_APPEND_TO);
+ }
+ break;
+
+ default:
+ {
+
+ }
+ break;
+ }
+ return path;
+ }
+#endif
+
+void CNvgEngine::SetTransformL(TDereferencer * aIconData, TUint32 & aCounter, const VGfloat* aCurrentMatrix)
+ {
+
+ COND_COM_OC(iInternal->iCreatingNVGIcon, ;,
+ vgLoadMatrix(aCurrentMatrix));
+
+ TUint32 lCommonData = aIconData->DerefInt32L();
+ TUint32 lTransformType = (lCommonData & 0x00ff0000)>>16 ;
+
+ VGfloat matrixTemp[9] = {
+ 1.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f };
+
+ aCounter = 0;
+
+ if (lTransformType != 1)
+ {
+ if (lTransformType == KTRANSFORM_COMPLETE)
+ {
+ matrixTemp[0] = aIconData->DerefReal32L((++aCounter) * sizeof (VGfloat));
+ matrixTemp[4] = aIconData->DerefReal32L((++aCounter) * sizeof (VGfloat));
+ matrixTemp[3] = aIconData->DerefReal32L((++aCounter) * sizeof (VGfloat));
+ matrixTemp[1] = aIconData->DerefReal32L((++aCounter) * sizeof (VGfloat));
+ matrixTemp[6] = aIconData->DerefReal32L((++aCounter) * sizeof (VGfloat));
+ matrixTemp[7] = aIconData->DerefReal32L((++aCounter) * sizeof (VGfloat));
+ }
+ else
+ {
+ if (lTransformType & KTRANSFORM_ROTATION)
+ {
+ //vgScale
+ matrixTemp[0] = aIconData->DerefReal32L((++aCounter) * sizeof (VGfloat));
+ matrixTemp[4] = aIconData->DerefReal32L((++aCounter) * sizeof (VGfloat));
+
+ //vgShear
+ matrixTemp[3] = aIconData->DerefReal32L((++aCounter) * sizeof (VGfloat));
+ matrixTemp[1] = aIconData->DerefReal32L((++aCounter) * sizeof (VGfloat));
+ }
+ else
+ {
+ if (lTransformType & KTRANSFORM_SCALING)
+ {
+ //vgScale
+ matrixTemp[0] = aIconData->DerefReal32L((++aCounter) * sizeof (VGfloat));
+ matrixTemp[4] = aIconData->DerefReal32L((++aCounter) * sizeof (VGfloat));
+ }
+
+ if (lTransformType & KTRANSFORM_SHEARING)
+ {
+ //vgShear
+ matrixTemp[3] = aIconData->DerefReal32L((++aCounter) * sizeof (VGfloat));
+ matrixTemp[1] = aIconData->DerefReal32L((++aCounter) * sizeof (VGfloat));
+ }
+ }
+
+ if (lTransformType & KTRANSFORM_TRANSLATION)
+ {
+ //vgTranslate
+ matrixTemp[6] = aIconData->DerefReal32L((++aCounter) * sizeof (VGfloat));
+ matrixTemp[7] = aIconData->DerefReal32L((++aCounter) * sizeof (VGfloat));
+ }
+ }
+
+ COND_COM_OC(iInternal->iCreatingNVGIcon,
+ CSICON(iInternal->iCurrentNVGIcon)->AddSetTransformCommandL(matrixTemp, 1),
+ vgMultMatrix(matrixTemp));
+ }
+ else
+ {
+ COND_COM_OC(iInternal->iCreatingNVGIcon,
+ CSICON(iInternal->iCurrentNVGIcon)->AddSetTransformCommandL(matrixTemp, 0), ;);
+ }
+ }
+
+void CNvgEngine::GenerateMask(CFbsBitmap* aMask)
+ {
+ if (!aMask || aMask->SizeInPixels() != iCurrentBufferSize)
+ {
+ return;
+ }
+
+ const TDisplayMode KMaskDisplayMode = aMask->DisplayMode();
+
+ if (KMaskDisplayMode != EGray256 && KMaskDisplayMode != EGray2)
+ {
+ return;
+ }
+
+ const TInt KOriginalFilterMasks = vgGeti(VG_FILTER_CHANNEL_MASK);
+ const TInt KStride = CFbsBitmap::ScanLineLength(iCurrentBufferSize.iWidth, KMaskDisplayMode);
+
+ // Change to get alpha values from OpenVG
+ vgSeti(VG_FILTER_CHANNEL_MASK, VG_ALPHA);
+
+ VGImageFormat format = (KMaskDisplayMode == EGray256) ? VG_A_8 : VG_BW_1;
+
+ aMask->LockHeap();
+
+ /*
+ * Get data address of last line and move upwards (negative stride)
+ * OpenVG uses Cartesian coordinate system and Symbian uses Screen coordinate system.
+ */
+ TUint* data = (TUint*)((TUint)aMask->DataAddress() + (KStride * (iCurrentBufferSize.iHeight - 1 )));
+
+ vgReadPixels(data, -KStride, format, 0, 0,
+ iCurrentBufferSize.iWidth, iCurrentBufferSize.iHeight);
+ aMask->UnlockHeap();
+
+ // Set back the original filter-masks
+ vgSeti(VG_FILTER_CHANNEL_MASK, KOriginalFilterMasks);
+ }
+
+void CNvgEngine::ClearBackground()
+ {
+ TUint32 rgba = (iBackgroundColor << 8) | (iBackgroundColor >> 24);
+ TInt32 r, g, b, a;
+ r = (TInt)((rgba & 0xFF000000) >> 24);
+ g = (TInt)((rgba & 0x00FF0000) >> 16);
+ b = (TInt)((rgba & 0x0000FF00) >> 8);
+ a = (TInt)(rgba & 0x000000FF);
+
+ r += r >> 7; g += g >> 7; b += b >> 7; a += a >> 7;
+
+ const VGfloat KInverse255 = 1.0f/256.0f;
+ const VGfloat clearColor[4] = { (KInverse255 * VGfloat (r)),
+ (KInverse255 * VGfloat (g)),
+ (KInverse255 * VGfloat (b)),
+ (KInverse255 * VGfloat (a)) };
+
+ vgSeti(VG_SCISSORING, VG_FALSE);
+ vgSetfv(VG_CLEAR_COLOR, 4, clearColor);
+ vgClear(0, 0, iCurrentBufferSize.iWidth, iCurrentBufferSize.iHeight);
+ vgSeti(VG_SCISSORING, VG_TRUE);
+ }
+
+TBool CNvgEngine::IsIdentity(VGfloat array[])
+ {
+ return ((array[0] == 1.0f && array[4] == 1.0f && array[8] == 1.0f)&&
+ (array[1] == 0.0f && array[2] == 0.0f && array[3] == 0.0f &&
+ array[5] == 0.0f && array[6] == 0.0f && array[7] == 0.0f));
+ }
+
+TInt CNvgEngine::OpenVGErrorToSymbianError( TInt aError )
+ {
+ TInt error = KErrNone;
+ switch (aError)
+ {
+ case VGU_OUT_OF_MEMORY_ERROR:
+ case VG_OUT_OF_MEMORY_ERROR:
+ {
+ error = KErrNoMemory;
+ break;
+ }
+
+ case VG_ILLEGAL_ARGUMENT_ERROR:
+ case VGU_ILLEGAL_ARGUMENT_ERROR:
+ {
+ error = KErrArgument;
+ break;
+ }
+
+ case VG_UNSUPPORTED_PATH_FORMAT_ERROR:
+ case VG_UNSUPPORTED_IMAGE_FORMAT_ERROR:
+ {
+ error = KErrNotSupported;
+ break;
+ }
+
+ case VG_IMAGE_IN_USE_ERROR:
+ {
+ error = KErrInUse;
+ break;
+ }
+
+ case VG_BAD_HANDLE_ERROR:
+ case VGU_BAD_HANDLE_ERROR:
+ {
+ error = KErrBadHandle;
+ break;
+ }
+
+ case VG_PATH_CAPABILITY_ERROR:
+ case VGU_PATH_CAPABILITY_ERROR:
+ case VGU_BAD_WARP_ERROR:
+ {
+ error = KErrUnknown;
+ break;
+ }
+
+ case VG_NO_CONTEXT_ERROR:
+ {
+ error = KErrNotReady;
+ break;
+ }
+
+ default:
+ {
+ error = KErrUnknown;
+ }
+ }
+
+ return error;
+ }
+
+void CNvgEngine::UpdateClientMatrices()
+ {
+ iMatrixMode = vgGeti(VG_MATRIX_MODE);
+ vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
+ vgGetMatrix(iPathMatrix);
+ vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
+ vgGetMatrix(iImageMatrix);
+ vgSeti(VG_MATRIX_MODE, iMatrixMode);
+ }
+
+void CNvgEngine::RestoreClientMatrices()
+ {
+ vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
+ vgLoadMatrix(iPathMatrix);
+ vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
+ vgLoadMatrix(iImageMatrix);
+ vgSeti(VG_MATRIX_MODE, iMatrixMode);
+ }
+
+TPoint CNvgEngine::GetTranslatedPoint(VGfloat aTRMatrix[9], TPoint aPoint)
+ {
+ TPoint trPoint;
+
+ trPoint.iX = aTRMatrix[0] * aPoint.iX + aTRMatrix[3] * aPoint.iY + aTRMatrix[6];
+ trPoint.iY = aTRMatrix[1] * aPoint.iX + aTRMatrix[4] * aPoint.iY + aTRMatrix[7];
+
+ return trPoint;
+ }
+
+VGfloat CNvgEngine::MinVal4(VGfloat x1, VGfloat x2, VGfloat x3, VGfloat x4 )
+ {
+ VGfloat min = x1;
+
+ if (min > x2)
+ {
+ min = x2;
+ }
+ if (min > x3)
+ {
+ min = x3;
+ }
+ if (min > x4)
+ {
+ min = x4;
+ }
+
+ return min;
+ }
+
+VGfloat CNvgEngine::MaxVal4(VGfloat x1, VGfloat x2, VGfloat x3, VGfloat x4 )
+ {
+ VGfloat max = x1;
+
+ if (max < x2)
+ {
+ max = x2;
+ }
+ if (max < x3)
+ {
+ max = x3;
+ }
+ if (max < x4)
+ {
+ max = x4;
+ }
+
+ return max;
+ }
+