os/graphics/graphicsdeviceinterface/directgdiadaptation/hwsrc/vgengine.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// Unless stated otherwise, all co-ordinates are recorded and calculated using 
sl@0
    15
// Symbian graphics format: origin at top left of image, 'y' increasing towards bottom
sl@0
    16
// of image. Note that OpenVG places the origin at an image's bottom left corner, with
sl@0
    17
// 'y' increasing towards the top of the image. 
sl@0
    18
// 
sl@0
    19
//
sl@0
    20
sl@0
    21
#include "vgengine.h"
sl@0
    22
#include "directgdiadapter.h"
sl@0
    23
#include "directgdidriverimpl.h"
sl@0
    24
#include "directgdiimagetargetimpl.h"
sl@0
    25
#include "directgdiimagesourceimpl.h"
sl@0
    26
#include "confighelper.h"
sl@0
    27
#include <graphics/directgdiimagetarget.h>
sl@0
    28
#include <graphics/directgdidrawablesource.h>
sl@0
    29
#include <fbs.h>
sl@0
    30
#include <e32cmn.h>
sl@0
    31
#include <e32math.h>
sl@0
    32
#include <s32strm.h>
sl@0
    33
#include <pixelformats.h>
sl@0
    34
#include <bitdraworigin.h>
sl@0
    35
#include <bitdrawinterfaceid.h>
sl@0
    36
sl@0
    37
#include "blendingalgorithms.inl"
sl@0
    38
sl@0
    39
/**
sl@0
    40
Pre-calculation for normalising a 0-255 colour channel to 0..1.
sl@0
    41
*/
sl@0
    42
const VGfloat KColorConversion = 1.0f/255.0f;
sl@0
    43
sl@0
    44
sl@0
    45
inline TInt Scale(TInt aValue,TInt aNum,TInt aDen)
sl@0
    46
	{
sl@0
    47
	if (aNum==aDen)
sl@0
    48
		return aValue;
sl@0
    49
	TInt64 result(aValue);
sl@0
    50
	result=(result*aNum+(aDen/2))/aDen;
sl@0
    51
	return I64INT(result);
sl@0
    52
	}
sl@0
    53
sl@0
    54
/**
sl@0
    55
Maps TDisplayMode onto a supported VGImageFormat. Only compatible formats are returned,
sl@0
    56
anything else results in VG_IMAGE_FORMAT_INVALID being returned.
sl@0
    57
sl@0
    58
@param 	aDisplayMode Mode to convert from.
sl@0
    59
sl@0
    60
@return The VGImageFormat which matches the specified TDisplayMode pixel format exactly.
sl@0
    61
		If no exact match exists, then VG_IMAGE_FORMAT_INVALID is returned.
sl@0
    62
 */
sl@0
    63
static VGImageFormat MapToVgDisplayMode(TDisplayMode aDisplayMode)
sl@0
    64
	{
sl@0
    65
	switch(aDisplayMode)
sl@0
    66
		{
sl@0
    67
	case ENone:
sl@0
    68
		return VG_IMAGE_FORMAT_INVALID;
sl@0
    69
	case EGray2:
sl@0
    70
		return VG_BW_1;
sl@0
    71
	case EGray4: 
sl@0
    72
	case EGray16:
sl@0
    73
		return VG_IMAGE_FORMAT_INVALID;
sl@0
    74
	case EGray256:
sl@0
    75
		return VG_sL_8;
sl@0
    76
	case EColor16:
sl@0
    77
	case EColor256:
sl@0
    78
	case EColor4K:
sl@0
    79
		return VG_IMAGE_FORMAT_INVALID;
sl@0
    80
	case EColor64K:
sl@0
    81
		return VG_sRGB_565;
sl@0
    82
	case EColor16M:
sl@0
    83
	case ERgb:
sl@0
    84
		return VG_IMAGE_FORMAT_INVALID;
sl@0
    85
	case EColor16MU:
sl@0
    86
		return VG_sXRGB_8888;
sl@0
    87
	case EColor16MA:
sl@0
    88
		return VG_sARGB_8888;
sl@0
    89
	case EColor16MAP:
sl@0
    90
		return VG_sARGB_8888_PRE;
sl@0
    91
	case EColorLast:
sl@0
    92
		return VG_IMAGE_FORMAT_INVALID;
sl@0
    93
		}
sl@0
    94
	
sl@0
    95
	return VG_IMAGE_FORMAT_INVALID;
sl@0
    96
	}
sl@0
    97
sl@0
    98
/**
sl@0
    99
Destructor
sl@0
   100
 */
sl@0
   101
CVgEngine::~CVgEngine()
sl@0
   102
	{
sl@0
   103
	iRegionManager.Close();
sl@0
   104
	
sl@0
   105
	if (iBrushPatternUser != VG_INVALID_HANDLE)	
sl@0
   106
		vgDestroyImage(iBrushPatternUser);		
sl@0
   107
		
sl@0
   108
	if (iBrushPatternStandard != VG_INVALID_HANDLE)
sl@0
   109
		vgDestroyImage(iBrushPatternStandard);		
sl@0
   110
	
sl@0
   111
	if (iBrushPatternStandardRegion != VG_INVALID_HANDLE)
sl@0
   112
		vgDestroyImage(iBrushPatternStandardRegion);		
sl@0
   113
	
sl@0
   114
	if (iBrushPatternNonZeroOrigin != VG_INVALID_HANDLE)
sl@0
   115
		vgDestroyImage(iBrushPatternNonZeroOrigin);	
sl@0
   116
	
sl@0
   117
	User::Free(iPathCommands);	
sl@0
   118
	User::Free(iPathCoords);
sl@0
   119
	
sl@0
   120
	Deactivate();
sl@0
   121
	}
sl@0
   122
sl@0
   123
/**
sl@0
   124
Constructor
sl@0
   125
 */
sl@0
   126
CVgEngine::CVgEngine(CDirectGdiDriverImpl& aDriver)
sl@0
   127
	:iDriver(aDriver),
sl@0
   128
	iPen(VG_INVALID_HANDLE),
sl@0
   129
	iBrush(VG_INVALID_HANDLE),
sl@0
   130
	iClearBrush(VG_INVALID_HANDLE),
sl@0
   131
	iVgPath(VG_INVALID_HANDLE),
sl@0
   132
	iTextBrush(VG_INVALID_HANDLE),
sl@0
   133
	iBrushPatternUser(VG_INVALID_HANDLE),
sl@0
   134
	iBrushPatternStandard(VG_INVALID_HANDLE),
sl@0
   135
	iBrushPatternStandardRegion(VG_INVALID_HANDLE),
sl@0
   136
	iBrushPatternNonZeroOrigin(VG_INVALID_HANDLE)
sl@0
   137
	{		
sl@0
   138
	// Set the default paint mode for drawing and filling shapes to
sl@0
   139
	// just draw the pen and not the brush as default (to match BitGdi)
sl@0
   140
	iPaintMode = VG_STROKE_PATH;
sl@0
   141
	
sl@0
   142
	//cache interface to use every time glyph gets drawn
sl@0
   143
	GetInterface(TUid::Uid(KDirectGdiGetGlyphStorageUid), (TAny*&) iFontGlyphImageStorage);
sl@0
   144
	}
sl@0
   145
sl@0
   146
/**
sl@0
   147
Applies the engine's state to OpenVG, re-applying all the VgEngine settings. It is called by 
sl@0
   148
Activate() as well as when the engine is being made current. 
sl@0
   149
*/
sl@0
   150
void CVgEngine::SetVgState()
sl@0
   151
	{
sl@0
   152
	ResetVgMatrix();
sl@0
   153
	vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_NONANTIALIASED);
sl@0
   154
	vgSeti(VG_IMAGE_QUALITY, VG_IMAGE_QUALITY_NONANTIALIASED);
sl@0
   155
	vgSeti(VG_STROKE_CAP_STYLE, VG_CAP_ROUND);
sl@0
   156
	vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_ROUND);
sl@0
   157
	vgSetPaint(iPen, VG_STROKE_PATH);
sl@0
   158
	vgSetPaint(iBrush, VG_FILL_PATH);
sl@0
   159
	SetDrawMode(iDrawMode); 
sl@0
   160
	SetPenColor(iPenColor);
sl@0
   161
	SetPenStyle(iPenStyle);
sl@0
   162
	SetPenSize(iPenSize);
sl@0
   163
	SetBrushColor(iBrushColor);
sl@0
   164
	SetBrushStyle(iBrushStyle);
sl@0
   165
	SetBrushOrigin(iBrushOrigin);
sl@0
   166
	vgSetParameteri(iClearBrush, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
sl@0
   167
	vgSetParameteri(iTextBrush, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
sl@0
   168
	}
sl@0
   169
sl@0
   170
/**
sl@0
   171
Binds a rendering target to this OpenVG rendering engine.
sl@0
   172
Activates the target, which increments the reference count of target as it can be shared across many 
sl@0
   173
DirectGDI contexts.
sl@0
   174
sl@0
   175
The rendering target, for this implementation, specifies an Embedded OpenVG rendering surface.
sl@0
   176
sl@0
   177
@see MDirectGdiEngine::Activate()
sl@0
   178
@see Deactivate()
sl@0
   179
sl@0
   180
@panic DGDIAdapter 34, if the passed target has a NULL handle.
sl@0
   181
@panic DGDIAdapter 39, if target associated with the handle is NULL.
sl@0
   182
 */
sl@0
   183
TInt CVgEngine::Activate(RDirectGdiImageTarget& aTarget)
sl@0
   184
	{
sl@0
   185
	TInt result = KErrNone;
sl@0
   186
	GRAPHICS_ASSERT_ALWAYS(aTarget.Handle(), EDirectGdiPanicActivateWithNullHandle);
sl@0
   187
	CDirectGdiImageTargetImpl* target = iDriver.GetImageTargetFromHandle(aTarget.Handle());
sl@0
   188
	GRAPHICS_ASSERT_ALWAYS(target, EDirectGdiPanicNullTargetActivate);
sl@0
   189
	if (target == iRenderingTarget)
sl@0
   190
		{
sl@0
   191
		return KErrNone;
sl@0
   192
		}
sl@0
   193
	
sl@0
   194
	Deactivate();	
sl@0
   195
	
sl@0
   196
	iDriver.Activate(target);
sl@0
   197
	iRenderingTarget = target;
sl@0
   198
	iDriver.SetCurrentEngine(this);
sl@0
   199
	iDriver.SetCurrentTarget(target);
sl@0
   200
	iSize = iRenderingTarget->Size();
sl@0
   201
	iTargetRegion.Clear();
sl@0
   202
	iTargetRegion.AddRect(iSize);
sl@0
   203
sl@0
   204
	iRegionManager.Initialize(vgGeti(VG_MAX_SCISSOR_RECTS), iSize);
sl@0
   205
	
sl@0
   206
	// Set the origin to top-left for path and image rendering. iIdentityMatrix is set so that we have a
sl@0
   207
	// record of the "identity" transform. After modifying the transform for offsets, rotations, etc, etc
sl@0
   208
	// just set to iIdentityMatrix to get back to "normal".
sl@0
   209
	//
sl@0
   210
	vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
sl@0
   211
	vgLoadIdentity();
sl@0
   212
	vgScale(1, -1);
sl@0
   213
	vgTranslate(0,  -iSize.iHeight);
sl@0
   214
	vgGetMatrix(iIdentityMatrix);
sl@0
   215
	// Set the origin to top-left for image matrix.
sl@0
   216
	vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
sl@0
   217
	vgLoadMatrix(iIdentityMatrix);
sl@0
   218
	
sl@0
   219
	// Create the path.
sl@0
   220
	if (!PreparePath(iVgPath, 1) || (iVgPath == VG_INVALID_HANDLE))
sl@0
   221
		result = KErrNoMemory;
sl@0
   222
sl@0
   223
	// Create the pen object and set it as the object for stroking (OpenVG equivalent of a pen).
sl@0
   224
	if (result == KErrNone)
sl@0
   225
		{
sl@0
   226
		iPen = vgCreatePaint();
sl@0
   227
		if (iPen != VG_INVALID_HANDLE)
sl@0
   228
			vgSetPaint(iPen, VG_STROKE_PATH);
sl@0
   229
		else
sl@0
   230
			result = KErrNoMemory;
sl@0
   231
		}
sl@0
   232
sl@0
   233
	if (result == KErrNone)
sl@0
   234
		{		
sl@0
   235
		// Create the brush object
sl@0
   236
		// This only need to be done the first time the context is activated
sl@0
   237
		iBrush = vgCreatePaint();
sl@0
   238
		if (iBrush != VG_INVALID_HANDLE)
sl@0
   239
			vgSetPaint(iBrush, VG_FILL_PATH);
sl@0
   240
		else
sl@0
   241
			result = KErrNoMemory;
sl@0
   242
		}
sl@0
   243
	
sl@0
   244
	if (result == KErrNone)
sl@0
   245
		{
sl@0
   246
		// Create the brush object for Clear operations.
sl@0
   247
		// This only need to be done the first time the context is activated
sl@0
   248
		iClearBrush = vgCreatePaint();
sl@0
   249
		if (iClearBrush == VG_INVALID_HANDLE)
sl@0
   250
			{
sl@0
   251
			result = KErrNoMemory;
sl@0
   252
			}
sl@0
   253
		}
sl@0
   254
	
sl@0
   255
	if (result == KErrNone)
sl@0
   256
		{
sl@0
   257
		iTextBrush = vgCreatePaint();
sl@0
   258
		if (iTextBrush == VG_INVALID_HANDLE)
sl@0
   259
			{
sl@0
   260
			result = KErrNoMemory;
sl@0
   261
			}
sl@0
   262
		}
sl@0
   263
	
sl@0
   264
	if (result == KErrNone)
sl@0
   265
		{
sl@0
   266
		result = iDriver.PreAllocateFontGlyphImages();
sl@0
   267
		}
sl@0
   268
sl@0
   269
	if (result == KErrNone)
sl@0
   270
		{
sl@0
   271
		SetVgState();
sl@0
   272
		}
sl@0
   273
sl@0
   274
	return result;
sl@0
   275
	}
sl@0
   276
sl@0
   277
/**
sl@0
   278
@see MDirectGdiEngine::Deactivate()
sl@0
   279
@see Activate()
sl@0
   280
 */
sl@0
   281
void CVgEngine::Deactivate()
sl@0
   282
	{
sl@0
   283
	if (iPen != VG_INVALID_HANDLE)
sl@0
   284
		{
sl@0
   285
		vgDestroyPaint(iPen);
sl@0
   286
		}
sl@0
   287
	if (iBrush != VG_INVALID_HANDLE)
sl@0
   288
		{
sl@0
   289
		vgDestroyPaint(iBrush);		
sl@0
   290
		}
sl@0
   291
	if (iClearBrush != VG_INVALID_HANDLE)
sl@0
   292
		{
sl@0
   293
		vgDestroyPaint(iClearBrush);		
sl@0
   294
		}
sl@0
   295
	if (iTextBrush != VG_INVALID_HANDLE)
sl@0
   296
		{
sl@0
   297
		vgDestroyPaint(iTextBrush);		
sl@0
   298
		}
sl@0
   299
	if (iVgPath != VG_INVALID_HANDLE)
sl@0
   300
		{
sl@0
   301
		vgDestroyPath(iVgPath);
sl@0
   302
		}
sl@0
   303
	iPen = VG_INVALID_HANDLE;
sl@0
   304
	iBrush = VG_INVALID_HANDLE;
sl@0
   305
	iClearBrush = VG_INVALID_HANDLE;
sl@0
   306
	iVgPath = VG_INVALID_HANDLE;
sl@0
   307
	iTextBrush = VG_INVALID_HANDLE;
sl@0
   308
	
sl@0
   309
	if (iRenderingTarget)
sl@0
   310
		{
sl@0
   311
		// Deactivating the render target could potentially unbind the current EGL context
sl@0
   312
		// which would make the above vgDestroy() calls do nothing, therefore call Deactivate() last.
sl@0
   313
		iDriver.Deactivate(iRenderingTarget);
sl@0
   314
		}
sl@0
   315
	}
sl@0
   316
sl@0
   317
/**
sl@0
   318
Checks whether the engine and target are current. If current, then nothing is done, else all the OpenVG settings 
sl@0
   319
and EGL context are reapplied. This function is called in every drawing function to ensure that the engine and 
sl@0
   320
target are current.
sl@0
   321
sl@0
   322
If this function returns EFalse, it means any subsequent setting of OpenVG state may be invalid 
sl@0
   323
and should be avoided as it is setting a null EGL context.
sl@0
   324
sl@0
   325
@pre	None.
sl@0
   326
@post	Applies the current state to OpenVG and is made the active EGL context, if the engine or target is 
sl@0
   327
        not current.
sl@0
   328
@return ETrue if as a result of calling this function, the underlying OpenVG context is now current. This
sl@0
   329
        effectively means whether we have a target or not. EFalse is returned otherwise.
sl@0
   330
*/
sl@0
   331
TBool CVgEngine::MakeEngineCurrent()
sl@0
   332
	{
sl@0
   333
	TBool vgCurrent = iRenderingTarget!=NULL;
sl@0
   334
	if(!iDriver.IsCurrentEngine(this) || !iDriver.IsCurrentTarget(iRenderingTarget))
sl@0
   335
		{
sl@0
   336
		iDriver.SetCurrentEngine(this);
sl@0
   337
		iDriver.SetCurrentTarget(iRenderingTarget);
sl@0
   338
		// Must reactivate the target (i.e. make it current to EGL) before resetting the OpenVG parameters.
sl@0
   339
		if (iRenderingTarget)
sl@0
   340
			{
sl@0
   341
			iDriver.Reactivate(iRenderingTarget);
sl@0
   342
			SetVgState();
sl@0
   343
			}
sl@0
   344
		else
sl@0
   345
			vgCurrent = EFalse;
sl@0
   346
		}
sl@0
   347
	
sl@0
   348
	return vgCurrent;
sl@0
   349
	}
sl@0
   350
sl@0
   351
/**
sl@0
   352
@see MDirectGdiEngine::SetOrigin()
sl@0
   353
 */
sl@0
   354
void CVgEngine::SetOrigin(const TPoint& aOrigin)
sl@0
   355
	{
sl@0
   356
	iOrigin = aOrigin + iDrawOrigin;
sl@0
   357
	
sl@0
   358
	if (!MakeEngineCurrent())
sl@0
   359
		return;
sl@0
   360
sl@0
   361
	ResetVgMatrix();
sl@0
   362
	}
sl@0
   363
sl@0
   364
/** 
sl@0
   365
@see MDrawDeviceOrigin::Set()
sl@0
   366
*/
sl@0
   367
TInt CVgEngine::Set(const TPoint& aDrawOrigin)
sl@0
   368
	{
sl@0
   369
	TPoint moveOrigin=aDrawOrigin;
sl@0
   370
 	moveOrigin-=iDrawOrigin;
sl@0
   371
 	iOrigin+=moveOrigin;
sl@0
   372
 	
sl@0
   373
 	//offset clipping region
sl@0
   374
 	TInt result = KErrNone;
sl@0
   375
 	RRegion clippingRegion;
sl@0
   376
 	clippingRegion.Copy(iRegionManager.ClippingRegion());
sl@0
   377
 	if(!clippingRegion.CheckError())
sl@0
   378
 		{
sl@0
   379
 		clippingRegion.Offset(moveOrigin);
sl@0
   380
 		result = iRegionManager.SetClippingRegion(clippingRegion);
sl@0
   381
 		}
sl@0
   382
 	else
sl@0
   383
 		{
sl@0
   384
 		result = KErrNoMemory;
sl@0
   385
 		}
sl@0
   386
 	
sl@0
   387
 	if(result != KErrNone)
sl@0
   388
 		{
sl@0
   389
 		iDriver.SetError(result);
sl@0
   390
 		}
sl@0
   391
 	
sl@0
   392
 	clippingRegion.Close();
sl@0
   393
 	
sl@0
   394
 	iDrawOrigin = aDrawOrigin;
sl@0
   395
 	return result;
sl@0
   396
 	}
sl@0
   397
 
sl@0
   398
/** 
sl@0
   399
@see MDrawDeviceOrigin::Get()
sl@0
   400
*/
sl@0
   401
void CVgEngine::Get(TPoint& aDrawOrigin)
sl@0
   402
 	{
sl@0
   403
 	aDrawOrigin=iDrawOrigin;
sl@0
   404
   	}
sl@0
   405
sl@0
   406
/**
sl@0
   407
@see MDirectGdiEngine::SetClippingRegion(const TRegion&)
sl@0
   408
*/
sl@0
   409
void CVgEngine::SetClippingRegion(const TRegion& aRegion)
sl@0
   410
	{
sl@0
   411
	TInt result = KErrNone;
sl@0
   412
	TRect boundingRect=iTargetRegion.BoundingRect();
sl@0
   413
	boundingRect.iTl-=iDrawOrigin;
sl@0
   414
	boundingRect.iBr-=iDrawOrigin;
sl@0
   415
	if (!aRegion.IsContainedBy(boundingRect))
sl@0
   416
		{
sl@0
   417
		result = KErrArgument;
sl@0
   418
		}
sl@0
   419
	else
sl@0
   420
		{
sl@0
   421
		RRegion clippingRegion;
sl@0
   422
		clippingRegion.Copy(aRegion);
sl@0
   423
		if(!clippingRegion.CheckError())
sl@0
   424
			{
sl@0
   425
			clippingRegion.Offset(iDrawOrigin);
sl@0
   426
			result = iRegionManager.SetClippingRegion (clippingRegion);
sl@0
   427
			}
sl@0
   428
		else
sl@0
   429
			{
sl@0
   430
			result = KErrNoMemory;
sl@0
   431
			}
sl@0
   432
		clippingRegion.Close();
sl@0
   433
		}
sl@0
   434
	
sl@0
   435
	if (result != KErrNone)
sl@0
   436
		{
sl@0
   437
		iDriver.SetError(result);
sl@0
   438
		}
sl@0
   439
	}
sl@0
   440
sl@0
   441
/**
sl@0
   442
@see MDirectGdiEngine::ResetClippingRegion()
sl@0
   443
*/
sl@0
   444
void CVgEngine::ResetClippingRegion()
sl@0
   445
	{
sl@0
   446
	iRegionManager.Reset();
sl@0
   447
	
sl@0
   448
	if (!MakeEngineCurrent())
sl@0
   449
		return;
sl@0
   450
		
sl@0
   451
	vgSeti(VG_SCISSORING, VG_FALSE);
sl@0
   452
	}
sl@0
   453
sl@0
   454
/**
sl@0
   455
@see MDirectGdiEngine::SetDrawMode()
sl@0
   456
sl@0
   457
The generic layer has already checked whether the draw mode is already aMode.
sl@0
   458
Draw mode is referred to as "blend" mode in OpenVG.
sl@0
   459
Note that only EDrawModePEN and EDrawModeWriteAlpha style blending are supported by OpenVG.
sl@0
   460
The default OpenVG blend mode is VG_BLEND_SRC_OVER.
sl@0
   461
 */
sl@0
   462
void CVgEngine::SetDrawMode(DirectGdi::TDrawMode aMode)
sl@0
   463
	{
sl@0
   464
	iDrawMode = aMode;
sl@0
   465
	
sl@0
   466
	if (!MakeEngineCurrent())
sl@0
   467
		return;
sl@0
   468
sl@0
   469
	// Invalid modes are filtered out in the generic layer.
sl@0
   470
	if (aMode == DirectGdi::EDrawModePEN)
sl@0
   471
		{
sl@0
   472
		// Blend the destination with the source using the source alpha for blending if 
sl@0
   473
		// alpha is available.		
sl@0
   474
		vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER);
sl@0
   475
		}
sl@0
   476
	else // DirectGdi::EDrawModeWriteAlpha
sl@0
   477
		{
sl@0
   478
		// Destination colors and alpha are overwritten with source colors and alpha.						
sl@0
   479
		vgSeti(VG_BLEND_MODE, VG_BLEND_SRC);											
sl@0
   480
		}
sl@0
   481
	}
sl@0
   482
sl@0
   483
/**
sl@0
   484
@see MDirectGdiEngine::SetPenColor()
sl@0
   485
*/
sl@0
   486
