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