windowing/windowserver/nonnga/SERVER/playbackgc.cpp
changeset 0 5d03bc08d59c
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     1 // Copyright (c) 1994-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 // GC.CPP
       
    15 // GC and Graphics functions
       
    16 // 
       
    17 //
       
    18 
       
    19 #include "playbackgc.h"
       
    20 
       
    21 #include <e32std.h>
       
    22 #include <s32mem.h> 
       
    23 
       
    24 #include "backedupwindow.h"
       
    25 #include "panics.h"
       
    26 #include "ScrDev.H"
       
    27 #include "windowgroup.h"
       
    28 #include "wsfont.h"
       
    29 #include "wstop.h"
       
    30 #include "Graphics/WSGRAPHICDRAWER.H"
       
    31 
       
    32 #if defined(__WINS__) && defined(_DEBUG)
       
    33 #   include "offscreenbitmap.h"
       
    34 #	define DEBUGOSB { CWsOffScreenBitmap * ofb = iWin->Screen()->OffScreenBitmap(); if (ofb) ofb->Update(); }
       
    35 #else
       
    36 #	define DEBUGOSB
       
    37 #endif
       
    38 
       
    39 CPlaybackGc * CPlaybackGc::iSelf=NULL;
       
    40 
       
    41 GLREF_C RWsRegion* InternalizeRegionL(RReadStream& aReadStream);
       
    42 
       
    43 /*CPlaybackGc*/
       
    44 
       
    45 void CPlaybackGc::InitStaticsL()
       
    46 	{
       
    47 	iSelf=new(ELeave) CPlaybackGc();
       
    48 	iSelf->ConstructL();
       
    49 	}
       
    50 
       
    51 void CPlaybackGc::DeleteStatics()
       
    52 	{
       
    53 	delete iSelf;
       
    54 	iSelf = 0;
       
    55 	}
       
    56 
       
    57 CPlaybackGc::CPlaybackGc()
       
    58 	{
       
    59 	}
       
    60 
       
    61 void CPlaybackGc::ConstructL()
       
    62 	{
       
    63 	iSelf->iScratchBitmap=new(ELeave) CFbsBitmap();
       
    64 	iSelf->iScratchMaskBitmap=new(ELeave) CFbsBitmap();
       
    65 	iGcBuf = CBufSeg::NewL(512);
       
    66 	}
       
    67 
       
    68 CPlaybackGc::~CPlaybackGc()
       
    69 	{
       
    70 	delete iPolyPoints;
       
    71 	delete iGcBuf;
       
    72 	iCurrentClippingRegion = NULL;
       
    73 	delete iScratchBitmap;
       
    74 	delete iScratchMaskBitmap;
       
    75 	}
       
    76 
       
    77 void CPlaybackGc::Activate(CWsClientWindow * aWin, CFbsBitGc * aGc, const TRegion * aRegion)
       
    78 	{
       
    79 	iWin = aWin;
       
    80 	iGc = aGc;
       
    81 	iTargetRegion = aRegion;
       
    82 	
       
    83 	iDrawRegion = iTargetRegion;
       
    84 	iMasterOrigin = iWin->Origin();
       
    85 	iOrigin.SetXY(0,0);
       
    86 	iGc->SetBrushColor(iWin->BackColor());
       
    87 	ResetClippingRect();
       
    88 	}
       
    89 	
       
    90 void CPlaybackGc::Deactivate()
       
    91 	{
       
    92 	iWin = 0;
       
    93 	iGc = 0;
       
    94 	iTargetRegion = 0;
       
    95 	iDrawRegion = 0;
       
    96 	CancelUserClippingRegion();
       
    97 	}
       
    98 	
       
    99 void CPlaybackGc::CancelUserClippingRegion()
       
   100 	{
       
   101 	if (iUserDefinedClippingRegion)
       
   102 		{
       
   103 		iUserDefinedClippingRegion->Destroy();
       
   104 		iUserDefinedClippingRegion = 0;
       
   105 		iDrawRegion = iTargetRegion;
       
   106 		}
       
   107 	}
       
   108 	
       
   109 void CPlaybackGc::SetClippingRect(const TRect &aRect)
       
   110 	{
       
   111 	iClippingRect=aRect;
       
   112 	iClippingRect.Move(iOrigin);
       
   113 	iClippingRectSet=ETrue;
       
   114 	}
       
   115 
       
   116 void CPlaybackGc::ResetClippingRect()
       
   117 	{
       
   118 	iClippingRectSet=EFalse;
       
   119 	}
       
   120 
       
   121 void CPlaybackGc::CheckPolyData(const TAny* aDataPtr, TInt aHeaderSize, TInt aNumPoints)
       
   122 	{
       
   123 	TInt maxDataLen;
       
   124 	if (CWsClient::iCurrentCommand.iOpcode>0)
       
   125 		{
       
   126 		maxDataLen=CWsClient::EndOfCommandBuffer()-static_cast<const TUint8*>(aDataPtr);
       
   127 		}
       
   128 	else
       
   129 		{
       
   130 		maxDataLen=CWsClient::iCurrentCommand.iCmdLength;
       
   131 		}
       
   132 	const TInt dataSize=aHeaderSize+aNumPoints*sizeof(TPoint);
       
   133 	if (dataSize>maxDataLen)
       
   134 		GcOwnerPanic(EWservPanicBadPolyData);
       
   135 	}
       
   136 
       
   137 void CPlaybackGc::DoDrawPolygon(const TWsGcCmdDrawPolygon *aDrawPolygon)
       
   138 	{
       
   139 	CheckPolyData(aDrawPolygon, sizeof(TWsGcCmdDrawPolygon), aDrawPolygon->numPoints);
       
   140 	iGc->DrawPolygon((TPoint *)(aDrawPolygon+1),aDrawPolygon->numPoints,aDrawPolygon->fillRule);
       
   141 	}
       
   142 
       
   143 void CPlaybackGc::StartSegmentedDrawPolygonL(const TWsGcCmdStartSegmentedDrawPolygon *aDrawPolygon)
       
   144 	{
       
   145 	// In case a Playback have been done before all the segment is in the RedrawStore
       
   146 	// (This allocation is deleted only thanks to the EWsGcOpDrawSegmentedPolygon opcode
       
   147 	//  which arrive after all the segments)
       
   148 	delete iPolyPoints;
       
   149 	iPolyPoints=NULL;	
       
   150 
       
   151 	iPolyPoints=(TPoint *)User::AllocL(aDrawPolygon->totalNumPoints*sizeof(TPoint));
       
   152 	iPolyPointListSize=aDrawPolygon->totalNumPoints;
       
   153 	}
       
   154 
       
   155 void CPlaybackGc::SegmentedDrawPolygonData(const TWsGcCmdSegmentedDrawPolygonData *aDrawPolygon)
       
   156 	{
       
   157 	if (aDrawPolygon->index<0 || (aDrawPolygon->index + aDrawPolygon->numPoints) > iPolyPointListSize)
       
   158 		GcOwnerPanic(EWservPanicBadPolyData);
       
   159 	Mem::Copy(iPolyPoints+aDrawPolygon->index,aDrawPolygon+1,aDrawPolygon->numPoints*sizeof(TPoint));
       
   160 	}
       
   161 
       
   162 void CPlaybackGc::EndSegmentedPolygon()
       
   163 	{
       
   164 	delete iPolyPoints;
       
   165 	iPolyPoints=NULL;
       
   166 	}
       
   167 
       
   168 void CPlaybackGc::DoDrawPolyLine(const TWsGcCmdDrawPolyLine *aDrawPolyLine, TBool aContinued)
       
   169 	{
       
   170 	TInt numPoints=aDrawPolyLine->numPoints;
       
   171 	CheckPolyData(aDrawPolyLine, sizeof(TWsGcCmdDrawPolyLine), numPoints);
       
   172 	const TPoint *points=(TPoint *)(aDrawPolyLine+1);
       
   173 	if (aContinued)
       
   174 		{
       
   175 		numPoints++;
       
   176 		points=&aDrawPolyLine->last;
       
   177 		}
       
   178 	if (aDrawPolyLine->more)	// more to come so don't draw the end point
       
   179 		iGc->DrawPolyLineNoEndPoint(points,numPoints);
       
   180 	else
       
   181 		iGc->DrawPolyLine(points,numPoints);
       
   182 	}
       
   183 
       
   184 void CPlaybackGc::GcOwnerPanic(TClientPanic aPanic)
       
   185 	{
       
   186 	iGc->SetClippingRegion(NULL);
       
   187 	iCurrentClippingRegion = NULL;
       
   188 	EndSegmentedPolygon();
       
   189 	iWin->WsOwner()->PPanic(aPanic);
       
   190 	}
       
   191 
       
   192 // implementing MWsGc
       
   193 
       
   194 MWsClient& CPlaybackGc::Client()
       
   195 	{
       
   196 	return *(iWin->WsOwner());
       
   197 	}
       
   198 
       
   199 MWsScreen& CPlaybackGc::Screen()
       
   200 	{
       
   201 	return *(iWin->Screen());
       
   202 	}
       
   203 
       
   204 TPoint CPlaybackGc::GcOrigin() const
       
   205 	{
       
   206 	return (iMasterOrigin + iOrigin);
       
   207 	}
       
   208 
       
   209 const TRegion& CPlaybackGc::ClippingRegion()
       
   210 	{
       
   211 	WS_ASSERT_ALWAYS(iCurrentClippingRegion,EWsPanicDrawCommandsInvalidState);
       
   212 	return* iCurrentClippingRegion;
       
   213 	}
       
   214 
       
   215 CFbsBitGc& CPlaybackGc::BitGc()
       
   216 	{
       
   217 	return *iGc;
       
   218 	}
       
   219 	
       
   220 TInt CPlaybackGc::PushBitGcSettings()
       
   221 	{
       
   222 	// the buf format is len+data where data is written by the GC's ExternalizeL()
       
   223 	CBufBase& buf = *iGcBuf;
       
   224 	const TInt start = buf.Size();
       
   225 	RBufWriteStream out(buf,start);
       
   226 	TRAPD(err,out.WriteInt32L(0));
       
   227 	if(!err)
       
   228 		{
       
   229 		TRAP(err,iGc->ExternalizeL(out));
       
   230 		}
       
   231 	if(err) //rollback addition
       
   232 		{
       
   233 		buf.Delete(start,buf.Size()-start);
       
   234 		}
       
   235 	else //fixup len
       
   236 		{
       
   237 		TRAP_IGNORE(out.CommitL();) // can't see this failing
       
   238 		TPckgBuf<TInt32> pckg(buf.Size()-sizeof(TInt32)-start);
       
   239 		buf.Write(start,pckg);
       
   240 		}
       
   241 	return err;
       
   242 	}
       
   243 
       
   244 void CPlaybackGc::PopBitGcSettings()
       
   245 	{
       
   246 	CBufBase& buf = *iGcBuf;
       
   247 	TInt ofs = 0;
       
   248 	FOREVER
       
   249 		{
       
   250 		TInt chunk = 0;
       
   251 		RBufReadStream in(buf,ofs);
       
   252 		TRAPD(err,chunk = in.ReadInt32L());
       
   253 		if(err)
       
   254 			{
       
   255 			WS_ASSERT_DEBUG(err != 0, EWsPanicWsGraphic);
       
   256 			return;
       
   257 			}
       
   258 		if(ofs+sizeof(TInt32)+chunk >= buf.Size()) // the last chunk?
       
   259 			{
       
   260 			TRAP_IGNORE(iGc->InternalizeL(in));
       
   261 			buf.Delete(ofs,buf.Size()-ofs);
       
   262 			return;
       
   263 			}
       
   264 		ofs += chunk + sizeof(TInt32);
       
   265 		}
       
   266 	}
       
   267 
       
   268 const TTime& CPlaybackGc::Now() const
       
   269 	{
       
   270 	return iWin->Screen()->Now();
       
   271 	}
       
   272 	
       
   273 void CPlaybackGc::ScheduleAnimation(const TRect& aRect,const TTimeIntervalMicroSeconds& aFromNow)
       
   274 	{
       
   275 	ScheduleAnimation(aRect,aFromNow,0,0);
       
   276 	}
       
   277 
       
   278 void CPlaybackGc::ScheduleAnimation(const TRect& aRect,const TTimeIntervalMicroSeconds& aFromNow,const TTimeIntervalMicroSeconds& aFreq,const TTimeIntervalMicroSeconds& aStop)
       
   279 	{
       
   280 	// convert window rect to screen rect
       
   281 	TRect rect(aRect);
       
   282 	rect.Move(GcOrigin());
       
   283 	// clip rect to window extent
       
   284 	rect.Intersection(iWin->Abs());
       
   285 	if (!rect.IsEmpty())
       
   286 		{
       
   287 		// and schedule it
       
   288 		iWin->Screen()->ScheduleAnimation(rect,aFromNow,aFreq,aStop);
       
   289 		}
       
   290 	}
       
   291 
       
   292 void CPlaybackGc::SetGcOrigin(const TPoint& aOrigin) 
       
   293 	{ 
       
   294 	iOrigin = aOrigin - iMasterOrigin; 
       
   295 	} 
       
   296 
       
   297 
       
   298 void CPlaybackGc::RemoteReadDataAndDrawL(const CWsGraphicDrawer* aGraphic, CWsClient* aOwner, const TWsGcCmdUnion &aData)
       
   299 	{
       
   300 	TPtrC8 data;
       
   301 	HBufC8* dataBuf = NULL;
       
   302 	const TInt len = aData.WsGraphic->iDataLen;
       
   303 	
       
   304 	if ((len >= KMaxTInt / 4) || (len < 0))
       
   305 		{
       
   306 		aOwner->PPanic(EWservPanicBuffer);	
       
   307 		}	
       
   308 	dataBuf = HBufC8::NewLC(len);
       
   309 	TPtr8 des = dataBuf->Des();
       
   310 	aOwner->RemoteRead(des, 0);
       
   311 
       
   312 	if(des.Size() != len)
       
   313 		{
       
   314 		aOwner->PPanic(EWservPanicBuffer);
       
   315 		}
       
   316 	data.Set(des);																
       
   317 	aGraphic->Draw(*this, aData.WsGraphic->iRect, data);
       
   318 	CleanupStack::PopAndDestroy(dataBuf);		
       
   319 	}
       
   320 
       
   321 TPtrC CPlaybackGc::BufferTPtr(TText* aStart,TInt aLen, const TDesC8& aCmdData)
       
   322 	{
       
   323 	if ((reinterpret_cast<TUint8*>(aStart) < aCmdData.Ptr()
       
   324 									|| reinterpret_cast<TUint8*>(aStart+aLen) > (aCmdData.Ptr() + aCmdData.Size()) ))
       
   325 		{
       
   326 		GcOwnerPanic(EWservPanicBufferPtr);
       
   327 		}
       
   328 	TPtrC gcPtr;
       
   329 	gcPtr.Set(aStart,aLen);
       
   330 	return(gcPtr);
       
   331 	} 
       
   332 
       
   333 void CPlaybackGc::DoDrawCommand(TWsGcOpcodes aOpcode, const TDesC8& aCmdData, const TRegion *aRegion)
       
   334 	{
       
   335 	TWsGcCmdUnion pData;
       
   336 	pData.any=aCmdData.Ptr();
       
   337 	
       
   338 	if (aRegion)
       
   339 		{
       
   340 		WS_ASSERT_DEBUG(iWin,EWsPanicWindowNull);
       
   341 		if (aRegion->Count()==0)
       
   342 			return;
       
   343 		iGc->SetClippingRegion(aRegion);
       
   344 		WS_ASSERT_DEBUG(!iCurrentClippingRegion, EWsPanicDrawCommandsInvalidState);
       
   345 		iCurrentClippingRegion = aRegion;
       
   346 		}
       
   347 	switch(aOpcode)
       
   348 		{
       
   349 		case EWsGcOpDrawWsGraphic:
       
   350 		case EWsGcOpDrawWsGraphicPtr:
       
   351 			{
       
   352 			TRect screenRect(pData.WsGraphic->iRect);
       
   353 			screenRect.Move(GcOrigin());
       
   354 			if(iCurrentClippingRegion->Intersects(screenRect))
       
   355 				{
       
   356 				const TInt dataLen = pData.WsGraphic->iDataLen;
       
   357 				TGraphicDrawerId id;
       
   358 				id.iId = pData.WsGraphic->iId;
       
   359 				id.iIsUid = (pData.WsGraphic->iFlags & EWsGraphicIdUid);
       
   360 				CWsClient* owner = iWin->WsOwner();
       
   361 				const CWsGraphicDrawer* graphic = owner->WindowServer().ResolveGraphic(id);
       
   362 				if(graphic && graphic->IsSharedWith(owner->SecureId()))
       
   363 					{
       
   364 					if(aOpcode == EWsGcOpDrawWsGraphicPtr)
       
   365 						{
       
   366 						TRAPD(err, RemoteReadDataAndDrawL(graphic, owner, pData))
       
   367 						if(err)
       
   368 							WS_PANIC_DEBUG(EWsPanicWsGraphic);
       
   369 						}
       
   370 					else
       
   371 						graphic->Draw(*this,pData.WsGraphic->iRect,CWsClient::BufferTPtr8((TUint8*)(pData.WsGraphic+1),dataLen));
       
   372 	
       
   373 					WS_ASSERT_DEBUG(!iGcBuf->Size(),EWsPanicWsGraphic);
       
   374 					iGcBuf->Reset();
       
   375 					}
       
   376 				}
       
   377 			break;
       
   378 			}
       
   379 		case EWsGcOpMapColorsLocal:
       
   380 			iGc->MapColors(pData.MapColorsLocal->rect, pData.MapColorsLocal->colors,pData.MapColorsLocal->numPairs,pData.MapColorsLocal->mapForwards);
       
   381 			break;
       
   382 		case EWsGcOpDrawPolyLineLocalBufLen:
       
   383 			iGc->DrawPolyLine(pData.DrawPolyLineLocalBufLen->points,pData.DrawPolyLineLocalBufLen->length);
       
   384 			break;
       
   385 		case EWsGcOpDrawPolyLineLocal:
       
   386 			iGc->DrawPolyLine(pData.PointList);
       
   387 			break;
       
   388 		case EWsGcOpDrawPolygonLocalBufLen:
       
   389 			iGc->DrawPolygon(pData.DrawPolygonLocalBufLen->points,pData.DrawPolygonLocalBufLen->length,pData.DrawPolygonLocalBufLen->fillRule);
       
   390 			break;
       
   391 		case EWsGcOpDrawPolygonLocal:
       
   392 			iGc->DrawPolygon(pData.DrawPolygonLocal->pointList,pData.DrawPolygonLocal->fillRule);
       
   393 			break;
       
   394 		case EWsGcOpDrawBitmapLocal:
       
   395 			iGc->DrawBitmap(pData.BitmapLocal->pos, pData.BitmapLocal->bitmap);
       
   396 			break;
       
   397 		case EWsGcOpDrawBitmap2Local:
       
   398 			iGc->DrawBitmap(pData.Bitmap2Local->rect, pData.Bitmap2Local->bitmap);
       
   399 			break;
       
   400 		case EWsGcOpDrawBitmap3Local:
       
   401 			iGc->DrawBitmap(pData.Bitmap3Local->rect, pData.Bitmap3Local->bitmap, pData.Bitmap3Local->srcRect);
       
   402 			break;
       
   403 		case EWsGcOpDrawBitmapMaskedLocal:
       
   404 			iGc->DrawBitmapMasked(pData.iBitmapMaskedLocal->iRect, pData.iBitmapMaskedLocal->iBitmap, pData.iBitmapMaskedLocal->iSrcRect, pData.iBitmapMaskedLocal->iMaskBitmap,pData.iBitmapMaskedLocal->iInvertMask);
       
   405 			break;
       
   406 		case EWsGcOpAlphaBlendBitmapsLocal:
       
   407 			iGc->AlphaBlendBitmaps(pData.AlphaBlendBitmapsLocal->point,pData.AlphaBlendBitmapsLocal->iBitmap,
       
   408 						   			pData.AlphaBlendBitmapsLocal->source, pData.AlphaBlendBitmapsLocal->iAlpha,
       
   409 									pData.AlphaBlendBitmapsLocal->alphaPoint);
       
   410 
       
   411 			break;
       
   412 		case EWsGcOpDrawText:
       
   413 			iGc->DrawText(BufferTPtr((TText *)(pData.DrawText+1),pData.DrawText->length,aCmdData),pData.DrawText->pos);
       
   414 			break;
       
   415 		case EWsGcOpDrawBoxTextOptimised1:
       
   416 			iGc->DrawText(BufferTPtr((TText *)(pData.BoxTextO1+1),pData.BoxTextO1->length,aCmdData),pData.BoxTextO1->box,
       
   417 							pData.BoxTextO1->baselineOffset,CGraphicsContext::ELeft,0);
       
   418 			break;
       
   419 		case EWsGcOpDrawBoxTextOptimised2:
       
   420 			iGc->DrawText(BufferTPtr((TText *)(pData.BoxTextO2+1),pData.BoxTextO2->length,aCmdData),pData.BoxTextO2->box,
       
   421 							pData.BoxTextO2->baselineOffset,pData.BoxTextO2->horiz,pData.BoxTextO2->leftMrg);
       
   422 			break;
       
   423 		case EWsGcOpDrawTextPtr:
       
   424 			iGc->DrawText(*pData.DrawTextPtr->text,pData.DrawTextPtr->pos);
       
   425 			break;
       
   426 		case EWsGcOpDrawTextPtr1:
       
   427 		   	iGc->DrawText(*pData.DrawTextPtr->text);
       
   428 			break;
       
   429 		case EWsGcOpDrawBoxText:
       
   430 			iGc->DrawText(BufferTPtr((TText *)(pData.BoxText+1),pData.BoxText->length,aCmdData),pData.BoxText->box,pData.BoxText->baselineOffset,pData.BoxText->width,pData.BoxText->horiz,pData.BoxText->leftMrg);
       
   431 			break;
       
   432 		case EWsGcOpDrawBoxTextPtr:
       
   433 			iGc->DrawText(*pData.DrawBoxTextPtr->text,pData.DrawBoxTextPtr->box,pData.DrawBoxTextPtr->baselineOffset,pData.DrawBoxTextPtr->width,pData.DrawBoxTextPtr->horiz,pData.DrawBoxTextPtr->leftMrg);
       
   434 			break;
       
   435 		case EWsGcOpDrawBoxTextPtr1:
       
   436 			iGc->DrawText(*pData.DrawBoxTextPtr->text,pData.DrawBoxTextPtr->box);
       
   437 			break;
       
   438 		case EWsGcOpDrawTextVertical:
       
   439 			iGc->DrawTextVertical(BufferTPtr((TText *)(pData.DrawTextVertical+1),pData.DrawTextVertical->length,aCmdData),pData.DrawTextVertical->pos
       
   440 							,pData.DrawTextVertical->up);
       
   441 			break;
       
   442 		case EWsGcOpDrawTextVerticalPtr:
       
   443 			iGc->DrawTextVertical(*pData.DrawTextVerticalPtr->text,pData.DrawTextVerticalPtr->pos,pData.DrawTextVerticalPtr->up);
       
   444 			break;
       
   445 		case EWsGcOpDrawTextVerticalPtr1:
       
   446 			iGc->DrawTextVertical(*pData.DrawTextVerticalPtr->text,pData.DrawTextVerticalPtr->up);
       
   447 			break;
       
   448 		case EWsGcOpDrawBoxTextVertical:
       
   449 			iGc->DrawTextVertical(BufferTPtr((TText *)(pData.DrawBoxTextVertical+1),pData.DrawBoxTextVertical->length,aCmdData),
       
   450 							pData.DrawBoxTextVertical->box,	pData.DrawBoxTextVertical->baselineOffset,
       
   451 							pData.DrawBoxTextVertical->up,(CGraphicsContext::TTextAlign)pData.DrawBoxTextVertical->vert,pData.DrawBoxTextVertical->margin);
       
   452 			break;
       
   453 		case EWsGcOpDrawBoxTextVerticalPtr:
       
   454 			iGc->DrawTextVertical(*pData.DrawBoxTextVerticalPtr->text,pData.DrawBoxTextVerticalPtr->box,pData.DrawBoxTextVerticalPtr->baselineOffset
       
   455 							,pData.DrawBoxTextVerticalPtr->width,pData.DrawBoxTextVerticalPtr->up,pData.DrawBoxTextVerticalPtr->vert,pData.DrawBoxTextVerticalPtr->margin);
       
   456 			break;
       
   457 		case EWsGcOpDrawBoxTextVerticalPtr1:
       
   458 			iGc->DrawTextVertical(*pData.DrawBoxTextVerticalPtr->text,pData.DrawBoxTextVerticalPtr->box,pData.DrawBoxTextVerticalPtr->up);
       
   459 			break;
       
   460 		case EWsGcOpDrawTextLocal:
       
   461 			iGc->DrawText(*pData.DrawTextLocal->desc,pData.DrawTextLocal->pos);
       
   462 			break;
       
   463 		case EWsGcOpDrawBoxTextLocal:
       
   464 			iGc->DrawText(*pData.BoxTextLocal->desc,pData.BoxTextLocal->box,pData.BoxTextLocal->baselineOffset,
       
   465 							pData.BoxTextLocal->horiz,pData.BoxTextLocal->leftMrg);
       
   466 			break;
       
   467 		case EWsGcOpDrawLine:
       
   468 			iGc->DrawLine(pData.DrawLine->pnt1,pData.DrawLine->pnt2);
       
   469 			break;
       
   470 		case EWsGcOpDrawTo:
       
   471 			iGc->DrawLine(iLinePos,*pData.Point);
       
   472 			break;
       
   473 		case EWsGcOpDrawBy:
       
   474 			iGc->DrawLine(iLinePos,iLinePos+(*pData.Point));
       
   475 			break;
       
   476 		case EWsGcOpPlot:
       
   477 			iGc->Plot(*pData.Point);
       
   478 			break;
       
   479 		case EWsGcOpMoveTo:
       
   480 		case EWsGcOpMoveBy:
       
   481 			break;
       
   482 		case EWsGcOpGdiBlt2Local:
       
   483 			iGc->BitBlt(pData.GdiBlt2Local->pos,pData.GdiBlt2Local->bitmap);
       
   484 			break;
       
   485 		case EWsGcOpGdiBlt3Local:
       
   486 			iGc->BitBlt(pData.GdiBlt3Local->pos,pData.GdiBlt3Local->bitmap, pData.GdiBlt3Local->rect);
       
   487 			break;
       
   488 		case EWsGcOpGdiBltMaskedLocal:
       
   489 			iGc->BitBltMasked(pData.GdiBltMaskedLocal->pos,pData.GdiBltMaskedLocal->bitmap,
       
   490 								pData.GdiBltMaskedLocal->rect,pData.GdiBltMaskedLocal->maskBitmap,
       
   491 								pData.GdiBltMaskedLocal->invertMask);
       
   492 			break;
       
   493 		case EWsGcOpGdiWsBlt2:
       
   494 		case EWsGcOpGdiWsBlt3:
       
   495 		case EWsGcOpGdiWsBltMasked:
       
   496 		case EWsGcOpGdiWsAlphaBlendBitmaps:
       
   497 		case EWsGcOpWsDrawBitmapMasked:
       
   498 			{
       
   499 			// Andy - we continually duplicate bitmaps in here, and yet we already have them
       
   500 			// somewhere as pointers so can't we both simplify and optimize this?
       
   501 			CFbsBitmap* scratchBitmap=iScratchBitmap;
       
   502 			CFbsBitmap* scratchMaskBimap=iScratchMaskBitmap;
       
   503 			TInt maskHandle=0;
       
   504 			TInt handle=WsBitmapHandle(aOpcode,pData, maskHandle);
       
   505 			CWsClient* owner=iWin->WsOwner();
       
   506 			if (owner!=NULL)
       
   507 				{
       
   508 				TInt wsBmpErr = KErrNone;
       
   509 				DWsBitmap *bitmap=(DWsBitmap *)owner->HandleToObj(handle, WS_HANDLE_BITMAP);
       
   510 				if (!bitmap)
       
   511 					wsBmpErr = KErrNotFound;
       
   512 				else
       
   513 					scratchBitmap=bitmap->FbsBitmap();
       
   514 				if (wsBmpErr == KErrNone)
       
   515 					if (aOpcode==EWsGcOpGdiWsBltMasked || aOpcode==EWsGcOpGdiWsAlphaBlendBitmaps || aOpcode==EWsGcOpWsDrawBitmapMasked)
       
   516 						{
       
   517 						DWsBitmap *bitmap2=(DWsBitmap *)owner->HandleToObj(maskHandle, WS_HANDLE_BITMAP);
       
   518 						if (!bitmap2)
       
   519 							wsBmpErr = KErrNotFound;
       
   520 						else
       
   521 							scratchMaskBimap=bitmap2->FbsBitmap();
       
   522 						}
       
   523 				if (wsBmpErr == KErrNone)
       
   524 					{
       
   525 					switch(aOpcode)
       
   526 						{
       
   527 						case EWsGcOpGdiWsBlt2:
       
   528 							iGc->BitBlt(pData.GdiBlt2->pos,scratchBitmap);
       
   529 							break;
       
   530 						case EWsGcOpGdiWsBlt3:
       
   531 							iGc->BitBlt(pData.GdiBlt3->pos,scratchBitmap, pData.GdiBlt3->rect);
       
   532 							break;
       
   533 						case EWsGcOpGdiWsBltMasked:
       
   534 							{
       
   535 							iGc->BitBltMasked(pData.GdiBltMasked->destination,scratchBitmap,
       
   536 											pData.GdiBltMasked->source, scratchMaskBimap,
       
   537 											pData.GdiBltMasked->invertMask);
       
   538 							}
       
   539 							break;
       
   540 						case EWsGcOpGdiWsAlphaBlendBitmaps:
       
   541 							{
       
   542 							iGc->AlphaBlendBitmaps(pData.AlphaBlendBitmaps->point,scratchBitmap,
       
   543 											   pData.AlphaBlendBitmaps->source, scratchMaskBimap,
       
   544 											   pData.AlphaBlendBitmaps->alphaPoint);
       
   545 							}
       
   546 							break;
       
   547 						case EWsGcOpWsDrawBitmapMasked:
       
   548 							{
       
   549 							iGc->DrawBitmapMasked(pData.iBitmapMasked->iRect,scratchBitmap, 
       
   550 												pData.iBitmapMasked->iSrcRect,scratchMaskBimap,
       
   551 												pData.iBitmapMasked->iInvertMask);
       
   552 							}
       
   553 							break;
       
   554 						}
       
   555 					}
       
   556 				}
       
   557 			break;
       
   558 			}
       
   559 		case EWsGcOpGdiBlt2:
       
   560 		case EWsGcOpGdiBlt3:
       
   561 		case EWsGcOpGdiBltMasked:
       
   562 		case EWsGcOpGdiAlphaBlendBitmaps:
       
   563 		case EWsGcOpDrawBitmap:
       
   564 		case EWsGcOpDrawBitmap2:
       
   565 		case EWsGcOpDrawBitmap3:
       
   566 		case EWsGcOpDrawBitmapMasked:
       
   567 			{
       
   568 			TInt maskHandle=0;
       
   569 			TInt ret = iScratchBitmap->Duplicate(FbsBitmapHandle(aOpcode, pData,maskHandle));
       
   570 			if (ret == KErrNone)
       
   571 				{
       
   572 				switch(aOpcode)
       
   573 					{
       
   574 					case EWsGcOpGdiBlt2:
       
   575 						iGc->BitBlt(pData.GdiBlt2->pos,iScratchBitmap);
       
   576 						break;
       
   577 					case EWsGcOpGdiBlt3:
       
   578 						iGc->BitBlt(pData.GdiBlt3->pos,iScratchBitmap, pData.GdiBlt3->rect);
       
   579 						break;
       
   580 					case EWsGcOpGdiBltMasked:
       
   581 						{
       
   582 						ret = iScratchMaskBitmap->Duplicate(pData.GdiBltMasked->maskHandle);
       
   583 						if (ret == KErrNone)
       
   584 							{
       
   585 							iGc->BitBltMasked(pData.GdiBltMasked->destination,iScratchBitmap,
       
   586 												pData.GdiBltMasked->source, iScratchMaskBitmap,
       
   587 												pData.GdiBltMasked->invertMask);
       
   588 							iScratchMaskBitmap->Reset();
       
   589 							}
       
   590 						}
       
   591 						break;
       
   592 					case EWsGcOpGdiAlphaBlendBitmaps:
       
   593 						{
       
   594 						ret = iScratchMaskBitmap->Duplicate(pData.AlphaBlendBitmaps->alphaHandle);
       
   595 						if (ret == KErrNone)
       
   596 							{
       
   597 							iGc->AlphaBlendBitmaps(pData.AlphaBlendBitmaps->point, iScratchBitmap,
       
   598 												pData.AlphaBlendBitmaps->source, iScratchMaskBitmap,
       
   599 												pData.AlphaBlendBitmaps->alphaPoint);
       
   600 							iScratchMaskBitmap->Reset();
       
   601 							}
       
   602 						break;
       
   603 						}
       
   604 					case EWsGcOpDrawBitmap:
       
   605 						iGc->DrawBitmap(pData.Bitmap->pos, iScratchBitmap);
       
   606 						break;
       
   607 					case EWsGcOpDrawBitmap2:
       
   608 						iGc->DrawBitmap(pData.Bitmap2->rect, iScratchBitmap);
       
   609 						break;
       
   610 					case EWsGcOpDrawBitmap3:
       
   611 						iGc->DrawBitmap(pData.Bitmap3->rect, iScratchBitmap, pData.Bitmap3->srcRect);
       
   612 						break;
       
   613 					case EWsGcOpDrawBitmapMasked:
       
   614 						{
       
   615 						ret = iScratchMaskBitmap->Duplicate(pData.iBitmapMasked->iMaskHandle);
       
   616 						if (ret == KErrNone)
       
   617 							{
       
   618 							iGc->DrawBitmapMasked(pData.iBitmapMasked->iRect, iScratchBitmap, 
       
   619 												pData.iBitmapMasked->iSrcRect, iScratchMaskBitmap,
       
   620 												pData.iBitmapMasked->iInvertMask);
       
   621 							iScratchMaskBitmap->Reset();
       
   622 							}
       
   623 						}
       
   624 						break;
       
   625 					}
       
   626 				iScratchBitmap->Reset();
       
   627 				}
       
   628 			break;
       
   629 			}
       
   630 		case EWsGcOpDrawSegmentedPolygon:
       
   631 			iGc->DrawPolygon(iPolyPoints,iPolyPointListSize,pData.DrawSegmentedPolygon->fillRule);
       
   632 			break;
       
   633 		case EWsGcOpDrawPolygon:
       
   634 			DoDrawPolygon(pData.Polygon);
       
   635 			break;
       
   636 		case EWsGcOpDrawPolyLine:
       
   637 			DoDrawPolyLine(pData.PolyLine, EFalse);
       
   638 			break;
       
   639 		case EWsGcOpDrawPolyLineContinued:
       
   640 			DoDrawPolyLine(pData.PolyLine, ETrue);
       
   641 			break;
       
   642 		case EWsGcOpClear:
       
   643 			iGc->Clear(TRect(iWin->Size()));
       
   644 			break;
       
   645 		case EWsGcOpClearRect:
       
   646 			iGc->Clear(*pData.Rect);
       
   647 			break;
       
   648 		case EWsGcOpDrawRect:
       
   649 			iGc->DrawRect(*pData.Rect);
       
   650 			break;
       
   651 		case EWsGcOpDrawEllipse:
       
   652 			iGc->DrawEllipse(*pData.Rect);
       
   653 			break;
       
   654 		case EWsGcOpDrawRoundRect:
       
   655 			iGc->DrawRoundRect(*pData.Rect,pData.RoundRect->ellipse);
       
   656 			break;
       
   657 		case EWsGcOpDrawArc:
       
   658 			iGc->DrawArc(*pData.Rect,pData.ArcOrPie->start,pData.ArcOrPie->end);
       
   659 			break;
       
   660 		case EWsGcOpDrawPie:
       
   661 			iGc->DrawPie(*pData.Rect,pData.ArcOrPie->start,pData.ArcOrPie->end);
       
   662 			break;
       
   663 		case EWsGcOpCopyRect:
       
   664 			iGc->CopyRect(pData.CopyRect->pos,*pData.Rect);
       
   665 			break;
       
   666 		case EWsGcOpMapColors:
       
   667 			iGc->MapColors(pData.MapColors->rect,(TRgb *)(pData.MapColors+1),pData.MapColors->numPairs,pData.MapColors->mapForwards);
       
   668 			break;
       
   669 		default:
       
   670 			TRAP_IGNORE(iWin->OwnerPanic(EWservPanicOpcode));
       
   671 			break;
       
   672 		}
       
   673 	// DEBUGOSB // comment in for per-draw-command debug osb updates
       
   674 	iGc->SetClippingRegion(NULL);
       
   675 	iCurrentClippingRegion = NULL;
       
   676 	}
       
   677 
       
   678 TInt CPlaybackGc::WsBitmapHandle(TInt aOpcode, const TWsGcCmdUnion &pData, TInt& aMaskHandle) 
       
   679 	{
       
   680 	TInt handle=0;
       
   681 	switch(aOpcode)
       
   682 		{
       
   683 		case EWsGcOpGdiWsBlt2:
       
   684 			handle=pData.GdiBlt2->handle;
       
   685 			break;
       
   686 		case EWsGcOpGdiWsBlt3:
       
   687 			handle=pData.GdiBlt3->handle;
       
   688 			break;
       
   689 		case EWsGcOpGdiWsBltMasked:
       
   690 			handle=pData.GdiBltMasked->handle;
       
   691 			aMaskHandle = pData.GdiBltMasked->maskHandle;
       
   692 			break;
       
   693 		case EWsGcOpGdiWsAlphaBlendBitmaps:
       
   694 			handle=pData.AlphaBlendBitmaps->bitmapHandle;
       
   695 			aMaskHandle = pData.AlphaBlendBitmaps->alphaHandle;
       
   696 			break;
       
   697 		case EWsGcOpWsDrawBitmapMasked:
       
   698 			handle=pData.iBitmapMasked->iHandle;
       
   699 			aMaskHandle=pData.iBitmapMasked->iMaskHandle;
       
   700 			break;
       
   701 		}
       
   702 	return handle;
       
   703 	}		
       
   704 
       
   705 TInt CPlaybackGc::FbsBitmapHandle(TInt aOpcode, const TWsGcCmdUnion &pData, TInt& aMaskHandle)
       
   706 	{
       
   707 	TInt handle=0;
       
   708 	aMaskHandle=0;
       
   709 	switch(aOpcode)
       
   710 		{
       
   711 		case EWsGcOpGdiWsBlt2:
       
   712 		case EWsGcOpGdiWsBlt3:
       
   713 		case EWsGcOpGdiWsBltMasked:
       
   714 		case EWsGcOpGdiWsAlphaBlendBitmaps:
       
   715 			{
       
   716 			TInt maskHandle = 0;
       
   717 			DWsBitmap *bitmap=(DWsBitmap *)iWin->WsOwner()->HandleToObj(WsBitmapHandle(aOpcode,pData, maskHandle), WS_HANDLE_BITMAP);
       
   718 			WS_ASSERT_DEBUG(bitmap, EWsPanicDrawCommandsInvalidState);
       
   719 			if (bitmap)
       
   720 				handle=bitmap->FbsBitmap()->Handle();
       
   721 			if (aOpcode==EWsGcOpGdiWsBltMasked || aOpcode==EWsGcOpGdiWsAlphaBlendBitmaps)
       
   722 				{
       
   723 				DWsBitmap *bitmap2=(DWsBitmap *)iWin->WsOwner()->HandleToObj(maskHandle, WS_HANDLE_BITMAP);
       
   724 				WS_ASSERT_DEBUG(bitmap2, EWsPanicDrawCommandsInvalidState);
       
   725 				if (bitmap2)
       
   726 					aMaskHandle=bitmap2->FbsBitmap()->Handle();
       
   727 				}
       
   728 			break;
       
   729 			}
       
   730 		case EWsGcOpGdiBlt2:
       
   731 			handle=pData.GdiBlt2->handle;
       
   732 			break;
       
   733 		case EWsGcOpGdiBlt3:
       
   734 			handle=pData.GdiBlt3->handle;
       
   735 			break;
       
   736 		case EWsGcOpGdiBltMasked:
       
   737 			handle=pData.GdiBltMasked->handle;
       
   738 			aMaskHandle=pData.GdiBltMasked->maskHandle;
       
   739 			break;
       
   740 		case EWsGcOpGdiAlphaBlendBitmaps:
       
   741 			handle=pData.AlphaBlendBitmaps->bitmapHandle;
       
   742 			aMaskHandle=pData.AlphaBlendBitmaps->alphaHandle;
       
   743 			break;
       
   744 		case EWsGcOpDrawBitmap:
       
   745 			handle=pData.Bitmap->handle;
       
   746 			break;
       
   747 		case EWsGcOpDrawBitmap2:
       
   748 			handle=pData.Bitmap2->handle;
       
   749 			break;
       
   750 		case EWsGcOpDrawBitmap3:
       
   751 			handle=pData.Bitmap3->handle;
       
   752 			break;
       
   753 		case EWsGcOpDrawBitmapMasked:
       
   754 			handle=pData.iBitmapMasked->iHandle;
       
   755 			aMaskHandle=pData.iBitmapMasked->iMaskHandle;
       
   756 			break;
       
   757 		}
       
   758 	return handle;
       
   759 	}
       
   760 
       
   761 
       
   762 void CPlaybackGc::UpdateJustification(TText* aText,TInt aLen, const TDesC8& aCmdData)
       
   763 	{
       
   764 	iGc->UpdateJustification(BufferTPtr(aText,aLen,aCmdData));
       
   765 	}
       
   766 
       
   767 void CPlaybackGc::DoDrawing(TWsGcOpcodes aOpcode, const TDesC8& aCmdData)
       
   768 	{
       
   769 	TWsGcCmdUnion pData;
       
   770 	pData.any=aCmdData.Ptr();
       
   771 	
       
   772 	// Andy. We do this every time?  Shouldn't this be set up for us already by the render stage?
       
   773 	// infact, aren't we breaking the render stage by doing it here?
       
   774 	iGc->SetUserDisplayMode(iWin->DisplayMode());
       
   775 	if (iClippingRectSet)
       
   776 		{
       
   777 		iGc->SetOrigin(iMasterOrigin);
       
   778 		iGc->SetClippingRect(iClippingRect);
       
   779 		}
       
   780 	iGc->SetOrigin(iMasterOrigin + iOrigin);
       
   781 	
       
   782 	DoDrawCommand(aOpcode,aCmdData,iDrawRegion);
       
   783 
       
   784 	iGc->CancelClippingRect();
       
   785 	iGc->SetUserDisplayMode(ENone);
       
   786 	switch(aOpcode)
       
   787 		{
       
   788 		case EWsGcOpDrawLine:
       
   789 			iLinePos=pData.DrawLine->pnt2;
       
   790 			break;
       
   791 		case EWsGcOpDrawTo:
       
   792 		case EWsGcOpMoveTo:
       
   793 		case EWsGcOpPlot:
       
   794 			iLinePos=(*pData.Point);
       
   795 			break;
       
   796 		case EWsGcOpDrawBy:
       
   797 		case EWsGcOpMoveBy:
       
   798 			iLinePos+=(*pData.Point);
       
   799 			break;
       
   800 		case EWsGcOpDrawSegmentedPolygon:
       
   801 			EndSegmentedPolygon();
       
   802 			break;
       
   803 		case EWsGcOpDrawText:
       
   804 			UpdateJustification((TText *)(pData.DrawText+1),pData.DrawText->length,aCmdData);
       
   805 			break;
       
   806 		case EWsGcOpDrawTextVertical:
       
   807 			UpdateJustification((TText *)(pData.DrawTextVertical+1),pData.DrawTextVertical->length,aCmdData);
       
   808 			break;
       
   809 		case EWsGcOpDrawBoxText:
       
   810 			UpdateJustification((TText *)(pData.BoxText+1),pData.BoxText->length,aCmdData);
       
   811 			break;
       
   812 		case EWsGcOpDrawBoxTextOptimised1:
       
   813 			UpdateJustification((TText *)(pData.BoxTextO1+1),pData.BoxTextO1->length,aCmdData);
       
   814 			break;
       
   815 		case EWsGcOpDrawBoxTextOptimised2:
       
   816 			UpdateJustification((TText *)(pData.BoxTextO2+1),pData.BoxTextO2->length,aCmdData);
       
   817 			break;
       
   818 		case EWsGcOpDrawBoxTextVertical:
       
   819 			UpdateJustification((TText *)(pData.DrawBoxTextVertical+1),pData.DrawBoxTextVertical->length,aCmdData);
       
   820 			break;
       
   821 		case EWsGcOpDrawTextLocal:
       
   822 			iGc->UpdateJustification(*pData.DrawTextLocal->desc);
       
   823 			break;
       
   824 		case EWsGcOpDrawBoxTextLocal:
       
   825 			iGc->UpdateJustification(*pData.BoxTextLocal->desc);
       
   826 			break;
       
   827 		case EWsGcOpDrawTextPtr:
       
   828 			iGc->UpdateJustification(*pData.DrawTextPtr->text);
       
   829 			break;
       
   830 		case EWsGcOpDrawTextVerticalPtr:
       
   831 			iGc->UpdateJustification(*pData.DrawTextVerticalPtr->text);
       
   832 			break;
       
   833 		case EWsGcOpDrawBoxTextPtr:
       
   834 			iGc->UpdateJustification(*pData.DrawBoxTextPtr->text);
       
   835 			break;
       
   836 		case EWsGcOpDrawBoxTextVerticalPtr:
       
   837 			iGc->UpdateJustification(*pData.DrawBoxTextVerticalPtr->text);
       
   838 			break;
       
   839 		}
       
   840 	}
       
   841 
       
   842 void CPlaybackGc::CommandL(TWsGcOpcodes aOpcode, const TDesC8& aCmdData)
       
   843 	{
       
   844 	TWsGcCmdUnion pData;
       
   845 	pData.any=aCmdData.Ptr();
       
   846 	
       
   847 	switch(aOpcode)
       
   848 		{
       
   849 	case EWsGcOpStartSegmentedDrawPolygon:
       
   850 		StartSegmentedDrawPolygonL(pData.StartSegmentedDrawPolygon);
       
   851 		break;
       
   852 	case EWsGcOpSegmentedDrawPolygonData:
       
   853 		SegmentedDrawPolygonData(pData.SegmentedDrawPolygonData);
       
   854 		break;
       
   855 	case EWsGcOpSetClippingRegion:
       
   856 		WS_ASSERT_DEBUG(aOpcode != EWsGcOpSetClippingRegion, EWsPanicDrawCommandsInvalidState);
       
   857 		break;
       
   858 	case EWsGcOpSetClippingRect:
       
   859 		SetClippingRect(*pData.Rect);
       
   860 		break;
       
   861 	case EWsGcOpCancelClippingRect:
       
   862 		ResetClippingRect();
       
   863 		break;
       
   864 	case EWsGcOpCancelClippingRegion:
       
   865 		CancelUserClippingRegion();
       
   866 		break;
       
   867 	case EWsGcOpSetFaded:
       
   868 		iGc->SetFaded(*pData.Bool);
       
   869 		break;
       
   870 	case EWsGcOpSetFadeParams:
       
   871 		iGc->SetFadingParameters(WservEncoding::ExtractFirst8BitValue(*pData.UInt),WservEncoding::ExtractSecond8BitValue(*pData.UInt));
       
   872 		break;
       
   873 	case EWsGcOpSetDrawMode:
       
   874 		iGc->SetDrawMode((CGraphicsContext::TDrawMode)*pData.UInt);
       
   875 		break;
       
   876 	case EWsGcOpUseFont:
       
   877 		if (CWsFontCache::Instance()->UseFont(iFont, *pData.UInt))
       
   878 			iGc->UseFont(*pData.UInt);
       
   879 		else
       
   880 			iGc->UseFontNoDuplicate(iFont);
       
   881 		break;
       
   882 	case EWsGcOpDiscardFont:
       
   883 		CWsFontCache::Instance()->ReleaseFont(iFont);
       
   884 		iGc->DiscardFont();
       
   885 		break;
       
   886 	case EWsGcOpSetUnderlineStyle:
       
   887 		iGc->SetUnderlineStyle(*pData.SetUnderlineStyle);
       
   888 		break;
       
   889 	case EWsGcOpSetStrikethroughStyle:
       
   890 		iGc->SetStrikethroughStyle(*pData.SetStrikethroughStyle);
       
   891 		break;
       
   892 	case EWsGcOpUseBrushPattern:
       
   893 		iGc->UseBrushPattern(*pData.handle);
       
   894 		break;
       
   895 	case EWsGcOpDiscardBrushPattern:
       
   896 		iGc->DiscardBrushPattern();
       
   897 		break;
       
   898 	case EWsGcOpSetBrushColor:
       
   899 		iGc->SetBrushColor(*pData.rgb);
       
   900 		break;
       
   901 	case EWsGcOpSetPenColor:
       
   902 		iGc->SetPenColor(*pData.rgb);
       
   903 		break;
       
   904 	case EWsGcOpSetPenStyle:
       
   905 		iGc->SetPenStyle((CGraphicsContext::TPenStyle)*pData.UInt);
       
   906 		break;
       
   907 	case EWsGcOpSetPenSize:
       
   908 		iGc->SetPenSize(*pData.Size);
       
   909 		break;
       
   910 	case EWsGcOpSetBrushStyle:
       
   911 		iGc->SetBrushStyle((CGraphicsContext::TBrushStyle)*pData.UInt);
       
   912 		break;
       
   913 	case EWsGcOpReset:
       
   914 		CWsFontCache::Instance()->ReleaseFont(iFont);
       
   915 		iGc->Reset();
       
   916 		iOrigin.SetXY(0,0);
       
   917 		ResetClippingRect();
       
   918 		iGc->SetBrushColor(iWin->BackColor());
       
   919 		break;
       
   920 	case EWsGcOpSetBrushOrigin:
       
   921 		iGc->SetBrushOrigin(*pData.Point);
       
   922 		break;
       
   923 	case EWsGcOpSetDitherOrigin:
       
   924 		iGc->SetDitherOrigin(*pData.Point);
       
   925 		break;
       
   926 	case EWsGcOpSetWordJustification:
       
   927 		iGc->SetWordJustification(pData.SetJustification->excessWidth, pData.SetJustification->numGaps);
       
   928 		break;
       
   929 	case EWsGcOpSetCharJustification:
       
   930 		iGc->SetCharJustification(pData.SetJustification->excessWidth, pData.SetJustification->numGaps);
       
   931 		break;
       
   932 	case EWsGcOpSetOrigin:
       
   933 		SetOrigin(*pData.Point);
       
   934 		break;
       
   935 	case EWsGcOpSetOpaque:
       
   936 		// Andy - opaque drawing has not been implemented yet.
       
   937 		//SetOpaque(*pData.Bool);
       
   938 		break;
       
   939 	case EWsGcOpSetShadowColor:
       
   940 		iGc->SetShadowColor(*pData.rgb);
       
   941 		break;
       
   942 	default:	// Assume remaining functions will draw
       
   943 		{
       
   944 		DoDrawing(aOpcode,aCmdData);
       
   945 		return;
       
   946 		}
       
   947 		}
       
   948 	}
       
   949 
       
   950 void CPlaybackGc::SetOrigin(const TPoint &aOrigin)
       
   951 	{
       
   952 	iOrigin=aOrigin;
       
   953 	}
       
   954 	
       
   955 /*------------------------------------------------------------------------------
       
   956   Description: Retrieves graphics context information back from a given buffer
       
   957                from a given start position.
       
   958  -----------------------------------------------------------------------------*/
       
   959 void CPlaybackGc::InternalizeL(const CBufBase& aBuffer,TInt& aStartPos)
       
   960 	{
       
   961 	// Open the stream used for the input from the given start position
       
   962 	// in the buffer.
       
   963 	RBufReadStream bufReadStream;
       
   964 	bufReadStream.Open(aBuffer,aStartPos);
       
   965 	CleanupClosePushL(bufReadStream);
       
   966 
       
   967 	// Read the font/bitmap server data
       
   968 	iGc->InternalizeL(bufReadStream);
       
   969 
       
   970 	iOrigin.iX = bufReadStream.ReadInt32L();
       
   971 	iOrigin.iY = bufReadStream.ReadInt32L();
       
   972 
       
   973 	iClippingRectSet=bufReadStream.ReadInt8L();
       
   974 	
       
   975 	// If there is a clipping rectangle data read it.
       
   976 	if (iClippingRectSet)
       
   977 		bufReadStream>>iClippingRect;
       
   978 	
       
   979 	// Force FbsBitGc to reset its user clipping rect in case orientation has changed.
       
   980 	// The user clipping rect of FbsBitGc will be set to iClippingRect later before
       
   981 	// drawing the command.
       
   982 	iGc->CancelClippingRect();
       
   983 	
       
   984 	// Read the clipping region data
       
   985 	InternalizeClippingRegionL(bufReadStream);
       
   986 
       
   987 	// Read the Alpha values for Brush and Pen colors.
       
   988 	InternalizeAlphaValueL(bufReadStream);
       
   989 	
       
   990 	CleanupStack::PopAndDestroy(&bufReadStream);
       
   991 	}
       
   992 
       
   993 /*------------------------------------------------------------------------------
       
   994   Description: Retrieves TRgb::alpha value information back from a given buffer
       
   995                and updates the Brushcolor with the same.
       
   996  -----------------------------------------------------------------------------*/
       
   997 void CPlaybackGc::InternalizeAlphaValueL(RReadStream& aReadStream)
       
   998 	{
       
   999 	TRgb brushColor(iGc->BrushColor());
       
  1000 	brushColor.SetAlpha(aReadStream.ReadUint8L());
       
  1001 	iGc->SetBrushColor(brushColor);
       
  1002 	TRgb penColor(iGc->PenColor());
       
  1003 	penColor.SetAlpha(aReadStream.ReadUint8L());
       
  1004 	iGc->SetPenColor(penColor);
       
  1005 	}
       
  1006 
       
  1007 /*------------------------------------------------------------------------------
       
  1008   Description: Helper method to retrieve clipping region data from a given
       
  1009                read stream.
       
  1010  -----------------------------------------------------------------------------*/
       
  1011 void CPlaybackGc::InternalizeClippingRegionL(RReadStream& aReadStream)
       
  1012 	{
       
  1013 	WS_ASSERT_DEBUG(iTargetRegion, EWsPanicDrawCommandsInvalidState);
       
  1014 	// Read flag to indicate if client had defined a clipping region
       
  1015 	TBool clipRegion = aReadStream.ReadInt8L();
       
  1016 	CancelUserClippingRegion();
       
  1017 	if (clipRegion)
       
  1018 		{
       
  1019 		// Note that this clipping region is in window relative coordinates when
       
  1020 		// received from the client (and being stored) but is in screen relative
       
  1021 		// coordinates after being retrieved from the redraw store.
       
  1022 		iUserDefinedClippingRegion = InternalizeRegionL(aReadStream);
       
  1023 		iUserDefinedClippingRegion->Offset(iWin->Origin());
       
  1024 		iUserDefinedClippingRegion->Intersect(*iTargetRegion);
       
  1025 		if (iUserDefinedClippingRegion->CheckError()) // fallback to no user clipping region
       
  1026 			{
       
  1027 			CancelUserClippingRegion();
       
  1028 			}
       
  1029 		else
       
  1030 			{
       
  1031 			iDrawRegion = iUserDefinedClippingRegion;
       
  1032 			}
       
  1033 		}
       
  1034 	}
       
  1035 
       
  1036 /**
       
  1037 This pretty much replaces the whole of what was TDrawDestination
       
  1038 This can only be sensibly called from outside a sequence of drawing commands,
       
  1039 since it negates any user defined clipping regions.
       
  1040 */
       
  1041 void CPlaybackGc::SetTargetRegion(const TRegion* aRegion)
       
  1042 	{
       
  1043 	iTargetRegion = aRegion;
       
  1044 	iDrawRegion = iTargetRegion;
       
  1045 	CancelUserClippingRegion();
       
  1046 	}
       
  1047 	
       
  1048 void CPlaybackGc::Reset()
       
  1049 	{
       
  1050 	iGc->Reset();
       
  1051 	}
       
  1052 
       
  1053 TAny * CPlaybackGc::ResolveObjectInterface(TUint aId)
       
  1054 	{
       
  1055 	switch (aId)
       
  1056 		{
       
  1057 		case MWsWindow::EWsObjectInterfaceId:
       
  1058 			return dynamic_cast<MWsWindow *>(iWin);
       
  1059 		case MWsFader::EWsObjectInterfaceId:
       
  1060 		  	return iWin->Screen()->Fader();
       
  1061 		}
       
  1062 	return NULL;
       
  1063 	}