void CVgEngine::SetPenColor(const TRgb& aColor)
sl@0
   487
	{
sl@0
   488
	iPenColor = aColor;
sl@0
   489
	
sl@0
   490
	if (!MakeEngineCurrent())
sl@0
   491
		return;
sl@0
   492
sl@0
   493
	// Make sure our pen is the current selected pen for stroking before we set the color	
sl@0
   494
	vgSetPaint(iPen, VG_STROKE_PATH);	
sl@0
   495
	
sl@0
   496
	// Set the color
sl@0
   497
	vgSetParameteri(iPen, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
sl@0
   498
	SetVgPaintColor(iPen, iPenColor);	
sl@0
   499
	SetVgPaintColor(iTextBrush, iPenColor);
sl@0
   500
	}
sl@0
   501
sl@0
   502
/**
sl@0
   503
Set the current pen style for drawing lines. This corresponds to setting the "stroke dash" pattern in OpenVG.
sl@0
   504
sl@0
   505
@see MDirectGdiEngine::SetPenStyle()
sl@0
   506
 */
sl@0
   507
void CVgEngine::SetPenStyle(DirectGdi::TPenStyle aStyle)
sl@0
   508
	{
sl@0
   509
	iPenStyle = aStyle;
sl@0
   510
	
sl@0
   511
	if (!MakeEngineCurrent())
sl@0
   512
		return;
sl@0
   513
	
sl@0
   514
	iPaintMode = iPaintMode | VG_STROKE_PATH;		
sl@0
   515
	
sl@0
   516
	switch (aStyle)
sl@0
   517
		{
sl@0
   518
		case DirectGdi::ENullPen:
sl@0
   519
			{
sl@0
   520
			iPaintMode = iPaintMode & (~VG_STROKE_PATH); // Unset stroke bit
sl@0
   521
			vgSetfv(VG_STROKE_DASH_PATTERN, 0, NULL);
sl@0
   522
			vgSetf(VG_STROKE_DASH_PHASE, 0.f);
sl@0
   523
			break;
sl@0
   524
			}
sl@0
   525
			
sl@0
   526
		case DirectGdi::ESolidPen:
sl@0
   527
			{
sl@0
   528
			vgSetfv(VG_STROKE_DASH_PATTERN, 0, NULL);	
sl@0
   529
			vgSetf(VG_STROKE_DASH_PHASE, 0.f);
sl@0
   530
			break;
sl@0
   531
			}
sl@0
   532
			
sl@0
   533
		case DirectGdi::EDottedPen:
sl@0
   534
			{
sl@0
   535
			VGfloat offset = (iPenSize.iWidth > 1) ? 2.f : 0.f;			
sl@0
   536
			VGfloat dashPattern[2] = {(1*iPenSize.iWidth)-offset, (3*iPenSize.iWidth)+offset};
sl@0
   537
			vgSetfv(VG_STROKE_DASH_PATTERN, 2, dashPattern);
sl@0
   538
			vgSetf(VG_STROKE_DASH_PHASE, 1.f);
sl@0
   539
			break;
sl@0
   540
			}
sl@0
   541
			
sl@0
   542
		case DirectGdi::EDashedPen:
sl@0
   543
			{
sl@0
   544
			VGfloat offset = (iPenSize.iWidth > 1) ? 2.f : 0.f;			
sl@0
   545
			VGfloat dashPattern[2] = {(3*iPenSize.iWidth)-offset, (3*iPenSize.iWidth)+offset};
sl@0
   546
			vgSetfv(VG_STROKE_DASH_PATTERN, 2, dashPattern);
sl@0
   547
			vgSetf(VG_STROKE_DASH_PHASE, (iPenSize.iWidth != 1) ? 1.f : 0.f);
sl@0
   548
			break;
sl@0
   549
			}
sl@0
   550
			
sl@0
   551
		case DirectGdi::EDotDashPen:
sl@0
   552
			{
sl@0
   553
			VGfloat offset = (iPenSize.iWidth > 1) ? 2.f : 0.f;			
sl@0
   554
			VGfloat dashPattern[4] = {(1*iPenSize.iWidth)-offset, (3*iPenSize.iWidth)+offset, (3*iPenSize.iWidth)-offset, (3*iPenSize.iWidth)+offset};
sl@0
   555
			vgSetfv(VG_STROKE_DASH_PATTERN, 4, dashPattern);
sl@0
   556
			vgSetf(VG_STROKE_DASH_PHASE, 1.f);
sl@0
   557
			break;
sl@0
   558
			}
sl@0
   559
			
sl@0
   560
		case DirectGdi::EDotDotDashPen:
sl@0
   561
			{
sl@0
   562
			VGfloat offset = (iPenSize.iWidth > 1) ? 2.f : 0.f;			
sl@0
   563
			VGfloat dashPattern[6] = {(1*iPenSize.iWidth)-offset, (3*iPenSize.iWidth)+offset, (1*iPenSize.iWidth)-offset, (3*iPenSize.iWidth)+offset, (3*iPenSize.iWidth)-offset, (3*iPenSize.iWidth)+offset};
sl@0
   564
			vgSetfv(VG_STROKE_DASH_PATTERN, 6, dashPattern);
sl@0
   565
			vgSetf(VG_STROKE_DASH_PHASE, (iPenSize.iWidth != 1) ? 1.f : 0.f);
sl@0
   566
			break;			
sl@0
   567
			}
sl@0
   568
			
sl@0
   569
		default:
sl@0
   570
			{
sl@0
   571
			// Copy BitGdi behaviour here and draw a solid line for any unknown pen style
sl@0
   572
			vgSetfv(VG_STROKE_DASH_PATTERN, 0, NULL);
sl@0
   573
			vgSetf(VG_STROKE_DASH_PHASE, 0.f);
sl@0
   574
			break;		
sl@0
   575
			}
sl@0
   576
		}
sl@0
   577
	}
sl@0
   578
sl@0
   579
sl@0
   580
/**
sl@0
   581
@see MDirectGdiEngine::SetPenSize()
sl@0
   582
 */
sl@0
   583
void CVgEngine::SetPenSize(const TSize& aSize)
sl@0
   584
	{
sl@0
   585
	iPenSize = aSize;
sl@0
   586
	
sl@0
   587
	if (!MakeEngineCurrent())
sl@0
   588
		return;
sl@0
   589
sl@0
   590
	// VG_STROKE_LINE_WIDTH expects a float	
sl@0
   591
	// Note that we set the pen size using just the width in the assumption that the pen width
sl@0
   592
	// and height are normally the same. For the special cases where the pen width and height
sl@0
   593
	// are different, the pen size is set to (1,1) then scaled to give the effect of a pen with 
sl@0
   594
	// different width and height. This is done for all functions in this file that draws shapes,  
sl@0
   595
	// see Plot(), DrawLine(), DrawArc(), DrawRect() etc.
sl@0
   596
	vgSetf(VG_STROKE_LINE_WIDTH, aSize.iWidth);	
sl@0
   597
		
sl@0
   598
	// Re-set the pen style as the pen size has changed, SetPenStyle() uses the pen size to set 
sl@0
   599
	// the dotted line styles.
sl@0
   600
	SetPenStyle(iPenStyle);
sl@0
   601
	}
sl@0
   602
sl@0
   603
/**
sl@0
   604
@see MDirectGdiEngine::SetTextShadowColor()
sl@0
   605
*/
sl@0
   606
void CVgEngine::SetTextShadowColor(const TRgb& aColor)
sl@0
   607
	{
sl@0
   608
	iTextShadowColor = aColor; //just cache this color
sl@0
   609
	}
sl@0
   610
sl@0
   611
sl@0
   612
/**
sl@0
   613
@see MDirectGdiEngine::SetBrushColor()
sl@0
   614
*/
sl@0
   615
void CVgEngine::SetBrushColor(const TRgb& aColor)
sl@0
   616
	{
sl@0
   617
	iBrushColor = aColor;
sl@0
   618
	
sl@0
   619
	if (!MakeEngineCurrent())
sl@0
   620
		return;
sl@0
   621
	
sl@0
   622
	// Convert the color components as that they are between 0.0f and 1.0f
sl@0
   623
	VGfloat color[4];	
sl@0
   624
	color[0] = aColor.Red() * KColorConversion;
sl@0
   625
	color[1] = aColor.Green() * KColorConversion;
sl@0
   626
	color[2] = aColor.Blue() * KColorConversion;
sl@0
   627
	color[3] = aColor.Alpha() * KColorConversion;
sl@0
   628
sl@0
   629
	// Make sure our brush is the current selected brush for filling before we set the color
sl@0
   630
	if (iBrushStyle != DirectGdi::ENullBrush)
sl@0
   631
		vgSetPaint(iBrush, VG_FILL_PATH);	
sl@0
   632
	
sl@0
   633
	vgSetParameteri(iBrush, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
sl@0
   634
	vgSetParameterfv(iBrush, VG_PAINT_COLOR, 4, color);
sl@0
   635
	
sl@0
   636
	// Set the clear color and the tile fill color as well as these should both
sl@0
   637
	// be the same as the brush color
sl@0
   638
	vgSetParameterfv(iClearBrush, VG_PAINT_COLOR, 4, color);
sl@0
   639
	vgSetfv(VG_CLEAR_COLOR, 4, color);
sl@0
   640
	vgSetfv(VG_TILE_FILL_COLOR, 4, color);
sl@0
   641
	
sl@0
   642
	// If using a patterned brush, need to reconstruct it as the colours may be out of sync.
sl@0
   643
	if ((iBrushStyle != DirectGdi::ENullBrush) && (iBrushStyle != DirectGdi::ESolidBrush))
sl@0
   644
		{
sl@0
   645
		SetBrushStyle(iBrushStyle);
sl@0
   646
		}	
sl@0
   647
	}
sl@0
   648
sl@0
   649
sl@0
   650
/**
sl@0
   651
The DirectGDI brush styles do not map directly to OpenVG, so brushes for styles > DirectGdi::EPatternedBrush
sl@0
   652
are created as bitmaps before being set.
sl@0
   653
sl@0
   654
@see MDirectGdiEngine::SetBrushColor()
sl@0
   655
@see CreateStandardBrush()
sl@0
   656
*/
sl@0
   657
void CVgEngine::SetBrushStyle(DirectGdi::TBrushStyle aStyle) 
sl@0
   658
	{	
sl@0
   659
	iBrushStyle = aStyle;
sl@0
   660
	
sl@0
   661
	if (!MakeEngineCurrent())
sl@0
   662
		return;
sl@0
   663
	
sl@0
   664
	TInt standardBrushErr = KErrNone;
sl@0
   665
	const TInt standardBrushSize = 3;
sl@0
   666
	const TInt standardBrushArea = standardBrushSize*standardBrushSize;
sl@0
   667
	const TInt diamondCrossHatchBrushSize = 4;
sl@0
   668
	const TInt diamondCrossHatchBrushArea = diamondCrossHatchBrushSize*diamondCrossHatchBrushSize;
sl@0
   669
	
sl@0
   670
	// Select the brush for drawing any style that is not ENullBrush
sl@0
   671
	iPaintMode = iPaintMode | VG_FILL_PATH;
sl@0
   672
	if (aStyle != DirectGdi::ENullBrush)
sl@0
   673
		vgSetPaint(iBrush, VG_FILL_PATH);
sl@0
   674
sl@0
   675
	// Paint using a pattern for all styles that are not ENullBrush or ESolidBrush
sl@0
   676
	if ((aStyle != DirectGdi::ENullBrush) && (aStyle != DirectGdi::ESolidBrush))
sl@0
   677
		{		
sl@0
   678
		vgSetParameteri(iBrush, VG_PAINT_TYPE, VG_PAINT_TYPE_PATTERN);
sl@0
   679
		vgSetParameteri(iBrush, VG_PAINT_PATTERN_TILING_MODE, VG_TILE_REPEAT);
sl@0
   680
		}	
sl@0
   681
sl@0
   682
	switch (aStyle)
sl@0
   683
		{
sl@0
   684
		case DirectGdi::ENullBrush:					
sl@0
   685
			iPaintMode = iPaintMode & (~VG_FILL_PATH);
sl@0
   686
			
sl@0
   687
			// Clear the current brush so that no brush color is drawn
sl@0
   688
			vgSetPaint(VG_INVALID_HANDLE, VG_FILL_PATH);
sl@0
   689
			break;			
sl@0
   690
sl@0
   691
		case DirectGdi::ESolidBrush:			
sl@0
   692
			// Paint using a solid color
sl@0
   693
			vgSetParameteri(iBrush, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
sl@0
   694
			break;			
sl@0
   695
sl@0
   696
		case DirectGdi::EPatternedBrush:						
sl@0
   697
			// Make sure the user has set a patterned brush for use
sl@0
   698
			GRAPHICS_ASSERT_ALWAYS(iBrushPatternUser != VG_INVALID_HANDLE, EDirectGdiPanicPatternedBrushNotSet);						
sl@0
   699
			
sl@0
   700
			if (NonZeroBrushPatternOrigin())
sl@0
   701
				{
sl@0
   702
				// The brush origin is non-zero, update the non-zero origin brush 
sl@0
   703
				// with the user brush and use that instead of the user brush
sl@0
   704
				CopyCurrentBrushPatternForNonZeroOrigin();										
sl@0
   705
				}
sl@0
   706
			else
sl@0
   707
				{
sl@0
   708
				// Set the brush to fill with the user selected bitmap pattern
sl@0
   709
				vgPaintPattern(iBrush, iBrushPatternUser);
sl@0
   710
				}
sl@0
   711
			break;			
sl@0
   712
sl@0
   713
		case DirectGdi::EVerticalHatchBrush:
sl@0
   714
			{
sl@0
   715
			// The brush fills with vertical hatching  lines going from top to bottom
sl@0
   716
			TSize size(standardBrushSize, standardBrushSize);
sl@0
   717
			VGbyte brushPattern[standardBrushArea] = {0,0,1, 0,0,1, 0,0,1};
sl@0
   718
			standardBrushErr = CreateStandardBrush(size, brushPattern);
sl@0
   719
			break;
sl@0
   720
			}
sl@0
   721
		
sl@0
   722
		case DirectGdi::EForwardDiagonalHatchBrush:
sl@0
   723
			{
sl@0
   724
			// The brush fills with diagonal hatching lines going from bottom left to top right
sl@0
   725
			TSize size(standardBrushSize, standardBrushSize);
sl@0
   726
			VGbyte brushPattern[standardBrushArea] = {1,0,0, 0,0,1, 0,1,0};
sl@0
   727
			standardBrushErr = CreateStandardBrush(size, brushPattern);
sl@0
   728
			break;
sl@0
   729
			}
sl@0
   730
		
sl@0
   731
		case DirectGdi::EHorizontalHatchBrush:
sl@0
   732
			{
sl@0
   733
			// The brush fills with horizontal hatching lines going from left to right
sl@0
   734
			TSize size(standardBrushSize, standardBrushSize);
sl@0
   735
			VGbyte brushPattern[standardBrushArea] = {0,0,0, 0,0,0, 1,1,1};
sl@0
   736
			standardBrushErr = CreateStandardBrush(size, brushPattern);
sl@0
   737
			break;
sl@0
   738
			}
sl@0
   739
		
sl@0
   740
		case DirectGdi::ERearwardDiagonalHatchBrush:
sl@0
   741
			{
sl@0
   742
			// The brush fills with rearward diagonal hatching lines going from top left to bottom right
sl@0
   743
			TSize size(standardBrushSize, standardBrushSize);
sl@0
   744
			VGbyte brushPattern[standardBrushArea] = {1,0,0, 0,1,0, 0,0,1};
sl@0
   745
			standardBrushErr = CreateStandardBrush(size, brushPattern);
sl@0
   746
			break;
sl@0
   747
			}
sl@0
   748
		
sl@0
   749
		case DirectGdi::ESquareCrossHatchBrush:
sl@0
   750
			{
sl@0
   751
			// The brush fills with horizontal and vertical hatching lines going from left to right 
sl@0
   752
			// plus lines going from top to bottom  giving the effect of a grid of small squares
sl@0
   753
			TSize size(standardBrushSize, standardBrushSize);
sl@0
   754
			VGbyte brushPattern[standardBrushArea] = {0,0,1, 0,0,1, 1,1,1};
sl@0
   755
			standardBrushErr = CreateStandardBrush(size, brushPattern);
sl@0
   756
			break;
sl@0
   757
			}
sl@0
   758
		
sl@0
   759
		case DirectGdi::EDiamondCrossHatchBrush:
sl@0
   760
			{
sl@0
   761
			// The brush fills with forward diagonal and rearward diagonal hatching lines going from  
sl@0
   762
			// bottom left to top right plus lines going from top left to bottom right giving the effect  
sl@0
   763
			// of a grid of small diamonds
sl@0
   764
			// The brush fills with diagonal hatching lines going from bottom left to top right
sl@0
   765
			TSize size(diamondCrossHatchBrushSize, diamondCrossHatchBrushSize);
sl@0
   766
			VGbyte brushPattern[diamondCrossHatchBrushArea] = {0,0,1,0, 0,1,0,1, 1,0,0,0, 0,1,0,1};
sl@0
   767
			standardBrushErr = CreateStandardBrush(size, brushPattern);
sl@0
   768
			break;	
sl@0
   769
			}		
sl@0
   770
		}
sl@0
   771
	
sl@0
   772
	// Select the standard brush for all styles > EPatternedBrush
sl@0
   773
	if (aStyle > DirectGdi::EPatternedBrush)
sl@0
   774
		{
sl@0
   775
		if (standardBrushErr == KErrNone)
sl@0
   776
			{
sl@0
   777
			if (NonZeroBrushPatternOrigin())
sl@0
   778
				{
sl@0
   779
				// The brush origin is non-zero, update the non-zero origin brush 
sl@0
   780
				// with the standard brush and use that instead of the standard brush
sl@0
   781
				CopyCurrentBrushPatternForNonZeroOrigin();
sl@0
   782
				}
sl@0
   783
			else
sl@0
   784
				{
sl@0
   785
				// Use the standard brush region
sl@0
   786
				vgPaintPattern(iBrush, iBrushPatternStandardRegion);
sl@0
   787
				}
sl@0
   788
			}
sl@0
   789
		else
sl@0
   790
			{
sl@0
   791
			iDriver.SetError(standardBrushErr);
sl@0
   792
			}
sl@0
   793
		}
sl@0
   794
	else
sl@0
   795
		{
sl@0
   796
		vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL);
sl@0
   797
		}
sl@0
   798
	}
sl@0
   799
sl@0
   800
/**
sl@0
   801
@see MDirectGdiEngine::SetBrushOrigin()
sl@0
   802
 */
sl@0
   803
void CVgEngine::SetBrushOrigin(const TPoint& aOrigin) 
sl@0
   804
	{
sl@0
   805
	iBrushOrigin = aOrigin;
sl@0
   806
	if (NonZeroBrushPatternOrigin())
sl@0
   807
		{
sl@0
   808
		// Copy the current brush pattern into iBrushPatternNonZeroOrigin, but shift it to
sl@0
   809
		// take into account the current non-zero brush origin.
sl@0
   810
		CopyCurrentBrushPatternForNonZeroOrigin();		
sl@0
   811
		}
sl@0
   812
	}
sl@0
   813
sl@0
   814
sl@0
   815
/**
sl@0
   816
@see MDirectGdiEngine::SetBrushPattern()
sl@0
   817
 */
sl@0
   818
TInt CVgEngine::SetBrushPattern(const CFbsBitmap& aPattern) 
sl@0
   819
	{
sl@0
   820
	if (aPattern.ExtendedBitmapType() != KNullUid)
sl@0
   821
		{
sl@0
   822
		return KErrNotSupported; // Not supported for extended bitmaps
sl@0
   823
		}
sl@0
   824
	
sl@0
   825
	// Destroy any previously set brush pattern
sl@0
   826
	MakeEngineCurrent();
sl@0
   827
	ResetBrushPattern();	
sl@0
   828
	iBrushPatternUser = CreateSourceVGImage(aPattern);
sl@0
   829
	if (iBrushPatternUser == VG_INVALID_HANDLE)
sl@0
   830
		{
sl@0
   831
		return KErrNoMemory;
sl@0
   832
		}
sl@0
   833
sl@0
   834
	iBrushPatternUserSize = aPattern.SizeInPixels();
sl@0
   835
	iBrushPatternUserBitmapHandle = aPattern.Handle();
sl@0
   836
	return KErrNone;
sl@0
   837
	}
sl@0
   838
sl@0
   839
sl@0
   840
/**
sl@0
   841
@see MDirectGdiEngine::ResetBrushPattern()
sl@0
   842
 */
sl@0
   843
void CVgEngine::ResetBrushPattern() 
sl@0
   844
	{
sl@0
   845
	MakeEngineCurrent();
sl@0
   846
	if (iBrushPatternUser != VG_INVALID_HANDLE)
sl@0
   847
		{
sl@0
   848
		vgDestroyImage(iBrushPatternUser);
sl@0
   849
		iBrushPatternUser = VG_INVALID_HANDLE;
sl@0
   850
		iBrushPatternUserBitmapHandle = KNullHandle;
sl@0
   851
		iBrushPatternUserSize = TSize(0,0);
sl@0
   852
		}	
sl@0
   853
	}
sl@0
   854
sl@0
   855
/**
sl@0
   856
@see MDirectGdiEngine::SetFont()
sl@0
   857
*/
sl@0
   858
void CVgEngine::SetFont(TUint32 aFontId) 
sl@0
   859
	{
sl@0
   860
	iFontId = aFontId;
sl@0
   861
	}
sl@0
   862
sl@0
   863
sl@0
   864
/**
sl@0
   865
@see MDirectGdiEngine::ResetFont()
sl@0
   866
 */
sl@0
   867
void CVgEngine::ResetFont() 
sl@0
   868
	{
sl@0
   869
	iFontId = 0;
sl@0
   870
	}
sl@0
   871
sl@0
   872
/**
sl@0
   873
Reset all the VgEngine-specific settings. Generic settings such as paint colour and pen colour
sl@0
   874
are set by calls from the CDirectGdiContext.
sl@0
   875
	
sl@0
   876
@see MDirectGdiEngine::Reset()
sl@0
   877
sl@0
   878
@post All VgEngine-specific settings have been reset to their default values.
sl@0
   879
 */
sl@0
   880
void CVgEngine::Reset() 
sl@0
   881
	{
sl@0
   882
	if (!MakeEngineCurrent())
sl@0
   883
		return;
sl@0
   884
sl@0
   885
	ResetVgMatrix();
sl@0
   886
	}
sl@0
   887
sl@0
   888
sl@0
   889
sl@0
   890
/**
sl@0
   891
@see MDirectGdiEngine::Clear(const TRect&)
sl@0
   892
sl@0
   893
@panic DGDIAdapter 62, if the brush for clearing is not valid (debug-only).
sl@0
   894
*/
sl@0
   895
void CVgEngine::Clear(const TRect& aRect) 
sl@0
   896
	{
sl@0
   897
	MakeEngineCurrent();
sl@0
   898
sl@0
   899
	if (255 == iBrushColor.Alpha())
sl@0
   900
		{
sl@0
   901
		const TPoint rectOrigin = ConvertToVgCoords(aRect);
sl@0
   902
		for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
   903
			vgClear(rectOrigin.iX, rectOrigin.iY, aRect.Width(), aRect.Height());
sl@0
   904
		}
sl@0
   905
	else
sl@0
   906
		{
sl@0
   907
		// If blending is enabled, we cannot use vgClear as it ignores the current blendmode and performs a WriteAlpha.
sl@0
   908
		// Therefore a clear is done by a filled rectangle.
sl@0
   909
		
sl@0
   910
		// The Clear brush should always be a solid brush.
sl@0
   911
		GRAPHICS_ASSERT_DEBUG(vgGetParameteri(iClearBrush, VG_PAINT_TYPE) == VG_PAINT_TYPE_COLOR, EDirectGdiPanicClearBrushInvalid);
sl@0
   912
				
sl@0
   913
		if (PreparePath(iVgPath, 5))
sl@0
   914
			{
sl@0
   915
			// Before any vgu command, call SetError() as this stores the current OpenVG error state (if any) 
sl@0
   916
			// on the driver. Some implementations of vgu clears error state so we'd lose error codes otherwise.
sl@0
   917
			iDriver.SetError(KErrNone);
sl@0
   918
			
sl@0
   919
			VGUErrorCode err = vguRect(iVgPath, aRect.iTl.iX, aRect.iTl.iY, aRect.Width(), aRect.Height());
sl@0
   920
			if (err == VGU_NO_ERROR)
sl@0
   921
				{
sl@0
   922
				// Temporarily set the brush to the clear brush and fill the path.
sl@0
   923
				vgSetPaint(iClearBrush, VG_FILL_PATH);
sl@0
   924
				for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
   925
					vgDrawPath(iVgPath, VG_FILL_PATH);
sl@0
   926
				vgSetPaint(iBrush, VG_FILL_PATH);	
sl@0
   927
				}
sl@0
   928
			else
sl@0
   929
				{
sl@0
   930
				SetVguError(err);
sl@0
   931
				}
sl@0
   932
			}
sl@0
   933
		}
sl@0
   934
	}
sl@0
   935
sl@0
   936
/**
sl@0
   937
@see MDirectGdiEngine::Clear()
sl@0
   938
 */
sl@0
   939
void CVgEngine::Clear() 
sl@0
   940
	{
sl@0
   941
	Clear(TRect(iSize));
sl@0
   942
	}
sl@0
   943
sl@0
   944
/**
sl@0
   945
@see MDirectGdiEngine::MoveTo()
sl@0
   946
 */
sl@0
   947
void CVgEngine::MoveTo(const TPoint& aPoint) 
sl@0
   948
	{
sl@0
   949
	iLinePos = aPoint;
sl@0
   950
	}
sl@0
   951
sl@0
   952
/**
sl@0
   953
@see MDirectGdiEngine::MoveBy()
sl@0
   954
 */
sl@0
   955
void CVgEngine::MoveBy(const TPoint& aVector) 
sl@0
   956
	{
sl@0
   957
	iLinePos += aVector;
sl@0
   958
	}
sl@0
   959
sl@0
   960
/**
sl@0
   961
@see MDirectGdiEngine::Plot()
sl@0
   962
 */
sl@0
   963
void CVgEngine::Plot(const TPoint& aPoint) 
sl@0
   964
	{
sl@0
   965
	MakeEngineCurrent();
sl@0
   966
	GRAPHICS_ASSERT_DEBUG(vgGeti(VG_STROKE_CAP_STYLE) == VG_CAP_ROUND,  EDirectGdiPanicPenEndCapStyleNotRound);
sl@0
   967
sl@0
   968
	
sl@0
   969
	// If the pen width and height are equal just plot as normal. 
sl@0
   970
	if (iPenSize.iWidth == iPenSize.iHeight)
sl@0
   971
		{
sl@0
   972
		if (PreparePath(iVgPath, 2))
sl@0
   973
			{
sl@0
   974
			// A point is plotted by drawing a line with start and end points the same.
sl@0
   975
			AppendPathCommand(VG_MOVE_TO_ABS, aPoint.iX + 0.5f, aPoint.iY + 0.5f);
sl@0
   976
			AppendPathCommand(VG_HLINE_TO_REL, 0.f);
sl@0
   977
			FinishPath(iVgPath);
sl@0
   978
			
sl@0
   979
			for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
   980
				vgDrawPath(iVgPath, iPaintMode&VG_STROKE_PATH);
sl@0
   981
			}
sl@0
   982
		}
sl@0
   983
	else if ((iPenSize.iWidth != 0) && (iPenSize.iHeight != 0))
sl@0
   984
		{
sl@0
   985
		// Setting a pen with different width and height is not available on OpenVG, so we need to scale 
sl@0
   986
		// the coordinates we are drawing and apply a scaling matrix that scales by the width and height 
sl@0
   987
		// of the pen to get the effect of a pen width different width and height.
sl@0
   988
		if (PreparePath(iVgPath, 2))
sl@0
   989
			{
sl@0
   990
			TSize penSize = iPenSize;
sl@0
   991
			SetPenSize(TSize(1, 1));
sl@0
   992
			vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
sl@0
   993
			vgScale(penSize.iWidth, penSize.iHeight);
sl@0
   994
			
sl@0
   995
			// A point is plotted by drawing a line with start and end points the same.
sl@0
   996
			AppendPathCommand(VG_MOVE_TO_ABS, (aPoint.iX + 0.5f)/(float)penSize.iWidth, (aPoint.iY + 0.5f)/(float)penSize.iHeight);
sl@0
   997
			AppendPathCommand(VG_HLINE_TO_REL, 0.f);
sl@0
   998
			FinishPath(iVgPath);
sl@0
   999
			
sl@0
  1000
			vgDrawPath(iVgPath, iPaintMode&VG_STROKE_PATH);
sl@0
  1001
			
sl@0
  1002
			ResetVgMatrix(VG_MATRIX_PATH_USER_TO_SURFACE);
sl@0
  1003
			SetPenSize(penSize);
sl@0
  1004
			}								
sl@0
  1005
		}	
sl@0
  1006
	}
sl@0
  1007
sl@0
  1008
/**
sl@0
  1009
@see MDirectGdiEngine::DrawLine()
sl@0
  1010
 */
sl@0
  1011
void CVgEngine::DrawLine(const TPoint& aStart, const TPoint& aEnd)
sl@0
  1012
	{
sl@0
  1013
	MakeEngineCurrent();
sl@0
  1014
	GRAPHICS_ASSERT_DEBUG(vgGeti(VG_STROKE_CAP_STYLE) == VG_CAP_ROUND, EDirectGdiPanicPenEndCapStyleNotRound);
sl@0
  1015
	
sl@0
  1016
    if (iPaintMode == 0)
sl@0
  1017
		{
sl@0
  1018
		return;
sl@0
  1019
		}    
sl@0
  1020
	
sl@0
  1021
	if (PreparePath(iVgPath, 2))
sl@0
  1022
		{
sl@0
  1023
		// If the pen width and height are the same then draw as normal
sl@0
  1024
		if (iPenSize.iWidth == iPenSize.iHeight)
sl@0
  1025
			{
sl@0
  1026
			// 0.5 is appended to all OpenVG drawing co-ordinates as when specifying them, the spec says
sl@0
  1027
			// co-ordinates are relative to pixel boundaries, not pixel centres, so 0,0 is the top left of the
sl@0
  1028
			// top pixel. We need to add 0.5 to specify the centre of pixels.
sl@0
  1029
			
sl@0
  1030
			AppendPathCommand(VG_MOVE_TO_ABS, aStart.iX + 0.5f, aStart.iY + 0.5f);		
sl@0
  1031
			if (aStart.iX == aEnd.iX)
sl@0
  1032
				{
sl@0
  1033
				AppendPathCommand(VG_VLINE_TO_ABS, aEnd.iY + 0.5f);			
sl@0
  1034
				}
sl@0
  1035
			else if (aStart.iY == aEnd.iY)
sl@0
  1036
				{
sl@0
  1037
				AppendPathCommand(VG_HLINE_TO_ABS, aEnd.iX + 0.5f);			
sl@0
  1038
				}
sl@0
  1039
			else
sl@0
  1040
				{
sl@0
  1041
				AppendPathCommand(VG_LINE_TO_ABS, aEnd.iX + 0.5f, aEnd.iY + 0.5f);
sl@0
  1042
				}		
sl@0
  1043
			FinishPath(iVgPath);
sl@0
  1044
			for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
  1045
				vgDrawPath(iVgPath, iPaintMode);			
sl@0
  1046
			}
sl@0
  1047
		else if ((iPenSize.iWidth != 0) && (iPenSize.iHeight != 0))
sl@0
  1048
			{
sl@0
  1049
			// Setting a pen with different width and height is not available on OpenVG, so we need to scale 
sl@0
  1050
			// the coordinates we are drawing and apply a scaling matrix that scales by the width and height 
sl@0
  1051
			// of the pen to get the effect of a pen width different width and height.
sl@0
  1052
			TSize penSize = iPenSize;
sl@0
  1053
			SetPenSize(TSize(1, 1));
sl@0
  1054
			vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
sl@0
  1055
			vgScale(penSize.iWidth, penSize.iHeight);
sl@0
  1056
					
sl@0
  1057
			VGfloat scaleX = 1.0f/(float)penSize.iWidth;
sl@0
  1058
			VGfloat scaleY = 1.0f/(float)penSize.iHeight;
sl@0
  1059
			AppendPathCommand(VG_MOVE_TO_ABS, (aStart.iX + 0.5f)*scaleX, (aStart.iY + 0.5f)*scaleY);		
sl@0
  1060
			if (aStart.iX == aEnd.iX)
sl@0
  1061
				{
sl@0
  1062
				AppendPathCommand(VG_VLINE_TO_ABS, (aEnd.iY + 0.5f)*scaleY);			
sl@0
  1063
				}
sl@0
  1064
			else if (aStart.iY == aEnd.iY)
sl@0
  1065
				{
sl@0
  1066
				AppendPathCommand(VG_HLINE_TO_ABS, (aEnd.iX + 0.5f)*scaleX);			
sl@0
  1067
				}
sl@0
  1068
			else
sl@0
  1069
				{
sl@0
  1070
				AppendPathCommand(VG_LINE_TO_ABS, (aEnd.iX + 0.5f)*scaleX, (aEnd.iY + 0.5f)*scaleY);
sl@0
  1071
				}		
sl@0
  1072
			FinishPath(iVgPath);				
sl@0
  1073
			vgDrawPath(iVgPath, iPaintMode);
sl@0
  1074
			
sl@0
  1075
			ResetVgMatrix(VG_MATRIX_PATH_USER_TO_SURFACE);
sl@0
  1076
			SetPenSize(penSize);
sl@0
  1077
			}			
sl@0
  1078
		}	
sl@0
  1079
sl@0
  1080
	iLinePos = aEnd;
sl@0
  1081
	}
sl@0
  1082
sl@0
  1083
/**
sl@0
  1084
@see MDirectGdiEngine::DrawLineTo()
sl@0
  1085
 */
sl@0
  1086
void CVgEngine::DrawLineTo(const TPoint& aPoint)
sl@0
  1087
	{
sl@0
  1088
	DrawLine(iLinePos, aPoint);
sl@0
  1089
	}
sl@0
  1090
sl@0
  1091
/**
sl@0
  1092
@see MDirectGdiEngine::DrawLineBy()
sl@0
  1093
 */
sl@0
  1094
void CVgEngine::DrawLineBy(const TPoint& aVector)
sl@0
  1095
	{
sl@0
  1096
	DrawLine(iLinePos, iLinePos + aVector);
sl@0
  1097
	}
sl@0
  1098
sl@0
  1099
/**
sl@0
  1100
@see MDirectGdiEngine::DrawRect()
sl@0
  1101
 */
sl@0
  1102
void CVgEngine::DrawRect(const TRect& aRect)
sl@0
  1103
	{
sl@0
  1104
	MakeEngineCurrent();
sl@0
  1105
	
sl@0
  1106
	// Only draw if we are not painting with a NULL pen and a NULL brush
sl@0
  1107
	if (iPaintMode == 0)
sl@0
  1108
		return;
sl@0
  1109
	
sl@0
  1110
	// If the pen size is larger then 1, make sure we are using the ESolidPen
sl@0
  1111
	// pen style (to match BitGdi behaviour)
sl@0
  1112
	DirectGdi::TPenStyle savedPenStyle = iPenStyle;
sl@0
  1113
	if (((iPenSize.iWidth > 1) || (iPenSize.iHeight > 1)) && (iPenStyle > DirectGdi::ESolidPen))
sl@0
  1114
		SetPenStyle(DirectGdi::ESolidPen);
sl@0
  1115
	
sl@0
  1116
	// Create a copy of the rect. If the pen style is not null, we have to shrink the 
sl@0
  1117
	// width and height of the rect by one pixel at the bottom left corner for conformance.	
sl@0
  1118
	TRect copyRect(aRect.iTl.iX, aRect.iTl.iY, aRect.iBr.iX, aRect.iBr.iY-1);
sl@0
  1119
	if (iPenStyle != DirectGdi::ENullPen)
sl@0
  1120
		{
sl@0
  1121
		--copyRect.iBr.iX;
sl@0
  1122
		}
sl@0
  1123
	else
sl@0
  1124
		{
sl@0
  1125
		--copyRect.iTl.iY;
sl@0
  1126
		}
sl@0
  1127
sl@0
  1128
	const TBool symmetricalPenSize = iPenSize.iWidth == iPenSize.iHeight;
sl@0
  1129
	
sl@0
  1130
	// If the pen is so thick it covers the entire area of the rect, don't do the fill, as per BitGdi.
sl@0
  1131
	const TBool penThickerThanRect = (iPenSize.iWidth >= copyRect.Width()) || (iPenSize.iHeight >= copyRect.Height());
sl@0
  1132
	
sl@0
  1133
	// If the pen width and height are the same then draw as normal. If they are different but we should be filling
sl@0
  1134
	// this shape we need to draw the filled area only as normal (not the outline). The outline of the shape is drawn 
sl@0
  1135
	// in the block of code below to allow the effect of a different width and height pen to be applied.
sl@0
  1136
	if (!penThickerThanRect || (iPenStyle == DirectGdi::ENullPen))
sl@0
  1137
		{
sl@0
  1138
		if (symmetricalPenSize || (iPaintMode & VG_FILL_PATH))
sl@0
  1139
			{
sl@0
  1140
			if (PreparePath(iVgPath, 5))
sl@0
  1141
				{
sl@0
  1142
				vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_MITER);
sl@0
  1143
				AppendPathCommand(VG_MOVE_TO_ABS, copyRect.iTl.iX + 0.5f, copyRect.iTl.iY + 0.5f);
sl@0
  1144
				AppendPathCommand(VG_HLINE_TO_ABS, copyRect.iBr.iX + 0.5f);
sl@0
  1145
				AppendPathCommand(VG_VLINE_TO_ABS, copyRect.iBr.iY + 0.5f);
sl@0
  1146
				AppendPathCommand(VG_HLINE_TO_ABS, copyRect.iTl.iX + 0.5f);
sl@0
  1147
				AppendPathCommand(VG_CLOSE_PATH);
sl@0
  1148
				FinishPath(iVgPath);
sl@0
  1149
			
sl@0
  1150
				for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
  1151
					vgDrawPath(iVgPath, symmetricalPenSize ? iPaintMode : VG_FILL_PATH);
sl@0
  1152
				vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_ROUND);
sl@0
  1153
				}
sl@0
  1154
			}
sl@0
  1155
		}
sl@0
  1156
	if((penThickerThanRect && (iPenStyle != DirectGdi::ENullPen)) ||  //we shouldn't draw if pen style is null
sl@0
  1157
		(!symmetricalPenSize &&	(iPaintMode & VG_STROKE_PATH) && (iPenSize.iWidth != 0) && (iPenSize.iHeight != 0)))
sl@0
  1158
		{
sl@0
  1159
		// Setting a pen with different width and height is not available on OpenVG, so we need to scale 
sl@0
  1160
		// the coordinates we are drawing and apply a scaling matrix that scales by the width and height 
sl@0
  1161
		// of the pen to get the effect of a pen width different width and height.
sl@0
  1162
		TSize penSize = iPenSize;
sl@0
  1163
		SetPenSize(TSize(1, 1));
sl@0
  1164
		vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
sl@0
  1165
		vgScale(penSize.iWidth, penSize.iHeight);
sl@0
  1166
			
sl@0
  1167
		if (PreparePath(iVgPath, 5))
sl@0
  1168
			{
sl@0
  1169
			vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_MITER);
sl@0
  1170
			VGfloat scaleX = 1.0f/(float)penSize.iWidth;
sl@0
  1171
			VGfloat scaleY = 1.0f/(float)penSize.iHeight;
sl@0
  1172
			AppendPathCommand(VG_MOVE_TO_ABS, (copyRect.iTl.iX + 0.5f)*scaleX, (copyRect.iTl.iY + 0.5f)*scaleY);
sl@0
  1173
			AppendPathCommand(VG_HLINE_TO_ABS, (copyRect.iBr.iX + 0.5f)*scaleX);
sl@0
  1174
			AppendPathCommand(VG_VLINE_TO_ABS, (copyRect.iBr.iY + 0.5f)*scaleY);
sl@0
  1175
			AppendPathCommand(VG_HLINE_TO_ABS, (copyRect.iTl.iX + 0.5f)*scaleX);
sl@0
  1176
			AppendPathCommand(VG_CLOSE_PATH);
sl@0
  1177
			FinishPath(iVgPath);
sl@0
  1178
			for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
  1179
				vgDrawPath(iVgPath, VG_STROKE_PATH);
sl@0
  1180
			vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_ROUND);
sl@0
  1181
			}
