/*
* Copyright (c) 2002 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: Graphics Extension Library source file
*
*/
#include "Gfx2dGcOpenVG.h"
//#include "Gfx2dDevice.h"
#include "GfxLine2D.h"
#include "GfxStroke.h"
#include "GfxGeneralPath.h"
#include "GfxFlatteningPathIterator.h"
#include "GfxColor.h"
#include "GfxImageTransformer.h"
//#include "hal.h"
//#include "hal_data.h"
#include "gdi.h"
#include "biditext.h"
#include "GfxFloatFixPt.h"
#include "GfxShape.h"
#include "GfxEllipse2D.h"
#include "GfxRoundRectangle2D.h"
//#include "svgBackendStd.h"
//#include "gulutil.h"
#include <AknFontAccess.h>
//#include <AknUtils.h>
//#include <featmgr.h>
#include<e32cmn.h>
#include<e32uid.h>//NGA
#include <e32math.h>
// OpenVG Includes
#include <VG/vgu.h>
#include <vg/vgcontext.h>
// OpenVG API Binding Symbian specific
#include <vg/vgcontext_symbian.h>
// For allocating path segment type array
// Found 130 to be max size at bootup
const TInt KPathSegmentTypeInitialSize = 130;
const TInt KPathSegmentTypeMaxSize = 1000;
const TInt KRenderQualityLow = 1;
const TInt KRenderQualityHigh = 2;
_LIT( KDefaultFont, "serif" ); // Similar changes should be applied to \
//SvgTextElementImpl.cpp file
// --------------------------------------------------------------------------
// CGfx2dGcOpenVG::CGfx2dGcOpenVG() : iScale( 1 ),
// ---------------------------------------------------------------------------
CGfx2dGcOpenVG::CGfx2dGcOpenVG( TBool /* aIsMainContext */ ) :
iFillOpacity( 1 ),
iScale( 1 ),
iStrokeColor( 0 ),
iStrokeOpacity( 1 ),
iBackgroundColor( 0xffffff ),
iFontSize( 10 ),
iFontWeight( -1 ),
iFontStyle( -1 ),
iFamilies( NULL ),
iTextAnchor( EGfxTextAnchorNone ),
iTextDecoration( EGfxTextDecorationNone ),
iGraphicsContextCreated( EFalse ),
iRenderQuality(VG_RENDERING_QUALITY_BETTER),
iCurrentRendererType(ESVGRendererSW)
{
}
//
// ==========================================================================
// Create a new instance.
// ==========================================================================
// --------------------------------------------------------------------------
// CGfx2dGcOpenVG* CGfx2dGcOpenVG::NewL( CFbsBitmap* aFrameBuffer, TFontSpec& aFontSpec )
// ---------------------------------------------------------------------------
CGfx2dGcOpenVG* CGfx2dGcOpenVG::NewL( const TSize aBufferSize, TFontSpec& aFontSpec, CSvgBitmapFontProvider* aSvgBitmapFontProvider, TBool aIsMainContext )
{
CGfx2dGcOpenVG* self = new( ELeave ) CGfx2dGcOpenVG( aIsMainContext );
CleanupStack::PushL( self );
self->ConstructL( aBufferSize, aFontSpec, aSvgBitmapFontProvider);
CleanupStack::Pop();
return self;
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::ConstructL( CFbsBitmap* aFrameBuffer, TFontSpec& aFontSpec )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::ConstructL( const TSize aBufferSize, TFontSpec& aFontSpec, CSvgBitmapFontProvider* aSvgBitmapFontProvider )
{
/* iApacAvailable = EFalse;
FeatureManager::InitializeLibL();
iApacAvailable = ( AknLayoutUtils::Variant() == EApacVariant );
FeatureManager::UnInitializeLib();*/
iFontSpec = aFontSpec;
if (iFontSpec.iTypeface.iName.Length() == 0)
{
//just for a safety check in case client didnt put it in
iFontSpec = TFontSpec(KDefaultFont, 100);
}
iSvgBitmapFontProvider = aSvgBitmapFontProvider ;
// Allocate path segment type array
iPathSegmentTypeCount = KPathSegmentTypeInitialSize;
iPathSegmentTypes = new (ELeave) VGubyte[KPathSegmentTypeInitialSize];
iDashArray = new ( ELeave ) CArrayFixFlat<VGfloat>( 32 );
iVgRenderer = CVGRenderer::NewL(ESVGRendererSW, 0);
iVgSurface = iVgRenderer->GetCurrentSurface();
ChangeBufferSizeL( aBufferSize );
}
//NGA
// --------------------------------------------------------------------------
// CGfx2dGcOpenVG* CGfx2dGcOpenVG::NewL( CFbsBitmap* aFrameBuffer, TFontSpec& aFontSpec )
// ---------------------------------------------------------------------------
CGfx2dGcOpenVG* CGfx2dGcOpenVG::NewL( const TSize aBufferSize, TFontSpec& aFontSpec, CSvgBitmapFontProvider* aSvgBitmapFontProvider,SVGRendererId aRendererType,TBool aIsMainContext )
{
CGfx2dGcOpenVG* self = new( ELeave ) CGfx2dGcOpenVG( aIsMainContext );
CleanupStack::PushL( self );
self->ConstructL( aBufferSize, aFontSpec, aSvgBitmapFontProvider,aRendererType);
CleanupStack::Pop();
return self;
}
//NGA
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::ConstructL( CFbsBitmap* aFrameBuffer, TFontSpec& aFontSpec )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::ConstructL( const TSize aBufferSize, TFontSpec& aFontSpec, CSvgBitmapFontProvider* aSvgBitmapFontProvider,SVGRendererId aRendererType )
{
iFontSpec = aFontSpec;
if (iFontSpec.iTypeface.iName.Length() == 0)
{
//just for a safety check in case client didnt put it in
iFontSpec = TFontSpec(KDefaultFont, 100);
}
iSvgBitmapFontProvider = aSvgBitmapFontProvider ;
// Allocate path segment type array
iPathSegmentTypeCount = KPathSegmentTypeInitialSize;
iPathSegmentTypes = new (ELeave) VGubyte[KPathSegmentTypeInitialSize];
iDashArray = new ( ELeave ) CArrayFixFlat<VGfloat>( 32 );
iCurrentRendererType = aRendererType;
iVgRenderer = CVGRenderer::NewL(aRendererType, 0);
iVgSurface = iVgRenderer->GetCurrentSurface();
iVgSurface->InitializeSurface( aBufferSize, VGI_COLORSPACE_SRGB );
iVgSurface->CreateSurface(EColor16MA, 0, 0);
ChangeBufferSizeL( aBufferSize );
}
// ==========================================================================
// Destructor.
// ==========================================================================
// --------------------------------------------------------------------------
// CGfx2dGcOpenVG::~CGfx2dGcOpenVG()
// ---------------------------------------------------------------------------
CGfx2dGcOpenVG::~CGfx2dGcOpenVG()
{
if ( iDashArray )
{
delete iDashArray;
iDashArray = NULL;
}
// This is no longer needed, the Font is owned by TextElement
// now as each text element may have its own specific font
// and keeping one copy at Gc level will not work.
// Gc is just refering to the Font from Textelement, so
// now need to free it here.
//
//if (iFont && iWsScreenDevice)
// {
// iWsScreenDevice->ReleaseFont(iFont);
// iFont = NULL;
// }
DestroyContext();
iGroupOpacityImages.Close();
TInt bufferCount = iGroupOpacityBuffers.Count();
for ( TInt i = 0; i < bufferCount; i++ )
{
delete [] iGroupOpacityBuffers[i];
}
iGroupOpacityBuffers.Close();
if ( iPathSegmentTypes )
{
delete [] iPathSegmentTypes;
}
delete iVgRenderer;
}
// private method
void CGfx2dGcOpenVG::DestroyContext()
{
if ( iGraphicsContextCreated )
{
// Destroy OpenVG context
iVgSurface->TerminateSurface();
ResetContextHandle();
iFillOpacity = 1;
iScale = 1;
iStrokeOpacity = 1;
}
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::SetFrameBufferL( CFbsBitmap* aFrameBuffer )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::ChangeBufferSizeL( const TSize aBufferSize )
{
if ( aBufferSize.iWidth <= 0 || aBufferSize.iHeight <= 0 || aBufferSize == iColorBufferSize )
{
return;
}
iColorBufferSize = aBufferSize;
// First time: creating OpenVG context
if( !iGraphicsContextCreated )
{
// Create OpenVG context
TInt err = iVgSurface->InitializeSurface( iColorBufferSize, VGI_COLORSPACE_SRGB );
if (!((err == KErrNone) || (err == KErrAlreadyExists)))
{
#ifdef _DEBUG
RDebug::Printf("SVG can't initialize OpenVG Context %d", err);
#endif //_DEBUG
iGraphicsContextCreated = EFalse;
User::Leave(err);
}
iGraphicsContextCreated = ETrue;
// By default the Rendering quality is VG_RENDERING_QUALITY_BETTER
iVgRenderer->vgSeti( VG_RENDERING_QUALITY, iRenderQuality );
}
// Only need to update context with color-buffer info
// when frame buffer size changes
else
{
TInt err = iVgSurface->ResizeSurface( iColorBufferSize );
if( err != KErrNone )
{
if(err == KErrNoMemory )
{
#ifdef _DEBUG
RDebug::Printf("OpenVG Context destroyed %d", err);
#endif //_DEBUG
// This indicates that OpenVG has destroyed the current context handle
// and also the Path, StrokePaint and FillPaint handles are no more valid.
// Thus reinitialize them to 0, so that they can be recreated.
ResetContextHandle();
}
#ifdef _DEBUG
RDebug::Printf("SVG can't RESIZE OpenVG Context %d", err);
#endif //_DEBUG
User::Leave(err);
}
}
iRenderInfo.SetDevice( 0, /*this parameter will be ignored */
iColorBufferSize.iWidth,
iColorBufferSize.iHeight,
0 /*this parameter will be ignored */);
}
// --------------------------------------------------------------------------
// TInt CGfx2dGcOpenVG::OpenVGErrorToSymbianError( int aError )
// ---------------------------------------------------------------------------
TInt CGfx2dGcOpenVG::OpenVGErrorToSymbianError( TInt aError )
{
TInt error = KErrNone;
switch( aError )
{
case VGI_OK:
{
error = KErrNone;
break;
}
case VGU_OUT_OF_MEMORY_ERROR:
case VG_OUT_OF_MEMORY_ERROR:
case VGI_ERROR_OUT_OF_MEMORY:
{
error = KErrNoMemory;
break;
}
case VG_ILLEGAL_ARGUMENT_ERROR:
case VGI_ERROR_INVALID_ARGUMENTS:
case VGU_ILLEGAL_ARGUMENT_ERROR:
{
error = KErrArgument;
break;
}
case VGI_ERROR_ALREADY_EXISTS:
{
error = KErrAlreadyExists;
break;
}
case VG_UNSUPPORTED_PATH_FORMAT_ERROR:
case VGI_ERROR_COLORSPACE_NOT_SUPPORTED:
case VG_UNSUPPORTED_IMAGE_FORMAT_ERROR:
case VGI_ERROR_NOT_SUPPORTED:
{
error = KErrNotSupported;
break;
}
case VGI_ERROR_ILLEGAL_IMAGE_HANDLE:
{
error = KErrBadHandle;
break;
}
case VG_IMAGE_IN_USE_ERROR:
case VGI_ERROR_IMAGE_IN_USE:
{
error = KErrInUse;
break;
}
case VGI_ERROR_ILLEGAL_OPERATION:
{
error = KErrPermissionDenied;
break;
}
case VG_BAD_HANDLE_ERROR:
case VG_PATH_CAPABILITY_ERROR:
case VGU_PATH_CAPABILITY_ERROR:
case VGU_BAD_WARP_ERROR:
case VGU_BAD_HANDLE_ERROR:
{
error = KErrUnknown;
break;
}
default:
{
error = KErrUnknown;
}
}
return error;
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::DoDrawL( MGfxShape* aShape )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::DoDrawL( MGfxShape* aShape )
{
VGbitfield drawMode = 0x0;
VGUErrorCode vguret;
// Do not render if both stroke and fill are none
if ( iStrokeColor.GetARGB() == KGfxColorNull && iFillColor == NULL )
return;
iVgRenderer->vgSeti( VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE );
if ( !iPath )
{
const float KScale = 1.0f / 65536.0f;
iPath = iVgRenderer->vgCreatePath( VG_PATH_FORMAT_STANDARD,
VG_PATH_DATATYPE_S_32, KScale, 0.0f, 0, 0,
VG_PATH_CAPABILITY_APPEND_TO );
if ( iPath == VG_INVALID_HANDLE )
{
VGErrorCode error = (VGErrorCode)iVgRenderer->vgGetError();
if (error == VG_OUT_OF_MEMORY_ERROR)
{
#ifdef _DEBUG
RDebug::Printf("OOM: vgCreatePath");
#endif
User::Leave(KErrNoMemory);
}
// handle other errors...
#ifdef _DEBUG
RDebug::Printf("SVG GFX2D Error: vgCreatePath");
#endif
}
}
if (iFillColor)
{
if(!iFillPaint)
{
iFillPaint = iVgRenderer->vgCreatePaint();
if ( iFillPaint == VG_INVALID_HANDLE )
{
VGErrorCode error = (VGErrorCode)iVgRenderer->vgGetError();
if (error == VG_OUT_OF_MEMORY_ERROR)
{
RDebug::Printf("SVG GFX2D Error OOMs: vgCreatePaint");
User::Leave(KErrNoMemory);
}
// handle other errors...
#ifdef _DEBUG
RDebug::Printf("SVG GFX2D Error: vgCreatePaint");
#endif
}
}
}
if(iStrokeColor.GetARGB() != KGfxColorNull)
{
if(!iStrokePaint)
{
iStrokePaint = iVgRenderer->vgCreatePaint();
if ( iStrokePaint == VG_INVALID_HANDLE )
{
VGErrorCode error = (VGErrorCode)iVgRenderer->vgGetError();
if (error == VG_OUT_OF_MEMORY_ERROR)
{
RDebug::Printf("SVGT CGfx2dGcOpenVG::DoDrawL vgCreatePaint OOM");
User::Leave(KErrNoMemory);
}
#ifdef _DEBUG
RDebug::Printf("SVGT CGfx2dGcOpenVG::DoDrawL vgCreatePaint failed %d", error);
#endif
}
}
}
TGfxRectangle2D bbRect;
TGfxAffineTransform identityMat;
//vgClear( 0, 0, VG_MAXINT, VG_MAXINT );
switch(aShape->ShapeType())
{
case MGfxShape::ERect:
{
TGfxRectangle2D* rect = (TGfxRectangle2D*)aShape;
rect->GetBounds( identityMat, bbRect );
drawMode = SetFillStroke(iFillPaint, iStrokePaint, bbRect);
vguret = (VGUErrorCode)iVgRenderer->vguRect(
iPath,
(VGfloat)rect->iX,
(VGfloat)rect->iY,
(VGfloat)rect->iWidth,
(VGfloat)rect->iHeight );
if( vguret != KErrNone )
{
User::LeaveIfError(OpenVGErrorToSymbianError(vguret));
}
iVgRenderer->vgDrawPath( iPath, drawMode );
}
break;
case MGfxShape::ERoundRect:
{
float rx, ry;
TGfxRoundRectangle2D* rect = (TGfxRoundRectangle2D*)aShape;
TFloatFixPt tWidth = rect->iArcWidth;
TFloatFixPt tHeight = rect->iArcHeight;
tWidth.iValue <<= 1;
tHeight.iValue <<= 1;
rx = (VGfloat)tWidth;
ry = (VGfloat)tHeight;
//If a properly specified value is provided for ry but not for rx,
// then the user agent must process the 'rect' element with the
// effective value for rx as equal to ry. However clamp to 0.
if ( rx <= 0 )
{
rx = ry;
}
if ( ry <= 0)
{
ry = rx;
}
if(rx < 0)
{
rx = 0;
}
if(ry < 0)
{
ry = 0;
}
rect->GetBounds( identityMat, bbRect );
drawMode = SetFillStroke(iFillPaint, iStrokePaint, bbRect);
// Rounded rectangle
if ( rx == 0.0f && ry == 0.0f )
{
vguret = (VGUErrorCode)iVgRenderer->vguRect(iPath,
(VGfloat)rect->iX, (VGfloat)rect->iY,
(VGfloat)rect->iWidth, (VGfloat)rect->iHeight );
}
else
{
vguret = (VGUErrorCode)iVgRenderer->vguRoundRect( iPath,
(VGfloat)rect->iX, (VGfloat)rect->iY,
(VGfloat)rect->iWidth, (VGfloat)rect->iHeight,
rx, ry );
}
if( vguret != KErrNone )
{
User::LeaveIfError(OpenVGErrorToSymbianError(vguret));
}
iVgRenderer->vgDrawPath( iPath, drawMode );
}
break;
case MGfxShape::EEllipse:
{
TGfxEllipse2D* ellipse = (TGfxEllipse2D*)aShape;
#ifdef SVG_FLOAT_BUILD
TFloatFixPt rx = ellipse->iWidth * TFloatFixPt(.5f);
TFloatFixPt ry = ellipse->iHeight * TFloatFixPt(.5f);
#else
TFloatFixPt rx = ellipse->iWidth >> 1; // rx = width / 2
TFloatFixPt ry = ellipse->iHeight >> 1; // ry = height / 2
#endif
ellipse->GetBounds( identityMat, bbRect );
drawMode = SetFillStroke(iFillPaint, iStrokePaint, bbRect);
// Element
vguret = (VGUErrorCode)iVgRenderer->vguEllipse(iPath,
(VGfloat)(ellipse->iX + rx),
(VGfloat)(ellipse->iY + ry),
(VGfloat)ellipse->iWidth,
(VGfloat)ellipse->iHeight);
if( vguret != KErrNone )
{
User::LeaveIfError(OpenVGErrorToSymbianError(vguret));
}
iVgRenderer->vgDrawPath(iPath,drawMode);
}
break;
case MGfxShape::EPath:
{
CGfxGeneralPath* gPath = (CGfxGeneralPath*)aShape;
RArray<TFloatFixPt>* coordArray = gPath->PointCoordsArrayAll();
if (coordArray->Count() > 0)
{
TFloatFixPt* coord = gPath->PointCoordsArray();
TUint8 count = gPath->Count();
RArray<TUint32>* type = gPath->PointTypeArray();
TInt typeCount = type->Count();
if(count && ( typeCount == count))
{
iVgRenderer->vgAppendPathData(iPath, count,gPath->PathSegmentTypeArray(),coord);
}
else
{
//RArray<TUint32>* type = gPath->PointTypeArray();
//TInt typeCount = type->Count();
// this is a multi path
// Using non-ELeave version and checking for NULL to avoid (ELeave) and TRAP
if ( iPathSegmentTypeCount < typeCount )
{
if ( iPathSegmentTypes )
{
delete [] iPathSegmentTypes;
iPathSegmentTypes = NULL;
}
iPathSegmentTypes = new VGubyte[typeCount];
iPathSegmentTypeCount = typeCount;
}
if ( !iPathSegmentTypes )
{
break;
}
for (TInt i=0; i < typeCount; i++)
{
iPathSegmentTypes[i] = (TGfxSegType) (*type)[i];
}
iVgRenderer->vgAppendPathData(iPath, typeCount, iPathSegmentTypes, coord);
}
gPath->GetBounds( identityMat, bbRect );
drawMode = SetFillStroke(iFillPaint, iStrokePaint, bbRect);
iVgRenderer->vgDrawPath(iPath,drawMode);
}
}
break;
case MGfxShape::ELine:
{
TGfxLine2D* line = (TGfxLine2D*)aShape;
// Force Stroke color... if not present
if(iFillColor && iStrokeColor.GetARGB() == KGfxColorNull)
{
iStrokeColor = iFillColor->GetColor();
}
line->GetBounds( identityMat, bbRect );
drawMode = SetFillStroke(iFillPaint, iStrokePaint, bbRect);
vguret = (VGUErrorCode)iVgRenderer->vguLine(
iPath,
(VGfloat)line->iX1,
(VGfloat)line->iY1,
(VGfloat)line->iX2,
(VGfloat)line->iY2);
if( vguret != KErrNone )
{
User::LeaveIfError(OpenVGErrorToSymbianError(vguret));
}
iVgRenderer->vgDrawPath(iPath,drawMode);
}
break;
}
iVgRenderer->vgClearPath( iPath, VG_PATH_CAPABILITY_APPEND_TO );
// Delete path segment type array to avoid large memory to persist,
// created by some content, but the larget size is not needed later.
if ( iPathSegmentTypeCount > KPathSegmentTypeMaxSize )
{
if ( iPathSegmentTypes )
{
delete [] iPathSegmentTypes;
iPathSegmentTypes = NULL;
iPathSegmentTypeCount = 0;
}
}
// Turn off any settings that are not needed by default
PostDraw();
}
void CGfx2dGcOpenVG::PostDraw()
{
if ( iDashArray && iDashArray->Count() > 0 )
{
iVgRenderer->vgSetfv(VG_STROKE_DASH_PATTERN, 0, NULL);
iDashArray->Reset();
}
}
// --------------------------------------------------------------------------
// VGbitfield CGfx2dGcOpenVG::SetFillStroke(VGPaint aFillPaint, VGPaint aStrokePaint, TGfxRectangle2D& bBox)
// ---------------------------------------------------------------------------
VGbitfield CGfx2dGcOpenVG::SetFillStroke(VGPaint aFillPaint, VGPaint aStrokePaint, TGfxRectangle2D& bBox)
{
VGbitfield returnVal = 0x0;
// Fill Color
if (iFillColor)
{
if( aFillPaint != VG_INVALID_HANDLE )
{
iFillColor->SetFill(aFillPaint, bBox, iFillOpacity, iVgRenderer);
returnVal |= VG_FILL_PATH;
}
}
//
// Color Correction for Symbian->OpenVG
// Symbian argb
// OpenVg rgba
//
// Stroke
//
if( iStrokeColor.GetARGB() != KGfxColorNull && iStrokeColor.GetARGB() != 0x1ffffff )
{
iVgRenderer->vgSetf( VG_STROKE_LINE_WIDTH, (VGfloat)iStroke.StrokeWidth() );
//SET LINECAP INFORMATION
SVGLineCap lineCap = (SVGLineCap)iStroke.StrokeCap();
if (lineCap == SVG_CAP_ROUND)
{
iVgRenderer->vgSeti( VG_STROKE_CAP_STYLE, VG_CAP_ROUND);
}
else if ( lineCap == SVG_CAP_SQUARE )
{
iVgRenderer->vgSeti( VG_STROKE_CAP_STYLE, VG_CAP_SQUARE);
}
else
{
iVgRenderer->vgSeti( VG_STROKE_CAP_STYLE, VG_CAP_BUTT);
}
//SET LINEJOIN INFORMATION
SVGLineJoin linejoin = (SVGLineJoin)iStroke.StrokeJoin();
if (linejoin == SVG_JOIN_ROUND)
{
iVgRenderer->vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_ROUND);
}
else if (linejoin == SVG_JOIN_BEVEL)
{
iVgRenderer->vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_BEVEL);
}
else
{
iVgRenderer->vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_MITER);
}
iVgRenderer->vgSetf( VG_STROKE_MITER_LIMIT, (VGfloat)iStroke.StrokeMiterLimit() );
if(aStrokePaint != VG_INVALID_HANDLE)
{
iVgRenderer->vgSetParameteri( aStrokePaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR );
TUint32 opacity = (TInt)(iStrokeOpacity * TFloatFixPt(255.0f));
iVgRenderer->vgSetColor( aStrokePaint, iStrokeColor.GetARGB() << 8 | opacity );
iVgRenderer->vgSetPaint( aStrokePaint, VG_STROKE_PATH );
returnVal |= VG_STROKE_PATH;
}
}
return returnVal;
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::SetWindingRule( TGfxWindingRule aRule )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::SetWindingRule( TGfxWindingRule aRule )
{
if ( aRule == EGfxWindEvenOdd )
{
iVgRenderer->vgSeti(VG_FILL_RULE, VG_EVEN_ODD);
}
else
{
iVgRenderer->vgSeti(VG_FILL_RULE, VG_NON_ZERO);
}
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::Draw( MGfxShape* aShape )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::DrawL( MGfxShape* aShape )
{
DoDrawL( aShape );
}
// --------------------------------------------------------------------------
// TGfxColor CGfx2dGcOpenVG::ForegroundColor()
// ---------------------------------------------------------------------------
TGfxColor CGfx2dGcOpenVG::ForegroundColor()
{
return iStrokeColor;
}
// --------------------------------------------------------------------------
// MGfxPaint* CGfx2dGcOpenVG::Paint()
// ---------------------------------------------------------------------------
MGfxPaint* CGfx2dGcOpenVG::Paint()
{
return iFillColor;
}
// --------------------------------------------------------------------------
// TGfxRenderingHints* CGfx2dGcOpenVG::RenderingHints()
// ---------------------------------------------------------------------------
TGfxRenderingHints* CGfx2dGcOpenVG::RenderingHints()
{
//return &iRenderingHints;
return NULL;
}
// --------------------------------------------------------------------------
// TGfxStroke CGfx2dGcOpenVG::Stroke()
// ---------------------------------------------------------------------------
TGfxStroke CGfx2dGcOpenVG::Stroke()
{
return iStroke;
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::SetDashOffset( TFloatFixPt aDashOffset )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::SetDashOffset( TFloatFixPt aDashOffset )
{
iDashOffset = aDashOffset;
iVgRenderer->vgSetf(VG_STROKE_DASH_PHASE, (VGfloat)iDashOffset);
// svgSetStrokeDashOffset(iHyb2dContext, svgScalarFromFloat(iDashOffset));
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::SetForegroundColor( const TGfxColor& aColor )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::SetForegroundColor( const TGfxColor& aColor )
{
// Both GDI and Gfx2D need to keep color value...
iStrokeColor = aColor;
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::SetStrokeWidth( const TGfxStroke& aColor )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::SetStrokeWidth( const TFloatFixPt& aWidth )
{
// Both GDI and Gfx2D need to keep stroke-width value...
iStroke.SetStrokeWidth(aWidth);
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::SetBackgroundColor( const TGfxColor& aColor )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::SetBackgroundColor( const TGfxColor& aColor )
{
// Only Gfx2D need to keep background color value.
iBackgroundColor = aColor;
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::SetPaint( MGfxPaint* aPaint )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::SetPaint( MGfxPaint* aPaint )
{
iFillColor = aPaint;
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::SetStroke( TGfxStroke aStroke )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::SetStroke( TGfxStroke aStroke )
{
iStroke = aStroke;
iVgRenderer->vgSetf( VG_STROKE_LINE_WIDTH, (VGfloat)iStroke.StrokeWidth() );
//SET LINECAP INFORMATION
SVGLineCap lineCap = (SVGLineCap)iStroke.StrokeCap();
if (lineCap == SVG_CAP_ROUND)
{
iVgRenderer->vgSeti( VG_STROKE_CAP_STYLE, VG_CAP_ROUND);
}
else if ( lineCap == SVG_CAP_SQUARE )
{
iVgRenderer->vgSeti( VG_STROKE_CAP_STYLE, VG_CAP_SQUARE);
}
else
{
iVgRenderer->vgSeti( VG_STROKE_CAP_STYLE, VG_CAP_BUTT);
}
//SET LINEJOIN INFORMATION
SVGLineJoin linejoin = (SVGLineJoin)iStroke.StrokeJoin();
if (linejoin == SVG_JOIN_ROUND)
{
iVgRenderer->vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_ROUND);
}
else if (linejoin == SVG_JOIN_BEVEL)
{
iVgRenderer->vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_BEVEL);
}
else
{
iVgRenderer->vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_MITER);
}
iVgRenderer->vgSetf( VG_STROKE_MITER_LIMIT, (VGfloat)iStroke.StrokeMiterLimit() );
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::SetRenderingHints( const TGfxRenderingHints& aRenderingHints )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::SetRenderingHints( const TGfxRenderingHints& /*aRenderingHints*/ )
{
//iRenderingHints = aRenderingHints;
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::SetTransform( const TGfxAffineTransform& aTransform )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::SetTransform( const TGfxAffineTransform& aTransform )
{
iTransform = aTransform;
// Calculate scale
TGfxPoint2D ep( 1, 0 ), org( 2, 0 );
iTransform.Transform( &ep, & ep, 1 );
iTransform.Transform( &org, & org, 1 );
ep.iX -= org.iX;
ep.iY -= org.iY;
iScale = TFloatFixPt::Sqrt( ep.iX * ep.iX + ep.iY * ep.iY );
// activate Graphics 2D engine
// set viewport coordinate system to map from canvas coordinates to pixels
// in order to provide resolution independent results
// SVGMatrix2x3 vmat;
// svgMatrix2x3Set( &vmat,
// iTransform.iM00.iValue,
// iTransform.iM01.iValue,
// iTransform.iM02.iValue,
// iTransform.iM10.iValue,
// iTransform.iM11.iValue,
// iTransform.iM12.iValue
// );
// svgSetViewportCoordinateSystem( iHyb2dContext, vmat.matrix );
ApplyTransform(iTransform);
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::SetClip( const TGfxRectangle2D& aClip )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::SetClip( const TGfxRectangle2D& aClip )
{
iClip = aClip;
TFloatFixPt newY = iColorBufferSize.iHeight - (TInt)aClip.iHeight - (TInt)aClip.iY;
VGint clipRect[4] =
{
(TInt)aClip.iX, (TInt)newY, (TInt)aClip.iWidth, (TInt)aClip.iHeight
};
// Set VG_SCISSORING to True
iVgRenderer->vgSeti(VG_SCISSORING, VG_TRUE);
// Set Clippling rectangle
iVgRenderer->vgSetiv(VG_SCISSOR_RECTS, 4,(const TInt*) clipRect);
}
void CGfx2dGcOpenVG::SetClipMediaElement( TSize aSize )
{
TFloatFixPt width = (TFloatFixPt)aSize.iWidth;
TFloatFixPt height = (TFloatFixPt)aSize.iHeight;
TFloatFixPt x = (TFloatFixPt)0;
TFloatFixPt y = (TFloatFixPt)0;
TGfxRectangle2D aClip(x,y,width,height);
iClipMain = iClip;
iClip = aClip;
// TFloatFixPt newY = aSize.iHeight - (TInt)aClip.iHeight - (TInt)aClip.iY;
VGint clipRect[4] =
{
(TInt)aClip.iX, (TInt)aClip.iY, (TInt)aClip.iWidth, (TInt)aClip.iHeight
};
// Set VG_SCISSORING to True
iVgRenderer->vgSeti(VG_SCISSORING, VG_TRUE);
// Set Clippling rectangle
iVgRenderer->vgSetiv(VG_SCISSOR_RECTS, 4, (const TInt*)clipRect);
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::SetDashArrayL( CArrayFix<TFloatFixPt>* aArray )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::SetDashArrayL( CArrayFix<TFloatFixPt>* aArray )
{
if ( !aArray || !iDashArray )
{
return;
}
TInt32 count = aArray->Count();
if ( count == 0 )
{
return;
}
if ( iDashArray->Count() > 0 )
{
iDashArray->Reset();
}
for ( TInt32 i = 0; i < count; i++ )
{
iDashArray->AppendL( (VGfloat)aArray->At( i ) );
}
if ( count & 0x00000001 )
{
//count was odd so we need to duplicate the current ones on the array
for (TInt32 i=0; i < count; i++)
{
iDashArray->AppendL( (VGfloat)aArray->At( i ) );
}
}
iVgRenderer->vgSetfv(VG_STROKE_DASH_PATTERN, iDashArray->Count(), (VGfloat*)&(*iDashArray)[0] );
}
// --------------------------------------------------------------------------
// TSize CGfx2dGcOpenVG::DeviceBounds()
// ---------------------------------------------------------------------------
TSize CGfx2dGcOpenVG::DeviceBounds()
{
return iColorBufferSize;
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::SetAntialiasingMode( const TInt32 /*aAntialiasingEnable*/)
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::SetAntialiasingMode( const TInt32 aAntialiasingMode )
{
// JSR226 has two values for Render Quality
//--------------------------------------------------------------------------------
// JSR226/M2G Values : TInt Value : OpenVG Constants
//--------------------------------------------------------------------------------
// RENDERING_QUALITY_LOW : = 1 = : VG_RENDERING_QUALITY_NONANTIALIASED
// RENDERING_QUALITY_HIGH : = 2 = : VG_RENDERING_QUALITY_BETTER
//--------------------------------------------------------------------------------.
if( aAntialiasingMode == KRenderQualityLow ) // RENDERING_QUALITY_LOW
{
iRenderQuality = VG_RENDERING_QUALITY_NONANTIALIASED ;
}
else if( aAntialiasingMode == KRenderQualityHigh ) // RENDERING_QUALITY_HIGH
{
iRenderQuality = VG_RENDERING_QUALITY_BETTER ;
}
iVgRenderer->vgSeti(VG_RENDERING_QUALITY, iRenderQuality );
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::SetFont( const CFont* aFont )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::SetFont( const CFont* aFont )
{
iFont = (CFont*)aFont;
}
// --------------------------------------------------------------------------
// CFont* CGfx2dGcOpenVG::Font()
// ---------------------------------------------------------------------------
CFont* CGfx2dGcOpenVG::Font()
{
if (iFont == NULL)
{
iSvgBitmapFontProvider->GetNearestFontToDesignHeightInTwips( iFont, iFontSpec );
}
return iFont;
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::GetSystemFontScaled(TFloatFixPt aHeight,
// const TDesC& aTypefaceName,
// CFont*& aFont,
// TFontSpec& aFontSpec )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::GetFontScaled( TFloatFixPt /* aHeight */,
const TDesC& /* aTypefaceName */,
CFont*& /* aFont */,
TFontSpec& /* aFontSpec */ )
{
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::SetFontSize( const TFloatFixPt aFontSize )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::SetFontSize( const TFloatFixPt aFontSize )
{
iFontSize = aFontSize;
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::SetFontWeight( const TInt32 aFontWeight )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::SetFontWeight( const TInt32 aFontWeight )
{
iFontWeight = aFontWeight;
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::SetFontStyle( const TInt32 aFontStyle )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::SetFontStyle( const TInt32 aFontStyle )
{
iFontStyle = aFontStyle;
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::SetFontFamily( CDesCArrayFlat* aFamilies )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::SetFontFamily( CDesCArrayFlat* aFamilies )
{
iFamilies = aFamilies;
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::SetTextanchor( const TInt32 aTextAnchor )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::SetTextanchor( const TInt32 aTextAnchor )
{
iTextAnchor = (TGfxTextAnchor)aTextAnchor;
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::SetTextDecoration( const TInt32 aTextDecoration )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::SetTextDecoration( const TInt32 aTextDecoration )
{
iTextDecoration = (TGfxTextDecoration)aTextDecoration;
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::GetBBoxForSystemText( TSvgFourPointRect& aFourPointBbox )
// ---------------------------------------------------------------------------
TGfxRectangle2D CGfx2dGcOpenVG::GetBBoxForSystemText( const TDesC& aText,
TFloatFixPt aX,
TFloatFixPt aY )
{
//bbox for bitmap fonts
TGfxRectangle2D lBbox;
TGfxPoint2D pt(aX,aY);
//iScale = GetCurrentScale();
//scaled already for bitmap text...
TInt textAdvance = iFont->TextWidthInPixels( aText );
TInt fontMaxHeight = iFont->FontMaxHeight();
TFloatFixPt lascent = iFont->AscentInPixels();
TFloatFixPt ldescent = TFloatFixPt(fontMaxHeight) - (TFloatFixPt)iFont->AscentInPixels();
lBbox.iWidth = textAdvance;
lBbox.iHeight = fontMaxHeight;
//need to work in the rotation factor somehow...
//without doing the scaling again
//at this point the bbox already scaled,translated but not rotated
//should we create 1/scale factor or create with scale factor then get inverse
//iScale scaling factor from the graphics context
TReal32 linverseScale = 1.0/(TReal)iScale;
TGfxAffineTransform lInverseScaleMat = TGfxAffineTransform::GetScaleInstance(linverseScale, linverseScale);
//this is with scale and rotation
TGfxPoint2D transformedPoint( pt.iX, pt.iY );
const TGfxAffineTransform& ctm = iTransform;
ctm.Transform(&pt, &transformedPoint, 1);
//remove the double scaling effect that we would have
TGfxAffineTransform ctmWithoutScale = iTransform;
ctmWithoutScale.Concatenate(lInverseScaleMat);
TGfxPoint2D scaledPoint( pt.iX * iScale, pt.iY * iScale );
//set up the initial box with just scale in it and not rotation.
// The base line is position at x,y co-ordinate of the text, but
// the bottom of bound box would be further below by amount ldescent.
TGfxPoint2D lTopLeftCorner(scaledPoint.iX, scaledPoint.iY + ldescent );
TGfxPoint2D lTopRightCorner(scaledPoint.iX + lBbox.iWidth , scaledPoint.iY + ldescent );
TGfxPoint2D lBottomLeftCorner(scaledPoint.iX, scaledPoint.iY - lascent);
TGfxPoint2D lBottomRightCorner(scaledPoint.iX + lBbox.iWidth, scaledPoint.iY - lascent );
TGfxPoint2D lTransTopLeftCorner;
TGfxPoint2D lTransBottomLeftCorner;
TGfxPoint2D lTransTopRightCorner;
TGfxPoint2D lTransBottomRightCorner;
//applying current rotation transform without the scale.
ctmWithoutScale.Transform(&lTopLeftCorner, &lTransTopLeftCorner,1);
ctmWithoutScale.Transform(&lTopRightCorner, &lTransTopRightCorner,1);
ctmWithoutScale.Transform(&lBottomLeftCorner, &lTransBottomLeftCorner,1);
ctmWithoutScale.Transform(&lBottomRightCorner, &lTransBottomRightCorner,1);
TFloatFixPt lXTranslation = transformedPoint.iX - lTransTopLeftCorner.iX;
//TFixPt lXTranslation = transformedPoint.iX - iPoint.iX;
TFloatFixPt lYTranslation = transformedPoint.iY - lTransTopLeftCorner.iY;
//TFixPt lYTranslation = transformedPoint.iY - iPoint.iY;
// X position is affected by anchor
switch( iTextAnchor )
{
case EGfxTextAnchorMiddle:
lXTranslation = lXTranslation - ( lBbox.iWidth / TFloatFixPt( 2 ) );
break;
case EGfxTextAnchorEnd:
lXTranslation = lXTranslation - lBbox.iWidth;
break;
default:
//do nothing
break;
}
lTransTopLeftCorner.iX += lXTranslation;
lTransTopLeftCorner.iY += lYTranslation;
lTransTopRightCorner.iX += lXTranslation;
lTransTopRightCorner.iY += lYTranslation;
lTransBottomLeftCorner.iX += lXTranslation;
lTransBottomLeftCorner.iY += lYTranslation;
lTransBottomRightCorner.iX += lXTranslation;
lTransBottomRightCorner.iY += lYTranslation;
//at this point I have the exact path coordinates of the bbox
//aFourPointBbox.SetRectPoints(lTransTopLeftCorner, lTransTopRightCorner, lTransBottomLeftCorner, lTransBottomRightCorner);
return GetTRect(lTransTopLeftCorner, lTransTopRightCorner, lTransBottomLeftCorner, lTransBottomRightCorner);
}
TGfxRectangle2D CGfx2dGcOpenVG::GetTRect(TGfxPoint2D lTransTopLeftCorner,TGfxPoint2D lTransTopRightCorner,TGfxPoint2D lTransBottomLeftCorner,TGfxPoint2D lTransBottomRightCorner)
{
TFloatFixPt lMaxX = lTransTopLeftCorner.iX;
if (lTransTopRightCorner.iX > lMaxX)
{
lMaxX = lTransTopRightCorner.iX;
}
if (lTransBottomLeftCorner.iX > lMaxX)
{
lMaxX = lTransBottomLeftCorner.iX;
}
if (lTransBottomRightCorner.iX > lMaxX)
{
lMaxX = lTransBottomRightCorner.iX;
}
TFloatFixPt lMaxY = lTransTopLeftCorner.iY;
if (lTransTopRightCorner.iY > lMaxY)
{
lMaxY = lTransTopRightCorner.iY;
}
if (lTransBottomLeftCorner.iY > lMaxY)
{
lMaxY = lTransBottomLeftCorner.iY;
}
if (lTransBottomRightCorner.iY > lMaxY)
{
lMaxY = lTransBottomRightCorner.iY;
}
TFloatFixPt lMinX = lTransTopLeftCorner.iX;
if (lTransTopRightCorner.iX < lMinX)
{
lMinX = lTransTopRightCorner.iX;
}
if (lTransBottomLeftCorner.iX < lMinX)
{
lMinX = lTransBottomLeftCorner.iX;
}
if (lTransBottomRightCorner.iX < lMinX)
{
lMinX = lTransBottomRightCorner.iX;
}
TFloatFixPt lMinY = lTransTopLeftCorner.iY;
if (lTransTopRightCorner.iY < lMinY)
{
lMinY = lTransTopRightCorner.iY;
}
if (lTransBottomLeftCorner.iY < lMinY)
{
lMinY = lTransBottomLeftCorner.iY;
}
if (lTransBottomRightCorner.iY < lMinY)
{
lMinY = lTransBottomRightCorner.iY;
}
TGfxRectangle2D aRect;
aRect.iX = lMinX;
aRect.iY = lMinY;
aRect.iWidth = lMaxX - lMinX;
aRect.iHeight = lMaxY - lMinY;
return aRect;
}
// Text Drawing
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::DrawStringL( const TDesC& aDesc,
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::DrawStringL( const TDesC& aDesc,
TFloatFixPt aX,
TFloatFixPt aY,
TInt8 ,// aTextAnchor
TInt8 ,// aTextDecoration
CDesCArrayFlat*, // aFamilies,
TReal aWordSpacing,
TReal aLetterSpacing,
CArrayFix<TReal32>* aArrayRotate,
CArrayFix<TFloatFixPt>* aArrayX,
CArrayFix<TFloatFixPt>* aArrayY,
TSize& aBoundingBox,
CFont*& aFont,
TFontSpec& /* aFontSpec */ )
{
if ( iStrokeColor.GetARGB() == KGfxColorNull &&
iFillColor == NULL )
return;
if(iFillOpacity == TFloatFixPt(0))
return;
if ( aDesc.Length() <= 0 )
return;
TPtrC outputText;
if ( *( aDesc.Right( 1 ).Ptr() ) < ' ' )
outputText.Set( aDesc.Left( aDesc.Length() - 1 ) );
else
outputText.Set( aDesc );
TBool rtl=EFalse;
if(TBidiText::TextDirectionality(outputText) == TBidiText::ERightToLeft)
{
rtl=ETrue;
}
if ( aFont == NULL )
{
return;
}
iFont = aFont;
float aFloat = 0.5;
//put in .50 for rounding issues 10.99 was going to 10
// iFontSize has been initialised at the SetGCL time for the
// this specific text element in question.
TInt32 fontsize = (TInt32)( iScale * iFontSize + TFloatFixPt(aFloat) );
if ( fontsize == 0 )
{
return;
}
CFont::TMeasureTextOutput myTextOutput;
TInt textAdvance = iFont->TextWidthInPixels( outputText );
if ( textAdvance == 0 )
{
return;
}
TInt fontMaxHeight = iFont->FontMaxHeight() + 2; //Tweak factor needed
TInt fontMaxAscent = iFont->FontMaxAscent() + 1; //Tweak factor needed
TInt fontAscent = iFont->AscentInPixels();
TInt fontDescent = iFont->DescentInPixels();
TInt maxDescent = fontMaxHeight-fontMaxAscent; //iFont->FontMaxDescent();
TInt fontHeightInPixels = iFont->HeightInPixels();
//added to correct for text clipping that system font has
TInt fontTweakFactor = (TInt)(TFloatFixPt( 1.5f ) * iScale);
TInt fontHorizontalTweakFactor = (TInt)(TFloatFixPt( 5.0f ) * iScale);
TInt numSpaces = myTextOutput.iSpaces;
TInt numChars = myTextOutput.iChars;
TGfxRectangle2D tempRect( aX,
aY,
textAdvance,
fontMaxHeight );
/******************************************************************
* Boundary Check to see if the Text to be drawn is within Bounds. *
******************************************************************/
TGfxAffineTransform tMatrix;
tMatrix = iTransform;
TInt32 transx = tMatrix.TranslateX();
TInt32 transy = tMatrix.TranslateY();
TGfxRectangle2D aRect = GetBBoxForSystemText( outputText , aX , aY );
TInt32 rectmaxx = aRect.MaxX(); //+ (TFloatFixPt)transx;
TInt32 rectmaxy = aRect.MaxY();//- (TFloatFixPt)fontMaxAscent; //+ (TFloatFixPt)transy;
TInt32 rectminx = aRect.MinX(); //- (TFloatFixPt)transx;
TInt32 rectminy = aRect.MinY();// - (TFloatFixPt)fontMaxHeight;//- (TFloatFixPt)fontMaxAscent; //- (TFloatFixPt)transy;
TInt32 clipminx = iRenderInfo.iClipMinX;// + transx;
TInt32 clipmaxx = iRenderInfo.iClipMaxX;// + transx;
TInt32 clipmaxy = iRenderInfo.iClipMaxY;// + transy;
TInt32 clipminy = iRenderInfo.iClipMinY;// + transy;
TInt advanceWidth = 0;
TInt advanceX = 0;
TInt excessSpace = 0;
TInt aMultipleXY = 0;
//Checking for multiple XY values.
if ( aArrayX != NULL && aArrayY != NULL )
{
if ( ( aArrayX->Count() > 1 ) || ( aArrayY->Count() > 1 ) )
aMultipleXY = 1;
}
// setting the boundbox for simple text with no xy and rotate
//this is set here because bound box should get always set as it is used in GetBBoxForSystemText in TextElement.
if ( ( aArrayRotate == NULL ) &&
( aMultipleXY == 0 ) &&
( aLetterSpacing == 0.0 ) &&
( aWordSpacing == 0.0 ) )
{
aBoundingBox.iWidth = textAdvance;
aBoundingBox.iHeight = fontMaxHeight;
}
if( rectmaxx < clipminx || rectmaxy < clipminy ||
rectminx > clipmaxx || rectminy > clipmaxy )
return;
/****************************************************************************
* Code to Draw Simple Text with only x, y and transform values and return.*
****************************************************************************/
if ( ( aArrayRotate == NULL ) &&
( aMultipleXY == 0 ) &&
( aLetterSpacing == 0.0 ) &&
( aWordSpacing == 0.0 ) )
{
CFbsBitmap* offScreenBitmap = new ( ELeave ) CFbsBitmap();
User::LeaveIfError( offScreenBitmap->Create( TSize( textAdvance, fontMaxHeight), EGray256 ) );
// User::LeaveIfError( offScreenBitmap->Create( TSize( textAdvance + fontHorizontalTweakFactor, fontMaxHeight + fontTweakFactor ), EGray256 ) );
CleanupStack::PushL( offScreenBitmap );
CGraphicsContext* bitmapContext = NULL;
CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL( offScreenBitmap );
CleanupStack::PushL( bitmapDevice );
User::LeaveIfError( bitmapDevice->CreateContext( bitmapContext ) );
CleanupStack::PushL( bitmapContext );
bitmapContext->SetBrushStyle( CGraphicsContext::ESolidBrush );
bitmapContext->SetBrushColor( 0x000000 );
bitmapContext->DrawRect( TRect( TPoint( 0, 0 ), offScreenBitmap->SizeInPixels() ) );
bitmapContext->UseFont( iFont );
bitmapContext->SetPenSize( TSize( 1, 1 ) );
bitmapContext->SetPenColor( 0xFFFFFF );
bitmapContext->SetPenStyle( CGraphicsContext::ESolidPen );
bitmapContext->SetBrushStyle( CGraphicsContext::ENullBrush );
if (iTextAnchor == EGfxTextAnchorEnd)
{
aX -= TFloatFixPt(textAdvance) / iScale;
}
if (iTextAnchor == EGfxTextAnchorMiddle)
{
aX -= (TFloatFixPt(textAdvance) / iScale) / TFloatFixPt(2);
}
// While drawing the text which has both arabic & normal left-to-right
// characters the DrawTextExtended should be used since there is no way
// to split the text according to the directionality.
CGraphicsContext::TDrawTextExtendedParam param;
param.iParRightToLeft = rtl;
bitmapContext->DrawTextExtended(outputText,
TPoint( 0, fontMaxAscent ), param);
VGint width = offScreenBitmap->SizeInPixels().iWidth;
VGint height = offScreenBitmap->SizeInPixels().iHeight;
/* The bilinear causes the text to blur a bit, but rotated (& scaled) text will look better, of course */
VGImage img = iVgRenderer->vgCreateImage( VG_A_8, width, height, VG_IMAGE_QUALITY_NONANTIALIASED );
//VGImage img = vgCreateImage( VG_A_8, width, height, VG_IMAGE_QUALITY_BETTER );
//VGImage img = vgCreateImage( VG_A_8, width, height, VG_IMAGE_QUALITY_FASTER );
VGPaint paint = iVgRenderer->vgCreatePaint();
if( img && paint )
{
offScreenBitmap->LockHeap();
/* OpenVG images have their y-axis flipped,
that is why when calling vgImageSubData we pass the address of offScreenBitmap's last scanline,
and use a negated stride value */
VGint stride = CFbsBitmap::ScanLineLength( width, EGray256 ); /* EGray256 == offScreenBitmap->DisplayMode() */
VGbyte *lastScanline = ( (VGbyte*)offScreenBitmap->DataAddress() ) + ( height - 1 ) * stride;
iVgRenderer->vgImageSubData( img, lastScanline, -stride, VG_A_8, 0, 0, width, height );
offScreenBitmap->UnlockHeap();
TGfxColor color( iFillColor ? iFillColor->GetColor() : iStrokeColor.GetColor() );
VGuint argb = color.GetARGB() | ( 0xff000000 ); /* set alpha to 255 */
VGfloat rgba_f[4];
int tr, tg, tb;
tr = (argb >> 16) & 0xff;
tg = (argb >> 8 ) & 0xff;
tb = (argb ) & 0xff;
rgba_f[0] = tr / 255.0f;
rgba_f[1] = tg / 255.0f;
rgba_f[2] = tb / 255.0f;
//rgba_f[3] = ( ( argb >> 24 ) & 0xff ) / 255.0f;
rgba_f[3] = 1.0f; /* was set to 255 */
if( paint != VG_INVALID_HANDLE )
{
iVgRenderer->vgSetParameteri( paint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR );
iVgRenderer->vgSetParameterfv( paint, VG_PAINT_COLOR, 4, rgba_f );
iVgRenderer->vgSetPaint( paint, VG_FILL_PATH );
}
// Get the current blend mode (set back at end of operation)
const TInt KBlendModeValue = iVgRenderer->vgGeti( VG_BLEND_MODE );
const TInt KImageModeValue = iVgRenderer->vgGeti( VG_IMAGE_MODE );
iVgRenderer->vgSeti( VG_BLEND_MODE, VG_BLEND_SRC_OVER );
iVgRenderer->vgSeti( VG_IMAGE_MODE, VG_DRAW_IMAGE_MULTIPLY );
VGfloat mat[9];
/* Retreive the Path transformation matrix */
GetMatrix( mat );
iVgRenderer->vgSeti( VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE );
iVgRenderer->vgSeti( VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE );
/* Since the text rendering has to match AA done by ext, we'll round the transformation.
Seems like Symbian does not have a 32-bit float round... */
TReal tx = mat[6], ty = mat[7];
Math::Round(tx, tx, 0); Math::Round(ty, ty, 0);
mat[6] = (VGfloat)tx;
mat[7] = (VGfloat)ty;
/* Load Path transformation matrix to Image transformation matrix */
/*nga vgLoadMatrix( mat );
// TFloatFixPt aY1( aY * iScale );
// aY -= ( iFont->AscentInPixels());
//vgTranslate( (VGfloat)aX, (VGfloat)aY + fontTweakFactor);
vgTranslate( (VGfloat)aX, (VGfloat)aY );
vgScale( 1.0f/(VGfloat)iScale, -1.0f/(VGfloat)iScale );
vgTranslate( (VGfloat)0, -(VGfloat)maxDescent);
vgDrawImage( img );
vgSeti( VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE );
vgLoadIdentity();
vgSeti( VG_IMAGE_MODE, KImageModeValue );
vgSeti( VG_BLEND_MODE, KBlendModeValue );*/
iVgRenderer->vgLoadMatrix( mat );
iVgRenderer->vgTranslate( (VGfloat)aX, (VGfloat)aY );
iVgRenderer->vgScale( 1.0f/(VGfloat)iScale, -1.0f/(VGfloat)iScale );
iVgRenderer->vgTranslate( (VGfloat)0, -(VGfloat)maxDescent);
iVgRenderer->vgDrawImage( img );
iVgRenderer->vgSeti( VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE );
iVgRenderer->vgLoadIdentity();
iVgRenderer->vgSeti( VG_IMAGE_MODE, KImageModeValue );
iVgRenderer->vgSeti( VG_BLEND_MODE, KBlendModeValue );
}
if( img )
{
iVgRenderer->vgDestroyImage( img );
}
if( paint )
{
iVgRenderer->vgDestroyPaint( paint );
}
bitmapContext->DiscardFont();
CleanupStack::PopAndDestroy( 3 );
if ( iTextDecoration == EGfxTextDecorationUnderLine )
{
TGfxLine2D aLine( aX,
aY,
(aX + ( TFloatFixPt )textAdvance / iScale ),
aY); //+ ( TFloatFixPt )(2));
DrawL( &aLine );
}
else if ( iTextDecoration == EGfxTextDecorationOverLine )
{
TGfxLine2D aLine( aX,
// aY - ( TFloatFixPt )fontMaxHeight / iScale,
aY,
(aX + ( TFloatFixPt )textAdvance / iScale ),
aY);// - ( TFloatFixPt )fontMaxHeight / iScale );
DrawL( &aLine );
}
else if ( iTextDecoration == EGfxTextDecorationLineThrough )
{
TGfxLine2D aLine( aX ,
aY - ( TFloatFixPt )( fontMaxHeight / 2 ) / iScale,
(aX + ( TFloatFixPt )textAdvance /iScale ),
aY - ( TFloatFixPt )( fontMaxHeight / 2 ) / iScale );
DrawL( &aLine );
}
//-----------------------------------------------------------------
return;
}
//Check Word/Letter Spacing.
if ( aWordSpacing > 0.0 )
excessSpace += ( TInt )
( aWordSpacing * ( TReal ) iScale ) * numSpaces;
if ( aLetterSpacing > 0.0 )
excessSpace += ( TInt )
( aLetterSpacing * ( TReal ) iScale ) * numChars;
textAdvance += excessSpace;
/*****************************************************************************
* Drawing one glyph(character) at a time for multiple XY and rotation Values.*
******************************************************************************/
if (rtl)
{
TBidiText* biditext = TBidiText::NewL(outputText,1);
biditext->WrapText(textAdvance,*iFont,0,1);
outputText.Set(biditext->DisplayText());
delete biditext;
biditext = NULL;
}
TLex aOutputText( outputText );
for ( TInt count = 0; count < outputText.Length() ; count++ )
{
TPtrC outputChar;
TChar ch( aOutputText.Get() );
outputChar.Set( &( outputText.operator[]( count ) ), 1 );
TInt charWidth = iFont->CharWidthInPixels( ch );
CFbsBitmap* offScreenBitmap = new ( ELeave ) CFbsBitmap();
User::LeaveIfError( offScreenBitmap->Create( TSize( charWidth,
fontMaxHeight + fontTweakFactor ),
EColor16MU ) );
CleanupStack::PushL( offScreenBitmap );
CGraphicsContext* bitmapContext = NULL;
CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL( offScreenBitmap );
CleanupStack::PushL( bitmapDevice );
User::LeaveIfError( bitmapDevice->CreateContext( bitmapContext ) );
CleanupStack::PushL( bitmapContext );
TBool isWhite = EFalse;
if ( iFillColor != NULL )
{
if ( ( ( TGfxColor * ) iFillColor )->GetARGB() == 0xffffff )
isWhite = ETrue;
}
else
{
if ( iStrokeColor.GetARGB() == 0xffffff )
isWhite = ETrue;
}
if ( isWhite )
{
// Fill with black if text color is white
TRect bmprect( 0, 0, charWidth, fontMaxHeight );
bitmapContext->SetBrushStyle( CGraphicsContext::ESolidBrush );
bitmapContext->SetBrushColor( 0x000000 );
bitmapContext->SetPenColor( 0x000000 );
bitmapContext->DrawRect( bmprect );
}
bitmapContext->UseFont( iFont );
bitmapContext->SetPenSize( TSize( 1, 1 ) );
if ( iFillColor != NULL )
{
TGfxColor lColor(iFillColor->GetColor());
bitmapContext->SetBrushColor( lColor.GetABGR() );
bitmapContext->SetPenColor( lColor.GetABGR() );
}
else
{
bitmapContext->SetBrushColor( iStrokeColor.GetABGR() );
bitmapContext->SetPenColor( iStrokeColor.GetABGR() );
}
bitmapContext->SetPenStyle( CGraphicsContext::ESolidPen );
bitmapContext->SetBrushStyle( CGraphicsContext::ENullBrush );
if ( ( aArrayX != NULL ) && ( count < aArrayX->Count() ) )
aX = aArrayX->At( count );
if ( ( aArrayY != NULL ) && ( count < aArrayY->Count() ) )
aY = aArrayY->At( count );
TFloatFixPt aY1( aY * iScale ), aX1( aX * iScale );
TFloatFixPt ScaleAA;
TGfxAffineTransform tempMatrix;
tempMatrix = iTransform;
ScaleAA = 1;
#ifdef SVG_FLOAT_BUILD
tempMatrix.Scale( ( TFloatFixPt( 1 ) / ( iScale ) ),
( TFloatFixPt( 1 ) / ( iScale ) ));
#else
tempMatrix.Scale( ( TFloatFixPt( 0x10000,ETrue ) / ( iScale ) ),
( TFloatFixPt( 0x10000,ETrue ) / ( iScale ) ));
#endif
if ( aMultipleXY == 1 )
{
aX1 = aX1 + ( TFloatFixPt ) advanceX;
}
else
aX1 = aX1 + ( TFloatFixPt ) advanceWidth;
aY1 -= ( iFont->AscentInPixels() );
if ( aMultipleXY == 0 )
{
if ( iTextAnchor == EGfxTextAnchorMiddle )
{
aX1 -= textAdvance / 2;
}
else if ( iTextAnchor == EGfxTextAnchorEnd )
{
aX1 -= textAdvance;
}
}
TGfxPoint2D p( aX1, aY1 );
TFloatFixPt trnsx, trnsy;
trnsx = aX1 ;
trnsy = aY1 + ( TFloatFixPt ) ( (fontMaxHeight / 2) + fontDescent);
//"rotate" Attribute Implementation
// If only one value is present, it is applied to all the glyphs
//otherwise, one-to-one mapping is taken. Any extra values are ignored!
if ( aArrayRotate != NULL )
{
if(count < aArrayRotate->Count())
{
TFloatFixPt KZero;
tempMatrix.Translate( trnsx, trnsy );
TReal32 aAngle( ( TReal32 ) aArrayRotate->At( count ) );
tempMatrix.Rotate( aAngle * 3.1415926f / 180.0f );
TFloatFixPt negX( KZero - trnsx );
TFloatFixPt negY( KZero - trnsy );
tempMatrix.Translate( negX, negY );
}
}
TGfxImageTransformer imgtrns( &tempMatrix, iVgRenderer);
TRect clip(iClip.iX, iClip.iY,
iClip.iWidth + iClip.iX, iClip.iHeight + iClip.iY);
p.iY -= fontTweakFactor;
imgtrns.ImageBlend( offScreenBitmap,
p,
iRenderInfo.iWidth,
iRenderInfo.iHeight,
clip,
ETrue);
if (rtl) // IsRightToLeft(outputText)
{
CGraphicsContext::TDrawTextExtendedParam param;
param.iParRightToLeft = ETrue;
bitmapContext->DrawTextExtended(outputText,
TPoint( 0, fontHeightInPixels - fontDescent + fontTweakFactor ), param);
}
else
{
bitmapContext->DrawText( outputChar, TPoint( 0, fontMaxAscent ) );
// bitmapContext->DrawText( outputChar, TPoint( 0, fontHeightInPixels - fontDescent + fontTweakFactor ));
}
TGfxRectangle2D textRect(p.iX, p.iY, textAdvance, fontMaxHeight);
imgtrns.ImageBlend( offScreenBitmap,
p,
iRenderInfo.iWidth,
iRenderInfo.iHeight,
clip);
bitmapContext->DiscardFont();
CleanupStack::PopAndDestroy( 3 );
if ( aMultipleXY == 0 )
{
TInt aSpacing = 0;
if ( aLetterSpacing > 0.0 )
{
if ( ch != 0x0020 )
aSpacing += ( TInt )
( aLetterSpacing * ( TReal ) iScale ) ;
}
if ( aWordSpacing > 0.0 )
{
if ( ch == 0x0020 )
aSpacing += ( TInt ) ( aWordSpacing * ( TReal ) iScale ) ;
}
if ( iStrokeColor.GetARGB() == KGfxColorNull )
{
if ( iFillColor != NULL )
this->iStrokeColor = TGfxColor( iFillColor->GetColor() );
}
if ( iTextDecoration == EGfxTextDecorationUnderLine )
{
if ( iTextAnchor == EGfxTextAnchorMiddle )
{
TGfxLine2D aLine( aX + (ScaleAA *
( TFloatFixPt )
( advanceWidth - textAdvance / 2 ) /
iScale),
aY,
( aX + (ScaleAA * ( ( TFloatFixPt )
( advanceWidth + charWidth + aSpacing - textAdvance / 2 ) /
iScale ) ) ),
aY );
DrawL( &aLine );
}
else if ( iTextAnchor == EGfxTextAnchorEnd )
{
TGfxLine2D aLine( aX + (ScaleAA *
( TFloatFixPt )
( advanceWidth - textAdvance ) /
iScale),
aY,
( aX + (ScaleAA * ( ( TFloatFixPt )
( advanceWidth + charWidth + aSpacing - textAdvance ) /
iScale ) ) ),
aY );
DrawL( &aLine );
}
else //Start
{
TGfxLine2D aLine( aX + (ScaleAA *
( TFloatFixPt )
advanceWidth /
iScale),
aY,
( aX + (ScaleAA * ( ( TFloatFixPt )
( advanceWidth + charWidth + aSpacing ) /
iScale ) ) ),
aY );
DrawL( &aLine );
}
}
if ( iTextDecoration == EGfxTextDecorationOverLine )
{
if ( iTextAnchor == EGfxTextAnchorMiddle )
{
TGfxLine2D aLine( aX + (ScaleAA *
( TFloatFixPt )
( advanceWidth - textAdvance / 2 ) /
iScale),
aY -
( TFloatFixPt )
fontMaxHeight /
iScale,
( aX + (ScaleAA * ( ( TFloatFixPt )
( advanceWidth + charWidth + aSpacing - textAdvance / 2 ) /
iScale ) ) ),
aY -
( TFloatFixPt )
fontMaxHeight /
iScale );
DrawL( &aLine );
}
else if ( iTextAnchor == EGfxTextAnchorEnd )
{
TGfxLine2D aLine( aX + (ScaleAA *
( TFloatFixPt )
( advanceWidth - textAdvance ) /
iScale),
aY -
( TFloatFixPt )
fontMaxHeight /
iScale,
( aX + (ScaleAA * ( ( TFloatFixPt )
( advanceWidth + charWidth + aSpacing - textAdvance ) /
iScale ) ) ),
aY -
( TFloatFixPt )
fontMaxHeight /
iScale );
DrawL( &aLine );
}
else //Start
{
TGfxLine2D aLine( aX + (ScaleAA *
( TFloatFixPt )
advanceWidth /
iScale),
aY -
( TFloatFixPt )
fontMaxHeight /
iScale,
( aX + (ScaleAA * ( ( TFloatFixPt )
( advanceWidth + charWidth + aSpacing ) /
iScale ) ) ),
aY -
( TFloatFixPt )
fontMaxHeight /
iScale );
DrawL( &aLine );
}
}
if ( iTextDecoration == EGfxTextDecorationLineThrough )
{
if ( iTextAnchor == EGfxTextAnchorMiddle )
{
TGfxLine2D aLine( aX + (ScaleAA *
( TFloatFixPt )
( advanceWidth - (textAdvance >> 1) ) /
iScale),
aY -
( TFloatFixPt )
( fontMaxHeight >> 1 ) /
iScale,
( aX + (ScaleAA * ( ( TFloatFixPt )
( advanceWidth + charWidth + aSpacing - ( textAdvance >> 1 )) /
iScale ) ) ),
aY -
( TFloatFixPt )
( fontMaxHeight >> 1 ) /
iScale );
DrawL( &aLine );
}
else if ( iTextAnchor == EGfxTextAnchorEnd )
{
TGfxLine2D aLine( aX + (ScaleAA *
( TFloatFixPt )
( advanceWidth - textAdvance ) /
iScale),
aY -
( TFloatFixPt )
( fontMaxHeight >> 1 ) /
iScale,
( aX + (ScaleAA * ( ( TFloatFixPt )
( advanceWidth + charWidth + aSpacing - textAdvance ) /
iScale ) ) ),
aY -
( TFloatFixPt )
( fontMaxHeight >> 1 ) /
iScale );
DrawL( &aLine );
}
else //Start
{
TGfxLine2D aLine( aX + (ScaleAA *
( TFloatFixPt )
advanceWidth /
iScale),
aY -
( TFloatFixPt )
( fontMaxHeight >> 1 ) /
iScale,
( aX + (ScaleAA * ( ( TFloatFixPt )
( advanceWidth + charWidth + aSpacing ) /
iScale ) ) ),
aY -
( TFloatFixPt )
( fontMaxHeight >> 1 ) /
iScale );
DrawL( &aLine );
}
}
advanceWidth += charWidth + aSpacing;
}
if ( aMultipleXY == 1 )
{
if ( count >= aArrayX->Count() - 1 )
advanceX += charWidth;
}
} //end for(Drawing single glyph)
}
// Raster image drawing
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::DrawImage( CFbsBitmap* aImage,
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::DrawImage( CFbsBitmap* aImage,
const TGfxRectangle2D& aImageRect,
TBool aHasAlpha )
{
if ( !aImage )
return;
TSize imageSize = aImage->SizeInPixels();
aImage->LockHeap();
VGImage vgImage = CreateVGImage( aImage->DataAddress(), imageSize, aImage->DisplayMode(), EFalse );
aImage->UnlockHeap();
// Transform to flip drawing to be like screen drawing (from Cartesian)
TGfxAffineTransform flipTransform = TGfxAffineTransform::GetScaleInstance( 1.0f, -1.0f );
// Shift x=0 line to top of screen (buffer)
flipTransform.Translate( TFloatFixPt ( 0 ), TFloatFixPt ( -iColorBufferSize.iHeight ) );
// Application transformations from element
flipTransform.Concatenate( iTransform );
// Set the topleft corner of image to draw
flipTransform.Translate( aImageRect.iX, aImageRect.iY );
// Caller to DrawImage already check for image size zero
float scaleX = (VGfloat)( TFloatFixPt ( aImageRect.iWidth ) / TFloatFixPt ( imageSize.iWidth ) );
float scaleY = (VGfloat)( TFloatFixPt ( aImageRect.iHeight ) / TFloatFixPt ( imageSize.iHeight ) );
// Scale to fit image to drawing area
flipTransform.Scale( scaleX, scaleY );
VGfloat matrix[] = { (VGfloat)flipTransform.iM00, (VGfloat)flipTransform.iM10, 0,
(VGfloat)flipTransform.iM01, (VGfloat)flipTransform.iM11, 0,
(VGfloat)flipTransform.iM02, (VGfloat)flipTransform.iM12, 1 };
iVgRenderer->vgSeti( VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE );
iVgRenderer->vgLoadMatrix( matrix );
// Get current blend-mode
const TInt KBlendMode = iVgRenderer->vgGeti( VG_BLEND_MODE );
iVgRenderer->vgSeti( VG_BLEND_MODE, aHasAlpha ? VG_BLEND_SRC_OVER : VG_BLEND_SRC );
/* Disable bilinear filtering -> faster, but lower rendering quality */
iVgRenderer->vgSeti( VG_IMAGE_QUALITY, VG_IMAGE_QUALITY_NONANTIALIASED );
iVgRenderer->vgDrawImage( vgImage );
iVgRenderer->vgSeti( VG_BLEND_MODE, KBlendMode );
iVgRenderer->vgDestroyImage( vgImage );
}
// ==========================================================================
// Clear the whole graphics context with the background color
// ==========================================================================
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::Clear(TUint32 aRGBA8888Color)
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::Clear(TUint32 aARGB )
{
TUint32 rgba = ( aARGB << 8 ) | ( aARGB >> 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 TFloatFixPt KInverse255 = TFloatFixPt ( 1.0f/256.0f );
const VGfloat clearColor[4] = { (VGfloat)(KInverse255 * TFloatFixPt (r)),
(VGfloat)(KInverse255 * TFloatFixPt (g)),
(VGfloat)(KInverse255 * TFloatFixPt (b)),
(VGfloat)(KInverse255 * TFloatFixPt (a)) };
iVgRenderer->vgSeti( VG_SCISSORING, VG_FALSE );
iVgRenderer->vgSetfv( VG_CLEAR_COLOR, 4, clearColor );
iVgRenderer->vgClear( 0, 0, iColorBufferSize.iWidth, iColorBufferSize.iHeight );
iVgRenderer->vgSeti( VG_SCISSORING, VG_TRUE );
}
// ==========================================================================
// This method copies the internal RGBA8888 framebuffer to CfbsBitmap that
// is specified in constructor. The CfbsBitmap could be 4k color (RGB0444),
// 64k color (RGB565), or 16M color (RGB888).
// ==========================================================================
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::UpdateFramebufferL()
// --------------------------------------------------------------------------
void CGfx2dGcOpenVG::UpdateFramebufferL( CFbsBitmap* aBitmap, CFbsBitmap* aMask)
{
if ( !aBitmap || aBitmap->SizeInPixels() != iColorBufferSize )
{
return;
}
const TDisplayMode KBitmapDisplayMode = aBitmap->DisplayMode();
// This check just before VGISymbianCopyToBitmap avoid putting lot
// many similar error checks in the code. If there is any problem
// during OpenVG call we simply leave without drawing any thing.
VGErrorCode vgret = (VGErrorCode)iVgRenderer->vgGetError();
if(vgret != VG_NO_ERROR )
{
User::LeaveIfError(OpenVGErrorToSymbianError(vgret));
}
// EGray2 is not support in VGISymbianCopyToBitmap API
if ( KBitmapDisplayMode == EGray2 )
{
const TInt KStride = CFbsBitmap::ScanLineLength( iColorBufferSize.iWidth, KBitmapDisplayMode );
aBitmap->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)aBitmap->DataAddress() + ( KStride * ( iColorBufferSize.iHeight - 1 ) ) );
iVgRenderer->vgReadPixels( data, -KStride, VG_BW_1, 0, 0,
iColorBufferSize.iWidth, iColorBufferSize.iHeight );
aBitmap->UnlockHeap();
if ( aMask )
{
GenerateMask( aMask );
}
}
// All other color modes
else
{
// No Mask -- to be generated in GenerateMask
TInt error=KErrNone;
//In cases, where the mask/aMaskBitmap != NULL, the hint should be defined as VGI_SKIP_TRANSPARENT_PIXELS.
//In all other cases, i.e., when mask/aMaskBitmap == NULL, the definition should be VGI_COPY_TRANSPARENT_PIXELS
error = iVgSurface->CopyBitmap(ENone,ENone, aBitmap, aMask, iColorBufferSize);
if ( error != KErrNone )
{
#ifdef _DEBUG
RDebug::Printf("VGISymbianCopyToBitmap failed: error code: %d", error );
RDebug::Printf(" - Color mode: %d", aBitmap->DisplayMode() );
RDebug::Printf(" - Bitmap size: %dx%d", iColorBufferSize.iWidth, iColorBufferSize.iHeight );
#endif
User::LeaveIfError(error);
}
// VGISymbianCopyToBitmap only generates Gray256 mask
if ( aMask && aMask->DisplayMode() == EGray2 )
{
GenerateMask( aMask );
}
}
}
//NGA
// ---------------------------------------------------------------------------------------------------------------------------------------
//void UpdateFramebufferL( CFbsBitmap* aBitmap, CFbsBitmap* aMask,TSize BitmapSize,TDisplayMode aBitmapDspMode,TDisplayMode aMaskDspMode )
// ---------------------------------------------------------------------------------------------------------------------------------------
void CGfx2dGcOpenVG::UpdateFramebufferL( CFbsBitmap* aBitmap, CFbsBitmap* aMask,TSize /*BitmapSize*/,TDisplayMode aBitmapDspMode,TDisplayMode aMaskDspMode )
{
if ( !aBitmap)
{
return;
}
const TDisplayMode KBitmapDisplayMode = aBitmap->DisplayMode();
// This check just before VGISymbianCopyToBitmap avoid putting lot
// many similar error checks in the code. If there is any problem
// during OpenVG call we simply leave without drawing any thing.
VGErrorCode vgret = (VGErrorCode)iVgRenderer->vgGetError();
if(vgret != VG_NO_ERROR )
{
User::LeaveIfError(OpenVGErrorToSymbianError(vgret));
}
// EGray2 is not support in VGISymbianCopyToBitmap API
if ( KBitmapDisplayMode == EGray2 )
{
const TInt KStride = CFbsBitmap::ScanLineLength( iColorBufferSize.iWidth, KBitmapDisplayMode );
aBitmap->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)aBitmap->DataAddress() + ( KStride * ( iColorBufferSize.iHeight - 1 ) ) );
iVgRenderer->vgReadPixels( data, -KStride, VG_BW_1, 0, 0,
iColorBufferSize.iWidth, iColorBufferSize.iHeight );
aBitmap->UnlockHeap();
if ( aMask )
{
GenerateMask( aMask );
}
}
// All other color modes
else
{
// No Mask -- to be generated in GenerateMask
TInt error=KErrNone;
//In cases, where the mask/aMaskBitmap != NULL, the hint should be defined as VGI_SKIP_TRANSPARENT_PIXELS.
//In all other cases, i.e., when mask/aMaskBitmap == NULL, the definition should be VGI_COPY_TRANSPARENT_PIXELS
error = iVgSurface->CopyBitmap(aBitmapDspMode, aMaskDspMode, aBitmap, aMask, iColorBufferSize);
if ( error != KErrNone )
{
#ifdef _DEBUG
RDebug::Printf("VGISymbianCopyToBitmap failed: error code: %d", error );
RDebug::Printf(" - Color mode: %d", aBitmap->DisplayMode() );
RDebug::Printf(" - Bitmap size: %dx%d", iColorBufferSize.iWidth, iColorBufferSize.iHeight );
#endif
User::LeaveIfError(error);
}
// VGISymbianCopyToBitmap only generates Gray256 mask
if ( aMask && aMask->DisplayMode() == EGray2 )
{
GenerateMask( aMask );
}
}
}
// ====================================================================================
// Blend bitmap with background according to group opacity
// This function gets called with the opacity framebuffer and the group opacity value
// The opacity buffer is initialized with the 0xAA55AA55 value. The pixels not matching
// the initialiazation value are the pixels that have to be blended with the background.
// ====================================================================================
// --------------------------------------------------------------------------
// void CGfx2dGcVGR::BlendWithBackground(TUint32* aFrameBuffer, TReal32 aOpacity)
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::BlendWithBackground(TUint32* /* aColorBuffer */, TReal32 /* aOpacity */)
{
/*
if ( !iColorBuffer || !aColorBuffer )
{
return;
}
TReal32 inverseAlpha = 1.0f - aOpacity;
const TInt KMax = iColorBufferSize.iWidth * iColorBufferSize.iHeight;
TUint32* dst = iColorBuffer;
TUint32* src = aColorBuffer;
for ( TInt i = KMax - 1; i >= 0; i-- )
{
TUint32 srcColor = src[i];
TUint32 dstColor = dst[i];
if ( srcColor != dstColor )
{
dst[i] = ((((TUint)((srcColor >> 24 ) * aOpacity) +
(TUint)((dstColor >> 24 ) * inverseAlpha))) << 24) | // red
((((TUint)((srcColor >> 16 & 0xff) * aOpacity) +
(TUint)((dstColor >> 16 & 0xff) * inverseAlpha))) << 16) | // green
((((TUint)((srcColor >> 8 & 0xff) * aOpacity) +
(TUint)((dstColor >> 8 & 0xff) * inverseAlpha))) << 8 ) | // blue
(srcColor & 0x000000FF); // keep orignal alpha
}
}
*/
}
// ==========================================================================
// Generate 8 bit gray or 1bit B/W mask from internal ARGB8888 frame buffer.
// ==========================================================================
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::GenerateMask(CFbsBitmap* aMask)
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::GenerateMask(CFbsBitmap* aMask)
{
if ( !aMask || aMask->SizeInPixels() != iColorBufferSize )
{
return;
}
const TDisplayMode KMaskDisplayMode = aMask->DisplayMode();
if ( KMaskDisplayMode != EGray256 && KMaskDisplayMode != EGray2 )
{
return;
}
const TInt KOriginalFilterMasks = iVgRenderer->vgGeti( VG_FILTER_CHANNEL_MASK );//
const TInt KStride = CFbsBitmap::ScanLineLength( iColorBufferSize.iWidth, KMaskDisplayMode );
// Change to get alpha values from OpenVG
iVgRenderer->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 * ( iColorBufferSize.iHeight - 1 ) ) );
iVgRenderer->vgReadPixels( data, -KStride, format, 0, 0,
iColorBufferSize.iWidth, iColorBufferSize.iHeight );
aMask->UnlockHeap();
// Set back the original filter-masks
iVgRenderer->vgSeti( VG_FILTER_CHANNEL_MASK, KOriginalFilterMasks );
}
// ==========================================================================
// This function calls the low level function to set fill opacity value
// ==========================================================================
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::SetFillOpacity(TFloatFixPt aFillOpacity)
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::SetFillOpacity(TFloatFixPt aFillOpacity)
{
iFillOpacity = aFillOpacity;
}
// ==========================================================================
// This function calls the low level function to set stroke opacity value
// ==========================================================================
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::SetStrokeOpacity(TFloatFixPt aStrokeOpacity)
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::SetStrokeOpacity(TFloatFixPt aStrokeOpacity)
{
iStrokeOpacity = aStrokeOpacity;
}
// ==========================================================================
// This function is called to set the dithering flag
// ==========================================================================
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::SetDoDithering( TBool aDoDithering )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::SetDoDithering( TBool /*aDoDithering*/ )
{
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::ApplyTransform
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::ApplyTransform( TGfxAffineTransform& aAffineTransform )
{
iVgRenderer->vgSeti( VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE );
TUint transformType = aAffineTransform.iTransType;
// Only translation is applied
if ( transformType == KTransformTranslate )
{
iVgRenderer->vgLoadIdentity();
iVgRenderer->vgScale( 1.0f, -1.0f );
iVgRenderer->vgTranslate( (VGfloat)aAffineTransform.iM02,
(VGfloat)(TFloatFixPt (-iColorBufferSize.iHeight) + aAffineTransform.iM12 ) );
}
// General case: Rotate and/or scaling, translation
else
{
TGfxAffineTransform flipTransform = TGfxAffineTransform::GetScaleInstance( 1.0f, -1.0f );
flipTransform.Translate( TFloatFixPt ( 0 ), TFloatFixPt ( -iColorBufferSize.iHeight ) );
flipTransform.Concatenate( aAffineTransform );
VGfloat matrix[] = { (VGfloat)flipTransform.iM00, (VGfloat)flipTransform.iM10, 0,
(VGfloat)flipTransform.iM01, (VGfloat)flipTransform.iM11, 0,
(VGfloat)flipTransform.iM02, (VGfloat)flipTransform.iM12, 1 };
iVgRenderer->vgLoadMatrix( matrix );
}
}
void CGfx2dGcOpenVG::ApplyTransformMediaElement( const TGfxAffineTransform& aAffineTransform,TSize& /*aSize*/ )
{
iVgRenderer->vgSeti( VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE );
// TUint transformType = aAffineTransform.iTransType;
// Only translation is applied
/* if ( transformType == KTransformTranslate )
{
vgLoadIdentity();
vgScale( 1.0f, -1.0f );
vgTranslate( (VGfloat)aAffineTransform.iM02,
(VGfloat)(TFloatFixPt (-iColorBufferSize.iHeight) + aAffineTransform.iM12 ) );
}
// General case: Rotate and/or scaling, translation
else
{
TGfxAffineTransform flipTransform = TGfxAffineTransform::GetScaleInstance( 1.0f, -1.0f );
flipTransform.Translate( TFloatFixPt ( 0 ), TFloatFixPt ( -iColorBufferSize.iHeight ) );
flipTransform.Concatenate( aAffineTransform );
VGfloat matrix[] = { (VGfloat)flipTransform.iM00, (VGfloat)flipTransform.iM10, 0,
(VGfloat)flipTransform.iM01, (VGfloat)flipTransform.iM11, 0,
(VGfloat)flipTransform.iM02, (VGfloat)flipTransform.iM12, 1 };
vgLoadMatrix( matrix );
}*/
TGfxAffineTransform flipTransform = TGfxAffineTransform::GetScaleInstance( 1.0f, -1.0f );
flipTransform.Translate( TFloatFixPt ( 0 ), TFloatFixPt ( -iColorBufferSize.iHeight ) );
//flipTransform.Concatenate( aAffineTransform );
TGfxAffineTransform flipTransformTemp = aAffineTransform;
flipTransformTemp.Concatenate( flipTransform );
flipTransform.Concatenate( flipTransformTemp );
VGfloat matrix[] = { (VGfloat)flipTransform.iM00, (VGfloat)flipTransform.iM10, 0,
(VGfloat)flipTransform.iM01, (VGfloat)flipTransform.iM11, 0,
(VGfloat)flipTransform.iM02, (VGfloat)flipTransform.iM12, 1 };
iVgRenderer->vgLoadMatrix( matrix );
}
VGImage CGfx2dGcOpenVG::CreateVGImage( void* aBuffer, TSize aSize, TDisplayMode aDisplayMode, TBool aPreMultiplied )
{
VGImage vgImage = VGImage( -1 );
if ( aBuffer )
{
VGint stride = CFbsBitmap::ScanLineLength( aSize.iWidth, aDisplayMode );
if ( aDisplayMode == EColor64K )
{
vgImage = iVgRenderer->vgCreateImage( VG_sRGB_565, aSize.iWidth, aSize.iHeight, VG_IMAGE_QUALITY_FASTER );
iVgRenderer->vgImageSubData( vgImage, aBuffer, stride, VG_sRGB_565,
0, 0, aSize.iWidth, aSize.iHeight );
}
else if ( aDisplayMode == EColor16MU )
{
VGImageFormat format = aPreMultiplied ? VG_sRGBA_8888_PRE :VG_sRGBA_8888;
vgImage = iVgRenderer->vgCreateImage( format, aSize.iWidth, aSize.iHeight, VG_IMAGE_QUALITY_FASTER );
iVgRenderer->vgImageSubData( vgImage, aBuffer, stride, format,
0, 0, aSize.iWidth, aSize.iHeight );
}
else
{
#ifdef _DEBUG
RDebug::Printf("SVGT CreateVGImage:: Color Mode not supported: %d ", aDisplayMode );
#endif
}
}
return vgImage;
}
void CGfx2dGcOpenVG::BindToImageL()
{
TUint32* buffer = NULL;
buffer = new (ELeave) TUint32[ iColorBufferSize.iWidth * iColorBufferSize.iHeight ] ;
iVgSurface->PrepareToBindClientBuffer();
VGImage vgImage = CreateVGImage( buffer, iColorBufferSize, EColor16MU, ETrue );
//Clear VGImage
VGfloat color[4] = { 1.0f, 1.0f, 1.0f, 0.0f };
iVgRenderer->vgSetfv(VG_CLEAR_COLOR, 4, color);
iVgRenderer->vgClearImage(vgImage,0,0,iColorBufferSize.iWidth,iColorBufferSize.iHeight);
//Clear VGImage
TInt error = iVgSurface->BindClientBuffer( vgImage );
if ( error != KErrNone )
{
#ifdef _DEBUG
RDebug::Printf("SVGT CGfx2dGcOpenVG::BindToImageL--VGISymbianBindToImageL failed: %d", error);
#endif
iVgRenderer->vgDestroyImage(vgImage) ;
// Delete color-buffer to match count with vgImage
delete[] buffer;
if( error == KErrNoMemory )
{
// Need to reset values at our side as OpenVG calls VGISymbianTerminate.
ResetContextHandle();
}
User::Leave(error);
}
iGroupOpacityBuffers.Append( buffer );
iGroupOpacityImages.Append( vgImage );
iVgRenderer->vgLoadIdentity();
}
void CGfx2dGcOpenVG::BindToMediaImageL(TInt aWidth, TInt aHeight)
{
TUint32* buffer = NULL;
buffer = new (ELeave) TUint32[ iColorBufferSize.iWidth * iColorBufferSize.iHeight ];
iVgSurface->PrepareToBindClientBuffer();
VGImage vgImage = CreateVGImage( buffer, iColorBufferSize, EColor16MU, ETrue );
VGfloat color[4] = { 1.0f, 1.0f, 1.0f, 0.0f };
iVgRenderer->vgSetfv(VG_CLEAR_COLOR, 4, color);
iVgRenderer->vgClearImage(vgImage,0,0,iColorBufferSize.iWidth,iColorBufferSize.iHeight);
//vgClearImage(vgImage,0,0,aWidth,aHeight);
TInt error = iVgSurface->BindClientBuffer( vgImage );
if ( error != KErrNone )
{
#ifdef _DEBUG
RDebug::Printf("SVGT CGfx2dGcOpenVG::BindToImage--VGISymbianBindToImage failed: %d", error);
#endif
iVgRenderer->vgDestroyImage(vgImage) ;
// Delete color-buffer to match count with vgImage
delete[] buffer;
if( error == KErrNoMemory )
{
// Need to reset values at our side as OpenVG calls VGISymbianTerminate.
ResetContextHandle();
}
User::Leave(error);
}
iGroupOpacityBuffers.Append( buffer );
iGroupOpacityImages.Append( vgImage );
iVgRenderer->vgLoadIdentity();
TGfxRectangle2D aClip(0,0,aWidth,aHeight);
iClipMain = iClip;
SetClip(aClip);
}
void CGfx2dGcOpenVG::UnbindFromImageL( TReal32 aOpacity )
{
if ( iGroupOpacityImages.Count() == 0 )
{
return;
}
TInt error = iVgSurface->UnBindClientBuffer();
if ( error != KErrNone )
{
#ifdef _DEBUG
RDebug::Printf("SVGT CGfx2dGcOpenVG::UnbindFromImage--VGISymbianUnBindImage failed: %d", error);
#endif
if( error == KErrNoMemory )
{
// Need to reset values at our side as OpenVG calls VGITerminate.
ResetContextHandle();
}
User::LeaveIfError(error);
}
// Need to bind to previous level image
// Else VGISymbianUnBindImage binds to non-image
if ( iGroupOpacityImages.Count() > 1 )
{
iVgSurface->PrepareToBindClientBuffer();
TInt error = iVgSurface->BindClientBuffer( iGroupOpacityImages[iGroupOpacityImages.Count()-2] );
if ( error != KErrNone )
{
#ifdef _DEBUG
RDebug::Printf("SVGT CGfx2dGcOpenVG::UnbindFromImage--VGISymbianBindToImage failed: %d", error);
#endif
iVgSurface->UnBindClientBuffer();
// Remove and Destroy all the previous images and buffer
TInt iIndex = iGroupOpacityImages.Count()-1;
for( ;iIndex >= 0 ; iIndex-- )
{
iVgRenderer->vgDestroyImage( iGroupOpacityImages[ iIndex ] );
iGroupOpacityImages.Remove( iIndex );
}
iIndex = iGroupOpacityBuffers.Count()-1;
for( ;iIndex >= 0 ; iIndex-- )
{
delete [] iGroupOpacityBuffers[ iIndex ];
iGroupOpacityBuffers.Remove( iIndex );
}
if( error == KErrNoMemory )
{
// Need to reset values at our side as OpenVG calls VGISymbianTerminate.
ResetContextHandle();
}
User::LeaveIfError(error);
}
}
// Check if default fill paint needs to be created
if ( iFillPaint == VG_INVALID_HANDLE )
{
iFillPaint = iVgRenderer->vgCreatePaint();
}
// Check if default stroke paint needs to be created
if ( iStrokePaint == VG_INVALID_HANDLE )
{
iStrokePaint = iVgRenderer->vgCreatePaint();
}
VGfloat opaquePaint[] = { 1.0f, 1.0f, 1.0f, aOpacity };
// Create paint object
VGPaint paint = iVgRenderer->vgCreatePaint();
if ( paint != VG_INVALID_HANDLE )
{
// Set solid paint of opacity
iVgRenderer->vgSetParameteri( paint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
iVgRenderer->vgSetParameterfv( paint, VG_PAINT_COLOR, 4, opaquePaint);
iVgRenderer->vgSetPaint( paint, VG_FILL_PATH | VG_STROKE_PATH );
// Set image mode to multiply
iVgRenderer->vgSeti( VG_IMAGE_MODE, VG_DRAW_IMAGE_MULTIPLY );
// Draw opacity image
iVgRenderer->vgSeti( VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE );
iVgRenderer->vgLoadIdentity();
iVgRenderer->vgDrawImage( iGroupOpacityImages[iGroupOpacityImages.Count()-1] );
// Reset the image draw mode
iVgRenderer->vgSeti( VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL );
// Restore the fill and paint
if ( iFillPaint != VG_INVALID_HANDLE )
{
iVgRenderer->vgSetPaint( iFillPaint, VG_FILL_PATH );
}
if ( iStrokePaint != VG_INVALID_HANDLE )
{
iVgRenderer->vgSetPaint( iStrokePaint, VG_STROKE_PATH );
}
iVgRenderer->vgDestroyPaint( paint );
}
else
{
VGErrorCode error = (VGErrorCode)iVgRenderer->vgGetError();
if (error == VG_OUT_OF_MEMORY_ERROR)
{
RDebug::Printf("SVGT CGfx2dGcOpenVG::UnbindFromImage vgCreatePaint OOM");
// Remove and Destroy all the previous images and buffer
TInt iIndex = iGroupOpacityImages.Count()-1;
for( ;iIndex >= 0 ; iIndex-- )
{
iVgRenderer->vgDestroyImage( iGroupOpacityImages[ iIndex ] );
iGroupOpacityImages.Remove( iIndex );
}
iIndex = iGroupOpacityBuffers.Count()-1;
for( ;iIndex >= 0 ; iIndex-- )
{
delete [] iGroupOpacityBuffers[ iIndex ];
iGroupOpacityBuffers.Remove( iIndex );
}
ResetContextHandle();
User::Leave(KErrNoMemory);
}
#ifdef _DEBUG
RDebug::Printf("SVGT CGfx2dGcOpenVG::UnbindFromImage vgCreatePaint failed");
#endif
}
// Remove/Delete OpenVG Image object
TInt imageIndex = iGroupOpacityImages.Count() - 1;
if ( imageIndex >= 0 )
{
iVgRenderer->vgDestroyImage( iGroupOpacityImages[ imageIndex ] );
iGroupOpacityImages.Remove( imageIndex );
}
// Remove/Delete color-buffer
TInt bufferIndex = iGroupOpacityBuffers.Count() - 1;
if ( bufferIndex >= 0 )
{
delete [] iGroupOpacityBuffers[ bufferIndex ];
iGroupOpacityBuffers.Remove( bufferIndex );
}
}
// --------------------------------------------------------------------------
// void CGfx2dGcOpenVG::UnbindFromMediaImageL(
// const TGfxAffineTransform& aAffineTransform,
// TReal32 aOpacity,
// TInt aWidth,
// TInt aHeight )
// ---------------------------------------------------------------------------
void CGfx2dGcOpenVG::UnbindFromMediaImageL(
const TGfxAffineTransform& aAffineTransform,
TReal32 aOpacity,
TInt aWidth,
TInt aHeight, TInt aDraw )
{
if ( iGroupOpacityImages.Count() == 0 )
{
return;
}
TInt error = iVgSurface->UnBindClientBuffer();
if ( error != KErrNone )
{
#ifdef _DEBUG
RDebug::Printf( "SVGT CGfx2dGcOpenVG::UnbindFromMediaImage--VGISymbianUnBindImage failed: %d", error);
#endif
if( error == KErrNoMemory )
{
// Need to reset values at our side as OpenVG calls
// VGITerminate.
ResetContextHandle();
}
User::LeaveIfError(error);
}
// Restore the clipping window back to main window
SetClip(iClipMain);
// Need to bind to previous level image
// Else VGISymbianUnBindImage binds to non-image
if ( iGroupOpacityImages.Count() > 1 )
{
iVgSurface->PrepareToBindClientBuffer();
TInt error = iVgSurface->BindClientBuffer( iGroupOpacityImages[iGroupOpacityImages.Count()-2] );
if ( error != KErrNone )
{
#ifdef _DEBUG
RDebug::Printf("SVGT CGfx2dGcOpenVG::UnbindFromMediaImage--VGISymbianBindToImage failed: %d", error);
#endif
iVgSurface->UnBindClientBuffer();
// Remove and Destroy all the previous images and buffer
TInt iIndex = iGroupOpacityImages.Count()-1;
for( ;iIndex >= 0 ; iIndex-- )
{
iVgRenderer->vgDestroyImage( iGroupOpacityImages[ iIndex ] );
iGroupOpacityImages.Remove( iIndex );
}
iIndex = iGroupOpacityBuffers.Count()-1;
for( ;iIndex >= 0 ; iIndex-- )
{
delete [] iGroupOpacityBuffers[ iIndex ];
iGroupOpacityBuffers.Remove( iIndex );
}
// Destroy the Previous two Opacity buffer
if( error == KErrNoMemory )
{
// Need to reset values at our side as OpenVG calls VGISymbianTerminate.
ResetContextHandle();
}
User::LeaveIfError(error);
}
}
// Create opaque paint
VGfloat opaquePaint[] = { 1.0f, 1.0f, 1.0f, aOpacity };
// Check if default fill paint needs to be created
if ( iFillPaint == VG_INVALID_HANDLE )
{
iFillPaint = iVgRenderer->vgCreatePaint();
}
// Check if default stroke paint needs to be created
if ( iStrokePaint == VG_INVALID_HANDLE )
{
iStrokePaint = iVgRenderer->vgCreatePaint();
}
// Create paint object
VGPaint paint = iVgRenderer->vgCreatePaint();
if ( paint != VG_INVALID_HANDLE )
{
// Set solid paint of opacity
iVgRenderer->vgSetParameteri( paint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
iVgRenderer->vgSetParameterfv( paint, VG_PAINT_COLOR, 4, opaquePaint);
iVgRenderer->vgSetPaint( paint, VG_FILL_PATH | VG_STROKE_PATH );
// Set image mode to normal
iVgRenderer->vgSeti( VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL );
// Draw the animation element with transforms applied on the
// main colour buffer
TSize size(aWidth,aHeight);
ApplyTransformMediaElement(aAffineTransform,size);
// Check so that animation element is drawn only when animation has started
if ( aDraw == KMediaAnimationVisible )
{
iVgRenderer->vgDrawImage( iGroupOpacityImages[iGroupOpacityImages.Count()-1] );
}
// Restore the fill and paint
if ( iFillPaint != VG_INVALID_HANDLE )
{
iVgRenderer->vgSetPaint( iFillPaint, VG_FILL_PATH );
}
if ( iStrokePaint != VG_INVALID_HANDLE )
{
iVgRenderer->vgSetPaint( iStrokePaint, VG_STROKE_PATH );
}
iVgRenderer->vgDestroyPaint( paint );
}
else
{
VGErrorCode error = (VGErrorCode)iVgRenderer->vgGetError();
if (error == VG_OUT_OF_MEMORY_ERROR)
{
RDebug::Printf("SVGT CGfx2dGcOpenVG::UnbindFromMediaImage vgCreatePaint OOM");
// Remove and Destroy all the previous images and buffer
TInt iIndex = iGroupOpacityImages.Count()-1;
for( ;iIndex >= 0 ; iIndex-- )
{
iVgRenderer->vgDestroyImage( iGroupOpacityImages[ iIndex ] );
iGroupOpacityImages.Remove( iIndex );
}
iIndex = iGroupOpacityBuffers.Count()-1;
for( ;iIndex >= 0 ; iIndex-- )
{
delete [] iGroupOpacityBuffers[ iIndex ];
iGroupOpacityBuffers.Remove( iIndex );
}
ResetContextHandle();
User::Leave(KErrNoMemory);
}
#ifdef _DEBUG
RDebug::Printf("SVGT CGfx2dGcOpenVG::UnbindFromMediaImage vgCreatePaint failed");
#endif
}
// Remove/Delete OpenVG Image object
TInt imageIndex = iGroupOpacityImages.Count() - 1;
if ( imageIndex >= 0 )
{
iVgRenderer->vgDestroyImage( iGroupOpacityImages[ imageIndex ] );
iGroupOpacityImages.Remove( imageIndex );
}
// Remove/Delete color-buffer
TInt bufferIndex = iGroupOpacityBuffers.Count() - 1;
if ( bufferIndex >= 0 )
{
delete [] iGroupOpacityBuffers[ bufferIndex ];
iGroupOpacityBuffers.Remove( bufferIndex );
}
}
// These are for work-around for OpenVG to simulate multiple contexts
void CGfx2dGcOpenVG::SetupContextL()
{
// Ensure OpenVG is initialized: could have been terminated by another Svg engine
// Returns immediately if already initialized
TInt err = iVgSurface->InitializeSurface( iColorBufferSize, VGI_COLORSPACE_SRGB );//NGA --- testing purpose//srikanth
if (!((err == KErrNone) || (err == KErrAlreadyExists)))
{
#ifdef _DEBUG
RDebug::Printf("SVG can't initialize OpenVG Context %d", err);
#endif
iGraphicsContextCreated = EFalse;
User::Leave(err);
}
iGraphicsContextCreated = ETrue;
// Ensure context size is correct: could have been change by another Svg engine
// Returns immediately if size is the same
err = iVgSurface->ResizeSurface( iColorBufferSize );
if( err != KErrNone )
{
if(err == KErrNoMemory )
{
#ifdef _DEBUG
RDebug::Printf("OpenVG Context destroyed %d", err);
#endif //_DEBUG
// This indicates that OpenVG has destroyed the current context handle
// and also the Path, StrokePaint and FillPaint handles are no more valid.
// Thus reinitialize them to 0, so that they can be recreated.
ResetContextHandle();
}
#ifdef _DEBUG
RDebug::Printf("SVG can't RESIZE OpenVG Context %d", err);
#endif //_DEBUG
User::Leave(err);
}
}
void CGfx2dGcOpenVG::Flush()
{
if (iCurrentRendererType == ESVGRendererTLV)
{
iPath = VG_INVALID_HANDLE;
iFillPaint = VG_INVALID_HANDLE;
iStrokePaint = VG_INVALID_HANDLE;
}
iVgRenderer->vgFlush();
}
/**
* Sets the Paint,Stroke and Path handle back to VG_INVALID_HANDLE
*
* @since
* @return void
*/
void CGfx2dGcOpenVG::ResetContextHandle()
{
iPath = VG_INVALID_HANDLE;
iFillPaint = VG_INVALID_HANDLE;
iStrokePaint = VG_INVALID_HANDLE;
iGraphicsContextCreated = EFalse;
}
void CGfx2dGcOpenVG::GetMatrix(TReal32 * m)
{
//Below is the replacement for vgGetMatrix
TGfxAffineTransform flipTransform;
if ( iTransform.iTransType == KTransformTranslate )
{
flipTransform = TGfxAffineTransform::GetScaleInstance( 1.0f, -1.0f );//get and identity matrix and scale the x,y axis to (1,-1)
flipTransform.Translate((VGfloat)iTransform.iM02, (VGfloat)(TFloatFixPt (-iColorBufferSize.iHeight) + iTransform.iM12 ) );
m[0] = (VGfloat)flipTransform.iM00;
m[1] = (VGfloat)flipTransform.iM10;
m[2] = 0;
m[3] = (VGfloat)flipTransform.iM01;
m[4] = (VGfloat)flipTransform.iM11;
m[5] = 0;
m[6] = (VGfloat)flipTransform.iM02;
m[7] = (VGfloat)flipTransform.iM12;
m[8] = 1;
}
// General case: Rotate and/or scaling, translation
else
{
flipTransform = TGfxAffineTransform::GetScaleInstance( 1.0f, -1.0f );
flipTransform.Translate( TFloatFixPt ( 0 ), TFloatFixPt ( -iColorBufferSize.iHeight ) );
flipTransform.Concatenate( iTransform );
m[0] = (VGfloat)flipTransform.iM00;
m[1] = (VGfloat)flipTransform.iM10;
m[2] = 0;
m[3] = (VGfloat)flipTransform.iM01;
m[4] = (VGfloat)flipTransform.iM11;
m[5] = 0;
m[6] = (VGfloat)flipTransform.iM02;
m[7] = (VGfloat)flipTransform.iM12;
m[8] = 1;
}
}
void CGfx2dGcOpenVG::SetBitmapHeader(const TDesC* aHeaderData)
{
iVgSurface->SetConfiguration(CVGSurface::BTIMAP_HEADER, aHeaderData);
}
const TPtrC8 CGfx2dGcOpenVG::TLVEncodedData() const
{
return(iVgRenderer->TLVEncodedData());
}