windowing/windowserver/nga/SERVER/openwfc/playbackgc.cpp
changeset 0 5d03bc08d59c
child 121 d72fc2aace31
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/nga/SERVER/openwfc/playbackgc.cpp	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,1391 @@
+// Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// GC and Graphics functions
+// 
+//
+
+#include "playbackgc.h"
+
+#include <e32std.h>
+#include <s32mem.h> 
+
+#include "panics.h"
+#include "ScrDev.H"
+#include "windowgroup.h"
+#include "wsfont.h"
+#include "wstop.h"
+#include "Graphics/WSGRAPHICDRAWER.H"
+#include "Graphics/surfaceconfiguration.h"
+#include "windowelementset.h"
+
+#include <graphics/wsgraphicscontext.h>
+#include <graphics/wsuibuffer.h>
+#include "bitgditomwsgraphicscontextmappings.h"
+
+#include "graphicscontextstate.h"
+#include "drawresource.h"
+#include "devicemap.h"
+
+CPlaybackGc * CPlaybackGc::iSelf=NULL;
+
+GLREF_C RWsRegion* InternalizeRegionL(RReadStream& aReadStream);
+
+/*CPlaybackGc*/
+
+void CPlaybackGc::InitStaticsL()
+	{
+	iSelf=new(ELeave) CPlaybackGc();
+	iSelf->ConstructL();
+	}
+
+void CPlaybackGc::DeleteStatics()
+	{
+	delete iSelf;
+	iSelf = 0;
+	}
+
+CPlaybackGc::CPlaybackGc()
+	{
+	}
+
+void CPlaybackGc::ConstructL()
+	{
+	iGcBuf = CBufSeg::NewL(512);
+	}
+
+CPlaybackGc::~CPlaybackGc()
+	{
+	delete iPolyPoints;
+	delete iGcBuf;
+	iCurrentClippingRegion = NULL;
+	iIntersectedRegion.Close();
+	}
+
+void CPlaybackGc::Activate(CWsClientWindow * aWin, MWsGraphicsContext * aGc, const TRegion * aRegion)
+	{
+	iWin = aWin;
+	iGc = aGc;
+	iTargetRegion = aRegion;
+	
+	iDrawRegion = iTargetRegion;
+	iMasterOrigin = iWin->Origin();
+	iOrigin.SetXY(0,0);
+	iSendOrigin = ETrue;
+	iGc->SetBrushColor(iWin->BackColor());
+	ResetClippingRect();
+	}
+	
+void CPlaybackGc::Deactivate()
+	{
+	iWin = 0;
+	iGc = 0;
+	iTargetRegion = 0;
+	iDrawRegion = 0;
+	CancelUserClippingRegion();
+	}
+	
+void CPlaybackGc::CancelUserClippingRegion()
+	{
+	if (iUserDefinedClippingRegion)
+		{
+		iUserDefinedClippingRegion->Destroy();
+		iUserDefinedClippingRegion = 0;
+		iDrawRegion = iTargetRegion;
+		}
+	}
+	
+void CPlaybackGc::SetClippingRect(const TRect &aRect)
+	{
+	iClippingRect=aRect;
+	iClippingRect.Move(iOrigin);
+	iClippingRectSet=ETrue;
+	}
+
+void CPlaybackGc::ResetClippingRect()
+	{
+	iClippingRectSet=EFalse;
+	}
+
+void CPlaybackGc::CheckPolyData(const TAny* aDataPtr, TInt aHeaderSize, TInt aNumPoints)
+	{
+	TInt maxDataLen;
+	if (CWsClient::iCurrentCommand.iOpcode>0)
+		{
+		maxDataLen=CWsClient::EndOfCommandBuffer()-static_cast<const TUint8*>(aDataPtr);
+		}
+	else
+		{
+		maxDataLen=CWsClient::iCurrentCommand.iCmdLength;
+		}
+	const TInt dataSize=aHeaderSize+aNumPoints*sizeof(TPoint);
+	if (dataSize>maxDataLen)
+		GcOwnerPanic(EWservPanicBadPolyData);
+	}
+
+void CPlaybackGc::DoDrawPolygon(const TWsGcCmdDrawPolygon *aDrawPolygon)
+	{
+	CheckPolyData(aDrawPolygon, sizeof(TWsGcCmdDrawPolygon), aDrawPolygon->numPoints);
+	TArrayWrapper<TPoint> points((TPoint*)(aDrawPolygon + 1), aDrawPolygon->numPoints);
+	iGc->DrawPolygon(points, BitGdiToMWsGraphicsContextMappings::Convert(aDrawPolygon->fillRule));
+	}
+
+void CPlaybackGc::StartSegmentedDrawPolygonL(const TWsGcCmdStartSegmentedDrawPolygon *aDrawPolygon)
+	{
+// In case a Playback have been done before all the segment is in the RedrawStore
+// (This allocation is deleted only thanks to the EWsGcOpDrawSegmentedPolygon opcode
+//  which arrive after all the segments)
+	if (iPolyPoints)
+		{
+		delete iPolyPoints;
+		iPolyPoints=NULL;	
+		}
+	if(!Rng(0, aDrawPolygon->totalNumPoints, KMaxTInt/2 - 1))
+		GcOwnerPanic(EWservPanicBadPolyData);	
+	iPolyPoints=(TPoint *)User::AllocL(aDrawPolygon->totalNumPoints*sizeof(TPoint));
+	iPolyPointListSize=aDrawPolygon->totalNumPoints;
+	}
+
+void CPlaybackGc::SegmentedDrawPolygonData(const TWsGcCmdSegmentedDrawPolygonData *aDrawPolygon)
+	{
+	if (aDrawPolygon->index<0 || (aDrawPolygon->index + aDrawPolygon->numPoints) > iPolyPointListSize)
+		GcOwnerPanic(EWservPanicBadPolyData);
+	Mem::Copy(iPolyPoints+aDrawPolygon->index,aDrawPolygon+1,aDrawPolygon->numPoints*sizeof(TPoint));
+	}
+
+void CPlaybackGc::EndSegmentedPolygon()
+	{
+	delete iPolyPoints;
+	iPolyPoints=NULL;
+	}
+
+void CPlaybackGc::DoDrawPolyLine(const TWsGcCmdDrawPolyLine *aDrawPolyLine, TBool aContinued)
+	{
+	TInt numPoints=aDrawPolyLine->numPoints;
+	CheckPolyData(aDrawPolyLine, sizeof(TWsGcCmdDrawPolyLine), numPoints);
+	const TPoint *points=(TPoint *)(aDrawPolyLine+1);
+	if (aContinued)
+		{
+		numPoints++;
+		points=&aDrawPolyLine->last;
+		}
+	TArrayWrapper<TPoint> pointsArr(points, numPoints);
+	if (aDrawPolyLine->more)	// more to come so don't draw the end point
+		iGc->DrawPolyLineNoEndPoint(pointsArr);
+	else
+		iGc->DrawPolyLine(pointsArr);
+	}
+
+void CPlaybackGc::GcOwnerPanic(TClientPanic aPanic)
+	{
+	iGc->ResetClippingRegion();
+	iCurrentClippingRegion = NULL;
+	EndSegmentedPolygon();
+	iWin->WsOwner()->PPanic(aPanic);
+	}
+	
+// implementing MWsGc
+
+MWsClient& CPlaybackGc::Client()
+	{
+	return *(iWin->WsOwner());
+	}
+
+MWsScreen& CPlaybackGc::Screen()
+	{
+	return *(iWin->Screen());
+	}
+
+const TTime& CPlaybackGc::Now() const
+	{
+	return iWin->Screen()->Now();
+	}
+	
+void CPlaybackGc::ScheduleAnimation(const TRect& aRect,const TTimeIntervalMicroSeconds& aFromNow)
+	{
+	ScheduleAnimation(aRect,aFromNow,0,0);
+	}
+
+void CPlaybackGc::ScheduleAnimation(const TRect& aRect,const TTimeIntervalMicroSeconds& aFromNow,const TTimeIntervalMicroSeconds& aFreq,const TTimeIntervalMicroSeconds& aStop)
+	{
+	// convert window rect to screen rect
+	TRect rect(aRect);
+	rect.Move(iGc->Origin());
+	// clip rect to window extent
+	rect.Intersection(iWin->Abs());
+	if (!rect.IsEmpty())
+		{
+		// and schedule it
+		iWin->Screen()->ScheduleAnimation(ECrpAnim, rect, aFromNow, aFreq, aStop, iWin);
+		}
+	}
+
+void CPlaybackGc::SetGcOrigin(const TPoint& aOrigin) 
+	{
+	iOrigin = aOrigin - iMasterOrigin;
+	} 
+
+void CPlaybackGc::RemoteReadDataAndDrawL(const CWsGraphicDrawer* aGraphic, CWsClient* aOwner, const TWsGcCmdUnion &aData)
+	{
+	TPtrC8 data;
+	HBufC8* dataBuf = NULL;
+	const TInt len = aData.WsGraphic->iDataLen;
+	
+	if ((len >= KMaxTInt / 4) || (len < 0))
+		{
+		aOwner->PPanic(EWservPanicBuffer);	
+		}	
+	dataBuf = HBufC8::NewLC(len);
+	TPtr8 des = dataBuf->Des();
+	aOwner->RemoteRead(des, 0);
+
+	if(des.Size() != len)
+		{
+		aOwner->PPanic(EWservPanicBuffer);
+		}
+	data.Set(des);																
+	aGraphic->Draw(*this, aData.WsGraphic->iRect, data);
+	CleanupStack::PopAndDestroy(dataBuf);		
+	}
+
+TPtrC CPlaybackGc::BufferTPtr(TText* aStart,TInt aLen, const TDesC8& aCmdData)
+	{
+	if ((reinterpret_cast<TUint8*>(aStart) < aCmdData.Ptr()
+									|| reinterpret_cast<TUint8*>(aStart+aLen) > (aCmdData.Ptr() + aCmdData.Size()) ))
+		{
+		GcOwnerPanic(EWservPanicBufferPtr);
+		}
+	TPtrC gcPtr;
+	gcPtr.Set(aStart,aLen);
+	return(gcPtr);
+	} 
+
+void CPlaybackGc::DoDrawCommand(TWsGcOpcodes aOpcode, const TDesC8& aCmdData, const TRegion *aRegion)
+	{
+    if (aRegion->Count()==0)
+        return;
+
+    TWsGcCmdUnion pData;
+	// coverity[returned_pointer]
+	pData.any=aCmdData.Ptr();
+
+	SendClippingRegionIfRequired(aRegion);
+
+	WS_ASSERT_DEBUG(!iCurrentClippingRegion, EWsPanicDrawCommandsInvalidState);
+	iCurrentClippingRegion = aRegion;
+
+	CGraphicsContext::TTextParameters contextParam;
+	
+	TBool bGcDrawingOccurred = ETrue;	//most commands in here draw using the gc
+	
+	switch(aOpcode)
+		{
+		case EWsGcOpDrawWsGraphic:
+		case EWsGcOpDrawWsGraphicPtr:
+			{
+			bGcDrawingOccurred = EFalse;	//best guess if the drawer did no happen 
+			TRect screenRect(pData.WsGraphic->iRect);
+			screenRect.Move(iGc->Origin());
+			if(iCurrentClippingRegion->Intersects(screenRect))
+				{
+				const TInt dataLen = pData.WsGraphic->iDataLen;
+				TGraphicDrawerId id;
+				id.iId = pData.WsGraphic->iId;
+				id.iIsUid = (pData.WsGraphic->iFlags & EWsGraphicIdUid);
+				CWsClient* owner = iWin->WsOwner();
+				const CWsGraphicDrawer* graphic = CWsTop::WindowServer()->ResolveGraphic(id);
+				TInt lastDrawCount=GcDrawingCount();
+				if(graphic && graphic->IsSharedWith(owner->SecureId()))
+					{
+					if(aOpcode == EWsGcOpDrawWsGraphicPtr)
+						{
+						TRAPD(err, RemoteReadDataAndDrawL(graphic, owner, pData))
+						if(err)
+							WS_PANIC_DEBUG(EWsPanicWsGraphic);
+						}
+					else
+						graphic->Draw(*this,pData.WsGraphic->iRect,CWsClient::BufferTPtr8((TUint8*)(pData.WsGraphic+1),dataLen));
+	
+					WS_ASSERT_DEBUG(!iGcBuf->Size(),EWsPanicWsGraphic);
+					iGcBuf->Reset();
+					}
+				if (lastDrawCount!=GcDrawingCount())
+					{
+					// Changes to the GcDrawingCount are used to tag placed and background surfaces as dirty.
+					// If drawing occurs inside a CRP and perhaps PlaceSurface occurs inside the CRP 
+					// then we tag to count again to cause the placed surface to get marked as dirty later.
+					bGcDrawingOccurred = ETrue;	//some GC drawing did occurr at some point
+					}
+				}
+			break;
+			}
+		case EWsGcOpMapColorsLocal:
+			GcOwnerPanic(EWservPanicOpcode); //deprecated, the client should never generate this op
+			break;
+		case EWsGcOpDrawPolyLineLocalBufLen:
+			{
+			TArrayWrapper<TPoint> points(pData.DrawPolyLineLocalBufLen->points, pData.DrawPolyLineLocalBufLen->length);
+			iGc->DrawPolyLine(points);
+			break;
+			}
+		case EWsGcOpDrawPolyLineLocal:
+			iGc->DrawPolyLine(pData.PointList->Array());
+			break;
+		case EWsGcOpDrawPolygonLocalBufLen:
+			{
+			TArrayWrapper<TPoint> points(pData.DrawPolygonLocalBufLen->points, pData.DrawPolygonLocalBufLen->length);
+			iGc->DrawPolygon(points, BitGdiToMWsGraphicsContextMappings::Convert(pData.DrawPolygonLocalBufLen->fillRule));
+			break;
+			}
+		case EWsGcOpDrawPolygonLocal:
+			iGc->DrawPolygon(pData.DrawPolygonLocal->pointList->Array(),BitGdiToMWsGraphicsContextMappings::Convert(pData.DrawPolygonLocal->fillRule));
+			break;
+		case EWsGcOpDrawBitmapLocal:
+			{
+			// DrawBitmap(TPoint&, ) uses the size of the bitmap in twips, but 
+			// MWsGraphicsContext::DrawBitmap() takes a TRect in pixels, so we need to convert
+			TRect destRect(iWin->Screen()->DeviceMap().TwipsToPixels(pData.BitmapLocal->bitmap->SizeInTwips()));
+			destRect.Move(pData.BitmapLocal->pos); //pos is defined in pixels, that's why we're not converting it
+			iGc->DrawBitmap(destRect, *pData.BitmapLocal->bitmap);
+			break;
+			}
+		case EWsGcOpDrawBitmap2Local:
+			iGc->DrawBitmap(pData.Bitmap2Local->rect, *pData.Bitmap2Local->bitmap);
+			break;
+		case EWsGcOpDrawBitmap3Local:
+			iGc->DrawBitmap(pData.Bitmap3Local->rect, *pData.Bitmap3Local->bitmap, pData.Bitmap3Local->srcRect);
+			break;
+		case EWsGcOpDrawBitmapMaskedLocal:
+			iGc->DrawBitmapMasked(pData.iBitmapMaskedLocal->iRect, *pData.iBitmapMaskedLocal->iBitmap, pData.iBitmapMaskedLocal->iSrcRect, *pData.iBitmapMaskedLocal->iMaskBitmap,pData.iBitmapMaskedLocal->iInvertMask);
+			break;
+		case EWsGcOpAlphaBlendBitmapsLocal:
+			iGc->BitBltMasked(pData.AlphaBlendBitmapsLocal->point, *pData.AlphaBlendBitmapsLocal->iBitmap,
+						                  pData.AlphaBlendBitmapsLocal->source, *pData.AlphaBlendBitmapsLocal->iAlpha,
+						                  pData.AlphaBlendBitmapsLocal->alphaPoint);
+			break;
+		case EWsGcOpDrawText:
+			if (iGc->HasFont())
+				iGc->DrawText(BufferTPtr((TText *)(pData.DrawText+1),pData.DrawText->length,aCmdData), NULL, pData.DrawText->pos);
+			break;
+		case EWsGcOpDrawBoxTextOptimised1:
+			if (iGc->HasFont())
+				iGc->DrawText(BufferTPtr((TText *)(pData.BoxTextO1+1),pData.BoxTextO1->length,aCmdData), NULL, pData.BoxTextO1->box,
+							  pData.BoxTextO1->baselineOffset,MWsGraphicsContext::ELeft,0);
+			break;
+		case EWsGcOpDrawBoxTextOptimised2:
+			if (iGc->HasFont())
+				iGc->DrawText(BufferTPtr((TText *)(pData.BoxTextO2+1),pData.BoxTextO2->length,aCmdData), NULL, pData.BoxTextO2->box,
+							  pData.BoxTextO2->baselineOffset,BitGdiToMWsGraphicsContextMappings::Convert(pData.BoxTextO2->horiz),pData.BoxTextO2->leftMrg);
+			break;
+		case EWsGcOpDrawTextPtr:
+			if (iGc->HasFont())
+				iGc->DrawText(*pData.DrawTextPtr->text, NULL, pData.DrawTextPtr->pos);
+			break;
+		case EWsGcOpDrawTextPtr1:
+			if (iGc->HasFont())
+				iGc->DrawText(*pData.DrawTextPtr->text, NULL);
+			break;
+		case EWsGcOpDrawBoxText:
+			if (iGc->HasFont())
+				iGc->DrawText(BufferTPtr((TText *)(pData.BoxText+1),pData.BoxText->length,aCmdData), NULL, pData.BoxText->box,
+							  pData.BoxText->baselineOffset,BitGdiToMWsGraphicsContextMappings::Convert(pData.BoxText->horiz),pData.BoxText->leftMrg);
+			break;
+		case EWsGcOpDrawBoxTextPtr:
+			if (iGc->HasFont())
+				iGc->DrawText(*pData.DrawBoxTextPtr->text, NULL, pData.DrawBoxTextPtr->box,pData.DrawBoxTextPtr->baselineOffset,BitGdiToMWsGraphicsContextMappings::Convert(pData.DrawBoxTextPtr->horiz),pData.DrawBoxTextPtr->leftMrg);
+			break;
+		case EWsGcOpDrawBoxTextPtr1:
+			if (iGc->HasFont())
+				iGc->DrawText(*pData.DrawBoxTextPtr->text, NULL, pData.DrawBoxTextPtr->box);
+			break;
+		case EWsGcOpDrawTextVertical:
+			if (iGc->HasFont())
+				iGc->DrawTextVertical(BufferTPtr((TText *)(pData.DrawTextVertical+1),pData.DrawTextVertical->length,aCmdData),NULL,pData.DrawTextVertical->pos
+							          ,pData.DrawTextVertical->up);
+			break;
+		case EWsGcOpDrawTextVerticalPtr:
+			if (iGc->HasFont())
+				iGc->DrawTextVertical(*pData.DrawTextVerticalPtr->text,NULL,pData.DrawTextVerticalPtr->pos,pData.DrawTextVerticalPtr->up);
+			break;
+		case EWsGcOpDrawTextVerticalPtr1:
+			if (iGc->HasFont())
+				iGc->DrawTextVertical(*pData.DrawTextVerticalPtr->text,NULL,pData.DrawTextVerticalPtr->up);
+			break;
+		case EWsGcOpDrawBoxTextVertical:
+			if (iGc->HasFont())
+				iGc->DrawTextVertical(BufferTPtr((TText *)(pData.DrawBoxTextVertical+1),pData.DrawBoxTextVertical->length,aCmdData), NULL,
+									  pData.DrawBoxTextVertical->box,	pData.DrawBoxTextVertical->baselineOffset,
+									  pData.DrawBoxTextVertical->up,BitGdiToMWsGraphicsContextMappings::Convert(pData.DrawBoxTextVertical->vert),pData.DrawBoxTextVertical->margin);
+			break;
+		case EWsGcOpDrawBoxTextVerticalPtr:
+			if (iGc->HasFont())
+				iGc->DrawTextVertical(*pData.DrawBoxTextVerticalPtr->text,NULL,pData.DrawBoxTextVerticalPtr->box,pData.DrawBoxTextVerticalPtr->baselineOffset
+									  ,pData.DrawBoxTextVerticalPtr->width,pData.DrawBoxTextVerticalPtr->up,BitGdiToMWsGraphicsContextMappings::Convert(pData.DrawBoxTextVerticalPtr->vert),pData.DrawBoxTextVerticalPtr->margin);
+			break;
+		case EWsGcOpDrawBoxTextVerticalPtr1:
+			if (iGc->HasFont())
+				iGc->DrawTextVertical(*pData.DrawBoxTextVerticalPtr->text,NULL,pData.DrawBoxTextVerticalPtr->box,pData.DrawBoxTextVerticalPtr->up);
+			break;
+		case EWsGcOpDrawTextLocal:
+			if (iGc->HasFont())
+				iGc->DrawText(*pData.DrawTextLocal->desc, NULL, pData.DrawTextLocal->pos);
+			break;
+		case EWsGcOpDrawBoxTextLocal:
+			if (iGc->HasFont())
+				iGc->DrawText(*pData.BoxTextLocal->desc, NULL, pData.BoxTextLocal->box,pData.BoxTextLocal->baselineOffset,
+							  BitGdiToMWsGraphicsContextMappings::Convert(pData.BoxTextLocal->horiz),pData.BoxTextLocal->leftMrg);
+			break;
+		/************* DrawText in Context function calls*********************************************/
+		case EWsGcOpDrawTextInContext:
+			contextParam.iStart = pData.DrawTextInContext->start;
+			contextParam.iEnd = pData.DrawTextInContext->end;
+			if((contextParam.iStart < contextParam.iEnd) && (iGc->HasFont()))
+				{
+				iGc->DrawText(BufferTPtr((TText *)(pData.DrawTextInContext+1),pData.DrawTextInContext->length,aCmdData),BitGdiToMWsGraphicsContextMappings::Convert(&contextParam),pData.DrawTextInContext->pos);
+				}
+			break;
+		case EWsGcOpDrawBoxTextInContextOptimised1:
+			contextParam.iStart = pData.BoxTextInContextO1->start;
+			contextParam.iEnd = pData.BoxTextInContextO1->end;
+			if((contextParam.iStart < contextParam.iEnd) && (iGc->HasFont()))
+				{
+				iGc->DrawText(BufferTPtr((TText *)(pData.BoxTextInContextO1+1),pData.BoxTextInContextO1->length,aCmdData),BitGdiToMWsGraphicsContextMappings::Convert(&contextParam),pData.BoxTextInContextO1->box,
+							  pData.BoxTextInContextO1->baselineOffset,MWsGraphicsContext::ELeft,0);
+				}
+			break;
+		case EWsGcOpDrawBoxTextInContextOptimised2:
+			contextParam.iStart = pData.BoxTextInContextO2->start;
+			contextParam.iEnd = pData.BoxTextInContextO2->end;
+			if((contextParam.iStart < contextParam.iEnd) && (iGc->HasFont()))
+				{
+				iGc->DrawText(BufferTPtr((TText *)(pData.BoxTextInContextO2+1),pData.BoxTextInContextO2->length,aCmdData),BitGdiToMWsGraphicsContextMappings::Convert(&contextParam),pData.BoxTextInContextO2->box,
+							  pData.BoxTextInContextO2->baselineOffset,BitGdiToMWsGraphicsContextMappings::Convert(pData.BoxTextInContextO2->horiz),pData.BoxTextInContextO2->leftMrg);
+				}
+			break;
+		case EWsGcOpDrawTextInContextPtr:
+			contextParam.iStart = pData.DrawTextInContextPtr->start;
+			contextParam.iEnd = pData.DrawTextInContextPtr->end;
+			if((contextParam.iStart < contextParam.iEnd) && (iGc->HasFont()))
+				{
+				iGc->DrawText(*pData.DrawTextInContextPtr->text,BitGdiToMWsGraphicsContextMappings::Convert(&contextParam),pData.DrawTextInContextPtr->pos);
+				}
+			break;
+		case EWsGcOpDrawTextInContextPtr1:
+			contextParam.iStart = pData.DrawTextInContextPtr->start;
+			contextParam.iEnd = pData.DrawTextInContextPtr->end;
+			if((contextParam.iStart < contextParam.iEnd) && (iGc->HasFont()))
+				{
+				iGc->DrawText(*pData.DrawTextInContextPtr->text,BitGdiToMWsGraphicsContextMappings::Convert(&contextParam));
+				}
+			break;
+		case EWsGcOpDrawBoxTextInContext:
+			contextParam.iStart = pData.BoxTextInContext->start;
+			contextParam.iEnd = pData.BoxTextInContext->end;
+			if((contextParam.iStart < contextParam.iEnd) && (iGc->HasFont()))
+				{
+				iGc->DrawText(BufferTPtr((TText *)(pData.BoxTextInContext+1),pData.BoxTextInContext->length,aCmdData),
+							  BitGdiToMWsGraphicsContextMappings::Convert(&contextParam),pData.BoxTextInContext->box,pData.BoxTextInContext->baselineOffset,
+							  BitGdiToMWsGraphicsContextMappings::Convert(pData.BoxTextInContext->horiz),pData.BoxTextInContext->leftMrg);
+				}
+			break;
+		case EWsGcOpDrawBoxTextInContextPtr:
+			contextParam.iStart = pData.DrawBoxTextInContextPtr->start;
+			contextParam.iEnd = pData.DrawBoxTextInContextPtr->end;
+			if((contextParam.iStart < contextParam.iEnd) && (iGc->HasFont()))
+				{
+				iGc->DrawText(*pData.DrawBoxTextInContextPtr->text,BitGdiToMWsGraphicsContextMappings::Convert(&contextParam),pData.DrawBoxTextInContextPtr->box,pData.DrawBoxTextInContextPtr->baselineOffset,
+							  BitGdiToMWsGraphicsContextMappings::Convert(pData.DrawBoxTextInContextPtr->horiz),pData.DrawBoxTextInContextPtr->leftMrg);
+				}
+			break;
+		case EWsGcOpDrawBoxTextInContextPtr1:
+			contextParam.iStart = pData.DrawBoxTextInContextPtr->start;
+			contextParam.iEnd = pData.DrawBoxTextInContextPtr->end;
+			if((contextParam.iStart < contextParam.iEnd) && (iGc->HasFont()))
+				{
+				iGc->DrawText(*pData.DrawBoxTextInContextPtr->text,BitGdiToMWsGraphicsContextMappings::Convert(&contextParam),pData.DrawBoxTextInContextPtr->box);
+				}
+			break;
+		case EWsGcOpDrawTextInContextVertical:
+			contextParam.iStart = pData.DrawTextInContextVertical->start;
+			contextParam.iEnd = pData.DrawTextInContextVertical->end;
+			if((contextParam.iStart < contextParam.iEnd) && (iGc->HasFont()))
+				{
+				iGc->DrawTextVertical(BufferTPtr((TText *)(pData.DrawTextInContextVertical+1),pData.DrawTextInContextVertical->length,aCmdData),
+									  BitGdiToMWsGraphicsContextMappings::Convert(&contextParam),pData.DrawTextInContextVertical->pos,pData.DrawTextInContextVertical->up);
+				}
+			break;
+		case EWsGcOpDrawTextInContextVerticalPtr:
+			contextParam.iStart = pData.DrawTextInContextVerticalPtr->start;
+			contextParam.iEnd = pData.DrawTextInContextVerticalPtr->end;
+			if((contextParam.iStart < contextParam.iEnd) && (iGc->HasFont()))
+				{
+				iGc->DrawTextVertical(*pData.DrawTextInContextVerticalPtr->text,BitGdiToMWsGraphicsContextMappings::Convert(&contextParam),
+									  pData.DrawTextInContextVerticalPtr->pos,pData.DrawTextInContextVerticalPtr->up);
+				}
+			break;
+		case EWsGcOpDrawTextInContextVerticalPtr1:
+			contextParam.iStart = pData.DrawTextInContextVerticalPtr->start;
+			contextParam.iEnd = pData.DrawTextInContextVerticalPtr->end;
+			if((contextParam.iStart < contextParam.iEnd) && (iGc->HasFont()))
+				{
+				iGc->DrawTextVertical(*pData.DrawTextInContextVerticalPtr->text,BitGdiToMWsGraphicsContextMappings::Convert(&contextParam),pData.DrawTextInContextVerticalPtr->up);
+				}
+			break;
+		case EWsGcOpDrawBoxTextInContextVertical:
+			contextParam.iStart = pData.DrawBoxTextInContextVertical->start;
+			contextParam.iEnd = pData.DrawBoxTextInContextVertical->end;
+			if((contextParam.iStart < contextParam.iEnd) && (iGc->HasFont()))
+				{
+				iGc->DrawTextVertical(BufferTPtr((TText *)(pData.DrawBoxTextInContextVertical+1),pData.DrawBoxTextInContextVertical->length,aCmdData),
+									  BitGdiToMWsGraphicsContextMappings::Convert(&contextParam),pData.DrawBoxTextInContextVertical->box,pData.DrawBoxTextInContextVertical->baselineOffset,
+									  pData.DrawBoxTextInContextVertical->up,BitGdiToMWsGraphicsContextMappings::Convert(pData.DrawBoxTextInContextVertical->vert),pData.DrawBoxTextInContextVertical->margin);
+				}
+			break;
+		case EWsGcOpDrawBoxTextInContextVerticalPtr:
+			contextParam.iStart = pData.DrawBoxTextInContextVerticalPtr->start;
+			contextParam.iEnd = pData.DrawBoxTextInContextVerticalPtr->end;
+			if((contextParam.iStart < contextParam.iEnd) && (iGc->HasFont()))
+				{
+				iGc->DrawTextVertical(*pData.DrawBoxTextVerticalPtr->text,BitGdiToMWsGraphicsContextMappings::Convert(&contextParam),pData.DrawBoxTextVerticalPtr->box,pData.DrawBoxTextVerticalPtr->baselineOffset
+									  ,pData.DrawBoxTextVerticalPtr->width,pData.DrawBoxTextVerticalPtr->up,BitGdiToMWsGraphicsContextMappings::Convert(pData.DrawBoxTextVerticalPtr->vert),pData.DrawBoxTextVerticalPtr->margin);
+				}
+			break;
+		case EWsGcOpDrawBoxTextInContextVerticalPtr1:
+			contextParam.iStart = pData.DrawBoxTextInContextVerticalPtr->start;
+			contextParam.iEnd = pData.DrawBoxTextInContextVerticalPtr->end;
+			if((contextParam.iStart < contextParam.iEnd) && (iGc->HasFont()))
+				{
+				iGc->DrawTextVertical(*pData.DrawBoxTextVerticalPtr->text,BitGdiToMWsGraphicsContextMappings::Convert(&contextParam),pData.DrawBoxTextVerticalPtr->box,pData.DrawBoxTextVerticalPtr->up);
+				}
+			break;
+		case EWsGcOpDrawTextInContextLocal:
+			contextParam.iStart = pData.DrawTextInContextLocal->start;
+			contextParam.iEnd = pData.DrawTextInContextLocal->end;
+			if((contextParam.iStart < contextParam.iEnd) && (iGc->HasFont()))
+				{
+				iGc->DrawText(*pData.DrawTextInContextLocal->desc,BitGdiToMWsGraphicsContextMappings::Convert(&contextParam),pData.DrawTextInContextLocal->pos);
+				}
+			break;
+		case EWsGcOpDrawBoxTextInContextLocal:
+			contextParam.iStart = pData.BoxTextInContextLocal->start;
+			contextParam.iEnd = pData.BoxTextInContextLocal->end;
+			if((contextParam.iStart < contextParam.iEnd) && (iGc->HasFont()))
+				{
+				iGc->DrawText(*pData.BoxTextInContextLocal->desc,BitGdiToMWsGraphicsContextMappings::Convert(&contextParam),pData.BoxTextInContextLocal->box,pData.BoxTextInContextLocal->baselineOffset,
+							  BitGdiToMWsGraphicsContextMappings::Convert(pData.BoxTextInContextLocal->horiz),pData.BoxTextInContextLocal->leftMrg);
+				}
+			break;
+		case EWsGcOpDrawLine:
+			iGc->DrawLine(pData.DrawLine->pnt1,pData.DrawLine->pnt2);
+			break;
+		case EWsGcOpDrawTo:
+			iGc->DrawLine(iLinePos,*pData.Point);
+			break;
+		case EWsGcOpDrawBy:
+			iGc->DrawLine(iLinePos,iLinePos+(*pData.Point));
+			break;
+		case EWsGcOpPlot:
+			iGc->Plot(*pData.Point);
+			break;
+		case EWsGcOpMoveTo:
+		case EWsGcOpMoveBy:
+			break;
+		case EWsGcOpGdiBlt2Local:
+			iGc->BitBlt(pData.GdiBlt2Local->pos,*pData.GdiBlt2Local->bitmap);
+			break;
+		case EWsGcOpGdiBlt3Local:
+			iGc->BitBlt(pData.GdiBlt3Local->pos,*pData.GdiBlt3Local->bitmap, pData.GdiBlt3Local->rect);
+			break;
+		case EWsGcOpGdiBltMaskedLocal:
+			iGc->BitBltMasked(pData.GdiBltMaskedLocal->pos,*pData.GdiBltMaskedLocal->bitmap,
+								pData.GdiBltMaskedLocal->rect,*pData.GdiBltMaskedLocal->maskBitmap,
+								pData.GdiBltMaskedLocal->invertMask);
+			break;
+		case EWsGcOpGdiWsBlt2:
+		case EWsGcOpGdiWsBlt3:
+		case EWsGcOpGdiWsBltMasked:
+		case EWsGcOpGdiWsAlphaBlendBitmaps:
+		case EWsGcOpWsDrawBitmapMasked:
+			{
+			CFbsBitmap* scratchBitmap = NULL;
+			CFbsBitmap* scratchMaskBimap = NULL;
+			TInt maskHandle=0;
+			TInt handle=WsBitmapHandle(aOpcode,pData, maskHandle);
+			CWsClient* owner=iWin->WsOwner();
+			if (owner!=NULL)
+				{
+				TInt wsBmpErr = KErrNone;
+				DWsBitmap *bitmap=(DWsBitmap *)owner->HandleToObj(handle, WS_HANDLE_BITMAP);
+				if (!bitmap)
+					wsBmpErr = KErrNotFound;
+				else
+					scratchBitmap=bitmap->FbsBitmap();
+				if (wsBmpErr == KErrNone)
+					if (aOpcode==EWsGcOpGdiWsBltMasked || aOpcode==EWsGcOpGdiWsAlphaBlendBitmaps || aOpcode==EWsGcOpWsDrawBitmapMasked)
+						{
+						DWsBitmap *bitmap2=(DWsBitmap *)owner->HandleToObj(maskHandle, WS_HANDLE_BITMAP);
+						if (!bitmap2)
+							wsBmpErr = KErrNotFound;
+						else
+							scratchMaskBimap=bitmap2->FbsBitmap();
+						}
+				if (wsBmpErr == KErrNone)
+					{
+					switch(aOpcode)
+						{
+						case EWsGcOpGdiWsBlt2:
+							iGc->BitBlt(pData.GdiBlt2->pos,*scratchBitmap);
+							break;
+						case EWsGcOpGdiWsBlt3:
+							iGc->BitBlt(pData.GdiBlt3->pos,*scratchBitmap, pData.GdiBlt3->rect);
+							break;
+						case EWsGcOpGdiWsBltMasked:
+							{
+							iGc->BitBltMasked(pData.GdiBltMasked->destination,*scratchBitmap,
+											pData.GdiBltMasked->source, *scratchMaskBimap,
+											pData.GdiBltMasked->invertMask);
+							}
+							break;
+						case EWsGcOpGdiWsAlphaBlendBitmaps:
+							{
+							iGc->BitBltMasked(pData.AlphaBlendBitmaps->point,*scratchBitmap,
+											   pData.AlphaBlendBitmaps->source, *scratchMaskBimap,
+											   pData.AlphaBlendBitmaps->alphaPoint);
+							}
+							break;
+						case EWsGcOpWsDrawBitmapMasked:
+							{
+							iGc->DrawBitmapMasked(pData.iBitmapMasked->iRect,*scratchBitmap, 
+												pData.iBitmapMasked->iSrcRect,*scratchMaskBimap,
+												pData.iBitmapMasked->iInvertMask);
+							}
+							break;
+						}
+					}
+				}
+			break;
+			}
+		case EWsGcOpGdiBlt2:
+		case EWsGcOpGdiBlt3:
+        case EWsGcOpDrawBitmap:
+        case EWsGcOpDrawBitmap2:
+        case EWsGcOpDrawBitmap3:
+            {
+			TInt bitmapMaskHandle=0;
+            TInt bitmapHandle = FbsBitmapHandle(aOpcode, pData, bitmapMaskHandle);
+            const CFbsBitmap* bitmap = iWin->Redraw()->BitmapFromHandle(bitmapHandle);
+			if(!bitmap)
+			    {
+			    WS_PANIC_DEBUG(EWsPanicBitmapNotFound);
+			    break;
+			    }
+			
+            switch(aOpcode)
+                {
+                case EWsGcOpGdiBlt2:
+                    iGc->BitBlt(pData.GdiBlt2->pos,*bitmap);
+                    break;
+                case EWsGcOpGdiBlt3:
+                    iGc->BitBlt(pData.GdiBlt3->pos,*bitmap, pData.GdiBlt3->rect);
+                    break;
+                case EWsGcOpDrawBitmap:
+                    {
+                    // DrawBitmap(TPoint&, ) uses the size of the bitmap in twips, but 
+                    // MWsGraphicsContext::DrawBitmap() takes a TRect in pixels, so we need to convert
+                    TRect destRect(iWin->Screen()->DeviceMap().TwipsToPixels(bitmap->SizeInTwips()));
+                    destRect.Move(pData.Bitmap->pos); //pos is defined in pixels, that's why we're not converting it
+                    iGc->DrawBitmap(destRect, *bitmap);
+                    break;
+                    }
+                case EWsGcOpDrawBitmap2:
+                    iGc->DrawBitmap(pData.Bitmap2->rect, *bitmap);
+                    break;
+                case EWsGcOpDrawBitmap3:
+                    iGc->DrawBitmap(pData.Bitmap3->rect, *bitmap, pData.Bitmap3->srcRect);
+                    break;
+                }
+			break;
+            }
+        case EWsGcOpGdiBltMasked:
+        case EWsGcOpGdiAlphaBlendBitmaps:
+        case EWsGcOpDrawBitmapMasked:
+            {
+            TInt bitmapMaskHandle=0;
+            TInt bitmapHandle = FbsBitmapHandle(aOpcode, pData, bitmapMaskHandle);
+            const CFbsBitmap* bitmap = iWin->Redraw()->BitmapFromHandle(bitmapHandle);
+            if(!bitmap)
+                {
+                WS_PANIC_DEBUG(EWsPanicBitmapNotFound);
+                break;
+                }
+            
+            CFbsBitmap* bitmapMask = iWin->Redraw()->BitmapFromHandle(bitmapMaskHandle);
+            if(!bitmapMask)
+                {
+                WS_PANIC_DEBUG(EWsPanicBitmapNotFound);
+                break;
+                }
+                        
+            switch(aOpcode)
+                {
+                case EWsGcOpGdiBltMasked:
+                    {
+                    iGc->BitBltMasked(pData.GdiBltMasked->destination,*bitmap,
+                                        pData.GdiBltMasked->source, *bitmapMask,
+                                        pData.GdiBltMasked->invertMask);
+                    break;
+                    }
+                case EWsGcOpGdiAlphaBlendBitmaps:
+                    {
+                    iGc->BitBltMasked(pData.AlphaBlendBitmaps->point, *bitmap,
+                                        pData.AlphaBlendBitmaps->source, *bitmapMask,
+                                        pData.AlphaBlendBitmaps->alphaPoint);
+                    break;
+                    }
+                case EWsGcOpDrawBitmapMasked:
+                    {
+                    iGc->DrawBitmapMasked(pData.iBitmapMasked->iRect, *bitmap, 
+                                        pData.iBitmapMasked->iSrcRect, *bitmapMask,
+                                        pData.iBitmapMasked->iInvertMask);
+                    break;
+                    }
+                }
+			break;
+			}
+		case EWsGcOpDrawSegmentedPolygon:
+			{
+			TArrayWrapper<TPoint> points(iPolyPoints, iPolyPointListSize);
+			iGc->DrawPolygon(points, BitGdiToMWsGraphicsContextMappings::Convert(pData.DrawSegmentedPolygon->fillRule));
+			break;
+			}
+		case EWsGcOpDrawPolygon:
+			DoDrawPolygon(pData.Polygon);
+			break;
+		case EWsGcOpDrawPolyLine:
+			DoDrawPolyLine(pData.PolyLine, EFalse);
+			break;
+		case EWsGcOpDrawPolyLineContinued:
+			DoDrawPolyLine(pData.PolyLine, ETrue);
+			break;
+		case EWsGcOpClear:
+			iGc->Clear(TRect(iWin->Size()));
+			break;
+		case EWsGcOpClearRect:
+			iGc->Clear(*pData.Rect);
+			break;
+		case EWsGcOpDrawRect:
+			iGc->DrawRect(*pData.Rect);
+			break;
+		case EWsGcOpDrawEllipse:
+			iGc->DrawEllipse(*pData.Rect);
+			break;
+		case EWsGcOpDrawRoundRect:
+			iGc->DrawRoundRect(*pData.Rect,pData.RoundRect->ellipse);
+			break;
+		case EWsGcOpDrawArc:
+			iGc->DrawArc(*pData.Rect,pData.ArcOrPie->start,pData.ArcOrPie->end);
+			break;
+		case EWsGcOpDrawPie:
+			iGc->DrawPie(*pData.Rect,pData.ArcOrPie->start,pData.ArcOrPie->end);
+			break;
+		case EWsGcOpCopyRect:
+			iGc->CopyRect(pData.CopyRect->pos,*pData.Rect);
+			break;
+		case EWsGcOpMapColors:
+			GcOwnerPanic(EWservPanicOpcode); //deprecated, the client should never generate this op
+			break;
+		case EWsGcOpSetShadowColor:
+			iGc->SetTextShadowColor(*pData.rgb);
+			break;
+		case EWsGcOpDrawResourceToPos:
+		case EWsGcOpDrawResourceToRect:
+		case EWsGcOpDrawResourceFromRectToRect:
+		case EWsGcOpDrawResourceWithData:
+			DoDrawResource(aOpcode, pData);
+			break;
+		default:
+			TRAP_IGNORE(iWin->OwnerPanic(EWservPanicOpcode));
+			break;
+		}
+	iGc->ResetClippingRegion();
+	iCurrentClippingRegion = NULL;
+	if (bGcDrawingOccurred)
+		{
+		GcDrawingDone();	//up the count (again for CRPs)
+		}
+	}
+/**
+ Helper function for drawing resources. 
+ It extracts DWsDrawableSource objects which corresponds RWsDrawableResource object on the server side and then redirect call to concrete implementation. 
+ @param aOpcode GC opcodes
+ @param aData An extra data which will be used for resource drawing 
+ */
+void CPlaybackGc::DoDrawResource(TWsGcOpcodes aOpcode, const TWsGcCmdUnion &aData)
+	{
+	CWsClient* owner=iWin->WsOwner(); // We can't just use iWsOwner - it can be null for stored commands
+	if (owner!=NULL)
+		{
+		CWsDrawableSource *drawable = static_cast<CWsDrawableSource*>(owner->HandleToObj(*aData.Int, WS_HANDLE_DRAWABLE_SOURCE));
+		if (!drawable)
+			return;
+		
+		switch(aOpcode)
+			{
+		case EWsGcOpDrawResourceToPos:
+			drawable->DrawResource(iGc, aData.DrawWsResourceToPos->pos, aData.DrawWsResourceToPos->rotation);
+			break;
+		case EWsGcOpDrawResourceToRect:
+			drawable->DrawResource(iGc, aData.DrawWsResourceToRect->rect, aData.DrawWsResourceToRect->rotation);
+			break;
+		case EWsGcOpDrawResourceFromRectToRect:
+			drawable->DrawResource(iGc, aData.DrawWsResourceFromRectToRect->rectDest, aData.DrawWsResourceFromRectToRect->rectSrc, aData.DrawWsResourceFromRectToRect->rotation);
+			break;
+		case EWsGcOpDrawResourceWithData:
+			drawable->DrawResource(iGc, aData.DrawWsResourceWithData->rect, *aData.DrawWsResourceWithData->desc);
+			break;
+		default:
+			break;
+			}
+		}
+	}
+
+TInt CPlaybackGc::WsBitmapHandle(TInt aOpcode, const TWsGcCmdUnion &pData, TInt& aMaskHandle) 
+	{
+	TInt handle=0;
+	switch(aOpcode)
+		{
+		case EWsGcOpGdiWsBlt2:
+			handle=pData.GdiBlt2->handle;
+			break;
+		case EWsGcOpGdiWsBlt3:
+			handle=pData.GdiBlt3->handle;
+			break;
+		case EWsGcOpGdiWsBltMasked:
+			handle=pData.GdiBltMasked->handle;
+			aMaskHandle = pData.GdiBltMasked->maskHandle;
+			break;
+		case EWsGcOpGdiWsAlphaBlendBitmaps:
+			handle=pData.AlphaBlendBitmaps->bitmapHandle;
+			aMaskHandle = pData.AlphaBlendBitmaps->alphaHandle;
+			break;
+		case EWsGcOpWsDrawBitmapMasked:
+			handle=pData.iBitmapMasked->iHandle;
+			aMaskHandle=pData.iBitmapMasked->iMaskHandle;
+			break;
+		}
+	return handle;
+	}		
+
+TInt CPlaybackGc::FbsBitmapHandle(TInt aOpcode, const TWsGcCmdUnion &pData, TInt& aMaskHandle)
+	{
+	TInt handle=0;
+	aMaskHandle=0;
+	switch(aOpcode)
+		{
+		case EWsGcOpGdiBlt2:
+			handle=pData.GdiBlt2->handle;
+			break;
+		case EWsGcOpGdiBlt3:
+			handle=pData.GdiBlt3->handle;
+			break;
+		case EWsGcOpGdiBltMasked:
+			handle=pData.GdiBltMasked->handle;
+			aMaskHandle=pData.GdiBltMasked->maskHandle;
+			break;
+		case EWsGcOpGdiAlphaBlendBitmaps:
+			handle=pData.AlphaBlendBitmaps->bitmapHandle;
+			aMaskHandle=pData.AlphaBlendBitmaps->alphaHandle;
+			break;
+		case EWsGcOpDrawBitmap:
+			handle=pData.Bitmap->handle;
+			break;
+		case EWsGcOpDrawBitmap2:
+			handle=pData.Bitmap2->handle;
+			break;
+		case EWsGcOpDrawBitmap3:
+			handle=pData.Bitmap3->handle;
+			break;
+		case EWsGcOpDrawBitmapMasked:
+			handle=pData.iBitmapMasked->iHandle;
+			aMaskHandle=pData.iBitmapMasked->iMaskHandle;
+			break;
+		default:
+			WS_ASSERT_DEBUG(EFalse, EWsPanicInvalidOperation);
+			break;
+		}
+	return handle;
+	}
+
+void CPlaybackGc::UpdateJustification(TText* aText,TInt aLen,const TDesC8& aCmdData,CGraphicsContext::TTextParameters* aParam)
+	{
+	iGc->UpdateJustification(BufferTPtr(aText,aLen,aCmdData), BitGdiToMWsGraphicsContextMappings::Convert(aParam));
+	}
+
+void CPlaybackGc::SendOriginIfRequired()
+    {
+    const TPoint currentOrigin(iMasterOrigin + iOrigin); 
+    if (iSendOrigin || currentOrigin != iLastSentOrigin)
+        {
+        iGc->SetOrigin(currentOrigin);
+        iLastSentOrigin = currentOrigin;
+        iSendOrigin = EFalse;
+        }
+    }
+
+void CPlaybackGc::SendClippingRegionIfRequired(const TRegion* aRegion)
+    {
+    if (iUserDefinedClippingRegion || iClippingRectSet || !iWin->Screen()->ChangeTracking())
+        {
+        iGc->SetClippingRegion(*aRegion);
+        }
+    }
+
+void CPlaybackGc::DoDrawing(TWsGcOpcodes aOpcode, const TDesC8& aCmdData)
+	{
+	TWsGcCmdUnion pData;
+	// coverity[returned_pointer]
+	pData.any=aCmdData.Ptr();
+
+	iIntersectedRegion.Clear();
+	iIntersectedRegion.Copy(*iDrawRegion);
+	
+	if (iClippingRectSet)
+		{
+	    // MWsGraphicsContext doesn't provide a SetClippingRect API. If a client calls SetClippingRect
+	    // the rect is passed to the render stage using MWsGraphicsContext::SetClippingRegion
+        TRect clippingRectRelativeToScreen(iClippingRect);
+        clippingRectRelativeToScreen.Move(iMasterOrigin);
+		iIntersectedRegion.ClipRect(clippingRectRelativeToScreen);
+        iIntersectedRegion.ClipRect(iWin->AbsRect());
+		}
+
+	SendOriginIfRequired();
+	
+	DoDrawCommand(aOpcode,aCmdData,&iIntersectedRegion);
+
+	CGraphicsContext::TTextParameters contextParam;
+	switch(aOpcode)
+		{
+		case EWsGcOpDrawLine:
+			iLinePos=pData.DrawLine->pnt2;
+			break;
+		case EWsGcOpDrawTo:
+		case EWsGcOpMoveTo:
+		case EWsGcOpPlot:
+			iLinePos=(*pData.Point);
+			break;
+		case EWsGcOpDrawBy:
+		case EWsGcOpMoveBy:
+			iLinePos+=(*pData.Point);
+			break;
+		case EWsGcOpDrawSegmentedPolygon:
+			EndSegmentedPolygon();
+			break;
+		case EWsGcOpDrawText:
+			UpdateJustification((TText *)(pData.DrawText+1),pData.DrawText->length,aCmdData,NULL);
+			break;
+		case EWsGcOpDrawTextVertical:
+			UpdateJustification((TText *)(pData.DrawTextVertical+1),pData.DrawTextVertical->length,aCmdData,NULL);
+			break;
+		case EWsGcOpDrawBoxText:
+			UpdateJustification((TText *)(pData.BoxText+1),pData.BoxText->length,aCmdData,NULL);
+			break;
+		case EWsGcOpDrawBoxTextOptimised1:
+			UpdateJustification((TText *)(pData.BoxTextO1+1),pData.BoxTextO1->length,aCmdData,NULL);
+			break;
+		case EWsGcOpDrawBoxTextOptimised2:
+			UpdateJustification((TText *)(pData.BoxTextO2+1),pData.BoxTextO2->length,aCmdData,NULL);
+			break;
+		case EWsGcOpDrawBoxTextVertical:
+			UpdateJustification((TText *)(pData.DrawBoxTextVertical+1),pData.DrawBoxTextVertical->length,aCmdData,NULL);
+			break;
+		case EWsGcOpDrawTextLocal:
+			iGc->UpdateJustification(*pData.DrawTextLocal->desc,NULL);
+			break;
+		case EWsGcOpDrawBoxTextLocal:
+			iGc->UpdateJustification(*pData.BoxTextLocal->desc,NULL);
+			break;
+		case EWsGcOpDrawTextPtr:
+			iGc->UpdateJustification(*pData.DrawTextPtr->text,NULL);
+			break;
+		case EWsGcOpDrawTextVerticalPtr:
+			iGc->UpdateJustification(*pData.DrawTextVerticalPtr->text,NULL);
+			break;
+		case EWsGcOpDrawBoxTextPtr:
+			iGc->UpdateJustification(*pData.DrawBoxTextPtr->text,NULL);
+			break;
+		case EWsGcOpDrawBoxTextVerticalPtr:
+			iGc->UpdateJustification(*pData.DrawBoxTextVerticalPtr->text,NULL);
+			break;
+		/***************DrawTextInContext*****************************************************************/
+		case EWsGcOpDrawTextInContext:
+			contextParam.iStart = pData.DrawTextInContext->start;
+			contextParam.iEnd = pData.DrawTextInContext->end;
+			if(contextParam.iStart < contextParam.iEnd)
+				{
+				UpdateJustification((TText *)(pData.DrawTextInContext+1),pData.DrawTextInContext->length,aCmdData,&contextParam);
+				}
+			break;
+		case EWsGcOpDrawTextInContextVertical:
+			contextParam.iStart = pData.DrawTextInContext->start;
+			contextParam.iEnd = pData.DrawTextInContext->end;
+			if(contextParam.iStart < contextParam.iEnd)
+				{
+				UpdateJustification((TText *)(pData.DrawTextInContextVertical+1),pData.DrawTextInContextVertical->length,aCmdData,&contextParam);
+				}
+			break;
+		case EWsGcOpDrawBoxTextInContext:
+			contextParam.iStart = pData.DrawTextInContext->start;
+			contextParam.iEnd = pData.DrawTextInContext->end;
+			if(contextParam.iStart < contextParam.iEnd)
+				{
+				UpdateJustification((TText *)(pData.BoxTextInContext+1),pData.BoxTextInContext->length,aCmdData,&contextParam);
+				}
+			break;
+		case EWsGcOpDrawBoxTextInContextOptimised1:
+			contextParam.iStart = pData.DrawTextInContext->start;
+			contextParam.iEnd = pData.DrawTextInContext->end;
+			if(contextParam.iStart < contextParam.iEnd)
+				{
+				UpdateJustification((TText *)(pData.BoxTextInContextO1+1),pData.BoxTextInContextO1->length,aCmdData,&contextParam);
+				}
+			break;
+		case EWsGcOpDrawBoxTextInContextOptimised2:
+			contextParam.iStart = pData.DrawTextInContext->start;
+			contextParam.iEnd = pData.DrawTextInContext->end;
+			if(contextParam.iStart < contextParam.iEnd)
+				{
+				UpdateJustification((TText *)(pData.BoxTextInContextO2+1),pData.BoxTextInContextO2->length,aCmdData,&contextParam);
+				}
+			break;
+		case EWsGcOpDrawBoxTextInContextVertical:
+			contextParam.iStart = pData.DrawTextInContext->start;
+			contextParam.iEnd = pData.DrawTextInContext->end;
+			if(contextParam.iStart < contextParam.iEnd)
+				{
+				UpdateJustification((TText *)(pData.DrawBoxTextInContextVertical+1),pData.DrawBoxTextInContextVertical->length,aCmdData,&contextParam);
+				}
+			break;
+		case EWsGcOpDrawTextInContextLocal:
+			contextParam.iStart = pData.DrawTextInContext->start;
+			contextParam.iEnd = pData.DrawTextInContext->end;
+			if(contextParam.iStart < contextParam.iEnd)
+				{
+				iGc->UpdateJustification(*pData.DrawTextInContextLocal->desc,BitGdiToMWsGraphicsContextMappings::Convert(&contextParam));
+				}
+			break;
+		case EWsGcOpDrawBoxTextInContextLocal:
+			contextParam.iStart = pData.DrawTextInContext->start;
+			contextParam.iEnd = pData.DrawTextInContext->end;
+			if(contextParam.iStart < contextParam.iEnd)
+				{
+				iGc->UpdateJustification(*pData.BoxTextInContextLocal->desc,BitGdiToMWsGraphicsContextMappings::Convert(&contextParam));
+				}
+			break;
+		case EWsGcOpDrawTextInContextPtr:
+			contextParam.iStart = pData.DrawTextInContext->start;
+			contextParam.iEnd = pData.DrawTextInContext->end;
+			if(contextParam.iStart < contextParam.iEnd)
+				{
+				iGc->UpdateJustification(*pData.DrawTextInContextPtr->text,BitGdiToMWsGraphicsContextMappings::Convert(&contextParam));
+				}
+			break;
+		case EWsGcOpDrawTextInContextVerticalPtr:
+			contextParam.iStart = pData.DrawTextInContext->start;
+			contextParam.iEnd = pData.DrawTextInContext->end;
+			if(contextParam.iStart < contextParam.iEnd)
+				{
+				iGc->UpdateJustification(*pData.DrawTextInContextVerticalPtr->text,BitGdiToMWsGraphicsContextMappings::Convert(&contextParam));
+				}
+			break;
+		case EWsGcOpDrawBoxTextInContextPtr:
+			contextParam.iStart = pData.DrawTextInContext->start;
+			contextParam.iEnd = pData.DrawTextInContext->end;
+			if(contextParam.iStart < contextParam.iEnd)
+				{
+				iGc->UpdateJustification(*pData.DrawBoxTextInContextPtr->text,BitGdiToMWsGraphicsContextMappings::Convert(&contextParam));
+				}
+			break;
+		case EWsGcOpDrawBoxTextInContextVerticalPtr:
+			contextParam.iStart = pData.DrawTextInContext->start;
+			contextParam.iEnd = pData.DrawTextInContext->end;
+			if(contextParam.iStart < contextParam.iEnd)
+				{
+				iGc->UpdateJustification(*pData.DrawBoxTextInContextVerticalPtr->text,BitGdiToMWsGraphicsContextMappings::Convert(&contextParam));
+				}
+			break;
+		}
+	}
+
+void CPlaybackGc::CommandL(TWsGcOpcodes aOpcode, const TDesC8& aCmdData)
+	{
+    WS_ASSERT_DEBUG(iWin,EWsPanicWindowNull);
+	TWsGcCmdUnion pData;
+	// coverity[returned_pointer]
+	pData.any=aCmdData.Ptr();
+	
+	switch(aOpcode)
+		{
+	case EWsGcOpStartSegmentedDrawPolygon:
+		StartSegmentedDrawPolygonL(pData.StartSegmentedDrawPolygon);
+		break;
+	case EWsGcOpSegmentedDrawPolygonData:
+		SegmentedDrawPolygonData(pData.SegmentedDrawPolygonData);
+		break;
+	case EWsGcOpSetClippingRegion:
+		WS_ASSERT_DEBUG(aOpcode != EWsGcOpSetClippingRegion, EWsPanicDrawCommandsInvalidState);
+		break;
+	case EWsGcOpSetClippingRect:
+		SetClippingRect(*pData.Rect);
+		break;
+	case EWsGcOpCancelClippingRect:
+		ResetClippingRect();
+		break;
+	case EWsGcOpCancelClippingRegion:
+		CancelUserClippingRegion();
+		break;
+	case EWsGcOpSetFaded: // deprecated
+		// do nothing
+		break;
+	case EWsGcOpSetFadeParams: // deprecated
+		// do nothing
+		break;
+	case EWsGcOpSetDrawMode:
+		iGc->SetDrawMode(BitGdiToMWsGraphicsContextMappings::LossyConvert((CGraphicsContext::TDrawMode)*pData.UInt));
+		break;
+	case EWsGcOpUseFont:
+		if (CWsFontCache::Instance()->UseFont(iFont, *pData.UInt))
+			{
+			CFbsBitGcFont font;
+			if(font.Duplicate(*pData.UInt) == KErrNone)
+				iGc->SetFont(&font);
+			font.Reset();
+			}
+		else
+			iGc->SetFontNoDuplicate(iFont);
+		break;
+	case EWsGcOpDiscardFont:
+		CWsFontCache::Instance()->ReleaseFont(iFont);
+		iGc->ResetFont();
+		break;
+	case EWsGcOpSetUnderlineStyle:
+		iGc->SetUnderlineStyle(BitGdiToMWsGraphicsContextMappings::Convert(*pData.SetUnderlineStyle));
+		break;
+	case EWsGcOpSetStrikethroughStyle:
+		iGc->SetStrikethroughStyle(BitGdiToMWsGraphicsContextMappings::Convert(*pData.SetStrikethroughStyle));
+		break;
+	case EWsGcOpUseBrushPattern:
+		iGc->SetBrushPattern(*pData.handle);
+		break;
+	case EWsGcOpDiscardBrushPattern:
+		iGc->ResetBrushPattern();
+		break;
+	case EWsGcOpSetBrushColor:
+		iGc->SetBrushColor(*pData.rgb);
+		break;
+	case EWsGcOpSetPenColor:
+		iGc->SetPenColor(*pData.rgb);
+		break;
+	case EWsGcOpSetPenStyle:
+		iGc->SetPenStyle(BitGdiToMWsGraphicsContextMappings::Convert((CGraphicsContext::TPenStyle)*pData.UInt));
+		break;
+	case EWsGcOpSetPenSize:
+		iGc->SetPenSize(*pData.Size);
+		break;
+	case EWsGcOpSetBrushStyle:
+		{
+		MWsGraphicsContext::TBrushStyle style = BitGdiToMWsGraphicsContextMappings::Convert((CGraphicsContext::TBrushStyle)*pData.UInt); 
+		if (iGc->HasBrushPattern() || style != MWsGraphicsContext::EPatternedBrush)
+			{
+			iGc->SetBrushStyle(style);
+			}
+		break;
+		}
+	case EWsGcOpReset:
+		CWsFontCache::Instance()->ReleaseFont(iFont);
+		iGc->Reset();
+		iOrigin.SetXY(0,0);
+		iSendOrigin = ETrue; // we must call SetOrigin at next opportunity because it's likely the render stage implementation of Reset (when resetting origin) doesn't take into account the window origin
+		ResetClippingRect();
+		iGc->SetBrushColor(iWin->BackColor());
+		break;
+	case EWsGcOpSetBrushOrigin:
+		iGc->SetBrushOrigin(*pData.Point);
+		break;
+	case EWsGcOpSetDitherOrigin:
+		GcOwnerPanic(EWservPanicOpcode); //deprecated, the client should never generate this op
+		break;
+	case EWsGcOpSetWordJustification:
+		iGc->SetWordJustification(pData.SetJustification->excessWidth, pData.SetJustification->numGaps);
+		break;
+	case EWsGcOpSetCharJustification:
+		iGc->SetCharJustification(pData.SetJustification->excessWidth, pData.SetJustification->numGaps);
+		break;
+	case EWsGcOpSetOrigin:
+		SetOrigin(*pData.Point);
+		break;
+	case EWsGcOpSetOpaque: // deprecated
+		// do nothing
+		break;
+	default:	// Assume remaining functions will draw
+		{
+		DoDrawing(aOpcode,aCmdData);
+		return;
+		}
+		}
+	}
+
+
+void CPlaybackGc::SetOrigin(const TPoint &aOrigin)
+	{
+	iOrigin=aOrigin;
+	}
+	
+/*------------------------------------------------------------------------------
+  Description: Retrieves graphics context information back from a given buffer
+               from a given start position.
+ -----------------------------------------------------------------------------*/
+void CPlaybackGc::InternalizeL(const CBufBase& aBuffer,TInt& aStartPos)
+	{
+	// Open the stream used for the input from the given start position
+	// in the buffer.
+	RBufReadStream bufReadStream;
+	bufReadStream.Open(aBuffer,aStartPos);
+	CleanupClosePushL(bufReadStream);
+	
+	// Read the font/bitmap server data
+	TInternalGcStatus::InternalizeGcAttributesL(iGc, bufReadStream);
+
+	iOrigin.iX = bufReadStream.ReadInt32L();
+	iOrigin.iY = bufReadStream.ReadInt32L();
+	iSendOrigin = ETrue;
+
+	iClippingRectSet=bufReadStream.ReadInt8L();
+	
+	// If there is a clipping rectangle data read it.
+	if (iClippingRectSet)
+		bufReadStream>>iClippingRect;
+		
+	// Read the clipping region data
+	InternalizeClippingRegionL(bufReadStream);
+
+	// Read the Alpha values for Brush and Pen colors.
+	InternalizeAlphaValueL(bufReadStream);
+	
+	CleanupStack::PopAndDestroy(&bufReadStream);
+	}
+
+/*------------------------------------------------------------------------------
+  Description: Retrieves TRgb::alpha value information back from a given buffer
+               and updates the Brushcolor with the same.
+ -----------------------------------------------------------------------------*/
+void CPlaybackGc::InternalizeAlphaValueL(RReadStream& aReadStream)
+	{
+	TRgb brushColor(iGc->BrushColor());
+	brushColor.SetAlpha(aReadStream.ReadUint8L());
+	iGc->SetBrushColor(brushColor);
+	TRgb penColor(iGc->PenColor());
+	penColor.SetAlpha(aReadStream.ReadUint8L());
+	iGc->SetPenColor(penColor);
+	}
+
+/*------------------------------------------------------------------------------
+  Description: Helper method to retrieve clipping region data from a given
+               read stream.
+ -----------------------------------------------------------------------------*/
+void CPlaybackGc::InternalizeClippingRegionL(RReadStream& aReadStream)
+	{
+	WS_ASSERT_DEBUG(iTargetRegion, EWsPanicDrawCommandsInvalidState);
+	// Read flag to indicate if client had defined a clipping region
+	TBool clipRegion = aReadStream.ReadInt8L();
+	CancelUserClippingRegion();
+	if (clipRegion)
+		{
+		// Note that this clipping region is in window relative coordinates when
+		// received from the client (and being stored) but is in screen relative
+		// coordinates after being retrieved from the redraw store.
+		iUserDefinedClippingRegion = InternalizeRegionL(aReadStream);
+		iUserDefinedClippingRegion->Offset(iWin->Origin());
+		iUserDefinedClippingRegion->Intersect(*iTargetRegion);
+		if (iUserDefinedClippingRegion->CheckError()) // fallback to no user clipping region
+			{
+			CancelUserClippingRegion();
+			}
+		else
+			{
+			iDrawRegion = iUserDefinedClippingRegion;
+			}
+		}
+	}
+
+/**
+* @deprecated
+*/
+TInt CPlaybackGc::PlaceSurface(const TSurfaceConfiguration& /*aConfig*/)
+    {
+    return KErrNotSupported;
+    }
+
+/**	Get the drawing occurred indication counter.	
+  	Callers can detect if drawing has occurred between two points 
+ 	by detecting that this count has changed.
+ 	Note that the changed value does not necessarily represent the exact number of operations which occurred.
+  	@return value which changes each time GC drawing occurrs.
+ **/
+TInt CPlaybackGc::GcDrawingCount()
+	{
+	return iGcDrawingCounter;
+	}
+
+/**	Update the drawing occurred indication counter.	
+ 	Called internally each time a drawing operation updates the UI content 
+ **/
+void CPlaybackGc::GcDrawingDone()
+	{
+	iGcDrawingCounter++;
+	}
+
+
+/**
+This pretty much replaces the whole of what was TDrawDestination
+This can only be sensibly called from outside a sequence of drawing commands,
+since it negates any user defined clipping regions.
+*/
+void CPlaybackGc::SetTargetRegion(const TRegion* aRegion)
+	{
+	iTargetRegion = aRegion;
+	iDrawRegion = iTargetRegion;
+	CancelUserClippingRegion();
+	}
+	
+void CPlaybackGc::Reset()
+	{
+	iGc->Reset();
+	}
+
+TAny * CPlaybackGc::ResolveObjectInterface(TUint aId)
+	{
+	switch (aId)
+		{
+	    case MWsSurfacePlacement::EWsObjectInterfaceId:
+	        return static_cast<MWsSurfacePlacement *>(this); //deprecated
+		case MWsWindow::EWsObjectInterfaceId:
+			return dynamic_cast<MWsWindow *>(iWin);
+		case MWsGraphicsContext::EWsObjectInterfaceId:
+			return static_cast<MWsGraphicsContext*>(iGc);
+		case MWsUiBuffer::EWsObjectInterfaceId:
+		case MWsFader::EWsObjectInterfaceId:	
+			return iWin->Screen()->ResolveObjectInterface(aId);
+		}
+	return NULL;
+	}