sl@0
  1182
		
sl@0
  1183
		ResetVgMatrix(VG_MATRIX_PATH_USER_TO_SURFACE);
sl@0
  1184
		SetPenSize(penSize);
sl@0
  1185
		}
sl@0
  1186
sl@0
  1187
	// Reset the pen style if we changed it above
sl@0
  1188
	if (savedPenStyle != iPenStyle)
sl@0
  1189
		SetPenStyle(savedPenStyle);
sl@0
  1190
	}
sl@0
  1191
sl@0
  1192
/**
sl@0
  1193
@see MDirectGdiEngine::DrawRoundRect()
sl@0
  1194
 */
sl@0
  1195
void CVgEngine::DrawRoundRect(const TRect& aRect, const TSize& aCornerSize) 
sl@0
  1196
	{
sl@0
  1197
	MakeEngineCurrent();
sl@0
  1198
	
sl@0
  1199
	// Only draw if we are not painting with a NULL pen and a NULL brush
sl@0
  1200
	if (iPaintMode == 0)		
sl@0
  1201
		return;
sl@0
  1202
	
sl@0
  1203
	// Create a copy of the rect. If the pen style is not null, we have to shrink the 
sl@0
  1204
	// width and height of the rect by one pixel at the bottom left corner for conformance.	
sl@0
  1205
	TRect copyRect(aRect.iTl.iX, aRect.iTl.iY, aRect.iBr.iX, aRect.iBr.iY-1);
sl@0
  1206
	if (iPenStyle != DirectGdi::ENullPen)
sl@0
  1207
		{
sl@0
  1208
		--copyRect.iBr.iX;
sl@0
  1209
		}
sl@0
  1210
	//If the penstyle is null and brush style is not null, then reduce the width and height by
sl@0
  1211
	//two pixels for conformation.
sl@0
  1212
	else if(iBrushStyle != DirectGdi::ENullBrush)
sl@0
  1213
		{
sl@0
  1214
		----copyRect.iBr.iX;		
sl@0
  1215
		--copyRect.iBr.iY;
sl@0
  1216
		}
sl@0
  1217
	else if(iPenStyle == DirectGdi::ENullPen)
sl@0
  1218
		{
sl@0
  1219
		--copyRect.iTl.iY;
sl@0
  1220
		}
sl@0
  1221
	
sl@0
  1222
	// check that the corner size is less than the rectangle size
sl@0
  1223
	if ((aRect.Width() > aCornerSize.iWidth) || (aRect.Height() > aCornerSize.iHeight))
sl@0
  1224
		{									
sl@0
  1225
		// Before any vgu command, call SetError() as this stores the current vg error state (if any) in the 
sl@0
  1226
		// driver. Some implementations of vgu clears error state so we'd lose error codes otherwise.
sl@0
  1227
		iDriver.SetError(KErrNone);
sl@0
  1228
		
sl@0
  1229
		// If the pen width and height are the same then draw as normal. If they are different but we should be filling
sl@0
  1230
		// this shape we need to draw the filled area only as normal (not the outline). The outline of the shape is drawn 
sl@0
  1231
		// in the block of code below to allow the effect of a different width and height pen to be applied.
sl@0
  1232
		if ((iPenSize.iWidth == iPenSize.iHeight) || (iPaintMode & VG_FILL_PATH))
sl@0
  1233
			{
sl@0
  1234
			if (PreparePath(iVgPath, 10))
sl@0
  1235
				{
sl@0
  1236
				VGUErrorCode err = vguRoundRect(iVgPath,
sl@0
  1237
											copyRect.iTl.iX + 0.5f, 
sl@0
  1238
											copyRect.iTl.iY + 0.5f,
sl@0
  1239
											copyRect.Width(), 
sl@0
  1240
											copyRect.Height(),
sl@0
  1241
											aCornerSize.iWidth * 2, 
sl@0
  1242
											aCornerSize.iHeight * 2);	
sl@0
  1243
				
sl@0
  1244
				if (err == VGU_NO_ERROR)
sl@0
  1245
					{
sl@0
  1246
					for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
  1247
						vgDrawPath(iVgPath, (iPenSize.iWidth == iPenSize.iHeight) ? iPaintMode : VG_FILL_PATH);	
sl@0
  1248
					}
sl@0
  1249
				else
sl@0
  1250
					{
sl@0
  1251
					SetVguError(err);
sl@0
  1252
					}
sl@0
  1253
				}
sl@0
  1254
			}
sl@0
  1255
		
sl@0
  1256
		if ((iPenSize.iWidth != iPenSize.iHeight)
sl@0
  1257
		&& (iPaintMode & VG_STROKE_PATH)		
sl@0
  1258
		&& (iPenSize.iWidth != 0) && (iPenSize.iHeight != 0))
sl@0
  1259
			{
sl@0
  1260
			// Setting a pen with different width and height is not available on OpenVG, so we need to scale 
sl@0
  1261
			// the coordinates we are drawing and apply a scaling matrix that scales by the width and height 
sl@0
  1262
			// of the pen to get the effect of a pen width different width and height.
sl@0
  1263
			TSize penSize = iPenSize;
sl@0
  1264
			SetPenSize(TSize(1, 1));
sl@0
  1265
			vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
sl@0
  1266
			vgScale(penSize.iWidth, penSize.iHeight);
sl@0
  1267
			
sl@0
  1268
			if (PreparePath(iVgPath, 10))
sl@0
  1269
				{
sl@0
  1270
				VGfloat scaleX = 1.0f/(float)penSize.iWidth;
sl@0
  1271
				VGfloat scaleY = 1.0f/(float)penSize.iHeight;
sl@0
  1272
				VGUErrorCode err = vguRoundRect(iVgPath,
sl@0
  1273
							                (copyRect.iTl.iX + 0.5f) * scaleX, 
sl@0
  1274
							                (copyRect.iTl.iY + 0.5f) * scaleY,
sl@0
  1275
							                copyRect.Width() * scaleX, 
sl@0
  1276
							                copyRect.Height() * scaleY,
sl@0
  1277
							                (aCornerSize.iWidth * 2) * scaleX, 
sl@0
  1278
							                (aCornerSize.iHeight * 2) * scaleY);	
sl@0
  1279
				if (err == VGU_NO_ERROR)
sl@0
  1280
					{
sl@0
  1281
					vgDrawPath(iVgPath, VG_STROKE_PATH);		
sl@0
  1282
					}
sl@0
  1283
				else
sl@0
  1284
					{
sl@0
  1285
					SetVguError(err);
sl@0
  1286
					}
sl@0
  1287
				}
sl@0
  1288
			
sl@0
  1289
			ResetVgMatrix(VG_MATRIX_PATH_USER_TO_SURFACE);
sl@0
  1290
			SetPenSize(penSize);
sl@0
  1291
			}
sl@0
  1292
		}
sl@0
  1293
	else
sl@0
  1294
		{
sl@0
  1295
		// Draw an ellipse as the corner size is greater than or equal to the rectangle size
sl@0
  1296
		DrawEllipse(copyRect);
sl@0
  1297
		}
sl@0
  1298
	}
sl@0
  1299
sl@0
  1300
/**
sl@0
  1301
@see MDirectGdiEngine::DrawPolyLine()
sl@0
  1302
sl@0
  1303
@panic DGDIAdapter 27, if the passed point list has zero points (debug-only).
sl@0
  1304
 */
sl@0
  1305
void CVgEngine::DrawPolyLine(const TArray<TPoint>& aPointList)
sl@0
  1306
	{
sl@0
  1307
	DrawPolyLineNoEndPoint(aPointList);
sl@0
  1308
	
sl@0
  1309
	// Do a plot at the end point to improve the appearance. For larger pen-sizes, a plot
sl@0
  1310
	// improves the correlation with BitGDI polylines, giving a subtly more rounded finish.
sl@0
  1311
	if (DirectGdi::ESolidPen == iPenStyle)
sl@0
  1312
		{
sl@0
  1313
		Plot(iLinePos);
sl@0
  1314
		}
sl@0
  1315
	}
sl@0
  1316
sl@0
  1317
/**
sl@0
  1318
@see MDirectGdiEngine::DrawPolyLineNoEndPoint()
sl@0
  1319
sl@0
  1320
@panic DGDIAdapter 27, if the passed point list has zero points (debug-only).
sl@0
  1321
 */
sl@0
  1322
void CVgEngine::DrawPolyLineNoEndPoint(const TArray<TPoint>& aPointList)
sl@0
  1323
	{
sl@0
  1324
	MakeEngineCurrent();
sl@0
  1325
sl@0
  1326
	GRAPHICS_ASSERT_DEBUG(aPointList.Count() > 0, EDirectGdiPanicInvalidPointArray);
sl@0
  1327
	
sl@0
  1328
	DoDrawPoly(aPointList, EFalse);
sl@0
  1329
	}
sl@0
  1330
sl@0
  1331
/**
sl@0
  1332
@see MDirectGdiEngine::DrawPolygon()
sl@0
  1333
sl@0
  1334
@panic DGDIAdapter 26, if the passed fill-rule is invalid (debug-only).
sl@0
  1335
 */
sl@0
  1336
void CVgEngine::DrawPolygon(const TArray<TPoint>& aPoints, DirectGdi::TFillRule aRule)
sl@0
  1337
	{
sl@0
  1338
	MakeEngineCurrent();
sl@0
  1339
	
sl@0
  1340
	GRAPHICS_ASSERT_DEBUG(aPoints.Count() > 0, EDirectGdiPanicInvalidPointArray);
sl@0
  1341
	
sl@0
  1342
	switch(aRule)
sl@0
  1343
	    {
sl@0
  1344
		case DirectGdi::EAlternate:
sl@0
  1345
			vgSeti(VG_FILL_RULE, VG_EVEN_ODD); 
sl@0
  1346
			break;
sl@0
  1347
		case DirectGdi::EWinding: 
sl@0
  1348
			vgSeti(VG_FILL_RULE, VG_NON_ZERO); 
sl@0
  1349
			break;
sl@0
  1350
		default: 
sl@0
  1351
			GRAPHICS_PANIC_DEBUG(EDirectGdiPanicInvalidFillRule);
sl@0
  1352
			return;
sl@0
  1353
	    };
sl@0
  1354
	
sl@0
  1355
	DoDrawPoly(aPoints, ETrue);
sl@0
  1356
	}
sl@0
  1357
sl@0
  1358
/**
sl@0
  1359
Helper function to assist with drawing polygons with DrawPolygon()/DrawPolyLine(). It takes care of 
sl@0
  1360
drawing the array of points given to it. It sets the internal drawing poisition to the last TPoint
sl@0
  1361
in the array.
sl@0
  1362
sl@0
  1363
@see	DrawPolyLine()
sl@0
  1364
@see 	DrawPolygon()
sl@0
  1365
sl@0
  1366
@param	aPoints	Array of points specifying the vertices of the polygon. There must be at least one 
sl@0
  1367
		vertex.
sl@0
  1368
@param  aClosed	If ETrue, the start and end points are joined, and the polygon filled using current 
sl@0
  1369
        brush settings, otherwise just a polyline is drawn.
sl@0
  1370
*/
sl@0
  1371
void CVgEngine::DoDrawPoly(const TArray<TPoint>& aPoints, TBool aClosed)
sl@0
  1372
	{
sl@0
  1373
	GRAPHICS_ASSERT_DEBUG(aPoints.Count() > 0, EDirectGdiPanicInvalidPointArray);	
sl@0
  1374
	const TInt numPoints = aPoints.Count();	
sl@0
  1375
	
sl@0
  1376
	// Set drawing position to last point in the array (regardless of whether the poly is open/closed)
sl@0
  1377
	iLinePos = aPoints[numPoints - 1];
sl@0
  1378
	
sl@0
  1379
	// Set the paint mode depending on whether we are drawing a line (not closed) or a poly (closed)
sl@0
  1380
	VGbitfield paintMode = iPaintMode;
sl@0
  1381
	if (!aClosed)
sl@0
  1382
		{
sl@0
  1383
		paintMode &= ~VG_FILL_PATH;
sl@0
  1384
		}
sl@0
  1385
	
sl@0
  1386
	if (!paintMode)
sl@0
  1387
		{
sl@0
  1388
		return;
sl@0
  1389
		}
sl@0
  1390
sl@0
  1391
	// If the pen width and height are the same then draw as normal. If they are different but we should be filling
sl@0
  1392
	// this shape we need to draw the filled area only as normal (not the outline). The outline of the shape is drawn 
sl@0
  1393
	// in the block of code below to allow the effect of a different width and height pen to be applied.
sl@0
  1394
	if ((iPenSize.iWidth == iPenSize.iHeight) || (paintMode & VG_FILL_PATH))
sl@0
  1395
		{
sl@0
  1396
		if (PreparePath(iVgPath, aClosed ? numPoints + 1 : numPoints))
sl@0
  1397
			{
sl@0
  1398
			AppendPathCommand(VG_MOVE_TO_ABS, aPoints[0].iX + 0.5f, aPoints[0].iY + 0.5f);
sl@0
  1399
			for (TInt point = 0; point < numPoints; ++point)
sl@0
  1400
				{
sl@0
  1401
				AppendPathCommand(VG_LINE_TO_ABS, aPoints[point].iX + 0.5f, aPoints[point].iY + 0.5f);	
sl@0
  1402
				}
sl@0
  1403
			if (aClosed)
sl@0
  1404
				{
sl@0
  1405
				AppendPathCommand(VG_CLOSE_PATH);
sl@0
  1406
				}
sl@0
  1407
			FinishPath(iVgPath);
sl@0
  1408
			for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
  1409
				vgDrawPath(iVgPath, (iPenSize.iWidth == iPenSize.iHeight) ? paintMode : VG_FILL_PATH);
sl@0
  1410
			}
sl@0
  1411
		}
sl@0
  1412
	
sl@0
  1413
	if ((iPenSize.iWidth != iPenSize.iHeight)
sl@0
  1414
		&& (paintMode & VG_STROKE_PATH)		
sl@0
  1415
		&& (iPenSize.iWidth != 0) && (iPenSize.iHeight != 0))
sl@0
  1416
		{
sl@0
  1417
		// Setting a pen with different width and height is not available on OpenVG, so we need to scale 
sl@0
  1418
		// the coordinates we are drawing and apply a scaling matrix that scales by the width and height 
sl@0
  1419
		// of the pen to get the effect of a pen width different width and height.
sl@0
  1420
		TSize penSize = iPenSize;
sl@0
  1421
		SetPenSize(TSize(1, 1));
sl@0
  1422
		vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
sl@0
  1423
		vgScale(penSize.iWidth, penSize.iHeight);
sl@0
  1424
		
sl@0
  1425
		if (PreparePath(iVgPath, aClosed ? numPoints + 1 : numPoints))
sl@0
  1426
			{
sl@0
  1427
			AppendPathCommand(VG_MOVE_TO_ABS, (aPoints[0].iX + 0.5f)/(float)penSize.iWidth, (aPoints[0].iY + 0.5f)/(float)penSize.iHeight);
sl@0
  1428
			for (TInt point = 0; point < numPoints; ++point)
sl@0
  1429
				{
sl@0
  1430
				AppendPathCommand(VG_LINE_TO_ABS, (aPoints[point].iX + 0.5f)/(float)penSize.iWidth, (aPoints[point].iY + 0.5f)/(float)penSize.iHeight);	
sl@0
  1431
				}				
sl@0
  1432
			if (aClosed)
sl@0
  1433
				{
sl@0
  1434
				AppendPathCommand(VG_CLOSE_PATH);
sl@0
  1435
				}			
sl@0
  1436
			FinishPath(iVgPath);		
sl@0
  1437
			vgDrawPath(iVgPath, VG_STROKE_PATH);
sl@0
  1438
			}
sl@0
  1439
		
sl@0
  1440
		ResetVgMatrix(VG_MATRIX_PATH_USER_TO_SURFACE);
sl@0
  1441
		SetPenSize(penSize);
sl@0
  1442
		}
sl@0
  1443
			
sl@0
  1444
	}
sl@0
  1445
sl@0
  1446
/**
sl@0
  1447
@see MDirectGdiEngine::DrawArc()
sl@0
  1448
@see DrawPie()
sl@0
  1449
@see DrawArc(const TRect&, const TPoint&, const TPoint&, VGUArcType)
sl@0
  1450
 */
sl@0
  1451
void CVgEngine::DrawArc(const TRect& aRect, const TPoint& aStart, const TPoint& aEnd) 
sl@0
  1452
	{	
sl@0
  1453
	DoDrawArc(aRect, aStart, aEnd, VGU_ARC_OPEN);
sl@0
  1454
	}
sl@0
  1455
sl@0
  1456
/**
sl@0
  1457
@see MDirectGdiEngine::DrawPie()
sl@0
  1458
@see DrawArc(const TRect&, const TPoint&, const TPoint&)
sl@0
  1459
@see DrawArc(const TRect&, const TPoint&, const TPoint&, VGUArcType)
sl@0
  1460
 */
sl@0
  1461
void CVgEngine::DrawPie(const TRect& aRect, const TPoint& aStart, const TPoint& aEnd) 
sl@0
  1462
	{	
sl@0
  1463
	DoDrawArc(aRect, aStart, aEnd, VGU_ARC_PIE);
sl@0
  1464
	}
sl@0
  1465
sl@0
  1466
/**
sl@0
  1467
@see MDirectGdiEngine::DrawEllipse()
sl@0
  1468
 */
sl@0
  1469
void CVgEngine::DrawEllipse(const TRect& aRect) 
sl@0
  1470
	{
sl@0
  1471
	// Null brush and pen, draw nothing.
sl@0
  1472
	if (iPaintMode == 0)
sl@0
  1473
		return;
sl@0
  1474
	
sl@0
  1475
	MakeEngineCurrent();	
sl@0
  1476
	VGfloat x = (aRect.iTl.iX + aRect.iBr.iX) * 0.5;
sl@0
  1477
	VGfloat y = (aRect.iTl.iY + aRect.iBr.iY) * 0.5;
sl@0
  1478
	
sl@0
  1479
	// Before any vgu command, call SetError() as this stores the current vg error state (if any) in the 
sl@0
  1480
	// driver. Some implementations of vgu clears error state so we'd lose error codes otherwise.
sl@0
  1481
	iDriver.SetError(KErrNone);
sl@0
  1482
	
sl@0
  1483
	TInt width = aRect.Width();
sl@0
  1484
	TInt height = aRect.Height();
sl@0
  1485
	
sl@0
  1486
	//If the penstyle is null and brush style is not null, then reduce the width and height by
sl@0
  1487
	//two pixels for conformation.
sl@0
  1488
	if(iPenStyle == DirectGdi::ENullPen && iBrushStyle != DirectGdi::ENullBrush)
sl@0
  1489
		{
sl@0
  1490
		width = aRect.Width() > 2 ? aRect.Width() - 2 : 1;
sl@0
  1491
		height = aRect.Height() > 2 ? aRect.Height() - 2 : 1;
sl@0
  1492
		}
sl@0
  1493
	
sl@0
  1494
	// If the pen width and height are the same then draw as normal. If they are different but we should be filling
sl@0
  1495
	// this shape we need to draw the filled area only as normal (not the outline). The outline of the shape is drawn 
sl@0
  1496
	// in the block of code below to allow the effect of a different width and height pen to be applied.
sl@0
  1497
	if ((iPenSize.iWidth == iPenSize.iHeight) || (iPaintMode & VG_FILL_PATH))
sl@0
  1498
		{
sl@0
  1499
		if (PreparePath(iVgPath, 4))
sl@0
  1500
			{
sl@0
  1501
			VGUErrorCode err = vguEllipse(iVgPath, x, y, width, height);
sl@0
  1502
			if (err == VGU_NO_ERROR)
sl@0
  1503
				{
sl@0
  1504
				for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
  1505
					vgDrawPath(iVgPath, (iPenSize.iWidth == iPenSize.iHeight) ? iPaintMode : VG_FILL_PATH);
sl@0
  1506
				}
sl@0
  1507
			else
sl@0
  1508
				{
sl@0
  1509
				SetVguError(err);
sl@0
  1510
				}
sl@0
  1511
			}
sl@0
  1512
		}
sl@0
  1513
	
sl@0
  1514
	if ((iPenSize.iWidth != iPenSize.iHeight)
sl@0
  1515
		&& (iPaintMode & VG_STROKE_PATH)		
sl@0
  1516
		&& (iPenSize.iWidth != 0) && (iPenSize.iHeight != 0))
sl@0
  1517
		{
sl@0
  1518
		// Setting a pen with different width and height is not available on OpenVG, so we need to scale 
sl@0
  1519
		// the coordinates we are drawing and apply a scaling matrix that scales by the width and height 
sl@0
  1520
		// of the pen to get the effect of a pen width different width and height.
sl@0
  1521
		TSize penSize = iPenSize;
sl@0
  1522
		SetPenSize(TSize(1, 1));
sl@0
  1523
		vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
sl@0
  1524
		vgScale(penSize.iWidth, penSize.iHeight);
sl@0
  1525
		
sl@0
  1526
		VGfloat scaleX = 1.0f/(float)penSize.iWidth;
sl@0
  1527
		VGfloat scaleY = 1.0f/(float)penSize.iHeight;
sl@0
  1528
		
sl@0
  1529
		if (PreparePath(iVgPath, 4))
sl@0
  1530
			{
sl@0
  1531
			VGUErrorCode err = vguEllipse(iVgPath, x*scaleX, y*scaleY, (float)width*scaleX, (float)height*scaleY);			
sl@0
  1532
			if (err == VGU_NO_ERROR)
sl@0
  1533
				{
sl@0
  1534
				vgDrawPath(iVgPath, VG_STROKE_PATH);
sl@0
  1535
				}
sl@0
  1536
			else
sl@0
  1537
				{
sl@0
  1538
				SetVguError(err);
sl@0
  1539
				}
sl@0
  1540
			}
sl@0
  1541
		
sl@0
  1542
		ResetVgMatrix(VG_MATRIX_PATH_USER_TO_SURFACE);
sl@0
  1543
		SetPenSize(penSize);			
sl@0
  1544
		}	
sl@0
  1545
	}
