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