sl@0
  1546
sl@0
  1547
/**
sl@0
  1548
Given a TDisplayMode, returns the closest TDisplayMode that is pixel-for-pixel-compatible
sl@0
  1549
with an OpenVG format, such that the given TDisplayMode may be converted into the result
sl@0
  1550
without loss of colour information.
sl@0
  1551
sl@0
  1552
@param 	aDisplayMode Pixel format to find a match for.
sl@0
  1553
sl@0
  1554
@return Closest TDisplayMode for which there is a OpenVG-compatible match.
sl@0
  1555
 */
sl@0
  1556
static TDisplayMode ClosestVgCompatibleDisplayMode(TDisplayMode aDisplayMode)
sl@0
  1557
	{
sl@0
  1558
	switch (aDisplayMode)
sl@0
  1559
		{
sl@0
  1560
		case EGray2:
sl@0
  1561
		case EGray4:
sl@0
  1562
		case EGray16:
sl@0
  1563
			return EGray256;
sl@0
  1564
sl@0
  1565
		case EColor16:
sl@0
  1566
		case EColor256:
sl@0
  1567
		case EColor4K:
sl@0
  1568
			return EColor64K;
sl@0
  1569
		
sl@0
  1570
		case EColor16M:
sl@0
  1571
			return EColor16MU;
sl@0
  1572
			
sl@0
  1573
		default:
sl@0
  1574
			return aDisplayMode;
sl@0
  1575
		}
sl@0
  1576
	}
sl@0
  1577
sl@0
  1578
/**
sl@0
  1579
Converts a CFbsBitmap into a VGImage.
sl@0
  1580
If the CFbsBitmap is not a volatile bitmap, the VGImage created will be stored in the thread-wide 
sl@0
  1581
VGImage cache. If the CFbsBitmap has been touched (i.e. its data has been changed since it was last 
sl@0
  1582
used), a new VGImage will be created and will replace that currently stored in the cache. An untouched 
sl@0
  1583
bitmap will store the created VGImage in the cache upon first use, and on subsequent use (if it is 
sl@0
  1584
still untouched), will just retrieve the VGImage stored in the cache.
sl@0
  1585
sl@0
  1586
@param aBitmap The CFbsBitmap to create a VGImage from.
sl@0
  1587
@param aImage Returns the VGImage created from the CFbsBitmap.
sl@0
  1588
@param aIsMask True if the CFbsBitmap is to be used as a mask.
sl@0
  1589
@param aOrigin Position of the first pixel in the mask bitmap.
sl@0
  1590
sl@0
  1591
@return ETrue if the VGimage has been stored in the cache, EFalse if not.
sl@0
  1592
*/
sl@0
  1593
TBool CVgEngine::ConvertBitmapToVgImage(const CFbsBitmap& aBitmap, VGImage& aImage, TBool aIsMask, const TPoint& aOrigin)
sl@0
  1594
	{
sl@0
  1595
	TBool createImage =  EFalse;
sl@0
  1596
	TBool storeImageInCache = EFalse;
sl@0
  1597
	TBool imageCached = EFalse;
sl@0
  1598
	// Set the options createImage, storeImageInCache and imageCached depending on
sl@0
  1599
	// whether the bitmap is volatile, has been touched since last used,
sl@0
  1600
	// and whether it already exists in the cache
sl@0
  1601
	if (aBitmap.IsVolatile()) 
sl@0
  1602
		{
sl@0
  1603
		// Source bitmap is volatile and so should not be stored in cache.
sl@0
  1604
		// Therefore create image only.
sl@0
  1605
		createImage = ETrue;
sl@0
  1606
		}
sl@0
  1607
	else //bitmap not volatile
sl@0
  1608
		{
sl@0
  1609
		// Source bitmap has not changed since last used.
sl@0
  1610
		// Retrieve from cache the image created from the bitmap and the touchCount of that image.
sl@0
  1611
		aImage = iDriver.GetVgImageFromCache(aBitmap, aOrigin);
sl@0
  1612
		// If the source bitmap already has an associated VGImage stored in the cache,
sl@0
  1613
		// just use that VGImage.  Otherwise, need to create a VGImage and add it to the cache.
sl@0
  1614
		if (aImage == VG_INVALID_HANDLE)
sl@0
  1615
			{
sl@0
  1616
			// VGImage not in cache
sl@0
  1617
			// Create image, and store in cache
sl@0
  1618
			createImage = ETrue;
sl@0
  1619
			storeImageInCache = ETrue;
sl@0
  1620
			}
sl@0
  1621
		else
sl@0
  1622
			{
sl@0
  1623
			// Image already in cache
sl@0
  1624
			imageCached = ETrue;
sl@0
  1625
			}
sl@0
  1626
		}
sl@0
  1627
sl@0
  1628
	// Create a new VGImage if needed
sl@0
  1629
	if (createImage)
sl@0
  1630
		{
sl@0
  1631
		aImage = CreateSourceVGImage(aBitmap, aIsMask, aOrigin);
sl@0
  1632
		// Error set on creation of VGImage if aImage == VG_INVALID_HANDLE.
sl@0
  1633
		}
sl@0
  1634
	// Store the VGImage in the cache if appropriate
sl@0
  1635
	if (storeImageInCache && aImage != VG_INVALID_HANDLE)
sl@0
  1636
		{
sl@0
  1637
		imageCached = iDriver.AddVgImageToCache(aBitmap, aImage, aOrigin);
sl@0
  1638
		}
sl@0
  1639
	return imageCached;
sl@0
  1640
	}
sl@0
  1641
sl@0
  1642
sl@0
  1643
/**
sl@0
  1644
Transforms coordinates for a TRect from Symbian Graphics to OpenVG surface coordinates.
sl@0
  1645
This is required for OpenVG operations which are not subject to user-to-surface 
sl@0
  1646
coordinate system transformations.
sl@0
  1647
sl@0
  1648
OpenVG coordinates locate the BOTTOM LEFT corner of the object relative to an origin
sl@0
  1649
at the BOTTOM LEFT of the rendering area.
sl@0
  1650
sl@0
  1651
Symbian Graphics coordinates locate the TOP LEFT corner of the object relative to an 
sl@0
  1652
origin located at the TOP LEFT of the rendering area.
sl@0
  1653
sl@0
  1654
@param	aCoord		Top-left of the rectangle, in Symbian graphics coordinates.
sl@0
  1655
@param  aWidth		The width of the desired rectangle.
sl@0
  1656
@param  aHeight		The height of the desired rectangle.
sl@0
  1657
@return A TRect in OpenVG coordinates which describes a rectangle at aCoord with aWidth and aHeight.
sl@0
  1658
*/
sl@0
  1659
TRect CVgEngine::SgMetricsToVgTRect(const TPoint& aCoord, const TInt aWidth, const TInt aHeight) const
sl@0
  1660
	{
sl@0
  1661
	return TRect (TPoint (aCoord.iX + iOrigin.iX, iSize.iHeight - (aCoord.iY + aHeight) - iOrigin.iY), TSize (aWidth, aHeight));
sl@0
  1662
	}
sl@0
  1663
sl@0
  1664
/** 
sl@0
  1665
@see MDirectGdiEngine::BitBlt()
sl@0
  1666
@see BitBltMasked(const TPoint&, const CFbsBitmap&, const TRect&, const CFbsBitmap&, TBool)
sl@0
  1667
@see BitBltMasked(const TPoint&, const CFbsBitmap&, const TRect&, const CFbsBitmap&, const TPoint&)
sl@0
  1668
 */
sl@0
  1669
void CVgEngine::BitBlt(const TPoint& aDestPos, const CFbsBitmap& aSourceBitmap, const TRect& aSourceRect)
sl@0
  1670
	{
sl@0
  1671
	if (aSourceBitmap.ExtendedBitmapType() != KNullUid)
sl@0
  1672
		{
sl@0
  1673
		iDriver.SetError(KErrNotSupported); // Not supported for extended bitmaps
sl@0
  1674
		return;
sl@0
  1675
		}
sl@0
  1676
	
sl@0
  1677
	DoVgImageDraw (TRect (aDestPos, aSourceRect.Size()), aSourceBitmap, aSourceRect);
sl@0
  1678
	}
sl@0
  1679
sl@0
  1680
/** 
sl@0
  1681
@see MDirectGdiEngine::DrawBitmap()
sl@0
  1682
@see DrawBitmapMasked()
sl@0
  1683
 */
sl@0
  1684
void CVgEngine::DrawBitmap(const TRect& aDestRect, const CFbsBitmap& aSourceBitmap, const TRect& aSourceRect) 
sl@0
  1685
	{
sl@0
  1686
	if (aSourceBitmap.ExtendedBitmapType() != KNullUid)
sl@0
  1687
		{
sl@0
  1688
		iDriver.SetError(KErrNotSupported); // Not supported for extended bitmaps
sl@0
  1689
		return;
sl@0
  1690
		}
sl@0
  1691
	
sl@0
  1692
	DoVgImageDraw (aDestRect, aSourceBitmap, aSourceRect);
sl@0
  1693
	}
sl@0
  1694
sl@0
  1695
sl@0
  1696
/**
sl@0
  1697
Helper method to perform basic VgDrawImage operations, explictly optimised for the case where
sl@0
  1698
the extents of the source image equal the specified source region.
sl@0
  1699
sl@0
  1700
@pre aSource image is a valid VG image handle.
sl@0
  1701
@pre Destination position and/or scaling has already been set in OpenVG. 
sl@0
  1702
sl@0
  1703
@param aDestRect	 	Destination rectangle to draw to.
sl@0
  1704
@param aSourceBitmap	Source bitmap to draw.
sl@0
  1705
@param aSourceRect 		Source rectangle to render. 
sl@0
  1706
*/
sl@0
  1707
void CVgEngine::DoVgImageDraw (const TRect& aDestRect, const CFbsBitmap& aSourceBitmap, const TRect& aSourceRect)
sl@0
  1708
	{
sl@0
  1709
	MakeEngineCurrent();
sl@0
  1710
	TRect destRect(aDestRect);
sl@0
  1711
	TRect srcRect(aSourceRect);
sl@0
  1712
	if (!IntersectsClippingRegion (TRect(iOrigin, destRect.Size()))) 
sl@0
  1713
		return;
sl@0
  1714
	
sl@0
  1715
	VGImage sourceImage = VG_INVALID_HANDLE;
sl@0
  1716
	TBool imageCached = ConvertBitmapToVgImage(aSourceBitmap, sourceImage);
sl@0
  1717
	// Error set on creation of VGImage.
sl@0
  1718
	if (sourceImage == VG_INVALID_HANDLE) return;
sl@0
  1719
sl@0
  1720
	vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
sl@0
  1721
	vgTranslate(destRect.iTl.iX, destRect.iTl.iY);
sl@0
  1722
	
sl@0
  1723
	if (aDestRect.Size() != aSourceRect.Size())
sl@0
  1724
		vgScale((VGfloat)destRect.Width()/aSourceRect.Width(), (VGfloat)destRect.Height()/aSourceRect.Height());
sl@0
  1725
	
sl@0
  1726
	if(aSourceBitmap.SizeInPixels() == aSourceRect.Size())
sl@0
  1727
		{
sl@0
  1728
		for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
  1729
			vgDrawImage(sourceImage);
sl@0
  1730
		}
sl@0
  1731
	else
sl@0
  1732
		{
sl@0
  1733
		VGImage sourceImageRegion = 
sl@0
  1734
			vgChildImage(
sl@0
  1735
				sourceImage, 
sl@0
  1736
				srcRect.iTl.iX, 
sl@0
  1737
				srcRect.iTl.iY, 
sl@0
  1738
				srcRect.Width(), 
sl@0
  1739
				srcRect.Height());
sl@0
  1740
		
sl@0
  1741
		if (sourceImageRegion != VG_INVALID_HANDLE)
sl@0
  1742
			{
sl@0
  1743
			for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
  1744
				vgDrawImage(sourceImageRegion);
sl@0
  1745
sl@0
  1746
			vgDestroyImage(sourceImageRegion);
sl@0
  1747
			}
sl@0
  1748
		}
sl@0
  1749
		
sl@0
  1750
	if (!imageCached) vgDestroyImage (sourceImage);
sl@0
  1751
	ResetVgMatrix(VG_MATRIX_IMAGE_USER_TO_SURFACE);	// Reset the transform matrix.		
sl@0
  1752
	}
sl@0
  1753
sl@0
  1754
/** 
sl@0
  1755
@see MDirectGdiEngine::BitBltMasked()
sl@0
  1756
@see BitBltMasked(const TPoint&, const CFbsBitmap&, const TRect&, const CFbsBitmap&, TBool)
sl@0
  1757
@see BitBlt()
sl@0
  1758
 */
sl@0
  1759
void CVgEngine::BitBltMasked(
sl@0
  1760
		const TPoint& aDestPos,
sl@0
  1761
		const CFbsBitmap& aBitmap,
sl@0
  1762
		const TRect& aSourceRect,
sl@0
  1763
		const CFbsBitmap& aMask,
sl@0
  1764
		const TPoint& aMaskPt)
sl@0
  1765
	{
sl@0
  1766
	if ((aBitmap.ExtendedBitmapType() != KNullUid) || (aMask.ExtendedBitmapType() != KNullUid))
sl@0
  1767
		{
sl@0
  1768
		iDriver.SetError(KErrNotSupported); // Not supported for extended bitmaps
sl@0
  1769
		return;
sl@0
  1770
		}
sl@0
  1771
	
sl@0
  1772
	DoBitBltMasked(aDestPos, aBitmap, aSourceRect, aMask, EFalse, aMaskPt);
sl@0
  1773
	}
sl@0
  1774
sl@0
  1775
/** 
sl@0
  1776
@see MDirectGdiEngine::BitBlt()
sl@0
  1777
@see BitBltMasked(const TPoint&, const CFbsBitmap&, const TRect&, const CFbsBitmap&, const TPoint&)
sl@0
  1778
@see BitBlt()
sl@0
  1779
 */
sl@0
  1780
void CVgEngine::BitBltMasked( 
sl@0
  1781
		const TPoint& aDestPos,
sl@0
  1782
		const CFbsBitmap& aSourceBitmap,
sl@0
  1783
		const TRect& aSourceRect,
sl@0
  1784
		const CFbsBitmap& aMaskBitmap, 
sl@0
  1785
		TBool aInvertMask)
sl@0
  1786
	{
sl@0
  1787
	if ((aSourceBitmap.ExtendedBitmapType() != KNullUid) || (aMaskBitmap.ExtendedBitmapType() != KNullUid))
sl@0
  1788
		{
sl@0
  1789
		iDriver.SetError(KErrNotSupported); // Not supported for extended bitmaps
sl@0
  1790
		return;
sl@0
  1791
		}
sl@0
  1792
	
sl@0
  1793
	DoBitBltMasked(aDestPos, aSourceBitmap, aSourceRect, aMaskBitmap, aInvertMask, TPoint(0, 0));
sl@0
  1794
	}
sl@0
  1795
sl@0
  1796
/**
sl@0
  1797
Helper method for performing BitBltMasked().
sl@0
  1798
Note that aInvertMask is ignored if aMaskPos is not at 0,0.
sl@0
  1799
sl@0
  1800
@see	CDirectGdiContext::BitBlt(const TPoint& aPoint, const CFbsBitmap& aBitmap, const TRect& aSourceRect);
sl@0
  1801
@see	CDirectGdiContext::BitBltMasked(const TPoint&, const CFbsBitmap&,const TRect&, const CFbsBitmap&, const TPoint&);
sl@0
  1802
sl@0
  1803
@param	aDestPos		The destination for the top left corner of the transferred bitmap. 
sl@0
  1804
						It is relative to the top left corner of the destination bitmap, which may be the screen. 
sl@0
  1805
@param	aSourceBitmap	A memory-resident source bitmap.
sl@0
  1806
@param	aSourceRect		A rectangle defining the piece of the bitmap to be drawn, 
sl@0
  1807
						with co-ordinates relative to the top left corner of the bitmap. 
sl@0
  1808
@param	aMaskBitmap		Mask bitmap.
sl@0
  1809
@param	aInvertMask		If EFalse, a source pixel that is masked by a black pixel is not transferred to 
sl@0
  1810
						the destination rectangle. If ETrue, then a source pixel that is masked by a 
sl@0
  1811
						white pixel is not transferred to the destination rectangle. If alpha blending
sl@0
  1812
						is used instead of masking, this flag is ignored and no inversion takes place.
sl@0
  1813
						Note that this parameter is ignored if aMaskPos does not equal TPoint(0,0).
sl@0
  1814
@param	aMaskPos		The point on the mask bitmap to use as the top left corner 
sl@0
  1815
*/
sl@0
  1816
void CVgEngine::DoBitBltMasked (
sl@0
  1817
		const TPoint& aDestPos,
sl@0
  1818
		const CFbsBitmap& aSourceBitmap,
sl@0
  1819
		const TRect& aSourceRect,
sl@0
  1820
		const CFbsBitmap& aMaskBitmap,
sl@0
  1821
		TBool aInvertMask,
sl@0
  1822
		const TPoint& aMaskPos)
sl@0
  1823
	{
sl@0
  1824
	MakeEngineCurrent();
sl@0
  1825
	ResetVgMatrix(VG_MATRIX_IMAGE_USER_TO_SURFACE);
sl@0
  1826
	if (!IntersectsClippingRegion (TRect (aDestPos+iOrigin, aSourceRect.Size()))) 
sl@0
  1827
		return;
sl@0
  1828
	
sl@0
  1829
	VGImage sourceImage = VG_INVALID_HANDLE;
sl@0
  1830
	TBool imageCached = ConvertBitmapToVgImage(aSourceBitmap, sourceImage);
sl@0
  1831
	if (sourceImage == VG_INVALID_HANDLE)
sl@0
  1832
		{
sl@0
  1833
		// Error set on creation of VGImage.
sl@0
  1834
		return;
sl@0
  1835
		}
sl@0
  1836
	
sl@0
  1837
	VGImage maskImage = VG_INVALID_HANDLE;
sl@0
  1838
	TBool maskImageCached = ConvertBitmapToVgImage(aMaskBitmap, maskImage, ETrue, aMaskPos);
sl@0
  1839
	if (maskImage == VG_INVALID_HANDLE)
sl@0
  1840
		{
sl@0
  1841
		// Error set on creation of VGImage.
sl@0
  1842
		if (!imageCached)
sl@0
  1843
			{
sl@0
  1844
			vgDestroyImage(sourceImage);
sl@0
  1845
			}
sl@0
  1846
		return;
sl@0
  1847
		}
sl@0
  1848
sl@0
  1849
	DoVgMaskedImageDraw(
sl@0
  1850
		aDestPos,
sl@0
  1851
		sourceImage,
sl@0
  1852
		aSourceBitmap.SizeInPixels(),
sl@0
  1853
		aSourceRect,
sl@0
  1854
		maskImage,
sl@0
  1855
		aMaskBitmap.SizeInPixels(),
sl@0
  1856
		aSourceRect.Size(),
sl@0
  1857
		aInvertMask);
sl@0
  1858
sl@0
  1859
	if (!maskImageCached)
sl@0
  1860
		{
sl@0
  1861
		vgDestroyImage(maskImage);
sl@0
  1862
		}
sl@0
  1863
	if (!imageCached)
sl@0
  1864
		{
sl@0
  1865
		vgDestroyImage(sourceImage);
sl@0
  1866
		}
sl@0
  1867
	}
sl@0
  1868
sl@0
  1869
sl@0
  1870
/** 
sl@0
  1871
This implementation stretches the mask first, and then performs mask tiling. Another approach is to
sl@0
  1872
tile first and then perform stretching. The latter method requires more memory and stretches
sl@0
  1873
once. Results between these methods are different. When stretching first, all tiles will be completely
sl@0
  1874
uniform. When stretching last, different tiles are affected differently, based on the tile's position
sl@0
  1875
and stretch factor.
sl@0
  1876
sl@0
  1877
@see MDirectGdiEngine::DrawBitmapMasked()
sl@0
  1878
@see DrawBitmap()
sl@0
  1879
 */
sl@0
  1880
void CVgEngine::DrawBitmapMasked(
sl@0
  1881
	const TRect& aDestRect,
sl@0
  1882
	const CFbsBitmap& aSourceBitmap,
sl@0
  1883
	const TRect& aSourceRect,
sl@0
  1884
	const CFbsBitmap& aMaskBitmap,
sl@0
  1885
	TBool aInvertMask)
sl@0
  1886
	{
sl@0
  1887
	if ((aSourceBitmap.ExtendedBitmapType() != KNullUid) || (aMaskBitmap.ExtendedBitmapType() != KNullUid))
sl@0
  1888
		{
sl@0
  1889
		iDriver.SetError(KErrNotSupported); // Not supported for extended bitmaps
sl@0
  1890
		return;
sl@0
  1891
		}
sl@0
  1892
	
sl@0
  1893
	MakeEngineCurrent();
sl@0
  1894
	TRect destRect(aDestRect);
sl@0
  1895
	if (!IntersectsClippingRegion (TRect(iOrigin, destRect.Size())))
sl@0
  1896
		{
sl@0
  1897
		return;
sl@0
  1898
		}
sl@0
  1899
sl@0
  1900
	// Create source image
sl@0
  1901
	VGImage sourceImage = VG_INVALID_HANDLE;
sl@0
  1902
	TBool imageCached = ConvertBitmapToVgImage(aSourceBitmap, sourceImage);
sl@0
  1903
	// Return if VGImage failed to be created (error set on creation of VGImage).
sl@0
  1904
	if (sourceImage == VG_INVALID_HANDLE)
sl@0
  1905
		{
sl@0
  1906
		return;
sl@0
  1907
		}
sl@0
  1908
		
sl@0
  1909
	// Convert aMask to a VGImage.
sl@0
  1910
	VGImage maskImage = VG_INVALID_HANDLE;
sl@0
  1911
	TBool maskImageCached = ConvertBitmapToVgImage(aMaskBitmap, maskImage, ETrue);
sl@0
  1912
	// Error set on creation of VGImage if mask == VG_INVALID_HANDLE
sl@0
  1913
sl@0
  1914
	if (maskImage != VG_INVALID_HANDLE)
sl@0
  1915
		{
sl@0
  1916
		TSize destSize = destRect.Size();
sl@0
  1917
		TSize sourceSize = aSourceRect.Size();
sl@0
  1918
		if ((destSize.iWidth == sourceSize.iWidth) && (destSize.iHeight == sourceSize.iHeight))
sl@0
  1919
			{
sl@0
  1920
			// No scaling of masked bitmap involved
sl@0
  1921
			DoVgMaskedImageDraw(
sl@0
  1922
					destRect.iTl,
sl@0
  1923
					sourceImage,
sl@0
  1924
					aSourceBitmap.SizeInPixels(),
sl@0
  1925
					aSourceRect,
sl@0
  1926
					maskImage,
sl@0
  1927
					aMaskBitmap.SizeInPixels(),
sl@0
  1928
					destSize,
sl@0
  1929
					aInvertMask);
sl@0
  1930
			}
sl@0
  1931
		else
sl@0
  1932
			{
sl@0
  1933
			// Unfortunately, the current implementation of VG does not support
sl@0
  1934
			// mask scaling. So, we render the mask into a VGImage pbuffer surface,
sl@0
  1935
			// and apply user to surface scaling to get a stretch. The stretched
sl@0
  1936
			// mask is then used for rendering.
sl@0
  1937
sl@0
  1938
			// Generate the VGImage to act as a pbuffer surface and receive the stretched mask.
sl@0
  1939
			const TSize maskSizeInPixels = aMaskBitmap.SizeInPixels();
sl@0
  1940
			const VGImageFormat vgFormat = MapToVgDisplayMode(ClosestVgCompatibleDisplayMode(aMaskBitmap.DisplayMode()));
sl@0
  1941
			TInt scaledMaskWidth = Scale(maskSizeInPixels.iWidth,destSize.iWidth,sourceSize.iWidth);
sl@0
  1942
			TInt scaledMaskHeight = Scale(maskSizeInPixels.iHeight,destSize.iHeight,sourceSize.iHeight);
sl@0
  1943
			VGImage stretchedMask = DoVgCreateImage(vgFormat,
sl@0
  1944
											scaledMaskWidth,
sl@0
  1945
											scaledMaskHeight,
sl@0
  1946
											VG_IMAGE_QUALITY_NONANTIALIASED);
sl@0
  1947
	 
sl@0
  1948
			if (stretchedMask != VG_INVALID_HANDLE)
sl@0
  1949
				{
sl@0
  1950
				// Get a configuration handle that is compatible with the mask pixel format.
sl@0
  1951
				EGLConfig utilConfig = 0;
sl@0
  1952
				TInt err = TConfigHelper::GetConfigForFbsBitmap (aMaskBitmap, utilConfig);
sl@0
  1953
				if (err == KErrNone)
sl@0
  1954
					{
sl@0
  1955
					TBool eglSuccess = EFalse;
sl@0
  1956
					EGLDisplay eglDisplay = iDriver.EglDisplay();
sl@0
  1957
					EGLSurface lastSurface = eglGetCurrentSurface(EGL_DRAW);
sl@0
  1958
sl@0
  1959
					// Create a Pbuffer surface from the stretched mask VGImage.
sl@0
  1960
					EGLSurface utilSurface = eglCreatePbufferFromClientBuffer(
sl@0
  1961
						eglDisplay, 
sl@0
  1962
						EGL_OPENVG_IMAGE,
sl@0
  1963
						static_cast<EGLClientBuffer>(stretchedMask), 
sl@0
  1964
						utilConfig,
sl@0
  1965
						NULL);
sl@0
  1966
					
sl@0
  1967
					if (utilSurface != EGL_NO_SURFACE)
sl@0
  1968
						{
sl@0
  1969
						EGLContext lastContext = eglGetCurrentContext();
sl@0
  1970
						// Create config. compatible context.
sl@0
  1971
						EGLContext utilContext = eglCreateContext(eglDisplay, utilConfig, lastContext, NULL);	
sl@0
  1972
					
sl@0
  1973
						if (utilContext != EGL_NO_CONTEXT)
sl@0
  1974
							{
sl@0
  1975
							// Make the utility surface and context current, and stretch the mask.
sl@0
  1976
							if (eglMakeCurrent(eglDisplay, utilSurface, utilSurface, utilContext) == EGL_TRUE)
sl@0
  1977
								{
sl@0
  1978
								// Set up the scaling transform for the current surface.
sl@0
  1979
								vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
sl@0
  1980
								// Scaling factors for x and y.
sl@0
  1981
								VGfloat xScale = ((VGfloat)destSize.iWidth/sourceSize.iWidth);
sl@0
  1982
								VGfloat yScale = ((VGfloat)destSize.iHeight/sourceSize.iHeight);
sl@0
  1983
								vgScale(xScale, yScale);
sl@0
  1984
								
sl@0
  1985
								// Render the stretched mask.
sl@0
  1986
								vgDrawImage(maskImage);
sl@0
  1987
								ResetVgMatrix(VG_MATRIX_IMAGE_USER_TO_SURFACE);
sl@0
  1988
								
sl@0
  1989
								// All done, make current the pre-existing rendering state.
sl@0
  1990
								eglMakeCurrent(eglDisplay, lastSurface, lastSurface, lastContext);
sl@0
  1991
								
sl@0
  1992
								eglSuccess = ETrue;
sl@0
  1993
								}
sl@0
  1994
							eglDestroyContext(eglDisplay, utilContext);
sl@0
  1995
							}
sl@0
  1996
						eglDestroySurface(eglDisplay, utilSurface);
sl@0
  1997
						}	
sl@0
  1998
					
sl@0
  1999
					if (eglSuccess)
sl@0
  2000
						{
sl@0
  2001
						DoVgMaskedImageDraw(destRect.iTl, sourceImage, aSourceBitmap.SizeInPixels(),
sl@0
  2002
											aSourceRect, stretchedMask,	maskSizeInPixels, destSize,	aInvertMask);
sl@0
  2003
						}
sl@0
  2004
					else
sl@0
  2005
						{						
sl@0
  2006
						// coverity[check_return]
sl@0
  2007
						// coverity[unchecked_value]
sl@0
  2008
						LogEglError();
sl@0
  2009
						}
sl@0
  2010
					}				
sl@0
  2011
				else
sl@0
  2012
					{
sl@0
  2013
					iDriver.SetError(err);
sl@0
  2014
					}
sl@0
  2015
				vgDestroyImage (stretchedMask);
sl@0
  2016
				}
sl@0
  2017
			if (!maskImageCached) vgDestroyImage (maskImage);
sl@0
  2018
			}
sl@0
  2019
		}
sl@0
  2020
	if (!imageCached) vgDestroyImage(sourceImage);
sl@0
  2021
	}
sl@0
  2022
sl@0
  2023
/** 
sl@0
  2024
Helper method that implements the core blitting functionality.
sl@0
  2025
sl@0
  2026
@param	aDestPos	The destination for the top left corner of the transferred bitmap. 
sl@0
  2027
					It is relative to the top left corner of the destination bitmap, which may be the screen. 
sl@0
  2028
@param	aSourceImage A valid VGImage to draw.
sl@0
  2029
@param  aSourceImageSize Extents of source bitmap.
sl@0
  2030
@param	aSourceRect	A rectangle defining the piece of the bitmap to be drawn, 
sl@0
  2031
					with co-ordinates relative to the top left corner of the bitmap. 
sl@0
  2032
@param	aScaledMaskImage A valid mask VGImage - pre-scaled, ready for rendering.
sl@0
  2033
@param	aSrcMaskSize The size of the (unscaled) mask image.
sl@0
  2034
@param	aXscale		Scaling factor to apply to x axis (already applied to mask).
sl@0
  2035
@param	aYscale		Scaling factor to apply to y axis (already applied to mask).
sl@0
  2036
@param	aDestSize	The size of the destination (used for calculating any scaling) 
sl@0
  2037
@param	aInvertMask	If EFalse, a source pixel that is masked by a black pixel 
sl@0
  2038
					is not transferred to the destination rectangle. If ETrue, then a source 
sl@0
  2039
					pixel that is masked by a white pixel is not transferred to the destination 
sl@0
  2040
					rectangle. 
sl@0
  2041
sl@0
  2042
@pre	The rendering target has been activated. aBitmap and aMaskBitmap are not NULL and hold Handles. 
sl@0
  2043
		Destination rectangle extents must intersect clipping region.
sl@0
  2044
		aSourceImage is a valid VGImage handle.
sl@0
  2045
@post	Request to draw the masked bitmap content has been accepted. 
sl@0
  2046
		There is no guarantee that the request has been processed when the method returns.
sl@0
  2047
 */
sl@0
  2048
void CVgEngine::DoVgMaskedImageDraw(
sl@0
  2049
		const TPoint& aDestPos,
sl@0
  2050
		VGImage aSourceImage,
sl@0
  2051
		const TRect& aSourceImageSize,
sl@0
  2052
		const TRect& aSourceRect,
sl@0
  2053
		const VGImage aScaledMaskImage,
sl@0
  2054
		const TSize& aSrcMaskSize,
sl@0
  2055
		const TSize& aDestSize,
sl@0
  2056
		TBool aInvertMask) 
sl@0
  2057
	{
sl@0
  2058
	TBool destroySourceImageAtEnd = EFalse;
sl@0
  2059
sl@0
  2060
	if(aSourceImageSize != aSourceRect)
sl@0
  2061
		{
sl@0
  2062
		aSourceImage = 
sl@0
  2063
			vgChildImage(
sl@0
  2064
				aSourceImage, 
sl@0
  2065
				aSourceRect.iTl.iX, 
sl@0
  2066
				aSourceRect.iTl.iY, 
sl@0
  2067
				aSourceRect.Width(), 
sl@0
  2068
				aSourceRect.Height());
sl@0
  2069
sl@0
  2070
		if (aSourceImage == VG_INVALID_HANDLE) return;
sl@0
  2071
		destroySourceImageAtEnd = ETrue;
sl@0
  2072
		}
sl@0
  2073
sl@0
  2074
	TBool maskOK = EFalse;
sl@0
  2075
	TSize sourceSize = aSourceRect.Size();
sl@0
  2076
	TRect destRect(aDestPos, TSize(Scale(aSourceRect.Width(),aDestSize.iWidth,sourceSize.iWidth),
sl@0
  2077
										Scale(aSourceRect.Height(),aDestSize.iHeight,sourceSize.iHeight)));
sl@0
  2078
	// VG does not provide mask tiling...we currently perform multiple
sl@0
  2079
	// vgMask operations to implement tiling. It should be possible to use
sl@0
  2080
	// pattern tiling to render the mask to a surface, convert surface region
sl@0
  2081
	// to VGImage and apply that as a mask (to take advantage of native VG
sl@0
  2082
	// tiling), though cost/benefit is has not yet been determined.
sl@0
  2083
	// NOTE: It may be worth optimising for cases where xScale or yScale equal one.
sl@0
  2084
sl@0
  2085
	TRect destVgRect = SgMetricsToVgTRect(aDestPos, destRect.Width(), destRect.Height());
sl@0
  2086
sl@0
  2087
	if (aScaledMaskImage != VG_INVALID_HANDLE)
sl@0
  2088
		{
sl@0
  2089
		const TSize scaledMaskSize(Scale(aSrcMaskSize.iWidth,aDestSize.iWidth,sourceSize.iWidth),
sl@0
  2090
										Scale(aSrcMaskSize.iHeight,aDestSize.iHeight,sourceSize.iHeight));
sl@0
  2091
		if (scaledMaskSize.iHeight > 0 && scaledMaskSize.iWidth > 0)
sl@0
  2092
			{
sl@0
  2093
			maskOK = ETrue;
sl@0
  2094
			// Determine mask image offset for rendering.
sl@0
  2095
			TInt scaledMaskXOffset = Scale(aSourceRect.iTl.iX%aSrcMaskSize.iWidth,aDestSize.iWidth,sourceSize.iWidth);
sl@0
  2096
sl@0
  2097
			// Sg coordinates are relative to top left, Vg are reletive to bottom left. As we
sl@0
  2098
			// tile from the bottom up we subtract from maskSize.iHeight to get the bottom edge
sl@0
  2099
			// offset.
sl@0
  2100
			TInt scaledMaskYOffset = (aSourceRect.iTl.iY + aSourceRect.Height()) % aSrcMaskSize.iHeight;
sl@0
  2101
			if (scaledMaskYOffset != 0)
sl@0
  2102
				{
sl@0
  2103
				scaledMaskYOffset = Scale(aSrcMaskSize.iHeight-scaledMaskYOffset,aDestSize.iHeight,sourceSize.iHeight);
sl@0
  2104
				}
sl@0
  2105
sl@0
  2106
			// If inverting the mask, we use a difference operation against the existing mask, so 
sl@0
  2107
			// we need to ensure the existing mask is set to the correct state.
sl@0
  2108
			// Fill the existing mask so that it is completly transparent (set to all ones).
sl@0
  2109
			if(aInvertMask)
sl@0
  2110
				{
sl@0
  2111
				vgMask(
sl@0
  2112
					VG_INVALID_HANDLE, 
sl@0
  2113
					VG_FILL_MASK, 
sl@0
  2114
					destVgRect.iTl.iX, 
sl@0
  2115
					destVgRect.iTl.iY, 
sl@0
  2116
					destVgRect.Width(), 
sl@0
  2117
					destVgRect.Height());			
sl@0
  2118
				}
sl@0
  2119
		
sl@0
  2120
			VGMaskOperation vgMaskOp = aInvertMask ? VG_SUBTRACT_MASK : VG_SET_MASK;
sl@0
  2121
			// NOTE: in VG destVgRect.iTl is physically at the bottom and destVgRect.iBr at the top
sl@0
  2122
			for (
sl@0
  2123
				TInt maskY = destVgRect.iTl.iY - scaledMaskYOffset; 
sl@0
  2124
				maskY < destVgRect.iBr.iY; 
sl@0
  2125
				maskY += scaledMaskSize.iHeight)
sl@0
  2126
				{
sl@0
  2127
				for (
sl@0
  2128
					TInt maskX = destVgRect.iTl.iX - scaledMaskXOffset;
sl@0
  2129
					maskX < destVgRect.iBr.iX;
sl@0
  2130
					maskX += scaledMaskSize.iWidth)
sl@0
  2131
					{
sl@0
  2132
					vgMask(
sl@0
  2133
						aScaledMaskImage, 
sl@0
  2134
						vgMaskOp, 
sl@0
  2135
						maskX,
sl@0
  2136
						maskY, 
sl@0
  2137
						scaledMaskSize.iWidth,
sl@0
  2138
						scaledMaskSize.iHeight);
sl@0
  2139
					}
sl@0
  2140
				}
sl@0
  2141
			}
sl@0
  2142
		}		
sl@0
  2143
	
sl@0
  2144
	// Set up translation and scale for the current surface - note that translation must
sl@0
  2145
	// occur first, as is unscaled.
sl@0
  2146
	vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
sl@0
  2147
	vgTranslate(aDestPos.iX, aDestPos.iY);
sl@0
  2148
	VGfloat xScale = ((VGfloat)aDestSize.iWidth/sourceSize.iWidth);
sl@0
  2149
	VGfloat yScale = ((VGfloat)aDestSize.iHeight/sourceSize.iHeight);
sl@0
  2150
	vgScale(xScale, yScale);
sl@0
  2151
	
sl@0
  2152
	//  Rather than bracketing vgDrawImage with VG_MASKING on/off we may want to always enable masking,
sl@0
  2153
	//  and remove the mask when finished:
sl@0
  2154
	//  vgMask(VG_INVALID_HANDLE, VG_CLEAR_MASK, 0, 0, iRenderingTarget->Size().iWidth, iRenderingTarget->Size().iHeight);
sl@0
  2155
	//  If the mask is not removed in some way, then subsequent rendering operations which intersect with the
sl@0
  2156
	//  masking region will be affected.
sl@0
  2157
	if (maskOK) 
sl@0
  2158
		{
sl@0
  2159
		vgSeti (VG_MASKING, VG_TRUE);
sl@0
  2160
		for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
  2161
			vgDrawImage(aSourceImage);
sl@0
  2162
		vgSeti (VG_MASKING, VG_FALSE);
sl@0
  2163
		}
sl@0
  2164
	else
sl@0
  2165
		{
sl@0
  2166
		for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
  2167
			vgDrawImage(aSourceImage);
sl@0
  2168
		}
sl@0
  2169
	// Reset the transform matrix.
sl@0
  2170
	ResetVgMatrix(VG_MATRIX_IMAGE_USER_TO_SURFACE);
sl@0
  2171
	
sl@0
  2172
	if (destroySourceImageAtEnd)
sl@0
  2173
		{
sl@0
  2174
		vgDestroyImage (aSourceImage);
sl@0
  2175
		}
sl@0
  2176
	}
sl@0
  2177
sl@0
  2178
/** 
sl@0
  2179
@see MDirectGdiEngine::DrawResource(const TPoint&, const RDirectGdiDrawableSource&, DirectGdi::TGraphicsRotation)
sl@0
  2180
@see DrawResource(const TRect&, const RDirectGdiDrawableSource&, const TRect&, DirectGdi::TGraphicsRotation)
sl@0
  2181
@see DrawResource(const TRect&, const RDirectGdiDrawableSource&, const TDesC8&)
sl@0
  2182
 */
sl@0
  2183
void CVgEngine::DrawResource(const TPoint& aPos, const RDirectGdiDrawableSource& aSource, DirectGdi::TGraphicsRotation aRotation)
sl@0
  2184
	{
sl@0
  2185
	MakeEngineCurrent();
sl@0
  2186
	
sl@0
  2187
	CDirectGdiImageSourceImpl* source = iDriver.GetImageSourceFromHandle(aSource.Handle());
sl@0
  2188
	if (source)
sl@0
  2189
		{			
sl@0
  2190
		const TSize sourceSize = source->Size();				
sl@0
  2191
		
sl@0
  2192
		if ((sourceSize.iWidth > 0) && (sourceSize.iHeight > 0))
sl@0
  2193
			{
sl@0
  2194
			VGImage vgImage = source->VgImage();
sl@0
  2195
			if (vgImage != VG_INVALID_HANDLE)
sl@0
  2196
				{
sl@0
  2197
				vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
sl@0
  2198
				
sl@0
  2199
				TPoint pos(aPos);
sl@0
  2200
				
sl@0
  2201
			
sl@0
  2202
				if (aRotation == DirectGdi::EGraphicsRotationNone ||
sl@0
  2203
					aRotation == DirectGdi::EGraphicsRotation180)
sl@0
  2204
					{
sl@0
  2205
					// Pixel-data in EGLImages appears to be upside down due to the Y-inversion 
sl@0
  2206
					// effect of the Identity matrix.  Therefore must undo the Y-inversion here 
sl@0
  2207
					// and adjust destination rect accordingly.
sl@0
  2208
					pos.iY = iSize.iHeight - aPos.iY - sourceSize.iHeight - iOrigin.iY;
sl@0
  2209
					pos.iX += iOrigin.iX;
sl@0
  2210
					vgLoadIdentity();
sl@0
  2211
					}
sl@0
  2212
				else
sl@0
  2213
					{
sl@0
  2214
					// But if rotation is 90 or 270 degrees we need to mirror in the X-axis
sl@0
  2215
					// and adjust destination translation accordingly.
sl@0
  2216
					vgScale(-1, 1);
sl@0
  2217
					}
sl@0
  2218
							
sl@0
  2219
				switch (aRotation)
sl@0
  2220
					{				
sl@0
  2221
					case DirectGdi::EGraphicsRotation90:
sl@0
  2222
						vgTranslate(-pos.iX, pos.iY);
sl@0
  2223
						vgRotate(90.0f);
sl@0
  2224
						break;
sl@0
  2225
					case DirectGdi::EGraphicsRotation180:
sl@0
  2226
						vgTranslate(pos.iX+sourceSize.iWidth, pos.iY+sourceSize.iHeight);
sl@0
  2227
						vgRotate(180.0f);				
sl@0
  2228
						break;
sl@0
  2229
					case DirectGdi::EGraphicsRotation270:
sl@0
  2230
						vgTranslate(-pos.iX-sourceSize.iHeight, pos.iY+sourceSize.iWidth);
sl@0
  2231
						vgRotate(270.0f);				
sl@0
  2232
						break;
sl@0
  2233
					default:
sl@0
  2234
						// No rotation
sl@0
  2235
						vgTranslate(pos.iX, pos.iY);									
sl@0
  2236
						break;
sl@0
  2237
					}
sl@0
  2238
				
sl@0
  2239
				for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
  2240
					vgDrawImage(vgImage);				
sl@0
  2241
				
sl@0
  2242
				ResetVgMatrix(VG_MATRIX_IMAGE_USER_TO_SURFACE);
sl@0
  2243
				}
sl@0
  2244
			}
sl@0
  2245
		}
sl@0
  2246
	}
sl@0
  2247
sl@0
  2248
/** 
sl@0
  2249
@see MDirectGdiEngine::DrawResource(const TRect&, const RDirectGdiDrawableSource&, DirectGdi::TGraphicsRotation)
sl@0
  2250
 */
sl@0
  2251
void CVgEngine::DrawResource(const TRect& aDestRect,
sl@0
  2252
		const RDirectGdiDrawableSource& aSource,
sl@0
  2253
		DirectGdi::TGraphicsRotation aRotation)
sl@0
  2254
	{
sl@0
  2255
	CDirectGdiImageSourceImpl* source = iDriver.GetImageSourceFromHandle(aSource.Handle());
sl@0
  2256
	if (source)
sl@0
  2257
		{		
sl@0
  2258
		TRect srcRect(TPoint(0, 0), source->Size());		
sl@0
  2259
		DoDrawResource(aDestRect, source, srcRect, aRotation);		
sl@0
  2260
		}
sl@0
  2261
	}
sl@0
  2262
sl@0
  2263
/** 
sl@0
  2264
@see MDirectGdiEngine::DrawResource(const TRect&, const RDirectGdiDrawableSource&, const TRect&, DirectGdi::TGraphicsRotation)
sl@0
  2265
 */
sl@0
  2266
void CVgEngine::DrawResource(const TRect& aDestRect,
sl@0
  2267
							const RDirectGdiDrawableSource& aSource,
sl@0
  2268
							const TRect& aSourceRect,
sl@0
  2269
							DirectGdi::TGraphicsRotation aRotation)
sl@0
  2270
	{	
sl@0
  2271
	CDirectGdiImageSourceImpl* source = iDriver.GetImageSourceFromHandle(aSource.Handle());
sl@0
  2272
	if (source)
sl@0
  2273
		{
sl@0
  2274
		// check source rectangle is fully contained within the image resource extent before drawing
sl@0
  2275
		TSize size = source->Size();				
sl@0
  2276
		if ((aSourceRect.iTl.iX < 0) 
sl@0
  2277
			|| (aSourceRect.iTl.iY < 0) 
sl@0
  2278
			|| (aSourceRect.iBr.iX > size.iWidth) 
sl@0
  2279
			|| (aSourceRect.iBr.iY > size.iHeight)
sl@0
  2280
			|| (aSourceRect.Width() <= 0) 
sl@0
  2281
			|| (aSourceRect.Height() <= 0))
sl@0
  2282
			{
sl@0
  2283
			iDriver.SetError(KErrArgument);
sl@0
  2284
			return;
sl@0
  2285
			}
sl@0
  2286
						
sl@0
  2287
		if (((aSourceRect.Width() == aDestRect.Width())
sl@0
  2288
			&& (aSourceRect.Height() == aDestRect.Height())
sl@0
  2289
			&& (aRotation == DirectGdi::EGraphicsRotationNone || aRotation == DirectGdi::EGraphicsRotation180))
sl@0
  2290
			||
sl@0
  2291
			((aSourceRect.Width() == aDestRect.Height())
sl@0
  2292
			&& (aSourceRect.Height() == aDestRect.Width())
sl@0
  2293
			&& (aRotation == DirectGdi::EGraphicsRotation90 || aRotation == DirectGdi::EGraphicsRotation270)))
sl@0
  2294
			{
sl@0
  2295
			// No scaling
sl@0
  2296
			DrawResource(TPoint(aDestRect.iTl.iX, aDestRect.iTl.iY), aSource, aRotation);
sl@0
  2297
			}
sl@0
  2298
		else
sl@0
  2299
			{
sl@0
  2300
			MakeEngineCurrent();			
sl@0
  2301
			DoDrawResource(aDestRect, source, aSourceRect, aRotation);												
sl@0
  2302
			}
sl@0
  2303
		}		
sl@0
  2304
	}
sl@0
  2305
sl@0
  2306
/** 
sl@0
  2307
This method only supports drawing of image sources as Drawables. An attempt to draw
sl@0
  2308
a Drawable that is not an image will result in a panic.
sl@0
  2309
sl@0
  2310
@see MDirectGdiEngine::DrawResource(const TRect&, const RDirectGdiDrawableSource&, const TDesC8&)
sl@0
  2311
sl@0
  2312
@panic DGDIAdapter 1, if an attempt is made to draw a drawable that is not an image source.
sl@0
  2313
 */
sl@0
  2314
void CVgEngine::DrawResource(
sl@0
  2315
			const TRect& aDestRect,
sl@0
  2316
			const RDirectGdiDrawableSource& aSource,
sl@0
  2317
			const TDesC8& /*aParam*/)
sl@0
  2318
	{
sl@0
  2319
	MakeEngineCurrent();
sl@0
  2320
	
sl@0
  2321
	// Check to see if the passed drawable is actually an image as we only support drawing of images at present
sl@0
  2322
	if (iDriver.IsImageSource(aSource.Handle()))
sl@0
  2323
		{
sl@0
  2324
		CDirectGdiImageSourceImpl* source = iDriver.GetImageSourceFromHandle(aSource.Handle());
sl@0
  2325
		if (source)
sl@0
  2326
			{		
sl@0
  2327
			DoDrawResource(aDestRect, source, DirectGdi::EGraphicsRotationNone);
sl@0
  2328
			}
sl@0
  2329
		}
sl@0
  2330
	else
sl@0
  2331
		{
sl@0
  2332
		// This method only supports drawing image sources at present
sl@0
  2333
		GRAPHICS_ASSERT_ALWAYS(0, EDirectGdiPanicNotImplemented);
sl@0
  2334
		}
sl@0
  2335
	}
sl@0
  2336
sl@0
  2337
/**
sl@0
  2338
@see MDirectGdiEngine::BeginDrawGlyph()
sl@0
  2339
sl@0
  2340
Sets the necessary OpenVG and engine state ready for receiving DrawGlyph() commands.
sl@0
  2341
Any OpenVG state that is common for all DrawGlyph() operations are set.
sl@0
  2342
 */
sl@0
  2343
void CVgEngine::BeginDrawGlyph()
sl@0
  2344
	{
sl@0
  2345
	MakeEngineCurrent();	
sl@0
  2346
	vgSetPaint(iTextBrush, VG_FILL_PATH);
sl@0
  2347
	vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
sl@0
  2348
#ifdef DRAWGLYPH_MULTIPLY_MODE
sl@0
  2349
	vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_MULTIPLY);
sl@0
  2350
#else
sl@0
  2351
	vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_STENCIL);
sl@0
  2352
#endif
sl@0
  2353
	
sl@0
  2354
#ifdef DRAWGLYPH_BUFFERED
sl@0
  2355
	iDrawGlyphCount = 0;
sl@0
  2356
#endif
sl@0
  2357
	}
sl@0
  2358
sl@0
  2359
/**
sl@0
  2360
Draws Glyph image to the given position and orientation. 
sl@0
  2361
The function crops the output image to the clipping rectangle specified as a parameter. 
sl@0
  2362
If the clipping region is defined on the current context, it will also be taken into consideration 
sl@0
  2363
sl@0
  2364
@param	aScrPos				Position to start drawing glyph after rotation has been applied (if necessary).
sl@0
  2365
@param	aChar				Character being drawn. Signifies general Unicode character value.
sl@0
  2366
@param	aGlyphImage			Pointer to the glyph image data.
sl@0
  2367
@param	aGlyphBitmapType	Type of bitmap format.
sl@0
  2368
@param	aGlyphImageSize		Glyph image size.
sl@0
  2369
@param	aScrClipRect			Clipping rect.
sl@0
  2370
@param	aRotation			Rotation specifying how the glyph will be drawn. The number can only be divisible by 90 degrees, 
sl@0
  2371
							i.e. horizontal and vertical rotation.
sl@0
  2372
sl@0
  2373
@see  CFont::TTextDirection
sl@0
  2374
@see MDirectGdiEngine::DrawGlyph()
sl@0
  2375
sl@0
  2376
@pre	The rendering target has been activated.
sl@0
  2377
@post	Request to draw the Glyph has been accepted.
sl@0
  2378
@panic  DGDIAdapter 8, if aClipRect is empty (debug-only).
sl@0
  2379
@panic  DGDIAdapter 61, if font glyph image storage does not exist (debug-only).
sl@0
  2380
*/
sl@0
  2381
void CVgEngine::DrawGlyph(
sl@0
  2382
			const TPoint& aScrPos, 
sl@0
  2383
			const TChar aChar, 
sl@0
  2384
			const TUint8* aGlyphImage,
sl@0
  2385
			const TGlyphBitmapType aGlyphBitmapType,
sl@0
  2386
			const TSize& aGlyphImageSize,
sl@0
  2387
			const TRect& aScrClipRect,			
sl@0
  2388
			const DirectGdi::TGraphicsRotation aRotation)
sl@0
  2389
	{
sl@0
  2390
	GRAPHICS_ASSERT_DEBUG(!aScrClipRect.IsEmpty(), EDirectGdiPanicInvalidRegion);
sl@0
  2391
	GRAPHICS_ASSERT_DEBUG(iFontGlyphImageStorage, EDirectGdiPanicGlyphImageStorageNotCreated);
sl@0
  2392
	
sl@0
  2393
	TPoint pos = aScrPos;
sl@0
  2394
	pos += iDrawOrigin;
sl@0
  2395
	TRect clipRect = aScrClipRect;
sl@0
  2396
	clipRect.iTl += iDrawOrigin;
sl@0
  2397
	clipRect.iBr += iDrawOrigin;
sl@0
  2398
	
sl@0
  2399
	if(	aGlyphImageSize.iHeight <= 0 ||	aGlyphImageSize.iWidth <= 0 ||
sl@0
  2400
		!clipRect.Intersects(iTargetRegion.BoundingRect()) || !iRegionManager.Intersects(clipRect))
sl@0
  2401
		{
sl@0
  2402
		// Just leave silently, as spaces could be passed with empty size.
sl@0
  2403
		return;
sl@0
  2404
		}
sl@0
  2405
	
sl@0
  2406
	// Clip the glyph against the target and the clipping rects.
sl@0
  2407
	// Calculate the axis-aligned bounding box of the glyph.
sl@0
  2408
	TRect glyphBoundingBox;
sl@0
  2409
	switch(aRotation)
sl@0
  2410
		{
sl@0
  2411
		case DirectGdi::EGraphicsRotation90:
sl@0
  2412
			glyphBoundingBox = TRect(TPoint(1+pos.iX-aGlyphImageSize.iHeight, pos.iY), TSize(aGlyphImageSize.iHeight, aGlyphImageSize.iWidth));
sl@0
  2413
			break;
sl@0
  2414
		case DirectGdi::EGraphicsRotation180:
sl@0
  2415
			glyphBoundingBox = TRect(TPoint(pos.iX-aGlyphImageSize.iHeight, pos.iY-aGlyphImageSize.iWidth), aGlyphImageSize);
sl@0
  2416
			break;
sl@0
  2417
		case DirectGdi::EGraphicsRotation270:
sl@0
  2418
			glyphBoundingBox = TRect(TPoint(pos.iX, 1+pos.iY-aGlyphImageSize.iWidth), TSize(aGlyphImageSize.iHeight, aGlyphImageSize.iWidth));
sl@0
  2419
			break;
sl@0
  2420
		default:
sl@0
  2421
			glyphBoundingBox = TRect(pos, aGlyphImageSize);
sl@0
  2422
			break;
sl@0
  2423
		}
sl@0
  2424
	if (!glyphBoundingBox.Intersects(iTargetRegion.BoundingRect()) || !iRegionManager.Intersects(glyphBoundingBox))
sl@0
  2425
		{
sl@0
  2426
		return;
sl@0
  2427
		}
sl@0
  2428
#ifdef DRAWGLYPH_BUFFERED
sl@0
  2429
	iDrawGlyphCommand[iDrawGlyphCount].pos = pos;
sl@0
  2430
	iDrawGlyphCommand[iDrawGlyphCount].aChar = aChar;
sl@0
  2431
	iDrawGlyphCommand[iDrawGlyphCount].aGlyphBitmapType = aGlyphBitmapType;
sl@0
  2432
	iDrawGlyphCommand[iDrawGlyphCount].aGlyphImageSize = aGlyphImageSize;
sl@0
  2433
	iDrawGlyphCommand[iDrawGlyphCount].aClipRect = clipRect;
sl@0
  2434
	iDrawGlyphCommand[iDrawGlyphCount].aRotation = aRotation;
sl@0
  2435
	iDrawGlyphCommand[iDrawGlyphCount].aGlyphImage = const_cast<TUint8*>(aGlyphImage);	
sl@0
  2436
	++iDrawGlyphCount;	
sl@0
  2437
	if (iDrawGlyphCount == KMaxGlyphs)
sl@0
  2438
		{
sl@0
  2439
		FlushDrawGlyphs();
sl@0
  2440
		iDrawGlyphCount = 0;
sl@0
  2441
		}
sl@0
  2442
#else	
sl@0
  2443
	VGImage foreground = VG_INVALID_HANDLE;
sl@0
  2444
	VGImage outline = VG_INVALID_HANDLE;
sl@0
  2445
	VGImage shadow = VG_INVALID_HANDLE;
sl@0
  2446
sl@0
  2447
	TInt err = iFontGlyphImageStorage -> GlyphImage(iFontId, aChar, aGlyphBitmapType, aGlyphImage, aGlyphImageSize, &foreground, &shadow, &outline);
sl@0
  2448
	if(err != KErrNone)
sl@0
  2449
		{
sl@0
  2450
		iDriver.SetError(err);
sl@0
  2451
		if(err == KErrNoMemory)
sl@0
  2452
			{
sl@0
  2453
			if((foreground == VG_INVALID_HANDLE) || 
sl@0
  2454
				((aGlyphBitmapType == EFourColourBlendGlyphBitmap) && ((shadow == VG_INVALID_HANDLE) || (outline == VG_INVALID_HANDLE))))
sl@0
  2455
				{
sl@0
  2456
				return;
sl@0
  2457
				}
sl@0
  2458
			}
sl@0
  2459
		else
sl@0
  2460
			{
sl@0
  2461
			return;
sl@0
  2462
			}
sl@0
  2463
		}
sl@0
  2464
	
sl@0
  2465
	RRegion oldClippingRegion;
sl@0
  2466
	oldClippingRegion.Copy(iRegionManager.ClippingRegion());
sl@0
  2467
	iRegionManager.ClipTo(clipRect);
sl@0
  2468
	
sl@0
  2469
	//  Load the matrix which converts Symbian coordinate system to OpenVG coordinate system
sl@0
  2470
	vgLoadMatrix(Identity());
sl@0
  2471
	if(aRotation == DirectGdi::EGraphicsRotation90)
sl@0
  2472
		{
sl@0
  2473
		vgTranslate(pos.iX+1, pos.iY);
sl@0
  2474
		vgRotate(90.0f);
sl@0
  2475
		}
sl@0
  2476
	else if(aRotation == DirectGdi::EGraphicsRotation270)
sl@0
  2477
		{
sl@0
  2478
		vgTranslate(pos.iX, pos.iY+1);
sl@0
  2479
		vgRotate(270.0f);
sl@0
  2480
		}
sl@0
  2481
	else
sl@0
  2482
		{
sl@0
  2483
		vgTranslate(pos.iX, pos.iY);
sl@0
  2484
		}		
sl@0
  2485
sl@0
  2486
	switch(aGlyphBitmapType)
sl@0
  2487
		{
sl@0
  2488
		case EMonochromeGlyphBitmap:
sl@0
  2489
		case EAntiAliasedGlyphBitmap:
sl@0
  2490
			for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
  2491
				vgDrawImage(foreground);
sl@0
  2492
			break;
sl@0
  2493
		case EFourColourBlendGlyphBitmap:
sl@0
  2494
			{
sl@0
  2495
			SetVgPaintColor(iTextBrush, iBrushColor);
sl@0
  2496
			for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
  2497
				vgDrawImage(foreground);
sl@0
  2498
	
sl@0
  2499
			SetVgPaintColor(iTextBrush, iTextShadowColor);
sl@0
  2500
			for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
  2501
				vgDrawImage(shadow);
sl@0
  2502
	
sl@0
  2503
			SetVgPaintColor(iTextBrush, iPenColor);
sl@0
  2504
			for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
  2505
				vgDrawImage(outline);
sl@0
  2506
			break;
sl@0
  2507
			}
sl@0
  2508
		}
sl@0
  2509
sl@0
  2510
	// Restore the clipping manager to its previous state.
sl@0
  2511
	iRegionManager.SetClippingRegion(oldClippingRegion);
sl@0
  2512
	oldClippingRegion.Close();
sl@0
  2513
#endif
sl@0
  2514
	}
sl@0
  2515
sl@0
  2516
/**
sl@0
  2517
@see MDirectGdiEngine::EndDrawGlyph()
sl@0
  2518
sl@0
  2519
Undoes any OpenVG or engine state changes made in BeginDrawGlyph().
sl@0
  2520
 */
sl@0
  2521
void CVgEngine::EndDrawGlyph()
sl@0
  2522
	{
sl@0
  2523
#ifdef DRAWGLYPH_BUFFERED
sl@0
  2524
	FlushDrawGlyphs();
sl@0
  2525
	iDrawGlyphCount = 0;
sl@0
  2526
#endif
sl@0
  2527
	vgLoadMatrix(Identity());
sl@0
  2528
	if (iOrigin != TPoint(0,0))
sl@0
  2529
		{
sl@0
  2530
		vgTranslate(iOrigin.iX, iOrigin.iY);
sl@0
  2531
		}
sl@0
  2532
		
sl@0
  2533
	vgSetPaint(iBrush, VG_FILL_PATH);
sl@0
  2534
	vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL);
sl@0
  2535
	}
sl@0
  2536
sl@0
  2537
#ifdef DRAWGLYPH_BUFFERED
sl@0
  2538
void CVgEngine::FlushDrawGlyphs()
sl@0
  2539
	{
sl@0
  2540
	VGImage foreground[KMaxGlyphs];
sl@0
  2541
	Mem::FillZ(foreground, iDrawGlyphCount*sizeof(VGImage));
sl@0
  2542
	VGImage outline[KMaxGlyphs];
sl@0
  2543
	VGImage shadow[KMaxGlyphs];
sl@0
  2544
	
sl@0
  2545
	for (TInt glyph = 0; glyph < iDrawGlyphCount; ++glyph)
sl@0
  2546
		{
sl@0
  2547
		if (foreground[glyph] == 0)
sl@0
  2548
			{			
sl@0
  2549
			TSize aGlyphImageSize = iDrawGlyphCommand[glyph].aGlyphImageSize;
sl@0
  2550
			TChar aChar = iDrawGlyphCommand[glyph].aChar;
sl@0
  2551
			TGlyphBitmapType aGlyphBitmapType = iDrawGlyphCommand[glyph].aGlyphBitmapType;
sl@0
  2552
			TUint8* aGlyphImage = iDrawGlyphCommand[glyph].aGlyphImage;
sl@0
  2553
		
sl@0
  2554
			VGImage foreground1 = VG_INVALID_HANDLE;
sl@0
  2555
			VGImage outline1 = VG_INVALID_HANDLE;
sl@0
  2556
			VGImage shadow1 = VG_INVALID_HANDLE;
sl@0
  2557
		
sl@0
  2558
			TInt err = iFontGlyphImageStorage -> GlyphImage(iFontId, aChar, aGlyphBitmapType, aGlyphImage, aGlyphImageSize, &foreground1, &shadow1, &outline1);
sl@0
  2559
			if(err != KErrNone)
sl@0
  2560
				{
sl@0
  2561
				iDriver.SetError(err);
sl@0
  2562
				if(err == KErrNoMemory)
sl@0
  2563
					{
sl@0
  2564
					if((foreground1 == VG_INVALID_HANDLE) || 
sl@0
  2565
						((aGlyphBitmapType == EFourColourBlendGlyphBitmap) && ((shadow1 == VG_INVALID_HANDLE) || (outline1 == VG_INVALID_HANDLE))))
sl@0
  2566
						{
sl@0
  2567
						return;
sl@0
  2568
						}
sl@0
  2569
					}
sl@0
  2570
				else
sl@0
  2571
					{
sl@0
  2572
					return;
sl@0
  2573
					}
sl@0
  2574
				}
sl@0
  2575
			
sl@0
  2576
			foreground[glyph] = foreground1;
sl@0
  2577
			outline[glyph] = outline1;
sl@0
  2578
			shadow[glyph] = shadow1;
sl@0
  2579
			
sl@0
  2580
			for (TInt nextGlyph = glyph+1; nextGlyph < iDrawGlyphCount; nextGlyph++)
sl@0
  2581
				{
sl@0
  2582
				if (foreground[nextGlyph] == 0)
sl@0
  2583
					{
sl@0
  2584
					if (iDrawGlyphCommand[glyph].SameGlyph(iDrawGlyphCommand[nextGlyph]))
sl@0
  2585
						{
sl@0
  2586
						foreground[nextGlyph] = foreground[glyph];
sl@0
  2587
						outline[nextGlyph] = outline[glyph];
sl@0
  2588
						shadow[nextGlyph] = shadow[glyph];
sl@0
  2589
						}
sl@0
  2590
					}
sl@0
  2591
				}
sl@0
  2592
			}
sl@0
  2593
		}
sl@0
  2594
		
sl@0
  2595
	RRegion oldClippingRegion;
sl@0
  2596
	oldClippingRegion.Copy(iRegionManager.ClippingRegion());
sl@0
  2597
	vgLoadMatrix(Identity());
sl@0
  2598
	TPoint lastPos;
sl@0
  2599
	for (TInt glyph = 0; glyph < iDrawGlyphCount; ++glyph)
sl@0
  2600
		{
sl@0
  2601
		TGlyphBitmapType aGlyphBitmapType = iDrawGlyphCommand[glyph].aGlyphBitmapType;
sl@0
  2602
		TRect aClipRect = iDrawGlyphCommand[glyph].aClipRect;
sl@0
  2603
		DirectGdi::TGraphicsRotation aRotation = iDrawGlyphCommand[glyph].aRotation;
sl@0
  2604
		TPoint aPos = iDrawGlyphCommand[glyph].pos;
sl@0
  2605
		
sl@0
  2606
		iRegionManager.ClipTo(aClipRect);
sl@0
  2607
		
sl@0
  2608
		//  Load the matrix which converts Symbian coordinate system to OpenVG coordinate system
sl@0
  2609
		
sl@0
  2610
		if(aRotation == DirectGdi::EGraphicsRotation90)
sl@0
  2611
			{
sl@0
  2612
			vgTranslate(aPos.iX+1, aPos.iY);
sl@0
  2613
			vgRotate(90.0f);
sl@0
  2614
			}
sl@0
  2615
		else if(aRotation == DirectGdi::EGraphicsRotation270)
sl@0
  2616
			{
sl@0
  2617
			vgTranslate(aPos.iX, aPos.iY+1);
sl@0
  2618
			vgRotate(270.0f);
sl@0
  2619
			}
sl@0
  2620
		else
sl@0
  2621
			{
sl@0
  2622
			//vgTranslate(aPos.iX, aPos.iY);
sl@0
  2623
			vgTranslate(aPos.iX-lastPos.iX, aPos.iY - lastPos.iY);
sl@0
  2624
			lastPos = aPos;
sl@0
  2625
			}		
sl@0
  2626
	
sl@0
  2627
		switch(aGlyphBitmapType)
sl@0
  2628
			{
sl@0
  2629
			case EMonochromeGlyphBitmap:
sl@0
  2630
			case EAntiAliasedGlyphBitmap:
sl@0
  2631
				for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
  2632
					vgDrawImage(foreground[glyph]);
sl@0
  2633
				break;
sl@0
  2634
			case EFourColourBlendGlyphBitmap:
sl@0
  2635
				{
sl@0
  2636
				SetVgPaintColor(iTextBrush, iBrushColor);
sl@0
  2637
				for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
  2638
					vgDrawImage(foreground[glyph]);
sl@0
  2639
		
sl@0
  2640
				SetVgPaintColor(iTextBrush, iTextShadowColor);
sl@0
  2641
				for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
  2642
					vgDrawImage(shadow[glyph]);
sl@0
  2643
		
sl@0
  2644
				SetVgPaintColor(iTextBrush, iPenColor);
sl@0
  2645
				for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
  2646
					vgDrawImage(outline[glyph]);
sl@0
  2647
				break;
sl@0
  2648
				}
sl@0
  2649
			}
sl@0
  2650
		
sl@0
  2651
		// Restore the clipping manager to its previous state.
sl@0
  2652
		iRegionManager.SetClippingRegion(oldClippingRegion);
sl@0
  2653
		}
sl@0
  2654
	oldClippingRegion.Close();
sl@0
  2655
	}
sl@0
  2656
#endif
sl@0
  2657
sl@0
  2658
/**
sl@0
  2659
@see MDirectGdiEngine::CopyRect()
sl@0
  2660
 */
sl@0
  2661
void CVgEngine::CopyRect(const TPoint& aOffset, const TRect& aRect)
sl@0
  2662
	{
sl@0
  2663
	MakeEngineCurrent();
sl@0
  2664
sl@0
  2665
	// Transformations, masking and blending are not applied.
sl@0
  2666
	// So need to convert to VG coordinate system.
sl@0
  2667
	// i.e. Need Bottom-Left coord of aRect in VG's coordinates.
sl@0
  2668
	// Also need to allow for drawing engine coordinate system (iOrigin)
sl@0
  2669
	const TPoint sourcePoint = ConvertToVgCoords(TPoint(aRect.iTl.iX, aRect.iBr.iY) + iOrigin);
sl@0
  2670
	// Scissoring is applied to destination, but does not affect reading of pixels.
sl@0
  2671
	for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
  2672
		vgCopyPixels(sourcePoint.iX + aOffset.iX, sourcePoint.iY - aOffset.iY,	// destination point
sl@0
  2673
						sourcePoint.iX, sourcePoint.iY,							// source point
sl@0
  2674
						aRect.Width(), aRect.Height());							// size of rect to copy
sl@0
  2675
	}
sl@0
  2676
sl@0
  2677
/**
sl@0
  2678
@see MDirectGdiEngine::ExternalizeL()
sl@0
  2679
@see InternalizeL()
sl@0
  2680
 */
sl@0
  2681
void CVgEngine::ExternalizeL(RWriteStream& aWriteStream) 
sl@0
  2682
	{
sl@0
  2683
	aWriteStream.WriteUint32L(iPaintMode);
sl@0
  2684
	aWriteStream << iLinePos;
sl@0
  2685
	}
sl@0
  2686
sl@0
  2687
/**
sl@0
  2688
@see MDirectGdiEngine::InternalizeL()
sl@0
  2689
@see ExternalizeL()
sl@0
  2690
 */
sl@0
  2691
void CVgEngine::InternalizeL(RReadStream& aReadStream)
sl@0
  2692
	{
sl@0
  2693
	iPaintMode = aReadStream.ReadUint32L();
sl@0
  2694
	aReadStream >> iLinePos;
sl@0
  2695
	}
sl@0
  2696
sl@0
  2697
/**
sl@0
  2698
@see MDirectGdiEngine::GetInterface()
sl@0
  2699
 */
sl@0
  2700
TInt CVgEngine::GetInterface(TUid aInterfaceId, TAny*& aInterface)
sl@0
  2701
	{
sl@0
  2702
	aInterface = NULL;
sl@0
  2703
	TInt err = KErrNone;
sl@0
  2704
	switch (aInterfaceId.iUid)
sl@0
  2705
		{
sl@0
  2706
		case KDirectGdiGetGlyphStorageUid:
sl@0
  2707
			{
sl@0
  2708
			aInterface = static_cast<MFontGlyphImageStorage*> (iDriver.FontGlyphImageStorage());
sl@0
  2709
			break;	
sl@0
  2710
			}
sl@0
  2711
		case KDirectGdiVgImageCacheUid:
sl@0
  2712
			{
sl@0
  2713
			aInterface =  static_cast<MVgImageCache*> (iDriver.VgImageCache());
sl@0
  2714
			break;
sl@0
  2715
			}
sl@0
  2716
		case KDrawDeviceOriginInterfaceID:
sl@0
  2717
			{
sl@0
  2718
			aInterface = static_cast<MDrawDeviceOrigin*>(this);
sl@0
  2719
			break;
sl@0
  2720
			}
sl@0
  2721
		default:
sl@0
  2722
			err = KErrNotSupported;
sl@0
  2723
			break;
sl@0
  2724
		}
sl@0
  2725
	return err;
sl@0
  2726
	}
sl@0
  2727
sl@0
  2728
/**
sl@0
  2729
Converts a point from the Symbian OS graphics coordinate system to the OpenVG coordinate system.
sl@0
  2730
sl@0
  2731
The Symbian OS coordinate system's x-axis increases positively from the origin rightwards.
sl@0
  2732
The y-axis increases positively from the origin downwards.
sl@0
  2733
sl@0
  2734
The OpenVG coordinate system's x-axis increases positively from the origin rightwards.
sl@0
  2735
The y-axis increases positively from the origin upwards.
sl@0
  2736
sl@0
  2737
Therefore a point (X,Y) in the Symbian OS coordinate system would be equivalent to a point
sl@0
  2738
(X',Y') in the OpenVG coordinate system by the following transformations:
sl@0
  2739
X' = X
sl@0
  2740
Y' = (Height of rendering target) - Y
sl@0
  2741
sl@0
  2742
@param	aPoint A point specified in the Symbian OS graphics coordinate system.
sl@0
  2743
sl@0
  2744
@return The point specified in the OpenVG-specific coordinate system.
sl@0
  2745
 */
sl@0
  2746
const TPoint CVgEngine::ConvertToVgCoords(const TPoint& aPoint)
sl@0
  2747
	{
sl@0
  2748
	MakeEngineCurrent();
sl@0
  2749
	TInt targetHeight = iSize.iHeight;
sl@0
  2750
	return TPoint(aPoint.iX, targetHeight - aPoint.iY);
sl@0
  2751
	}
sl@0
  2752
sl@0
  2753
/**
sl@0
  2754
Converts the position of a rectangle from the Symbian OS graphics coordinate system to the 
sl@0
  2755
OpenVG coordinate system.
sl@0
  2756
sl@0
  2757
The Symbian OS coordinate system's x-axis increases positively from the origin rightwards.
sl@0
  2758
The y-axis increases positively from the origin downwards.
sl@0
  2759
A rectangle's position is specified by the top-left coordinate.
sl@0
  2760
sl@0
  2761
The OpenVG coordinate system's x-axis increases positively from the origin rightwards.
sl@0
  2762
The y-axis increases positively from the origin upwards.
sl@0
  2763
A rectangle's position is specified by the bottom-left coordinate.
sl@0
  2764
sl@0
  2765
A point (X,Y) in the Symbian OS coordinate system would be equivalent to point
sl@0
  2766
(X',Y') in the OpenVG coordinate system by the following transformations:
sl@0
  2767
X' = X
sl@0
  2768
Y' = (Height of rendering target) - Y
sl@0
  2769
sl@0
  2770
@param	aRect	A rectangle whose position is to be converted for use in OpenVG.
sl@0
  2771
sl@0
  2772
@return The bottom-left point of the rectangle, specified in the OpenVG specific coordinate system.
sl@0
  2773
 */
sl@0
  2774
const TPoint CVgEngine::ConvertToVgCoords(const TRect& aRect)
sl@0
  2775
	{
sl@0
  2776
	MakeEngineCurrent();
sl@0
  2777
	TInt targetHeight = iSize.iHeight;
sl@0
  2778
	return TPoint(aRect.iTl.iX, targetHeight - aRect.iBr.iY);
sl@0
  2779
	}
sl@0
  2780
sl@0
  2781
/**
sl@0
  2782
Resets the user-to-surface OpenVG matrices to the default system matrix.
sl@0
  2783
 */
sl@0
  2784
void CVgEngine::ResetVgMatrix()
sl@0
  2785
	{
sl@0
  2786
	ResetVgMatrix(VG_MATRIX_PATH_USER_TO_SURFACE);
sl@0
  2787
	ResetVgMatrix(VG_MATRIX_IMAGE_USER_TO_SURFACE);
sl@0
  2788
	}
sl@0
  2789
sl@0
  2790
/**
sl@0
  2791
Resets an OpenVG matrix to the default system matrix. Current origin offset applies.
sl@0
  2792
@param aMatrixMode The OpenVG matrix being reset.
sl@0
  2793
 */
sl@0
  2794
void CVgEngine::ResetVgMatrix(const VGMatrixMode aMatrixMode)
sl@0
  2795
	{
sl@0
  2796
	vgSeti(VG_MATRIX_MODE, aMatrixMode);
sl@0
  2797
	//  Load matrix which converts Symbian coordinate system to VG coordinate system
sl@0
  2798
	vgLoadMatrix(Identity());
sl@0
  2799
		
sl@0
  2800
	// Add in translation for drawing engine coordinate system
sl@0
  2801
	vgTranslate(iOrigin.iX, iOrigin.iY);
sl@0
  2802
	}
sl@0
  2803
sl@0
  2804
/**
sl@0
  2805
If aPath is a null handle, a VGPath is created with enough space to hold aExpectedCommandCount commands.
sl@0
  2806
If the path is already a handle to a valid path, the path is simply cleared instead of recreated.
sl@0
  2807
Also allocates memory for two arrays; one to hold all commands we will add to the newly
sl@0
  2808
created path, and one to hold all coordinates we will add to the newly created path.
sl@0
  2809
Commands and coordinates are not added to the path until FinishPath() is called for this path. 
sl@0
  2810
Commands and coordinates are saved for adding to the path when FinishPath() is
sl@0
  2811
called by calling AppendPathCommand(). Any failures are reported to the driver before returning.
sl@0
  2812
sl@0
  2813
@param  aPath A handle to the path being cleared/created.
sl@0
  2814
@param	aExpectedCommandCount The number of commands the path is expected to hold. If this size
sl@0
  2815
		is underestimated, the arrays that hold the current commands and coordinates will grow
sl@0
  2816
		as additional items are added beyond the original estimated size. Once a path is finished, the current
sl@0
  2817
		command and coordinate counters are reset, but the memory remains to cut down on memory allocations.
sl@0
  2818
		
sl@0
  2819
@return EFalse if memory allocation or path creation fails, ETrue otherwise.
sl@0
  2820
sl@0
  2821
@see CVgEngine::AppendPathCommand(VGubyte)
sl@0
  2822
@see CVgEngine::AppendPathCommand(VGubyte, VGfloat)
sl@0
  2823
@see CVgEngine::AppendPathCommand(VGubyte, VGfloat, VGfloat)
sl@0
  2824
@see CVgEngine::PrepareForPathCommand()
sl@0
  2825
@see CVgEngine::FinishPath()
sl@0
  2826
@see CVgEngine::AllocPathCommands()
sl@0
  2827
@see CVgEngine::AllocPathCoords()
sl@0
  2828
 */
sl@0
  2829
TBool CVgEngine::PreparePath(VGPath& aPath, TInt aExpectedCommandCount)
sl@0
  2830
	{	
sl@0
  2831
	TInt err = KErrNone;
sl@0
  2832
	err = AllocPathCommands(aExpectedCommandCount);		
sl@0
  2833
	if(KErrNone == err)
sl@0
  2834
		{
sl@0
  2835
		err = AllocPathCoords(aExpectedCommandCount*2);	// guess at the number of coords needed, this will be reallocated if it is not big enough
sl@0
  2836
		}
sl@0
  2837
	if(KErrNone == err)
sl@0
  2838
		{
sl@0
  2839
		if (aPath != VG_INVALID_HANDLE)
sl@0
  2840
			vgClearPath(aPath, VG_PATH_CAPABILITY_APPEND_TO);
sl@0
  2841
		else
sl@0
  2842
			{
sl@0
  2843
			aPath = vgCreatePath(VG_PATH_FORMAT_STANDARD,
sl@0
  2844
							VG_PATH_DATATYPE_F,
sl@0
  2845
							1.0f, //scale
sl@0
  2846
							0.0f, //bias
sl@0
  2847
							aExpectedCommandCount,
sl@0
  2848
							aExpectedCommandCount*2, //expected coord count
sl@0
  2849
							VG_PATH_CAPABILITY_APPEND_TO);
sl@0
  2850
			
sl@0
  2851
			if (aPath == VG_INVALID_HANDLE)
sl@0
  2852
				err = KErrNoMemory;
sl@0
  2853
			}
sl@0
  2854
		}
sl@0
  2855
	if (KErrNone != err)
sl@0
  2856
		{
sl@0
  2857
		iDriver.SetError(err);
sl@0
  2858
		return EFalse;
sl@0
  2859
		}
sl@0
  2860
	return ETrue;
sl@0
  2861
	}
sl@0
  2862
sl@0
  2863
/**
sl@0
  2864
Adds a path command to the currently saved array of path commands. Any error that occurs is stored
sl@0
  2865
with the driver.
sl@0
  2866
sl@0
  2867
@param aCommand	The VGPathCommand to add to the current path, e.g VG_CLOSE_PATH.
sl@0
  2868
sl@0
  2869
@see CVgEngine::CreatePath()
sl@0
  2870
@see CVgEngine::AppendPathCommand(VGubyte, VGfloat)
sl@0
  2871
@see CVgEngine::AppendPathCommand(VGubyte, VGfloat, VGfloat)
sl@0
  2872
@see CVgEngine::PrepareForPathCommand()
sl@0
  2873
@see CVgEngine::FinishPath()
sl@0
  2874
@see CVgEngine::AllocPathCommands()
sl@0
  2875
@see CVgEngine::AllocPathCoords()
sl@0
  2876
 */
sl@0
  2877
void CVgEngine::AppendPathCommand(VGubyte aCommand)
sl@0
  2878
	{
sl@0
  2879
	TInt err = PrepareForPathCommand(1, 0);
sl@0
  2880
	if (KErrNone == err)
sl@0
  2881
		{
sl@0
  2882
		iPathCommands[iPathCommandCount++] = aCommand;
sl@0
  2883
		}
sl@0
  2884
	else
sl@0
  2885
		{
sl@0
  2886
		iDriver.SetError(err);
sl@0
  2887
		}	
sl@0
  2888
	}
sl@0
  2889
sl@0
  2890
/**
sl@0
  2891
Adds a path command and a single coordinate to the currently saved array of path commands.
sl@0
  2892
Any error that occurs is stored with the driver.  
sl@0
  2893
sl@0
  2894
@param	aCommand The VGPathCommand to add to the current path, e.g VG_HLINE_TO_ABS.
sl@0
  2895
@param	aCoord	 The coordinate to add to the current path, e.g. 10.f.
sl@0
  2896
sl@0
  2897
@see CVgEngine::CreatePath()
sl@0
  2898
@see CVgEngine::AppendPathCommand(VGubyte)
sl@0
  2899
@see CVgEngine::AppendPathCommand(VGubyte, VGfloat, VGfloat)
sl@0
  2900
@see CVgEngine::PrepareForPathCommand()
sl@0
  2901
@see CVgEngine::FinishPath()
sl@0
  2902
@see CVgEngine::AllocPathCommands()
sl@0
  2903
@see CVgEngine::AllocPathCoords()
sl@0
  2904
 */
sl@0
  2905
void CVgEngine::AppendPathCommand(VGubyte aCommand, VGfloat aCoord)
sl@0
  2906
	{
sl@0
  2907
	TInt err = PrepareForPathCommand(1, 1);
sl@0
  2908
	if (KErrNone == err)
sl@0
  2909
		{				
sl@0
  2910
		iPathCommands[iPathCommandCount++] = aCommand;			
sl@0
  2911
		iPathCoords[iPathCoordCount++] = aCoord;		
sl@0
  2912
		}
sl@0
  2913
	else
sl@0
  2914
		{
sl@0
  2915
		iDriver.SetError(err);
sl@0
  2916
		}	
sl@0
  2917
	}
sl@0
  2918
sl@0
  2919
/**
sl@0
  2920
Adds a path command and two coordinates to the currently saved array of path commands. 
sl@0
  2921
Any error that occurs is stored with the driver.
sl@0
  2922
sl@0
  2923
@param	aCommand	The VGPathCommand to add to the current path, e.g VG_MOVE_TO_ABS.
sl@0
  2924
@param	aCoord1		The coordinate to add to the current path, e.g. 10.f.
sl@0
  2925
@param	aCoord2		The coordinate to add to the current path, e.g. 10.f.
sl@0
  2926
sl@0
  2927
@see CVgEngine::CreatePath()
sl@0
  2928
@see CVgEngine::AppendPathCommand(VGubyte)
sl@0
  2929
@see CVgEngine::AppendPathCommand(VGubyte, VGfloat)
sl@0
  2930
@see CVgEngine::PrepareForPathCommand()
sl@0
  2931
@see CVgEngine::FinishPath()
sl@0
  2932
@see CVgEngine::AllocPathCommands()
sl@0
  2933
@see CVgEngine::AllocPathCoords()
sl@0
  2934
 */
sl@0
  2935
void CVgEngine::AppendPathCommand(VGubyte aCommand, VGfloat aCoord1, VGfloat aCoord2)
sl@0
  2936
	{
sl@0
  2937
	TInt err = PrepareForPathCommand(1, 2);
sl@0
  2938
	if (KErrNone == err)
sl@0
  2939
		{			
sl@0
  2940
		iPathCommands[iPathCommandCount++] = aCommand;					
sl@0
  2941
		iPathCoords[iPathCoordCount++] = aCoord1;
sl@0
  2942
		iPathCoords[iPathCoordCount++] = aCoord2;		
sl@0
  2943
		}
sl@0
  2944
	else
sl@0
  2945
		{
sl@0
  2946
		iDriver.SetError(err);
sl@0
  2947
		}	
sl@0
  2948
	}
sl@0
  2949
sl@0
  2950
/**
sl@0
  2951
Allocates memory to store the passed number of commands and coordinates in the saved command and 
sl@0
  2952
coordinate arrays. Any error that occurs is stored with the driver.
sl@0
  2953
sl@0
  2954
@param	aCommandCount	The number of new commands expected to be added to the current command array.
sl@0
  2955
@param	aCoordCount		The number of new commands expected to be added to the current coordinate array.
sl@0
  2956
sl@0
  2957
@return	KErrNoMemory if memory allocation fails, KErrNone otherwise.
sl@0
  2958
sl@0
  2959
@see CVgEngine::CreatePath()
sl@0
  2960
@see CVgEngine::AppendPathCommand(VGubyte)
sl@0
  2961
@see CVgEngine::AppendPathCommand(VGubyte, VGfloat)
sl@0
  2962
@see CVgEngine::AppendPathCommand(VGubyte, VGfloat, VGfloat)
sl@0
  2963
@see CVgEngine::FinishPath()
sl@0
  2964
@see CVgEngine::AllocPathCommands()
sl@0
  2965
@see CVgEngine::AllocPathCoords()
sl@0
  2966
 */
sl@0
  2967
TInt CVgEngine::PrepareForPathCommand(TInt aCommandCount, TInt aCoordCount)
sl@0
  2968
	{
sl@0
  2969
	// Do we need to add space for the new commands and coords?
sl@0
  2970
	TInt err = AllocPathCommands(iPathCommandCount+aCommandCount);
sl@0
  2971
	if (err == KErrNone)
sl@0
  2972
		{
sl@0
  2973
		err = AllocPathCoords(iPathCoordCount+aCoordCount);
sl@0
  2974
		}
sl@0
  2975
	if (err != KErrNone)
sl@0
  2976
		{
sl@0
  2977
		iDriver.SetError(err);
sl@0
  2978
		}
sl@0
  2979
	return err;
sl@0
  2980
	}
sl@0
  2981
sl@0
  2982
/**
sl@0
  2983
Adds the contents of the saved command and coordinate arrays to the passed VGPath ready for drawing.
sl@0
  2984
Clears the counts of saved commands and coordinates.
sl@0
  2985
sl@0
  2986
@param	aPath	The path that the current commands and coordinates are to be added to. 
sl@0
  2987
sl@0
  2988
@see CVgEngine::CreatePath()
sl@0
  2989
@see CVgEngine::AppendPathCommand(VGubyte)
sl@0
  2990
@see CVgEngine::AppendPathCommand(VGubyte, VGfloat)
sl@0
  2991
@see CVgEngine::AppendPathCommand(VGubyte, VGfloat, VGfloat)
sl@0
  2992
@see CVgEngine::PrepareForPathCommand()
sl@0
  2993
@see CVgEngine::AllocPathCommands()
sl@0
  2994
@see CVgEngine::AllocPathCoords()
sl@0
  2995
 */
sl@0
  2996
void CVgEngine::FinishPath(VGPath aPath)
sl@0
  2997
	{
sl@0
  2998
	vgAppendPathData(aPath, iPathCommandCount, iPathCommands, iPathCoords);
sl@0
  2999
	iPathCommandCount = 0;
sl@0
  3000
	iPathCoordCount = 0;
sl@0
  3001
	}
sl@0
  3002
sl@0
  3003
/**
sl@0
  3004
Allocates enough memory to hold aCommandCount path commands, unless the command array already holds
sl@0
  3005
enough memory.
sl@0
  3006
sl@0
  3007
@param	aCommandCount The number of commands to allocate space for in the command array.
sl@0
  3008
sl@0
  3009
@return	KErrNoMemory if memory allocation fails, KErrNone otherwise.
sl@0
  3010
sl@0
  3011
@see CVgEngine::CreatePath(TInt)
sl@0
  3012
@see CVgEngine::AppendPathCommand(VGubyte)
sl@0
  3013
@see CVgEngine::AppendPathCommand(VGubyte, VGfloat)
sl@0
  3014
@see CVgEngine::AppendPathCommand(VGubyte, VGfloat, VGfloat)
sl@0
  3015
@see CVgEngine::PrepareForPathCommand(TInt, TInt)
sl@0
  3016
@see CVgEngine::FinishPath(VGPath)
sl@0
  3017
@see CVgEngine::AllocPathCoords(TInt)
sl@0
  3018
 */
sl@0
  3019
TInt CVgEngine::AllocPathCommands(TInt aCommandCount)
sl@0
  3020
	{
sl@0
  3021
	TInt err = KErrNone;
sl@0
  3022
	if (iCurrentMaxCommands < aCommandCount)
sl@0
  3023
		{
sl@0
  3024
		VGubyte* oldPathCommands = iPathCommands;
sl@0
  3025
		iPathCommands = static_cast<VGubyte*>(User::ReAlloc(iPathCommands, sizeof(VGubyte)*aCommandCount));					
sl@0
  3026
		if (iPathCommands)
sl@0
  3027
			{
sl@0
  3028
			iCurrentMaxCommands = aCommandCount;	
sl@0
  3029
			}	
sl@0
  3030
		else
sl@0
  3031
			{
sl@0
  3032
			delete oldPathCommands;
sl@0
  3033
			iCurrentMaxCommands = 0;
sl@0
  3034
			}
sl@0
  3035
		}
sl@0
  3036
	if(!iPathCommands)
sl@0
  3037
		err = KErrNoMemory;
sl@0
  3038
	return err;	
sl@0
  3039
	}
sl@0
  3040
sl@0
  3041
/**
sl@0
  3042
Allocates enough memory to hold aCoordCount path coordinates, unless the coordinate array already holds
sl@0
  3043
enough memory.
sl@0
  3044
sl@0
  3045
@param	aCoordCount	The number of coordinates to allocate space for in the coordinate array.
sl@0
  3046
sl@0
  3047
@return	KErrNoMemory if memory allocation fails, KErrNone otherwise.
sl@0
  3048
sl@0
  3049
@see CVgEngine::CreatePath()
sl@0
  3050
@see CVgEngine::AppendPathCommand(VGubyte)
sl@0
  3051
@see CVgEngine::AppendPathCommand(VGubyte, VGfloat)
sl@0
  3052
@see CVgEngine::AppendPathCommand(VGubyte, VGfloat, VGfloat)
sl@0
  3053
@see CVgEngine::PrepareForPathCommand()
sl@0
  3054
@see CVgEngine::FinishPath()
sl@0
  3055
@see CVgEngine::AllocPathCommands()
sl@0
  3056
 */
sl@0
  3057
TInt CVgEngine::AllocPathCoords(TInt aCoordCount)
sl@0
  3058
	{
sl@0
  3059
	TInt err = KErrNone;
sl@0
  3060
	if (iCurrentMaxCoords < aCoordCount)
sl@0
  3061
		{
sl@0
  3062
		VGfloat* oldPathCoords = iPathCoords;
sl@0
  3063
		iPathCoords = static_cast<VGfloat*>(User::ReAlloc(iPathCoords, sizeof(VGfloat)*aCoordCount));			
sl@0
  3064
		if (iPathCoords)
sl@0
  3065
			{
sl@0
  3066
			iCurrentMaxCoords = aCoordCount;	
sl@0
  3067
			}	
sl@0
  3068
		else
sl@0
  3069
			{
sl@0
  3070
			delete oldPathCoords;
sl@0
  3071
			iCurrentMaxCoords = 0;
sl@0
  3072
			}
sl@0
  3073
		}
sl@0
  3074
	if(!iPathCoords)
sl@0
  3075
		err = KErrNoMemory;
sl@0
  3076
	return err;	
sl@0
  3077
	}
sl@0
  3078
sl@0
  3079
/**
sl@0
  3080
Helper method for creating a VGImage from a CFbsBitmap. A temporary VGImageFormat-compatible 
sl@0
  3081
copy of the image may be created, if the source bitmap pixel format is not directly supported 
sl@0
  3082
by OpenVG. If there is not enough memory available, the error state on the driver is set to KErrNoMemory.
sl@0
  3083
It sets the error in the driver if out-of-memory occurs when creating a VGImage. OpenVG will set its 
sl@0
  3084
own internal error if creation of VGImage fails.
sl@0
  3085
sl@0
  3086
@param	aSource	The source bitmap.
sl@0
  3087
@param  aFlipY If 'ETrue' then inverts the image in the y axis.
sl@0
  3088
@param  aOrigin An offset from the top-left of the image in which to take the first pixel of the image.
sl@0
  3089
sl@0
  3090
@return	Returns a valid VGImage created using the passed CFbsBitmap. If unable to
sl@0
  3091
		create a valid VGImage then VG_INVALID_HANDLE.
sl@0
  3092
*/
sl@0
  3093
VGImage CVgEngine::CreateSourceVGImage(const CFbsBitmap& aSource, TBool aFlipY, const TPoint& aOrigin)
sl@0
  3094
	{		
sl@0
  3095
	TDisplayMode srcDisplayMode = aSource.DisplayMode();
sl@0
  3096
	TDisplayMode vgCompatibleDisplayMode = ClosestVgCompatibleDisplayMode(srcDisplayMode);
sl@0
  3097
	VGImageFormat imageFormat = MapToVgDisplayMode(vgCompatibleDisplayMode);
sl@0
  3098
	const TSize sourceSize = aSource.SizeInPixels();
sl@0
  3099
	VGImage image = DoVgCreateImage(imageFormat, sourceSize.iWidth, sourceSize.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED);
sl@0
  3100
	if (image != VG_INVALID_HANDLE)
sl@0
  3101
		{
sl@0
  3102
		const TInt pixmapStride = CFbsBitmap::ScanLineLength(sourceSize.iWidth, vgCompatibleDisplayMode);	
sl@0
  3103
		
sl@0
  3104
		// Conversion is performed if changing display mode (pixel format), source is compressed, or want to flip the y orientation.
sl@0
  3105
		if ((vgCompatibleDisplayMode != srcDisplayMode) || (aSource.Header().iCompression != ENoBitmapCompression) || aFlipY)
sl@0
  3106
			{
sl@0
  3107
			// May be worth using a static memory buffer for smaller scan-lines, to avoid overhead of alloc.
sl@0
  3108
			TAny* data = User::Alloc(pixmapStride);
sl@0
  3109
			if (data)
sl@0
  3110
				{
sl@0
  3111
				// Allocate memory and transform source into target format.
sl@0
  3112
				TPoint sourcePoint (0, aFlipY ? (sourceSize.iHeight - 1) : 0);
sl@0
  3113
				TPtr8 targetPoint ((TUint8*)data, pixmapStride, pixmapStride);
sl@0
  3114
				TInt adj = aFlipY ? -1 : 1;
sl@0
  3115
	
sl@0
  3116
				if (aOrigin == TPoint(0,0)) // Not shifted
sl@0
  3117
					{
sl@0
  3118
					for (TInt targetY = 0; targetY < sourceSize.iHeight; targetY++, sourcePoint.iY += adj)
sl@0
  3119
						{
sl@0
  3120
						aSource.GetScanLine(targetPoint, sourcePoint, sourceSize.iWidth, vgCompatibleDisplayMode);
sl@0
  3121
						vgImageSubData(image, data, pixmapStride, imageFormat, 0, targetY, sourceSize.iWidth, 1);
sl@0
  3122
						}
sl@0
  3123
					}
sl@0
  3124
				else if (aOrigin.iX == 0) // Only shifted in Y.
sl@0
  3125
					{
sl@0
  3126
					for (TInt targetY = 0x00; targetY < sourceSize.iHeight; targetY++, sourcePoint.iY += adj)
sl@0
  3127
						{
sl@0
  3128
						aSource.GetScanLine(targetPoint, sourcePoint, sourceSize.iWidth, vgCompatibleDisplayMode);
sl@0
  3129
						vgImageSubData(image, data, pixmapStride, imageFormat, 0, targetY + aOrigin.iY,                      sourceSize.iWidth, 1);
sl@0
  3130
						vgImageSubData(image, data, pixmapStride, imageFormat, 0, targetY + aOrigin.iY - sourceSize.iHeight, sourceSize.iWidth, 1);
sl@0
  3131
						}
sl@0
  3132
					}
sl@0
  3133
				else if (aOrigin.iY == 0) // Only shifted in X.
sl@0
  3134
					{
sl@0
  3135
					for (TInt targetY = 0x00; targetY < sourceSize.iHeight; targetY++, sourcePoint.iY += adj)
sl@0
  3136
						{
sl@0
  3137
						aSource.GetScanLine(targetPoint, sourcePoint, sourceSize.iWidth, vgCompatibleDisplayMode);
sl@0
  3138
						vgImageSubData(image, data, pixmapStride, imageFormat, -aOrigin.iX,                     targetY, sourceSize.iWidth, 1);
sl@0
  3139
						vgImageSubData(image, data, pixmapStride, imageFormat, -aOrigin.iX + sourceSize.iWidth, targetY, sourceSize.iWidth, 1);
sl@0
  3140
						}				
sl@0
  3141
					}
sl@0
  3142
				else						  // Shifted in both X and Y.
sl@0
  3143
					{
sl@0
  3144
					for (TInt targetY = 0; targetY < sourceSize.iHeight; targetY++, sourcePoint.iY += adj)
sl@0
  3145
						{
sl@0
  3146
						aSource.GetScanLine(targetPoint, sourcePoint, sourceSize.iWidth, vgCompatibleDisplayMode);
sl@0
  3147
						vgImageSubData(image, data, pixmapStride, imageFormat, -aOrigin.iX, 					targetY + aOrigin.iY, 						sourceSize.iWidth, 1);
sl@0
  3148
						vgImageSubData(image, data, pixmapStride, imageFormat, -aOrigin.iX, 					targetY + aOrigin.iY - sourceSize.iHeight, sourceSize.iWidth, 1);
sl@0
  3149
						vgImageSubData(image, data, pixmapStride, imageFormat, -aOrigin.iX + sourceSize.iWidth, targetY + aOrigin.iY, 						sourceSize.iWidth, 1);
sl@0
  3150
						vgImageSubData(image, data, pixmapStride, imageFormat, -aOrigin.iX + sourceSize.iWidth, targetY + aOrigin.iY - sourceSize.iHeight, sourceSize.iWidth, 1);
sl@0
  3151
						}
sl@0
  3152
					}
sl@0
  3153
				User::Free(data);
sl@0
  3154
				}
sl@0
  3155
			else
sl@0
  3156
				{
sl@0
  3157
				iDriver.SetError(KErrNoMemory);
sl@0
  3158
				vgDestroyImage(image);
sl@0
  3159
				return VG_INVALID_HANDLE;
sl@0
  3160
				}
sl@0
  3161
			}
sl@0
  3162
		else
sl@0
  3163
			{
sl@0
  3164
			aSource.BeginDataAccess();
sl@0
  3165
			const TInt sourceDataStride = aSource.DataStride();
sl@0
  3166
			if (aOrigin == TPoint(0,0))			// Not shifted
sl@0
  3167
				{
sl@0
  3168
				vgImageSubData(image, aSource.DataAddress(), sourceDataStride, imageFormat, 0, 0, sourceSize.iWidth, sourceSize.iHeight);			
sl@0
  3169
				}
sl@0
  3170
			else
sl@0
  3171
				{
sl@0
  3172
				TUint32* dataAddress = aSource.DataAddress();
sl@0
  3173
				
sl@0
  3174
				if (aOrigin.iX == 0) 		// Only shifted in Y.
sl@0
  3175
					{
sl@0
  3176
					vgImageSubData(image, dataAddress, sourceDataStride, imageFormat, 0, aOrigin.iY,                      sourceSize.iWidth, sourceSize.iHeight);						
sl@0
  3177
					vgImageSubData(image, dataAddress, sourceDataStride, imageFormat, 0, aOrigin.iY - sourceSize.iHeight, sourceSize.iWidth, sourceSize.iHeight);						
sl@0
  3178
					}
sl@0
  3179
				else if (aOrigin.iY == 0) 	// Only shifted in X.
sl@0
  3180
					{
sl@0
  3181
					vgImageSubData(image, dataAddress, sourceDataStride, imageFormat, -aOrigin.iX,                     0, sourceSize.iWidth, sourceSize.iHeight);						
sl@0
  3182
					vgImageSubData(image, dataAddress, sourceDataStride, imageFormat, -aOrigin.iX + sourceSize.iWidth, 0, sourceSize.iWidth, sourceSize.iHeight);						
sl@0
  3183
					}
sl@0
  3184
				else							// Shifted in both X and Y.
sl@0
  3185
					{
sl@0
  3186
					vgImageSubData(image, dataAddress, sourceDataStride, imageFormat, -aOrigin.iX, aOrigin.iY,                      sourceSize.iWidth, sourceSize.iHeight);						
sl@0
  3187
					vgImageSubData(image, dataAddress, sourceDataStride, imageFormat, -aOrigin.iX, aOrigin.iY - sourceSize.iHeight, sourceSize.iWidth, sourceSize.iHeight);							
sl@0
  3188
					vgImageSubData(image, dataAddress, sourceDataStride, imageFormat, -aOrigin.iX + sourceSize.iWidth, aOrigin.iY,                      sourceSize.iWidth, sourceSize.iHeight);						
sl@0
  3189
					vgImageSubData(image, dataAddress, sourceDataStride, imageFormat, -aOrigin.iX + sourceSize.iWidth, aOrigin.iY - sourceSize.iHeight, sourceSize.iWidth, sourceSize.iHeight);							
sl@0
  3190
					}
sl@0
  3191
				}
sl@0
  3192
			aSource.EndDataAccess(ETrue);
sl@0
  3193
			}
sl@0
  3194
		}
sl@0
  3195
	return image;
sl@0
  3196
	}
sl@0
  3197
sl@0
  3198
/**
sl@0
  3199
Creates an image which represents a standard brush pattern (e.g. EVerticalHatchBrush), by
sl@0
  3200
drawing the pattern using the current pen and brush colour to an image.
sl@0
  3201
sl@0
  3202
@param	aPatternSize	The dimensions in pixels of the image to create.
sl@0
  3203
@param	aBrushPattern	An array of 1s and 0s representing the pattern to create, the length
sl@0
  3204
						of this array is aSize.iWidth*aSize.iHeight.	
sl@0
  3205
sl@0
  3206
@return	KErrNone if the brush is created successfully, KErrNoMemory if we fail to create 
sl@0
  3207
		the brush image, KErrArgument if aBrushPattern is invalid.
sl@0
  3208
 */
sl@0
  3209
TInt CVgEngine::CreateStandardBrush(TSize& aPatternSize, VGbyte* aBrushPattern)
sl@0
  3210
	{		
sl@0
  3211
	if (aBrushPattern == NULL)
sl@0
  3212
		return KErrArgument;
sl@0
  3213
	
sl@0
  3214
	TInt err = KErrNone;	
sl@0
  3215
	MakeEngineCurrent();
sl@0
  3216
	
sl@0
  3217
	// The image format to use as the standard brush. If this changes, it also needs changing in 
sl@0
  3218
	// GetCurrentBrush().	
sl@0
  3219
	const VGImageFormat dataFormat = VG_sARGB_8888;
sl@0
  3220
	
sl@0
  3221
	// We want to create the brush to the nearest power of 4 size.
sl@0
  3222
	TSize brushSize((aPatternSize.iWidth+3)&~3, (aPatternSize.iHeight+3)&~3);		
sl@0
  3223
	
sl@0
  3224
	// Allocate some memory to write the brush pattern to.
sl@0
  3225
	TUint32* data = new TUint32[brushSize.iWidth*brushSize.iHeight];
sl@0
  3226
	if (data == NULL)
sl@0
  3227
		err = KErrNoMemory;		
sl@0
  3228
	
sl@0
  3229
	if (err == KErrNone)
sl@0
  3230
		{
sl@0
  3231
		if (iBrushPatternStandardRegion != VG_INVALID_HANDLE)
sl@0
  3232
			{
sl@0
  3233
			vgDestroyImage(iBrushPatternStandardRegion);
sl@0
  3234
			iBrushPatternStandardRegion = VG_INVALID_HANDLE;
sl@0
  3235
			}
sl@0
  3236
		
sl@0
  3237
		// Check the size of the existing standard brush as it can't be re-used if the
sl@0
  3238
		// new brush to be created is a different size.
sl@0
  3239
		if (iBrushPatternStandard != VG_INVALID_HANDLE)
sl@0
  3240
			{
sl@0
  3241
			if (iBrushPatternStandardSize != brushSize)
sl@0
  3242
				{
sl@0
  3243
				vgDestroyImage(iBrushPatternStandard);
sl@0
  3244
				iBrushPatternStandard = VG_INVALID_HANDLE;
sl@0
  3245
				}
sl@0
  3246
			}					
sl@0
  3247
		
sl@0
  3248
		if (iBrushPatternStandard == VG_INVALID_HANDLE)
sl@0
  3249
			{
sl@0
  3250
			// Create an image to draw the brush pattern onto, this will be our offscreen buffer
sl@0
  3251
			iBrushPatternStandardSize = brushSize;
sl@0
  3252
			iBrushPatternStandard = DoVgCreateImage(dataFormat, brushSize.iWidth, brushSize.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED);
sl@0
  3253
			if (iBrushPatternStandard == VG_INVALID_HANDLE)
sl@0
  3254
				err = KErrNoMemory;
sl@0
  3255
			}
sl@0
  3256
		}			
sl@0
  3257
sl@0
  3258
	if (err == KErrNone)
sl@0
  3259
		{
sl@0
  3260
		// Set the colour used for the pen. If not fully opaque and not in WriteAlpha mode,
sl@0
  3261
		// blend the pen colour with the brush colour.
sl@0
  3262
		TRgb penColor = iPenColor;
sl@0
  3263
		if ((iPenColor.Alpha() != 255) && (iDrawMode != DirectGdi::EDrawModeWriteAlpha))
sl@0
  3264
			{
sl@0
  3265
			penColor.SetInternal(
sl@0
  3266
				PMA2NonPMAPixel(
sl@0
  3267
					PMAPixelBlend(
sl@0
  3268
					    NonPMA2PMAPixel(iBrushColor.Internal()), 
sl@0
  3269
						NonPMA2PMAPixel(iPenColor.Internal()))));
sl@0
  3270
			}
sl@0
  3271
		
sl@0
  3272
		// Draw the pattern on to the brush, pixel by pixel.
sl@0
  3273
		for (TInt j = 0; j < aPatternSize.iHeight; ++j)
sl@0
  3274
			{
sl@0
  3275
			for (TInt i = 0; i < aPatternSize.iWidth; ++i)
sl@0
  3276
				{				
sl@0
  3277
				if (aBrushPattern[(j*aPatternSize.iWidth)+i])			
sl@0
  3278
					{					
sl@0
  3279
					data[(j*brushSize.iWidth)+i] = penColor._Color16MA(); 
sl@0
  3280
					}
sl@0
  3281
				else
sl@0
  3282
					{
sl@0
  3283
					data[(j*brushSize.iWidth)+i] = iBrushColor._Color16MA();
sl@0
  3284
					}
sl@0
  3285
				}
sl@0
  3286
			}					
sl@0
  3287
				
sl@0
  3288
		// Copy the pattern to the VGImage so we can set it as the current brush
sl@0
  3289
		vgImageSubData(iBrushPatternStandard,	// the image to copy to		
sl@0
  3290
					data, 						// the source data
sl@0
  3291
					brushSize.iWidth*4,	 		// the stride of the source data
sl@0
  3292
					dataFormat, 				// the format of the source data
sl@0
  3293
					0, 							// x
sl@0
  3294
					0, 							// y
sl@0
  3295
					brushSize.iWidth, 			// width
sl@0
  3296
					brushSize.iHeight);			// height
sl@0
  3297
		iBrushPatternStandardSize = brushSize;
sl@0
  3298
		
sl@0
  3299
		// We only want to use the region of the brush we just created that is the size of the pattern
sl@0
  3300
		iBrushPatternStandardRegion = vgChildImage(iBrushPatternStandard, 
sl@0
  3301
													0, 
sl@0
  3302
													0, 
sl@0
  3303
													aPatternSize.iWidth, 
sl@0
  3304
													aPatternSize.iHeight);
sl@0
  3305
		iBrushPatternStandardRegionSize = aPatternSize;
sl@0
  3306
		}		
sl@0
  3307
	
sl@0
  3308
	// Clean up
sl@0
  3309
	delete [] data;
sl@0
  3310
sl@0
  3311
	return err;
sl@0
  3312
	}
sl@0
  3313
sl@0
  3314
/**
sl@0
  3315
Internal function to return the currently active brush and its properties.
sl@0
  3316
@param aBrush On success, holds the current VGImage brush being used.
sl@0
  3317
@param aSize On success, holds the dimensions of VGImage being used as the brush.
sl@0
  3318
@param aFormat On success, holds the VGImageFormat of the brush. 
sl@0
  3319
@return ETrue if a brush is currently being used, EFalse otherwise.
sl@0
  3320
*/
sl@0
  3321
TBool CVgEngine::GetCurrentBrushPattern(VGImage& aBrush, TSize& aSize, VGImageFormat& aFormat) const
sl@0
  3322
	{
sl@0
  3323
	TBool success = ETrue;
sl@0
  3324
	if (iBrushStyle == DirectGdi::EPatternedBrush)
sl@0
  3325
		{
sl@0
  3326
		aBrush = iBrushPatternUser;
sl@0
  3327
		aSize = iBrushPatternUserSize;
sl@0
  3328
		aFormat = static_cast<VGImageFormat>(vgGetParameteri(aBrush, VG_IMAGE_FORMAT));
sl@0
  3329
		}
sl@0
  3330
	else if (iBrushStyle > DirectGdi::EPatternedBrush)
sl@0
  3331
		{
sl@0
  3332
		aBrush = iBrushPatternStandardRegion;
sl@0
  3333
		aSize = iBrushPatternStandardRegionSize;
sl@0
  3334
		// Currently we only ever use VG_sARGB_8888 for the standard brush format.
sl@0
  3335
		aFormat = VG_sARGB_8888;
sl@0
  3336
		}
sl@0
  3337
	else 
sl@0
  3338
		success = EFalse;
sl@0
  3339
	return success;
sl@0
  3340
	}
sl@0
  3341
sl@0
  3342
/**
sl@0
  3343
Copies the current brush pattern (if a brush pattern is set) into iBrushPatternNonZeroOrigin.
sl@0
  3344
This function should only be used if the current brush origin is not (0,0). When copying the
sl@0
  3345
current brush pattern, it is shifted to take into account the non-zero origin. This shifted brush
sl@0
  3346
pattern should be used for all brush operations while a non-zero origin is set.
sl@0
  3347
sl@0
  3348
@return	KErrNone if successful, KErrNotFound if the brush pattern could not be copied.
sl@0
  3349
 */
sl@0
  3350
TInt CVgEngine::CopyCurrentBrushPatternForNonZeroOrigin()
sl@0
  3351
	{
sl@0
  3352
	MakeEngineCurrent();
sl@0
  3353
	TInt ret = KErrNotFound;
sl@0
  3354
	VGImage brush = VG_INVALID_HANDLE;
sl@0
  3355
	TSize brushSize;
sl@0
  3356
	VGImageFormat imageFormat;
sl@0
  3357
	
sl@0
  3358
	if (GetCurrentBrushPattern(brush, brushSize, imageFormat))
sl@0
  3359
		{
sl@0
  3360
		const TInt width = brushSize.iWidth;
sl@0
  3361
		const TInt height = brushSize.iHeight;
sl@0
  3362
		
sl@0
  3363
		if ((width != 0) && (height != 0))
sl@0
  3364
			{
sl@0
  3365
			if (iBrushPatternNonZeroOrigin != VG_INVALID_HANDLE)
sl@0
  3366
				{
sl@0
  3367
				vgDestroyImage(iBrushPatternNonZeroOrigin);
sl@0
  3368
				iBrushPatternNonZeroOrigin = VG_INVALID_HANDLE;
sl@0
  3369
				}
sl@0
  3370
			
sl@0
  3371
			// Create the brush we are going to copy the current brush into
sl@0
  3372
			iBrushPatternNonZeroOrigin = DoVgCreateImage(imageFormat,
sl@0
  3373
													width,
sl@0
  3374
													height,
sl@0
  3375
													VG_IMAGE_QUALITY_FASTER);
sl@0
  3376
			if (iBrushPatternNonZeroOrigin != VG_INVALID_HANDLE)
sl@0
  3377
				{
sl@0
  3378
				TInt offsetX = width - (iBrushOrigin.iX % width);
sl@0
  3379
				TInt offsetY = height - (iBrushOrigin.iY % height);	
sl@0
  3380
				
sl@0
  3381
				// Top left to bottom right			
sl@0
  3382
				if (offsetX != 0 && offsetY != 0) // check the width and height we are copying are not 0
sl@0
  3383
					vgCopyImage(iBrushPatternNonZeroOrigin, width-offsetX, height-offsetY, brush, 0, 0, offsetX, offsetY, VG_FALSE);
sl@0
  3384
				
sl@0
  3385
				// Top right to bottom left
sl@0
  3386
				if ((width-offsetX) != 0 && offsetY != 0) 
sl@0
  3387
					vgCopyImage(iBrushPatternNonZeroOrigin, 0, height-offsetY, brush, offsetX, 0, width-offsetX, offsetY, VG_FALSE);
sl@0
  3388
				
sl@0
  3389
				// Bottom left to top right
sl@0
  3390
				if (offsetX != 0 && (height-offsetY) != 0) 
sl@0
  3391
					vgCopyImage(iBrushPatternNonZeroOrigin, width-offsetX, 0, brush, 0, offsetY, offsetX, height-offsetY, VG_FALSE);				
sl@0
  3392
				
sl@0
  3393
				// Bottom right to top left
sl@0
  3394
				if ((width-offsetX) != 0 && (height-offsetY) != 0) 
sl@0
  3395
					vgCopyImage(iBrushPatternNonZeroOrigin, 0, 0, brush, offsetX, offsetY, width-offsetX, height-offsetY, VG_FALSE);
sl@0
  3396
				
sl@0
  3397
				// Paint with the new non-zero origin brush
sl@0
  3398
				vgPaintPattern(iBrush, iBrushPatternNonZeroOrigin);
sl@0
  3399
				
sl@0
  3400
				ret = KErrNone;
sl@0
  3401
				}	
sl@0
  3402
			else
sl@0
  3403
				{
sl@0
  3404
				ret = KErrNoMemory;
sl@0
  3405
				}
sl@0
  3406
			}
sl@0
  3407
		}
sl@0
  3408
	
sl@0
  3409
	return ret;
sl@0
  3410
	}
sl@0
  3411
sl@0
  3412
/**
sl@0
  3413
Calculates the angle in degrees formed anti-clockwise between vector V1 and V2, where V1 is a 
sl@0
  3414
horizontal vector to the right from aOriginX, and V2 is the vector (aPointX-aOriginX, aPointY-aOriginY).
sl@0
  3415
sl@0
  3416
@param aOriginX	The x coordinate of a point which represents the origin of our calculation.
sl@0
  3417
@param aOriginY	The y coordinate of a point which represents the origin of our calculation.
sl@0
  3418
@param aPointX	The x coordinate of the point which defines the angle with the origin's x-axis.
sl@0
  3419
@param aPointY 	The y coordinate of the point which defines the angle with the origin's y-axis.
sl@0
  3420
@param aWidth	Width of the rectangle which defines where to draw the ellipse.
sl@0
  3421
@param aHeight 	Height of the rectangle which defines where to draw the ellipse.
sl@0
  3422
sl@0
  3423
@panic DGDIAdapter 1006, if either width or height are less than 1 (debug-only).
sl@0
  3424
@return	The angle in degrees between the vectors V1 and V2 described above.
sl@0
  3425
 */
sl@0
  3426
TReal CVgEngine::GetAngleFromXAxisAnticlockwise(const TReal aOriginX, const TReal aOriginY, const TReal aPointX, const TReal aPointY, const TReal aWidth, const TReal aHeight)
sl@0
  3427
	{
sl@0
  3428
	GRAPHICS_ASSERT_DEBUG((aWidth > 0) && (aHeight > 0), EDirectGdiPanicInvalidParameter);
sl@0
  3429
sl@0
  3430
// The angle is calculated from the radius line that joins the point to the origin.
sl@0
  3431
// The point initially provided defines a line relative to the ellipse.
sl@0
  3432
// But the VG spec states that the required angle is that for a perfect circle
sl@0
  3433
// before that circle is scaled by the bounding rect into an ellipse.
sl@0
  3434
// Therefore, downscale the position of the point relative to the origin, by the
sl@0
  3435
// relative dimensions of the width/height of the ellipse to make it relative to
sl@0
  3436
// the underlying circle. Then use the resulting circle radius line to calculate the angle.
sl@0
  3437
sl@0
  3438
	TReal angle = 0.0f;		
sl@0
  3439
	TReal pointX = aPointX-aOriginX;
sl@0
  3440
	TReal pointY = aPointY-aOriginY;
sl@0
  3441
sl@0
  3442
	const TReal scalingFactor = (aWidth / aHeight);
sl@0
  3443
	pointY *= scalingFactor;
sl@0
  3444
	Math::ATan(angle, pointY, pointX);
sl@0
  3445
	
sl@0
  3446
	// Adjust the angle for Q2 and Q3
sl@0
  3447
	if (pointY < 0)
sl@0
  3448
		angle = (KPi*2)+angle; 
sl@0
  3449
		
sl@0
  3450
	return angle*KRadToDeg;
sl@0
  3451
	}
sl@0
  3452
sl@0
  3453
/**
sl@0
  3454
Method for drawing arcs or pies. An arc is a segment of an ellipse which is defined by a given rectangle. 
sl@0
  3455
The arc is drawn anti-clockwise from the arc start point to the arc end point. The arc start point is the 
sl@0
  3456
intersection between vectors from the centre of the ellipse to the given start position and the ellipse.
sl@0
  3457
The arc end point is defined in the same way.
sl@0
  3458
sl@0
  3459
@param	aRect		The rectangle which defines where to draw the ellipse.
sl@0
  3460
@param	aStart		Position to be used in defining the arc start point.
sl@0
  3461
@param	aEnd		Position to be used in defining the arc end point.
sl@0
  3462
@param 	aArcType	The type of arc to draw; an arc, a chord or a pie.	
sl@0
  3463
sl@0
  3464
@post	Request to draw an arc has been accepted. There is no guarantee that the request 
sl@0
  3465
		has been processed when the method returns.
sl@0
  3466
		
sl@0
  3467
@see	CVgEngine::DrawPie()
sl@0
  3468
@see	CVgEngine::DrawArc()
sl@0
  3469
 */
sl@0
  3470
void CVgEngine::DoDrawArc(const TRect& aRect, const TPoint& aStart, const TPoint& aEnd, VGUArcType aArcType)
sl@0
  3471
	{
sl@0
  3472
	MakeEngineCurrent();
sl@0
  3473
	
sl@0
  3474
	// Only draw if we are not painting with a NULL pen and a NULL brush
sl@0
  3475
	if (iPaintMode == 0)
sl@0
  3476
		return;
sl@0
  3477
		
sl@0
  3478
	// If the pen width and height are the same then draw as normal. If they are different but we should be filling
sl@0
  3479
	// this shape we need to draw the filled area only as normal (not the outline). The outline of the shape is drawn 
sl@0
  3480
	// in the block of code below to allow the effect of a different width and height pen to be applied.
sl@0
  3481
	if ((iPenSize.iWidth == iPenSize.iHeight) || ((iPaintMode & VG_FILL_PATH) && (aArcType == VGU_ARC_PIE)))
sl@0
  3482
		{
sl@0
  3483
		TReal originX = aRect.iTl.iX + (static_cast<TReal>(aRect.Width())*0.5);
sl@0
  3484
		TReal originY = aRect.iTl.iY + (static_cast<TReal>(aRect.Height())*0.5);
sl@0
  3485
		TReal startAngle = GetAngleFromXAxisAnticlockwise(originX, originY, aStart.iX, aStart.iY, aRect.Width(), aRect.Height());
sl@0
  3486
		TReal endAngle = GetAngleFromXAxisAnticlockwise(originX, originY, aEnd.iX, aEnd.iY, aRect.Width(), aRect.Height());		
sl@0
  3487
		TReal extent = endAngle - startAngle;
sl@0
  3488
		
sl@0
  3489
		// The extent defines what direction the arc is drawn in, so make sure we always draw
sl@0
  3490
		// anti-clockwise (-ve extent)
sl@0
  3491
		if (extent > 0.0f)
sl@0
  3492
			extent -= 360.0f;
sl@0
  3493
		
sl@0
  3494
		// If the start and end points are the same, make sure we draw arc all the way round the ellipse
sl@0
  3495
		if ((aStart == aEnd) || (extent > -0.0001f))
sl@0
  3496
			extent = -360.0f;
sl@0
  3497
		
sl@0
  3498
		// Before any vgu command, call SetError() as this stores the current vg error state (if any) in the 
sl@0
  3499
		// driver. Some implementations of vgu clears error state so we'd lose error codes otherwise.
sl@0
  3500
		iDriver.SetError(KErrNone);
sl@0
  3501
		
sl@0
  3502
		if (PreparePath(iVgPath, 5)) // N.B. 5 is just an initial hint as to how large the path may be, not its final size
sl@0
  3503
			{
sl@0
  3504
			VGUErrorCode err = vguArc(iVgPath, 
sl@0
  3505
				originX + 0.5f, 
sl@0
  3506
				originY + 0.5f, 
sl@0
  3507
				aRect.Width(), 
sl@0
  3508
				aRect.Height(), 
sl@0
  3509
				startAngle, 
sl@0
  3510
				extent, 
sl@0
  3511
				aArcType);
sl@0
  3512
			
sl@0
  3513
			if (err == VGU_NO_ERROR)
sl@0
  3514
				{
sl@0
  3515
				VGbitfield paintMode = iPaintMode;		
sl@0
  3516
				if(aArcType == VGU_ARC_OPEN)
sl@0
  3517
					{
sl@0
  3518
					paintMode &= ~VG_FILL_PATH;  
sl@0
  3519
					}
sl@0
  3520
				for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
  3521
					vgDrawPath(iVgPath, (iPenSize.iWidth == iPenSize.iHeight) ? paintMode : VG_FILL_PATH);				
sl@0
  3522
				}
sl@0
  3523
			else
sl@0
  3524
				{
sl@0
  3525
				SetVguError(err);
sl@0
  3526
				}
sl@0
  3527
			}
sl@0
  3528
		}
sl@0
  3529
	
sl@0
  3530
	if ((iPenSize.iWidth != iPenSize.iHeight)
sl@0
  3531
	&& (iPaintMode & VG_STROKE_PATH)		
sl@0
  3532
	&& (iPenSize.iWidth != 0) && (iPenSize.iHeight != 0))
sl@0
  3533
		{
sl@0
  3534
		// Setting a pen with different width and height is not available on OpenVG, so we need to scale 
sl@0
  3535
		// the coordinates we are drawing and apply a scaling matrix that scales by the width and height 
sl@0
  3536
		// of the pen to get the effect of a pen width different width and height.
sl@0
  3537
		TSize penSize = iPenSize;
sl@0
  3538
		SetPenSize(TSize(1, 1));
sl@0
  3539
		vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
sl@0
  3540
		vgScale(penSize.iWidth, penSize.iHeight);			
sl@0
  3541
		VGfloat scaleX = 1.0f/(float)penSize.iWidth;
sl@0
  3542
		VGfloat scaleY = 1.0f/(float)penSize.iHeight;
sl@0
  3543
		
sl@0
  3544
		TReal originX = aRect.iTl.iX + (static_cast<TReal>(aRect.Width())*0.5);
sl@0
  3545
		TReal originY = aRect.iTl.iY + (static_cast<TReal>(aRect.Height())*0.5);
sl@0
  3546
		TReal startAngle = GetAngleFromXAxisAnticlockwise(originX, originY, aStart.iX, aStart.iY, aRect.Width(), aRect.Height());
sl@0
  3547
		TReal endAngle = GetAngleFromXAxisAnticlockwise(originX, originY, aEnd.iX, aEnd.iY, aRect.Width(), aRect.Height());		
sl@0
  3548
		TReal extent = endAngle - startAngle;
sl@0
  3549
		
sl@0
  3550
		// The extent defines what direction the arc is drawn in, so make sure we always draw
sl@0
  3551
		// anti-clockwise (-ve extent)
sl@0
  3552
		if (extent > 0.0f)
sl@0
  3553
			extent -= 360.0f;
sl@0
  3554
		
sl@0
  3555
		// If the start and end points are the same, make sure we draw arc all the way round the ellipse
sl@0
  3556
		if ((aStart == aEnd) || (extent > -0.0001f))
sl@0
  3557
			extent = -360.0f;
sl@0
  3558
		
sl@0
  3559
		// Before any vgu command, call SetError() as this stores the current vg error state (if any) in the 
sl@0
  3560
		// driver. Some implementations of vgu clears error state so we'd lose error codes otherwise.
sl@0
  3561
		iDriver.SetError(KErrNone);
sl@0
  3562
		
sl@0
  3563
		if (PreparePath(iVgPath, 5))
sl@0
  3564
			{
sl@0
  3565
			VGUErrorCode err = vguArc(iVgPath, 
sl@0
  3566
				(originX + 0.5f) * scaleX, 
sl@0
  3567
				(originY + 0.5f) * scaleY, 
sl@0
  3568
				(float)aRect.Width() * scaleX, 
sl@0
  3569
				(float)aRect.Height() * scaleY, 
sl@0
  3570
				startAngle, 
sl@0
  3571
				extent, 
sl@0
  3572
				aArcType);
sl@0
  3573
			
sl@0
  3574
			if (err == VGU_NO_ERROR)
sl@0
  3575
				{	
sl@0
  3576
				for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
  3577
					vgDrawPath(iVgPath, VG_STROKE_PATH);				
sl@0
  3578
				}
sl@0
  3579
			else
sl@0
  3580
				{
sl@0
  3581
				SetVguError(err);
sl@0
  3582
				}
sl@0
  3583
			}
sl@0
  3584
		
sl@0
  3585
		ResetVgMatrix(VG_MATRIX_PATH_USER_TO_SURFACE);
sl@0
  3586
		SetPenSize(penSize);
sl@0
  3587
		}
sl@0
  3588
	
sl@0
  3589
	}
sl@0
  3590
sl@0
  3591
/**
sl@0
  3592
Helper function for drawing a source as a CDirectGdiImageSource.
sl@0
  3593
 
sl@0
  3594
@see DrawResource(const TRect&, const RDirectGdiDrawableSource&, DirectGdi::TGraphicsRotation).
sl@0
  3595
 */
sl@0
  3596
void CVgEngine::DoDrawResource(const TRect& aDestRect,
sl@0
  3597
					CDirectGdiImageSourceImpl* aSource,
sl@0
  3598
					DirectGdi::TGraphicsRotation aRotation)
sl@0
  3599
sl@0
  3600
	{
sl@0
  3601
	TSize size = aSource->Size();
sl@0
  3602
	TRect srcRect(0, 0, size.iWidth, size.iHeight);
sl@0
  3603
	
sl@0
  3604
	DoDrawResource(aDestRect, aSource, srcRect, aRotation);
sl@0
  3605
	}
sl@0
  3606
sl@0
  3607
/**
sl@0
  3608
Helper function for drawing a source as a CDirectGdiImageSource. 
sl@0
  3609
sl@0
  3610
@see DrawResource(const TRect&, const RDirectGdiDrawableSource&, const TRect&, DirectGdi::TGraphicsRotation). 
sl@0
  3611
 */
sl@0
  3612
void CVgEngine::DoDrawResource(const TRect& aDestRect,
sl@0
  3613
					CDirectGdiImageSourceImpl* aSource,
sl@0
  3614
					const TRect& aSourceRect,
sl@0
  3615
					DirectGdi::TGraphicsRotation aRotation)
sl@0
  3616
	{				 
sl@0
  3617
	// If the source rect is smaller than the actual source size then we need to create a child VGImage to draw
sl@0
  3618
	VGImage vgImage = aSource->VgImage();
sl@0
  3619
	TSize size = aSource->Size();
sl@0
  3620
	if ((aSourceRect.Width() < size.iWidth) || (aSourceRect.Height() < size.iHeight))
sl@0
  3621
		{
sl@0
  3622
		vgImage = vgChildImage(vgImage, aSourceRect.iTl.iX, aSourceRect.iTl.iY, aSourceRect.Width(), aSourceRect.Height());
sl@0
  3623
		}
sl@0
  3624
		
sl@0
  3625
	if (vgImage != VG_INVALID_HANDLE)
sl@0
  3626
		{
sl@0
  3627
		vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);	
sl@0
  3628
		
sl@0
  3629
		TRect destRect(aDestRect);
sl@0
  3630
		TRect sourceRect(aSourceRect);
sl@0
  3631
sl@0
  3632
		if (aRotation == DirectGdi::EGraphicsRotationNone ||
sl@0
  3633
			aRotation == DirectGdi::EGraphicsRotation180)
sl@0
  3634
			{
sl@0
  3635
			// Pixel-data in EGLImages appears to be upside down due to the Y-inversion 
sl@0
  3636
			// effect of the Identity matrix.  Therefore must undo the Y-inversion here 
sl@0
  3637
			// and adjust destination rect accordingly.			
sl@0
  3638
			const TInt destRectHeight = aDestRect.Height();
sl@0
  3639
			destRect.iTl.iY = (iSize.iHeight - aDestRect.iTl.iY - iOrigin.iY) - destRectHeight;
sl@0
  3640
			destRect.iTl.iX += iOrigin.iX;
sl@0
  3641
			destRect.iBr.iX += iOrigin.iX;
sl@0
  3642
			destRect.iBr.iY = destRect.iTl.iY + destRectHeight;
sl@0
  3643
			sourceRect.iBr.iY = aSource->Size().iHeight - sourceRect.iTl.iY;
sl@0
  3644
			sourceRect.iTl.iY = sourceRect.iBr.iY - aSourceRect.Height();
sl@0
  3645
			vgLoadIdentity();
sl@0
  3646
			}
sl@0
  3647
		else
sl@0
  3648
			{
sl@0
  3649
			// But if rotation is 90 or 270 degrees, only need to mirror in the X-axis.
sl@0
  3650
			vgScale(-1, 1);
sl@0
  3651
			}
sl@0
  3652
sl@0
  3653
		VGfloat xScale = 1.f;
sl@0
  3654
		VGfloat yScale = 1.f;				
sl@0
  3655
		VGint posX = destRect.iTl.iX;
sl@0
  3656
		VGint posY = destRect.iTl.iY;		
sl@0
  3657
					
sl@0
  3658
		switch (aRotation)
sl@0
  3659
			{									
sl@0
  3660
			case DirectGdi::EGraphicsRotation90:
sl@0
  3661
				xScale = ((VGfloat)destRect.Width()/(VGfloat)sourceRect.Height());
sl@0
  3662
				yScale = ((VGfloat)destRect.Height()/(VGfloat)sourceRect.Width());																	
sl@0
  3663
				vgTranslate(-posX, posY);
sl@0
  3664
				vgScale(xScale, yScale);
sl@0
  3665
				vgRotate(90.0f);					
sl@0
  3666
				break;
sl@0
  3667
			case DirectGdi::EGraphicsRotation180:								
sl@0
  3668
				xScale = ((VGfloat)destRect.Width()/(VGfloat)sourceRect.Width());
sl@0
  3669
				yScale = ((VGfloat)destRect.Height()/(VGfloat)sourceRect.Height());
sl@0
  3670
				vgTranslate(posX+destRect.Width(), posY+destRect.Height());
sl@0
  3671
				vgScale(xScale, yScale);
sl@0
  3672
				vgRotate(180.0f);												
sl@0
  3673
				break;
sl@0
  3674
			case DirectGdi::EGraphicsRotation270:
sl@0
  3675
				xScale = ((VGfloat)destRect.Width()/(VGfloat)sourceRect.Height());
sl@0
  3676
				yScale = ((VGfloat)destRect.Height()/(VGfloat)sourceRect.Width());
sl@0
  3677
				vgTranslate(-posX-destRect.Width(), (posY+destRect.Height()));
sl@0
  3678
				vgScale(xScale, yScale);
sl@0
  3679
				vgRotate(270.0f);
sl@0
  3680
				break;
sl@0
  3681
			default: // DirectGdi::EGraphicsRotationNone
sl@0
  3682
				xScale = ((VGfloat)destRect.Width()/(VGfloat)sourceRect.Width());
sl@0
  3683
				yScale = ((VGfloat)destRect.Height()/(VGfloat)sourceRect.Height());
sl@0
  3684
				vgTranslate(posX, posY);
sl@0
  3685
				vgScale(xScale, yScale);
sl@0
  3686
				break;
sl@0
  3687
			}																							
sl@0
  3688
		
sl@0
  3689
		for (iRegionManager.Begin(); iRegionManager.ApplyClipRegion(); iRegionManager.Next())
sl@0
  3690
			vgDrawImage(vgImage);
sl@0
  3691
		
sl@0
  3692
		if (vgImage != aSource->VgImage())
sl@0
  3693
			{
sl@0
  3694
			// Created a child VGImage, so destroy after use.
sl@0
  3695
			vgDestroyImage(vgImage);
sl@0
  3696
			}
sl@0
  3697
		
sl@0
  3698
		ResetVgMatrix(VG_MATRIX_IMAGE_USER_TO_SURFACE);
sl@0
  3699
		}
sl@0
  3700
	}
sl@0
  3701
sl@0
  3702
/**
sl@0
  3703
Maps a VGU error code to a Symbian OS error code, and sets the driver's error state. If the 
sl@0
  3704
error is unrecognised, the error is set to KErrGeneral.
sl@0
  3705
sl@0
  3706
@param aErr The return value (error state) from a VGU command.
sl@0
  3707
@post If empty, the driver's error state is updated to the mapped error code.
sl@0
  3708
*/
sl@0
  3709
void CVgEngine::SetVguError(VGUErrorCode aErr)
sl@0
  3710
	{
sl@0
  3711
	switch(aErr)
sl@0
  3712
		{
sl@0
  3713
		case VGU_NO_ERROR:
sl@0
  3714
			break;
sl@0
  3715
		case VGU_OUT_OF_MEMORY_ERROR:
sl@0
  3716
			iDriver.SetError(KErrNoMemory);
sl@0
  3717
			break;
sl@0
  3718
		case VGU_BAD_HANDLE_ERROR:
sl@0
  3719
			iDriver.SetError(KErrBadHandle);
sl@0
  3720
			break;
sl@0
  3721
		case VGU_ILLEGAL_ARGUMENT_ERROR:
sl@0
  3722
			iDriver.SetError(KErrArgument);
sl@0
  3723
			break;
sl@0
  3724
		case VGU_PATH_CAPABILITY_ERROR:
sl@0
  3725
			iDriver.SetError(KErrNotSupported);
sl@0
  3726
			break;
sl@0
  3727
		default:
sl@0
  3728
			iDriver.SetError(KErrGeneral);
sl@0
  3729
			break;
sl@0
  3730
		}
sl@0
  3731
	}	
sl@0
  3732
sl@0
  3733
/**
sl@0
  3734
Helper method for creating a VGImage. This method clears the VG image cache in an attempt to  
sl@0
  3735
reclaim some memory if creation of a VGImage fails due to no memory being available, 
sl@0
  3736
it then tries to create the image again. If image creation fails again it then clears the glyph 
sl@0
  3737
cache and tries to create the image again. If image creation still fails, OpenVG is forced to 
sl@0
  3738
complete all currently outstanding drawing requests, so that any OpenVG objects marked for deletion,
sl@0
  3739
such as VGImages that are currently waiting to be drawn, are freed. This is an attempt to make sure 
sl@0
  3740
that images are still displayed in low memory conditions. Use this method instead of calling 
sl@0
  3741
vgCreateImage() directly. Clearing the VG image cache in this way will have a negative effect on 
sl@0
  3742
performance regarding speed, but it is more important that an attempt is made to draw something 
sl@0
  3743
when memory is low.
sl@0
  3744
sl@0
  3745
@param aFormat The pixel format of the image to be created
sl@0
  3746
@param aWidth The width of the image to be created
sl@0
  3747
@param aHeight The height of the image to be created
sl@0
  3748
@param aAllowedQuality One of the VGImageQuality flags
sl@0
  3749
sl@0
  3750
@return A VGImage handle if the image was created successfully, VG_INVALID_HANDLE otherwise 
sl@0
  3751
 */
sl@0
  3752
VGImage CVgEngine::DoVgCreateImage(VGImageFormat aFormat, VGint aWidth, VGint aHeight, VGbitfield aAllowedQuality)
sl@0
  3753
	{
sl@0
  3754
	const TInt oldVgError = CDirectGdiDriverImpl::GetVgError();
sl@0
  3755
	VGImage imageRet = vgCreateImage(aFormat, aWidth, aHeight, aAllowedQuality);
sl@0
  3756
	
sl@0
  3757
	if (imageRet == VG_INVALID_HANDLE)
sl@0
  3758
		{
sl@0
  3759
		// If the new error is anything other than KErrNoMemory, there is nothing that can be done.
sl@0
  3760
		TInt newVgError = CDirectGdiDriverImpl::GetVgError();		
sl@0
  3761
		if (newVgError != KErrNoMemory)
sl@0
  3762
			{
sl@0
  3763
			iDriver.SetError(oldVgError != KErrNone ? oldVgError : newVgError);
sl@0
  3764
			return imageRet;
sl@0
  3765
			}
sl@0
  3766
sl@0
  3767
		// From here on, we are assuming any failure to create the image is due to OOM.
sl@0
  3768
		if (iDriver.VgImageCache())
sl@0
  3769
			{
sl@0
  3770
			// Delete all the images that are currently in the cache then try and create the image again
sl@0
  3771
			iDriver.VgImageCache()->ResetCache();
sl@0
  3772
			imageRet = vgCreateImage(aFormat, aWidth, aHeight, aAllowedQuality);
sl@0
  3773
			}
sl@0
  3774
		if ((imageRet == VG_INVALID_HANDLE) && iFontGlyphImageStorage)
sl@0
  3775
			{
sl@0
  3776
			// Clear the glyph cache as well then try and create the image again
sl@0
  3777
			iFontGlyphImageStorage->CleanGlyphImageCache();
sl@0
  3778
			imageRet = vgCreateImage(aFormat, aWidth, aHeight, aAllowedQuality);
sl@0
  3779
			}
sl@0
  3780
		if ((imageRet == VG_INVALID_HANDLE))
sl@0
  3781
			{
sl@0
  3782
			// Finally, force completion of any outstanding drawing, may free any VGImages marked for deletion.
sl@0
  3783
			// Empty the current OpenVG error state before calling Finish(), as Finish() may call SetError(),
sl@0
  3784
			// and could prematurely set the driver error state to KErrNoMemory.
sl@0
  3785
			//coverity[check_return]
sl@0
  3786
			//coverity[unchecked_value]
sl@0
  3787
			vgGetError();
sl@0
  3788
			iDriver.Finish();
sl@0
  3789
			imageRet = vgCreateImage(aFormat, aWidth, aHeight, aAllowedQuality);
sl@0
  3790
			}
sl@0
  3791
sl@0
  3792
		// If the above worked, empty any OpenVG error state set by any failed attempts to create the image.
sl@0
  3793
		if (imageRet != VG_INVALID_HANDLE)
sl@0
  3794
			{
sl@0
  3795
			//coverity[check_return]
sl@0
  3796
			//coverity[unchecked_value]
sl@0
  3797
			vgGetError();
sl@0
  3798
			}
sl@0
  3799
		}
sl@0
  3800
	
sl@0
  3801
	// Reset the error code to the original VG error code. If oldVgError is KErrNone, 
sl@0
  3802
	// SetError() will use the current OpenVG error state.
sl@0
  3803
	iDriver.SetError(oldVgError);
sl@0
  3804
	
sl@0
  3805
	return imageRet;
sl@0
  3806
	}
sl@0
  3807
sl@0
  3808
/**
sl@0
  3809
Helper method for setting the colour property of a VGPaint object from a TRgb structure.
sl@0
  3810
sl@0
  3811
@param aPaint The VGPaint object to change the colour property of.
sl@0
  3812
@param aColor The colour to set the paint to.
sl@0
  3813
*/ 
sl@0
  3814
void CVgEngine::SetVgPaintColor(VGPaint& aPaint, const TRgb& aColor)
sl@0
  3815
	{
sl@0
  3816
	// Need to swap from internal ARGB to RGBA for OpenVG.
sl@0
  3817
	const TUint argb = aColor.Internal();
sl@0
  3818
	const VGuint rgba = ((argb & 0xFFFFFF) << 8) + ((argb & 0xFF000000) >> 24);
sl@0
  3819
	vgSetColor(aPaint, rgba);
sl@0
  3820
	}