windowing/windowserver/nga/SERVER/openwfc/gc.cpp
author William Roberts <williamr@symbian.org>
Thu, 03 Jun 2010 17:39:46 +0100
branchNewGraphicsArchitecture
changeset 87 0709f76d91e5
parent 0 5d03bc08d59c
child 121 d72fc2aace31
permissions -rw-r--r--
Add MMP files to build libOpenVG_sw.lib which uses LINKAS to redirect to libOpenVG.dll (and the same for libEGL_sw.lib and libOpenVGU_sw.lib). Only the libEGL_sw.lib redirection isn't activated - this can't happen until there is a merged libEGL.dll which supports the OpenWF synchronisation and also implements the graphical support functions. The overall aim is to eliminate the *_sw.dll implementations, at least as a compile-time way of choosing a software-only implementation.The correct way to choose is to put the right set of libraries into a ROM with suitable renaming, and in the emulator to use the "switching DLL" technique to pick the right set. As the Symbian Foundation doesn't have any alternative implementations, we don't need the switching DLLs and we can build directly to the correct name.

// 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 <e32std.h>
#include <s32mem.h> 
#include "gc.h"
#include "backedupwindow.h"
#include "windowgroup.h"
#include "ScrDev.H"
#include "wstop.h"
#include "panics.h"
#include "Graphics/WSGRAPHICDRAWER.H"
#include "wsfont.h"

class TPlacedAttributes;

CFbsBitmap *CWsGc::iScratchBitmap=NULL;
CFbsBitmap *CWsGc::iScratchMaskBitmap=NULL;

GLREF_C TInt ExternalizeRegionL(RWriteStream& aWriteStream, const RWsRegion& aRegion);

/*CWsGc*/

CWsGc* CWsGc::NewL(CWsClient *aOwner)	
	{
	CWsGc* self = new(ELeave) CWsGc(aOwner);
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	return self;
	}

void CWsGc::InitStaticsL()
	{
	iScratchBitmap=new(ELeave) CFbsBitmap();
	iScratchMaskBitmap=new(ELeave) CFbsBitmap();
	}

void CWsGc::DeleteStatics()
	{
	delete iScratchBitmap;
	delete iScratchMaskBitmap;
	}

CWsGc::CWsGc(CWsClient *owner) : CWsObject(owner,WS_HANDLE_GC)
	{
	__DECLARE_NAME(_S("CWsGc"));
	}

void CWsGc::ConstructL()
	{
	NewObjL();
	iBackedUpWinGc=CFbsBitGc::NewL();
	iInternalStatus.ResetInternalStatus(iWin);
	}

void CWsGc::Activate(CWsClientWindow *win)
	{
	if (iWin!=NULL)
		{
		if (CWsClient::iCurrentCommand.iOpcode==0)
			{
			WS_PANIC_ALWAYS(EWsPanicDrawCommandsInvalidState);
			}
		else
			{
			OwnerPanic(EWservPanicGcActive);
			}
		}

	iWin = win;
	if (iWin->Redraw()->OutputDevice()) // Activated on a backed up window
		iBackedUpWinGc->ActivateNoJustAutoUpdate(iWin->Redraw()->OutputDevice());
	iWin->GcActivated(this);
	iInternalStatus.iBrushColor = iWin->BackColor();
	if (iWin->Redraw()->OutputDevice())
		iBackedUpWinGc->SetBrushColor(iInternalStatus.iBrushColor);
	iOrigin.SetXY(0,0);
	ResetClippingRect();
	if(iWsOwner)
		{
		CWsWindowGroup *winGp = iWin->WinGroup();
		if(!winGp->Device())
			OwnerPanic(EWservPanicGroupWinScreenDeviceDeleted);		
		SetReply(winGp->Device()->ClientDevicePointer());			
		}	
	}

void CWsGc::Activate(const TInt &aHandle)
	{
	CWsClientWindow *win;
	iWsOwner->HandleToClientWindow(aHandle,&win);
	if (!win->BaseParent())
		OwnerPanic(EWservPanicParentDeleted);
	Activate(win);
	}

void CWsGc::Reactivate()
	{
	WS_ASSERT_DEBUG(iWin != NULL, EWsPanicDrawCommandsInvalidState);
	if (iWin->Redraw()->OutputDevice()) // Activated on a backed up window
		iBackedUpWinGc->ActivateNoJustAutoUpdate(iWin->Redraw()->OutputDevice());
	}

CWsGc::~CWsGc()
	{
	if (iWin!=NULL)
		Deactivate();
	delete iBackedUpWinGc;
	delete iPolyPoints;
	}

void CWsGc::Deactivate()
	{
	if (iWin)	// Protect against deactivating an already deactivated GC, this is allowed to aid clean up code.
		{
		CWsFontCache::Instance()->ReleaseFont(iFont);
		iBackedUpWinGc->Reset();
		iInternalStatus.ResetInternalStatus(iWin);
		iWin->GcDeactivated(this);
		CancelClippingRegion();
		iWin->Redraw()->GcDeactivate(this);
		iWin=NULL;
		}
	}

void CWsGc::SetClippingRect(const TRect &aRect)
	{
	iClippingRect=aRect;
	iClippingRect.Move(iOrigin);
	iClippingRectSet=ETrue;
	}

void CWsGc::ResetClippingRect()
	{
	iClippingRectSet=EFalse;
	}

void CWsGc::SetClippingRegionL(TInt aRegionCount)
	{
	RWsRegion *newRegion=GetRegionFromClientL(iWsOwner, aRegionCount);
	CancelClippingRegion();
	iUserDefinedClippingRegion=newRegion;

	if (iUserDefinedClippingRegion)
		{
		iUserDefinedClippingRegion->Offset(iOrigin);
		}
	}

void CWsGc::CancelClippingRegion()
	{
	if (iUserDefinedClippingRegion)
		{
		iUserDefinedClippingRegion->Destroy();
		iUserDefinedClippingRegion=NULL;
		}
	}

void CWsGc::CheckPolyData(const TAny* aDataPtr, TInt aHeaderSize, TInt aNumPoints)
	{
	TInt maxDataLen;
	if (CWsClient::iCurrentCommand.iOpcode>0)
		{
		maxDataLen=CWsClient::EndOfCommandBuffer()-static_cast<const TUint8*>(aDataPtr);
		}
	else	// Playing back from redraw store??
		{
		maxDataLen=CWsClient::iCurrentCommand.iCmdLength;
		}
	const TInt dataSize=aHeaderSize+aNumPoints*sizeof(TPoint);
	if (dataSize>maxDataLen)
		GcOwnerPanic(EWservPanicBadPolyData);
	}

void CWsGc::DoDrawPolygon(const TWsGcCmdDrawPolygon *aDrawPolygon)
	{
	CheckPolyData(aDrawPolygon,sizeof(TWsGcCmdDrawPolygon),aDrawPolygon->numPoints);
	iBackedUpWinGc->DrawPolygon((TPoint *)(aDrawPolygon+1),aDrawPolygon->numPoints,aDrawPolygon->fillRule);
	}

void CWsGc::StartSegmentedDrawPolygonL(const TWsGcCmdStartSegmentedDrawPolygon* aDrawPolygon)
	{
	WS_ASSERT_DEBUG(iWin->Redraw()->OutputDevice(), EWsPanicWindowType);
	if (iPolyPoints || !Rng(0, aDrawPolygon->totalNumPoints, KMaxTInt/2 - 1))	// Restarting without finishing old polygon or invalid size
		GcOwnerPanic(EWservPanicBadPolyData);
	iPolyPoints=(TPoint *)User::AllocL(aDrawPolygon->totalNumPoints*sizeof(TPoint));
	iPolyPointListSize=aDrawPolygon->totalNumPoints;
	}

void CWsGc::SegmentedDrawPolygonData(const TWsGcCmdSegmentedDrawPolygonData* aDrawPolygon)
	{
	WS_ASSERT_DEBUG(iWin->Redraw()->OutputDevice(), EWsPanicWindowType);
	if (aDrawPolygon->index<0 || (aDrawPolygon->index+aDrawPolygon->numPoints)>iPolyPointListSize)
		GcOwnerPanic(EWservPanicBadPolyData);
	Mem::Copy(iPolyPoints+aDrawPolygon->index,aDrawPolygon+1,aDrawPolygon->numPoints*sizeof(TPoint));
	}

void CWsGc::EndSegmentedPolygon()
	{
	delete iPolyPoints;
	iPolyPoints=NULL;
	iPolyPointListSize = 0;
	}

void CWsGc::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;
		}
	if (aDrawPolyLine->more)	// more to come so don't draw the end point
		iBackedUpWinGc->DrawPolyLineNoEndPoint(points,numPoints);
	else
		iBackedUpWinGc->DrawPolyLine(points,numPoints);
	}

void CWsGc::GcOwnerPanic(TClientPanic aPanic)
	{
	iBackedUpWinGc->SetClippingRegion(NULL);
	EndSegmentedPolygon();
	iWin->WsOwner()->PPanic(aPanic);
	}
	
TPtrC CWsGc::BufferTPtr(TText* aStart,TInt aLen)
	{
	TPtrC gcPtr;
	if (!CWsClient::BufferTPtrGc(aStart,aLen,gcPtr))
		GcOwnerPanic(EWservPanicBufferPtr);
	return(gcPtr);
	}

void CWsGc::DoDrawCommand(TWsGcOpcodes aOpcode, const TWsGcCmdUnion &pData)
	{
	WS_ASSERT_DEBUG(iWin,EWsPanicWindowNull);
	WS_ASSERT_DEBUG(iWin->Redraw()->OutputDevice(), EWsPanicWindowType); // Must be activated on a backed up window

	if (iUserDefinedClippingRegion)
		{
		if (iUserDefinedClippingRegion->Count()==0)
			return;
		if (iUserDefinedClippingRegion->IsContainedBy(TRect(TPoint(0,0), iBackedUpWinGc->Device()->SizeInPixels())))
			{
			iBackedUpWinGc->SetClippingRegion(iUserDefinedClippingRegion);
			}
		}
	CGraphicsContext::TTextParameters contextParam;
	switch(aOpcode)
		{
		case EWsGcOpDrawWsGraphic:
		case EWsGcOpDrawWsGraphicPtr:
			{
			// CWsGc doesn't support CRPs.  CPlaybackGc does.  This means backedup windows
			// don't get to play with them yet.
			break;
			}
		case EWsGcOpMapColorsLocal:
			GcOwnerPanic(EWservPanicOpcode); //deprecated, the client should never generate this op
			break;
		case EWsGcOpDrawPolyLineLocalBufLen:
			iBackedUpWinGc->DrawPolyLine(pData.DrawPolyLineLocalBufLen->points,pData.DrawPolyLineLocalBufLen->length);
			break;
		case EWsGcOpDrawPolyLineLocal:
			iBackedUpWinGc->DrawPolyLine(pData.PointList);
			break;
		case EWsGcOpDrawPolygonLocalBufLen:
			iBackedUpWinGc->DrawPolygon(pData.DrawPolygonLocalBufLen->points,pData.DrawPolygonLocalBufLen->length,pData.DrawPolygonLocalBufLen->fillRule);
			break;
		case EWsGcOpDrawPolygonLocal:
			iBackedUpWinGc->DrawPolygon(pData.DrawPolygonLocal->pointList,pData.DrawPolygonLocal->fillRule);
			break;
		case EWsGcOpDrawBitmapLocal:
			iBackedUpWinGc->DrawBitmap(pData.BitmapLocal->pos, pData.BitmapLocal->bitmap);
			break;
		case EWsGcOpDrawBitmap2Local:
			iBackedUpWinGc->DrawBitmap(pData.Bitmap2Local->rect, pData.Bitmap2Local->bitmap);
			break;
		case EWsGcOpDrawBitmap3Local:
			iBackedUpWinGc->DrawBitmap(pData.Bitmap3Local->rect, pData.Bitmap3Local->bitmap, pData.Bitmap3Local->srcRect);
			break;
		case EWsGcOpDrawBitmapMaskedLocal:
			iBackedUpWinGc->DrawBitmapMasked(pData.iBitmapMaskedLocal->iRect, pData.iBitmapMaskedLocal->iBitmap, pData.iBitmapMaskedLocal->iSrcRect, pData.iBitmapMaskedLocal->iMaskBitmap,pData.iBitmapMaskedLocal->iInvertMask);
			break;
		case EWsGcOpAlphaBlendBitmapsLocal:
			iBackedUpWinGc->AlphaBlendBitmaps(pData.AlphaBlendBitmapsLocal->point,pData.AlphaBlendBitmapsLocal->iBitmap,
						   			pData.AlphaBlendBitmapsLocal->source, pData.AlphaBlendBitmapsLocal->iAlpha,
									pData.AlphaBlendBitmapsLocal->alphaPoint);

			break;
		case EWsGcOpDrawText:
			iBackedUpWinGc->DrawText(BufferTPtr((TText *)(pData.DrawText+1),pData.DrawText->length),pData.DrawText->pos);
			break;
		case EWsGcOpDrawBoxTextOptimised1:
			iBackedUpWinGc->DrawText(BufferTPtr((TText *)(pData.BoxTextO1+1),pData.BoxTextO1->length),pData.BoxTextO1->box,
							pData.BoxTextO1->baselineOffset,CGraphicsContext::ELeft,0);
			break;
		case EWsGcOpDrawBoxTextOptimised2:
			iBackedUpWinGc->DrawText(BufferTPtr((TText *)(pData.BoxTextO2+1),pData.BoxTextO2->length),pData.BoxTextO2->box,
							pData.BoxTextO2->baselineOffset,pData.BoxTextO2->horiz,pData.BoxTextO2->leftMrg);
			break;
		case EWsGcOpDrawTextPtr:
			iBackedUpWinGc->DrawText(*pData.DrawTextPtr->text,pData.DrawTextPtr->pos);
			break;
		case EWsGcOpDrawTextPtr1:
		   	iBackedUpWinGc->DrawText(*pData.DrawTextPtr->text);
			break;
		case EWsGcOpDrawBoxText:
			iBackedUpWinGc->DrawText(BufferTPtr((TText *)(pData.BoxText+1),pData.BoxText->length),pData.BoxText->box,pData.BoxText->baselineOffset,pData.BoxText->width,pData.BoxText->horiz,pData.BoxText->leftMrg);
			break;
		case EWsGcOpDrawBoxTextPtr:
			iBackedUpWinGc->DrawText(*pData.DrawBoxTextPtr->text,pData.DrawBoxTextPtr->box,pData.DrawBoxTextPtr->baselineOffset,pData.DrawBoxTextPtr->width,pData.DrawBoxTextPtr->horiz,pData.DrawBoxTextPtr->leftMrg);
			break;
		case EWsGcOpDrawBoxTextPtr1:
			iBackedUpWinGc->DrawText(*pData.DrawBoxTextPtr->text,pData.DrawBoxTextPtr->box);
			break;
		case EWsGcOpDrawTextVertical:
			iBackedUpWinGc->DrawTextVertical(BufferTPtr((TText *)(pData.DrawTextVertical+1),pData.DrawTextVertical->length),pData.DrawTextVertical->pos
							,pData.DrawTextVertical->up);
			break;
		case EWsGcOpDrawTextVerticalPtr:
			iBackedUpWinGc->DrawTextVertical(*pData.DrawTextVerticalPtr->text,pData.DrawTextVerticalPtr->pos,pData.DrawTextVerticalPtr->up);
			break;
		case EWsGcOpDrawTextVerticalPtr1:
			iBackedUpWinGc->DrawTextVertical(*pData.DrawTextVerticalPtr->text,pData.DrawTextVerticalPtr->up);
			break;
		case EWsGcOpDrawBoxTextVertical:
			iBackedUpWinGc->DrawTextVertical(BufferTPtr((TText *)(pData.DrawBoxTextVertical+1),pData.DrawBoxTextVertical->length),
							pData.DrawBoxTextVertical->box,	pData.DrawBoxTextVertical->baselineOffset,
							pData.DrawBoxTextVertical->up,(CGraphicsContext::TTextAlign)pData.DrawBoxTextVertical->vert,pData.DrawBoxTextVertical->margin);
			break;
		case EWsGcOpDrawBoxTextVerticalPtr:
			iBackedUpWinGc->DrawTextVertical(*pData.DrawBoxTextVerticalPtr->text,pData.DrawBoxTextVerticalPtr->box,pData.DrawBoxTextVerticalPtr->baselineOffset
							,pData.DrawBoxTextVerticalPtr->width,pData.DrawBoxTextVerticalPtr->up,pData.DrawBoxTextVerticalPtr->vert,pData.DrawBoxTextVerticalPtr->margin);
			break;
		case EWsGcOpDrawBoxTextVerticalPtr1:
			iBackedUpWinGc->DrawTextVertical(*pData.DrawBoxTextVerticalPtr->text,pData.DrawBoxTextVerticalPtr->box,pData.DrawBoxTextVerticalPtr->up);
			break;
		case EWsGcOpDrawTextLocal:
			iBackedUpWinGc->DrawText(*pData.DrawTextLocal->desc,pData.DrawTextLocal->pos);
			break;
		case EWsGcOpDrawBoxTextLocal:
			iBackedUpWinGc->DrawText(*pData.BoxTextLocal->desc,pData.BoxTextLocal->box,pData.BoxTextLocal->baselineOffset,
							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)
				{
				iBackedUpWinGc->DrawText(BufferTPtr((TText *)(pData.DrawTextInContext+1),pData.DrawTextInContext->length),&contextParam,pData.DrawTextInContext->pos);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			break;
		case EWsGcOpDrawBoxTextInContextOptimised1:
			contextParam.iStart = pData.BoxTextInContextO1->start;
			contextParam.iEnd = pData.BoxTextInContextO1->end;
			if(contextParam.iStart < contextParam.iEnd)
				{
				iBackedUpWinGc->DrawText(BufferTPtr((TText *)(pData.BoxTextInContextO1+1),pData.BoxTextInContextO1->length),&contextParam,pData.BoxTextInContextO1->box,
						pData.BoxTextInContextO1->baselineOffset,CGraphicsContext::ELeft,0);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			break;
		case EWsGcOpDrawBoxTextInContextOptimised2:
			contextParam.iStart = pData.BoxTextInContextO2->start;
			contextParam.iEnd = pData.BoxTextInContextO2->end;
			if(contextParam.iStart < contextParam.iEnd)
				{
				iBackedUpWinGc->DrawText(BufferTPtr((TText *)(pData.BoxTextInContextO2+1),pData.BoxTextInContextO2->length),&contextParam,pData.BoxTextInContextO2->box,
						pData.BoxTextInContextO2->baselineOffset,pData.BoxTextInContextO2->horiz,pData.BoxTextInContextO2->leftMrg);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			break;
		case EWsGcOpDrawTextInContextPtr:
			contextParam.iStart = pData.DrawTextInContextPtr->start;
			contextParam.iEnd = pData.DrawTextInContextPtr->end;
			if(contextParam.iStart < contextParam.iEnd)
				{
				iBackedUpWinGc->DrawText(*pData.DrawTextInContextPtr->text,&contextParam,pData.DrawTextInContextPtr->pos);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			break;
		case EWsGcOpDrawTextInContextPtr1:
			contextParam.iStart = pData.DrawTextInContextPtr->start;
			contextParam.iEnd = pData.DrawTextInContextPtr->end;
			if(contextParam.iStart < contextParam.iEnd)
				{
				iBackedUpWinGc->DrawText(*pData.DrawTextInContextPtr->text,&contextParam);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			break;
		case EWsGcOpDrawBoxTextInContext:
			contextParam.iStart = pData.BoxTextInContext->start;
			contextParam.iEnd = pData.BoxTextInContext->end;
			if(contextParam.iStart < contextParam.iEnd)
				{
				iBackedUpWinGc->DrawText(BufferTPtr((TText *)(pData.BoxTextInContext+1),pData.BoxTextInContext->length),&contextParam,
						pData.BoxTextInContext->box,pData.BoxTextInContext->baselineOffset,pData.BoxTextInContext->width,pData.BoxTextInContext->horiz,pData.BoxTextInContext->leftMrg);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			break;
		case EWsGcOpDrawBoxTextInContextPtr:
			contextParam.iStart = pData.DrawBoxTextInContextPtr->start;
			contextParam.iEnd = pData.DrawBoxTextInContextPtr->end;
			if(contextParam.iStart < contextParam.iEnd)
				{
				iBackedUpWinGc->DrawText(*pData.DrawBoxTextInContextPtr->text,&contextParam,pData.DrawBoxTextInContextPtr->box,pData.DrawBoxTextInContextPtr->baselineOffset,pData.DrawBoxTextInContextPtr->width,pData.DrawBoxTextInContextPtr->horiz,pData.DrawBoxTextInContextPtr->leftMrg);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			break;
		case EWsGcOpDrawBoxTextInContextPtr1:
			contextParam.iStart = pData.DrawBoxTextInContextPtr->start;
			contextParam.iEnd = pData.DrawBoxTextInContextPtr->end;
			if(contextParam.iStart < contextParam.iEnd)
				{
				iBackedUpWinGc->DrawText(*pData.DrawBoxTextInContextPtr->text,&contextParam,pData.DrawBoxTextInContextPtr->box);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			break;
		case EWsGcOpDrawTextInContextVertical:
			contextParam.iStart = pData.DrawTextInContextVertical->start;
			contextParam.iEnd = pData.DrawTextInContextVertical->end;
			if(contextParam.iStart < contextParam.iEnd)
				{
				iBackedUpWinGc->DrawTextVertical(BufferTPtr((TText *)(pData.DrawTextInContextVertical+1),pData.DrawTextInContextVertical->length),&contextParam,pData.DrawTextInContextVertical->pos
						,pData.DrawTextInContextVertical->up);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			break;
		case EWsGcOpDrawTextInContextVerticalPtr:
			contextParam.iStart = pData.DrawTextInContextVerticalPtr->start;
			contextParam.iEnd = pData.DrawTextInContextVerticalPtr->end;
			if(contextParam.iStart < contextParam.iEnd)
				{
				iBackedUpWinGc->DrawTextVertical(*pData.DrawTextInContextVerticalPtr->text,&contextParam,pData.DrawTextInContextVerticalPtr->pos,pData.DrawTextInContextVerticalPtr->up);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			break;
		case EWsGcOpDrawTextInContextVerticalPtr1:
			contextParam.iStart = pData.DrawTextInContextVerticalPtr->start;
			contextParam.iEnd = pData.DrawTextInContextVerticalPtr->end;
			if(contextParam.iStart < contextParam.iEnd)
				{
				iBackedUpWinGc->DrawTextVertical(*pData.DrawTextInContextVerticalPtr->text,&contextParam,pData.DrawTextInContextVerticalPtr->up);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			break;
		case EWsGcOpDrawBoxTextInContextVertical:
			contextParam.iStart = pData.DrawBoxTextInContextVertical->start;
			contextParam.iEnd = pData.DrawBoxTextInContextVertical->end;
			if(contextParam.iStart < contextParam.iEnd)
				{
				iBackedUpWinGc->DrawTextVertical(BufferTPtr((TText *)(pData.DrawBoxTextInContextVertical+1),pData.DrawBoxTextInContextVertical->length),&contextParam,
						pData.DrawBoxTextInContextVertical->box,pData.DrawBoxTextInContextVertical->baselineOffset,
						pData.DrawBoxTextInContextVertical->up,(CGraphicsContext::TTextAlign)pData.DrawBoxTextInContextVertical->vert,pData.DrawBoxTextInContextVertical->margin);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			break;
		case EWsGcOpDrawBoxTextInContextVerticalPtr:
			contextParam.iStart = pData.DrawBoxTextInContextVerticalPtr->start;
			contextParam.iEnd = pData.DrawBoxTextInContextVerticalPtr->end;
			if(contextParam.iStart < contextParam.iEnd)
				{
				iBackedUpWinGc->DrawTextVertical(*pData.DrawBoxTextVerticalPtr->text,&contextParam,pData.DrawBoxTextVerticalPtr->box,pData.DrawBoxTextVerticalPtr->baselineOffset
						,pData.DrawBoxTextVerticalPtr->width,pData.DrawBoxTextVerticalPtr->up,pData.DrawBoxTextVerticalPtr->vert,pData.DrawBoxTextVerticalPtr->margin);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			break;
		case EWsGcOpDrawBoxTextInContextVerticalPtr1:
			contextParam.iStart = pData.DrawBoxTextInContextVerticalPtr->start;
			contextParam.iEnd = pData.DrawBoxTextInContextVerticalPtr->end;
			if(contextParam.iStart < contextParam.iEnd)
				{
				iBackedUpWinGc->DrawTextVertical(*pData.DrawBoxTextVerticalPtr->text,&contextParam,pData.DrawBoxTextVerticalPtr->box,pData.DrawBoxTextVerticalPtr->up);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			break;
		case EWsGcOpDrawTextInContextLocal:
			contextParam.iStart = pData.DrawTextInContextLocal->start;
			contextParam.iEnd = pData.DrawTextInContextLocal->end;
			if(contextParam.iStart < contextParam.iEnd)
				{
				iBackedUpWinGc->DrawText(*pData.DrawTextInContextLocal->desc,&contextParam,pData.DrawTextInContextLocal->pos);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			break;
		case EWsGcOpDrawBoxTextInContextLocal:
			contextParam.iStart = pData.BoxTextInContextLocal->start;
			contextParam.iEnd = pData.BoxTextInContextLocal->end;
			if(contextParam.iStart < contextParam.iEnd)
				{
				iBackedUpWinGc->DrawText(*pData.BoxTextInContextLocal->desc,pData.BoxTextInContextLocal->box,pData.BoxTextInContextLocal->baselineOffset,
						pData.BoxTextInContextLocal->horiz,pData.BoxTextInContextLocal->leftMrg);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			break;
		case EWsGcOpDrawLine:
			iBackedUpWinGc->DrawLine(pData.DrawLine->pnt1,pData.DrawLine->pnt2);
			break;
		case EWsGcOpDrawTo:
			iBackedUpWinGc->DrawLine(iLinePos,*pData.Point);
			break;
		case EWsGcOpDrawBy:
			iBackedUpWinGc->DrawLine(iLinePos,iLinePos+(*pData.Point));
			break;
		case EWsGcOpPlot:
			iBackedUpWinGc->Plot(*pData.Point);
			break;
		case EWsGcOpMoveTo:
		case EWsGcOpMoveBy:
			break;
		case EWsGcOpGdiBlt2Local:
			iBackedUpWinGc->BitBlt(pData.GdiBlt2Local->pos,pData.GdiBlt2Local->bitmap);
			break;
		case EWsGcOpGdiBlt3Local:
			iBackedUpWinGc->BitBlt(pData.GdiBlt3Local->pos,pData.GdiBlt3Local->bitmap, pData.GdiBlt3Local->rect);
			break;
		case EWsGcOpGdiBltMaskedLocal:
			iBackedUpWinGc->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* scratchBimap=iScratchBitmap;
			CFbsBitmap* scratchMaskBimap=iScratchMaskBitmap;
			TInt maskHandle=0;
			TInt handle=WsBitmapHandle(aOpcode,pData, maskHandle);
			CWsClient* owner=iWin->WsOwner(); // We can't just use iWsOwner - it can be null for stored commands
			if (owner!=NULL)
				{
				DWsBitmap *bitmap=(DWsBitmap *)owner->HandleToObj(handle, WS_HANDLE_BITMAP);
				if (!bitmap)
					GcOwnerPanic(EWservPanicBitmap);
				scratchBimap=bitmap->FbsBitmap();
				if (aOpcode==EWsGcOpGdiWsBltMasked || aOpcode==EWsGcOpGdiWsAlphaBlendBitmaps || aOpcode==EWsGcOpWsDrawBitmapMasked)
					{
					DWsBitmap *bitmap2=(DWsBitmap *)owner->HandleToObj(maskHandle, WS_HANDLE_BITMAP);
					if (!bitmap2)
						GcOwnerPanic(EWservPanicBitmap);
					scratchMaskBimap=bitmap2->FbsBitmap();
					}
				}
			else 
				{
				GcOwnerPanic(EWservPanicBitmap);
				}
			switch(aOpcode)
				{
				case EWsGcOpGdiWsBlt2:
					iBackedUpWinGc->BitBlt(pData.GdiBlt2->pos,scratchBimap);
					break;
				case EWsGcOpGdiWsBlt3:
					iBackedUpWinGc->BitBlt(pData.GdiBlt3->pos,scratchBimap, pData.GdiBlt3->rect);
					break;
				case EWsGcOpGdiWsBltMasked:
					{
					iBackedUpWinGc->BitBltMasked(pData.GdiBltMasked->destination,scratchBimap,
									pData.GdiBltMasked->source, scratchMaskBimap,
									pData.GdiBltMasked->invertMask);
					}
					break;
				case EWsGcOpGdiWsAlphaBlendBitmaps:
					{
					iBackedUpWinGc->AlphaBlendBitmaps(pData.AlphaBlendBitmaps->point,scratchBimap,
									   pData.AlphaBlendBitmaps->source, scratchMaskBimap,
									   pData.AlphaBlendBitmaps->alphaPoint);
					}
					break;
				case EWsGcOpWsDrawBitmapMasked:
					{
					iBackedUpWinGc->DrawBitmapMasked(pData.iBitmapMasked->iRect,scratchBimap, 
										pData.iBitmapMasked->iSrcRect,scratchMaskBimap,
										pData.iBitmapMasked->iInvertMask);
					}
					break;
				}
			break;
			}
		case EWsGcOpGdiBlt2:
		case EWsGcOpGdiBlt3:
		case EWsGcOpGdiBltMasked:
		case EWsGcOpGdiAlphaBlendBitmaps:
		case EWsGcOpDrawBitmap:
		case EWsGcOpDrawBitmap2:
		case EWsGcOpDrawBitmap3:
		case EWsGcOpDrawBitmapMasked:
			{
			TInt maskHandle=0;
			TInt ret = iScratchBitmap->Duplicate(FbsBitmapHandle(aOpcode, pData,maskHandle));
			if(ret == KErrNoMemory)
				break;	
			if (ret !=KErrNone)
				GcOwnerPanic(EWservPanicBitmap);
			
			switch(aOpcode)
				{
				case EWsGcOpGdiBlt2:
					iBackedUpWinGc->BitBlt(pData.GdiBlt2->pos,iScratchBitmap);
					break;
				case EWsGcOpGdiBlt3:
					iBackedUpWinGc->BitBlt(pData.GdiBlt3->pos,iScratchBitmap, pData.GdiBlt3->rect);
					break;
				case EWsGcOpGdiBltMasked:
					{
					TInt ret = iScratchMaskBitmap->Duplicate(pData.GdiBltMasked->maskHandle);
					if(ret == KErrNoMemory)
						break;	
					if (ret !=KErrNone)
						GcOwnerPanic(EWservPanicBitmap);
			
					iBackedUpWinGc->BitBltMasked(pData.GdiBltMasked->destination,iScratchBitmap,
										pData.GdiBltMasked->source, iScratchMaskBitmap,
										 pData.GdiBltMasked->invertMask);
					iScratchMaskBitmap->Reset();
					}
					break;
				case EWsGcOpGdiAlphaBlendBitmaps:
					{
					TInt ret = iScratchMaskBitmap->Duplicate(pData.AlphaBlendBitmaps->alphaHandle);
					if (ret == KErrNoMemory)
						break;	
					if (ret != KErrNone)
						GcOwnerPanic(EWservPanicBitmap);

					iBackedUpWinGc->AlphaBlendBitmaps(pData.AlphaBlendBitmaps->point, iScratchBitmap,
									   pData.AlphaBlendBitmaps->source, iScratchMaskBitmap,
									   pData.AlphaBlendBitmaps->alphaPoint);
					iScratchMaskBitmap->Reset();
					break;
					}
				case EWsGcOpDrawBitmap:
					iBackedUpWinGc->DrawBitmap(pData.Bitmap->pos, iScratchBitmap);
					break;
				case EWsGcOpDrawBitmap2:
					iBackedUpWinGc->DrawBitmap(pData.Bitmap2->rect, iScratchBitmap);
					break;
				case EWsGcOpDrawBitmap3:
					iBackedUpWinGc->DrawBitmap(pData.Bitmap3->rect, iScratchBitmap, pData.Bitmap3->srcRect);
					break;
				case EWsGcOpDrawBitmapMasked:
					{
					TInt ret = iScratchMaskBitmap->Duplicate(pData.iBitmapMasked->iMaskHandle);
					if (ret == KErrNoMemory)
						break;	
					if (ret != KErrNone)
						GcOwnerPanic(EWservPanicBitmap);

					iBackedUpWinGc->DrawBitmapMasked(pData.iBitmapMasked->iRect, iScratchBitmap, 
										pData.iBitmapMasked->iSrcRect, iScratchMaskBitmap,
										pData.iBitmapMasked->iInvertMask);
					iScratchMaskBitmap->Reset();
					}
					break;
				}
			iScratchBitmap->Reset();
			break;
			}
		case EWsGcOpDrawSegmentedPolygon:
			iBackedUpWinGc->DrawPolygon(iPolyPoints,iPolyPointListSize,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:
			iBackedUpWinGc->Clear(TRect(iWin->Size()));
			break;
		case EWsGcOpClearRect:
			iBackedUpWinGc->Clear(*pData.Rect);
			break;
		case EWsGcOpDrawRect:
			iBackedUpWinGc->DrawRect(*pData.Rect);
			break;
		case EWsGcOpDrawEllipse:
			iBackedUpWinGc->DrawEllipse(*pData.Rect);
			break;
		case EWsGcOpDrawRoundRect:
			iBackedUpWinGc->DrawRoundRect(*pData.Rect,pData.RoundRect->ellipse);
			break;
		case EWsGcOpDrawArc:
			iBackedUpWinGc->DrawArc(*pData.Rect,pData.ArcOrPie->start,pData.ArcOrPie->end);
			break;
		case EWsGcOpDrawPie:
			iBackedUpWinGc->DrawPie(*pData.Rect,pData.ArcOrPie->start,pData.ArcOrPie->end);
			break;
		case EWsGcOpCopyRect:
			iBackedUpWinGc->CopyRect(pData.CopyRect->pos,*pData.Rect);
			break;
		case EWsGcOpMapColors:
			GcOwnerPanic(EWservPanicOpcode); //deprecated, the client should never generate this op
			break;
			
		default:
			GcOwnerPanic(EWservPanicOpcode);
		}
	iBackedUpWinGc->SetClippingRegion(NULL);
	}

TInt CWsGc::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;
		default:
			OwnerPanic(EWservPanicOpcode);
		}
	return handle;
	}		

TInt CWsGc::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:
			OwnerPanic(EWservPanicOpcode);
		}
	return handle;
	}

TInt CWsGc::WsDrawableSourceHandle(TInt aOpcode, const TWsGcCmdUnion &aData) 
	{
	TInt handle=0;
	switch(aOpcode)
		{
		case EWsGcOpDrawResourceToPos:
			handle=aData.DrawWsResourceToPos->wsHandle;
			break;
		case EWsGcOpDrawResourceToRect:
			handle=aData.DrawWsResourceToRect->wsHandle;
			break;
		case EWsGcOpDrawResourceFromRectToRect:
			handle=aData.DrawWsResourceFromRectToRect->wsHandle;
			break;
		case EWsGcOpDrawResourceWithData:
			handle=aData.DrawWsResourceWithData->wsHandle;
			break;
		default:
			OwnerPanic(EWservPanicOpcode);
		}
	return handle;
	}		

void CWsGc::UpdateJustification(TText* aText,TInt aLen)
	{
	iBackedUpWinGc->UpdateJustification(BufferTPtr(aText,aLen));
	}

void CWsGc::UpdateJustification(TText* aText,TInt aLen,CGraphicsContext::TTextParameters* aParam)
	{
	iBackedUpWinGc->UpdateJustification(BufferTPtr(aText,aLen),aParam);
	}

void CWsGc::DoDrawing2(TWsGcOpcodes aOpcode, const TWsGcCmdUnion &pData)
	{
	WS_ASSERT_DEBUG(iWin->Redraw()->OutputDevice(), EWsPanicWindowType);

	iBackedUpWinGc->SetUserDisplayMode(iWin->DisplayMode());
	if (iClippingRectSet)
		{
		iBackedUpWinGc->SetOrigin(TPoint(0,0));
		iBackedUpWinGc->SetClippingRect(iClippingRect);
		}
	iBackedUpWinGc->SetOrigin(iOrigin);
	iInternalStatus.iOrigin = iOrigin;
	
	DoDrawCommand(aOpcode,pData);

	iBackedUpWinGc->SetUserDisplayMode(ENone);
	iBackedUpWinGc->CancelClippingRect();
	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);
			break;
		case EWsGcOpDrawTextVertical:
			UpdateJustification((TText *)(pData.DrawTextVertical+1),pData.DrawTextVertical->length);
			break;
		case EWsGcOpDrawBoxText:
			UpdateJustification((TText *)(pData.BoxText+1),pData.BoxText->length);
			break;
		case EWsGcOpDrawBoxTextOptimised1:
			UpdateJustification((TText *)(pData.BoxTextO1+1),pData.BoxTextO1->length);
			break;
		case EWsGcOpDrawBoxTextOptimised2:
			UpdateJustification((TText *)(pData.BoxTextO2+1),pData.BoxTextO2->length);
			break;
		case EWsGcOpDrawBoxTextVertical:
			UpdateJustification((TText *)(pData.DrawBoxTextVertical+1),pData.DrawBoxTextVertical->length);
			break;
		case EWsGcOpDrawTextLocal:
			iBackedUpWinGc->UpdateJustification(*pData.DrawTextLocal->desc);
			break;
		case EWsGcOpDrawBoxTextLocal:
			iBackedUpWinGc->UpdateJustification(*pData.BoxTextLocal->desc);
			break;
		case EWsGcOpDrawTextPtr:
			iBackedUpWinGc->UpdateJustification(*pData.DrawTextPtr->text);
			break;
		case EWsGcOpDrawTextVerticalPtr:
			iBackedUpWinGc->UpdateJustification(*pData.DrawTextVerticalPtr->text);
			break;
		case EWsGcOpDrawBoxTextPtr:
			iBackedUpWinGc->UpdateJustification(*pData.DrawBoxTextPtr->text);
			break;
		case EWsGcOpDrawBoxTextVerticalPtr:
			iBackedUpWinGc->UpdateJustification(*pData.DrawBoxTextVerticalPtr->text);
			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,&contextParam);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			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,&contextParam);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			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,&contextParam);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			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,&contextParam);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			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,&contextParam);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			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,&contextParam);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			break;
		case EWsGcOpDrawTextInContextLocal:
			contextParam.iStart = pData.DrawTextInContext->start;
			contextParam.iEnd = pData.DrawTextInContext->end;
			if(contextParam.iStart < contextParam.iEnd)
				{
				iBackedUpWinGc->UpdateJustification(*pData.DrawTextInContextLocal->desc,&contextParam);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			break;
		case EWsGcOpDrawBoxTextInContextLocal:
			contextParam.iStart = pData.DrawTextInContext->start;
			contextParam.iEnd = pData.DrawTextInContext->end;
			if(contextParam.iStart < contextParam.iEnd)
				{
				iBackedUpWinGc->UpdateJustification(*pData.BoxTextInContextLocal->desc,&contextParam);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			break;
		case EWsGcOpDrawTextInContextPtr:
			contextParam.iStart = pData.DrawTextInContext->start;
			contextParam.iEnd = pData.DrawTextInContext->end;
			if(contextParam.iStart < contextParam.iEnd)
				{
				iBackedUpWinGc->UpdateJustification(*pData.DrawTextInContextPtr->text,&contextParam);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			break;
		case EWsGcOpDrawTextInContextVerticalPtr:
			contextParam.iStart = pData.DrawTextInContext->start;
			contextParam.iEnd = pData.DrawTextInContext->end;
			if(contextParam.iStart < contextParam.iEnd)
				{
				iBackedUpWinGc->UpdateJustification(*pData.DrawTextInContextVerticalPtr->text,&contextParam);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			break;
		case EWsGcOpDrawBoxTextInContextPtr:
			contextParam.iStart = pData.DrawTextInContext->start;
			contextParam.iEnd = pData.DrawTextInContext->end;
			if(contextParam.iStart < contextParam.iEnd)
				{
				iBackedUpWinGc->UpdateJustification(*pData.DrawBoxTextInContextPtr->text,&contextParam);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			break;
		case EWsGcOpDrawBoxTextInContextVerticalPtr:
			contextParam.iStart = pData.DrawTextInContext->start;
			contextParam.iEnd = pData.DrawTextInContext->end;
			if(contextParam.iStart < contextParam.iEnd)
				{
				iBackedUpWinGc->UpdateJustification(*pData.DrawBoxTextInContextVerticalPtr->text,&contextParam);
				}
			else
				{
				iWin->WsOwner()->PPanic(EWservPanicInvalidParameter);
				}
			break;
		}
	}

void CWsGc::DoDrawing1(TWsGcOpcodes aOpcode, const TWsGcCmdUnion &pData)
	{
	WS_ASSERT_DEBUG(iWin->Redraw()->OutputDevice(), EWsPanicWindowType);

	TWsGcLargeStruct newData;
	TWsGcCmdUnion pNewData;
	TWsGcOpcodes opcode;
	TDesC **string;
	TInt toGo;
	pNewData.LargeStruct=&newData;
	switch (aOpcode)
		{
		case EWsGcOpDrawTextPtr:
			WS_ASSERT_DEBUG(sizeof(TWsGcLargeStruct)>=sizeof(TWsGcCmdDrawTextPtr), EWsPanicGcStructSizeError);
			opcode=EWsGcOpDrawTextPtr1;
			toGo=pData.DrawText->length;
			pNewData.DrawTextPtr->pos=pData.DrawText->pos;
			string=&(pNewData.DrawTextPtr->text);
			break;
		case EWsGcOpDrawTextVerticalPtr:
			WS_ASSERT_DEBUG(sizeof(TWsGcLargeStruct)>=sizeof(TWsGcCmdDrawTextVerticalPtr), EWsPanicGcStructSizeError);
			opcode=EWsGcOpDrawTextVerticalPtr1;
			toGo=pData.DrawTextVertical->length;
			pNewData.DrawTextVerticalPtr->pos=pData.DrawTextVertical->pos;
			pNewData.DrawTextVerticalPtr->up=pData.DrawTextVertical->up;
			string=&(pNewData.DrawTextVerticalPtr->text);
			break;
			
		case EWsGcOpDrawBoxTextPtr:
			WS_ASSERT_DEBUG(sizeof(TWsGcLargeStruct)>=sizeof(TWsGcCmdBoxTextPtr), EWsPanicGcStructSizeError);
			opcode=EWsGcOpDrawBoxTextPtr1;
			toGo=pData.BoxText->length;
			pNewData.DrawBoxTextPtr->box=pData.BoxText->box;
			pNewData.DrawBoxTextPtr->baselineOffset=pData.BoxText->baselineOffset;
			pNewData.DrawBoxTextPtr->horiz=pData.BoxText->horiz;
			pNewData.DrawBoxTextPtr->leftMrg=pData.BoxText->leftMrg;
			pNewData.DrawBoxTextPtr->width=pData.BoxText->width;
			string=&(pNewData.DrawBoxTextPtr->text);
			break;
			
		case EWsGcOpDrawBoxTextVerticalPtr:
			WS_ASSERT_DEBUG(sizeof(TWsGcLargeStruct)>=sizeof(TWsGcCmdBoxTextVerticalPtr), EWsPanicGcStructSizeError);
			opcode=EWsGcOpDrawBoxTextVerticalPtr1;
			toGo=pData.DrawBoxTextVertical->length;
			pNewData.DrawBoxTextVerticalPtr->box=pData.DrawBoxTextVertical->box;
			pNewData.DrawBoxTextVerticalPtr->baselineOffset=pData.DrawBoxTextVertical->baselineOffset;
			pNewData.DrawBoxTextVerticalPtr->up=pData.DrawBoxTextVertical->up;
			pNewData.DrawBoxTextVerticalPtr->vert=pData.DrawBoxTextVertical->vert;
			pNewData.DrawBoxTextVerticalPtr->margin=pData.DrawBoxTextVertical->margin;
			pNewData.DrawBoxTextVerticalPtr->width=pData.DrawBoxTextVertical->width;
			string=&(pNewData.DrawBoxTextVerticalPtr->text);
			break;

		case EWsGcOpDrawTextInContextPtr:
			WS_ASSERT_DEBUG(sizeof(TWsGcLargeStruct)>=sizeof(TWsGcCmdDrawTextInContextPtr), EWsPanicGcStructSizeError);
			opcode=EWsGcOpDrawTextInContextPtr1;
			toGo=pData.DrawTextInContext->length;
			pNewData.DrawTextInContextPtr->pos=pData.DrawTextInContext->pos;
			pNewData.DrawTextInContextPtr->start=pData.DrawTextInContext->start;
			pNewData.DrawTextInContextPtr->end=pData.DrawTextInContext->end;
			string=&(pNewData.DrawTextInContextPtr->text);
			break;
			
		case EWsGcOpDrawTextInContextVerticalPtr:
			WS_ASSERT_DEBUG(sizeof(TWsGcLargeStruct)>=sizeof(TWsGcCmdDrawTextInContextVerticalPtr), EWsPanicGcStructSizeError);
			opcode=EWsGcOpDrawTextInContextVerticalPtr1;
			toGo=pData.DrawTextInContextVertical->length;
  			pNewData.DrawTextInContextVerticalPtr->pos=pData.DrawTextInContextVerticalPtr->pos;
  			pNewData.DrawTextInContextVerticalPtr->up=pData.DrawTextInContextVerticalPtr->up;
  			pNewData.DrawTextInContextVerticalPtr->start=pData.DrawTextInContextVerticalPtr->start;
  			pNewData.DrawTextInContextVerticalPtr->end=pData.DrawTextInContextVerticalPtr->end;
			string=&(pNewData.DrawTextVerticalPtr->text);
			break;
			
		case EWsGcOpDrawBoxTextInContextPtr:
			WS_ASSERT_DEBUG(sizeof(TWsGcLargeStruct)>=sizeof(TWsGcCmdBoxTextInContextPtr), EWsPanicGcStructSizeError);
			opcode=EWsGcOpDrawBoxTextInContextPtr1;
			toGo=pData.BoxTextInContext->length;
   			pNewData.DrawBoxTextInContextPtr->box=pData.BoxTextInContext->box;
   			pNewData.DrawBoxTextInContextPtr->baselineOffset=pData.BoxTextInContext->baselineOffset;
   			pNewData.DrawBoxTextInContextPtr->horiz=pData.BoxTextInContext->horiz;
   			pNewData.DrawBoxTextInContextPtr->leftMrg=pData.BoxTextInContext->leftMrg;
   			pNewData.DrawBoxTextInContextPtr->width=pData.BoxTextInContext->width;
   			pNewData.DrawBoxTextInContextPtr->start=pData.BoxTextInContext->start;
  			pNewData.DrawBoxTextInContextPtr->end=pData.BoxTextInContext->end;
			string=&(pNewData.DrawBoxTextPtr->text);
			break;
			
		case EWsGcOpDrawBoxTextInContextVerticalPtr:
			WS_ASSERT_DEBUG(sizeof(TWsGcLargeStruct)>=sizeof(TWsGcCmdBoxTextInContextVerticalPtr), EWsPanicGcStructSizeError);
			opcode=EWsGcOpDrawBoxTextInContextVerticalPtr1;
			toGo=pData.DrawBoxTextInContextVertical->length;
   			pNewData.DrawBoxTextInContextVerticalPtr->box=pData.DrawBoxTextInContextVertical->box;
   			pNewData.DrawBoxTextInContextVerticalPtr->baselineOffset=pData.DrawBoxTextInContextVertical->baselineOffset;
   			pNewData.DrawBoxTextInContextVerticalPtr->up=pData.DrawBoxTextInContextVertical->up;
   			pNewData.DrawBoxTextInContextVerticalPtr->vert=pData.DrawBoxTextInContextVertical->vert;
   			pNewData.DrawBoxTextInContextVerticalPtr->margin=pData.DrawBoxTextInContextVertical->margin;
   			pNewData.DrawBoxTextInContextVerticalPtr->width=pData.DrawBoxTextInContextVertical->width;
   			pNewData.DrawBoxTextInContextVerticalPtr->start=pData.DrawBoxTextInContextVertical->start;
   			pNewData.DrawBoxTextInContextVerticalPtr->end=pData.DrawBoxTextInContextVertical->end;
 			string=&(pNewData.DrawBoxTextInContextVerticalPtr->text);			
			break;

		default:
			DoDrawing2(aOpcode,pData);
			return;
		}

	TBuf<ETextPtrBufLen> buf;
	TInt len=ETextPtrBufLen;
	TInt bufOffset=0;
	*string=&buf;
	while(toGo>0)
		{
		if (len>toGo)
			len=toGo;
		iWsOwner->RemoteRead(buf,bufOffset);
		DoDrawing2(aOpcode,pNewData);
		aOpcode=opcode;
		bufOffset+=len;
		toGo-=len;
		}
	}

void CWsGc::SetGcAttribute(TInt aOpcode, TWsGcCmdUnion pData)
	{
	switch(aOpcode)
		{
		case EWsGcOpSetDrawMode:
			iInternalStatus.iDrawMode = (CGraphicsContext::TDrawMode) (*pData.UInt);
			if (iWin->Redraw()->OutputDevice())
				iBackedUpWinGc->SetDrawMode(iInternalStatus.iDrawMode);
			break;
		case EWsGcOpUseFont:
			if (CWsFontCache::Instance()->UseFont(iFont, *pData.UInt))
				{	// Couldn't cache it
				if (iWin->Redraw()->OutputDevice())
					{
					TInt ret = iBackedUpWinGc->UseFont(*pData.UInt);
					if (ret == KErrNoMemory)
						return;
					if (ret != KErrNone)
						GcOwnerPanic(EWservPanicFont);
					}
				iInternalStatus.iFontHandle = *pData.UInt;
				}
			else
				{
				if (iFont==NULL)
					{
					iInternalStatus.iFontHandle = NULL;
					GcOwnerPanic(EWservPanicFont);
					}
				if (iWin->Redraw()->OutputDevice())
					iBackedUpWinGc->UseFontNoDuplicate(iFont);
				iInternalStatus.iFontHandle = iFont->Handle();
				}
			break;
		case EWsGcOpDiscardFont:
			CWsFontCache::Instance()->ReleaseFont(iFont);
			if (iWin->Redraw()->OutputDevice())
				iBackedUpWinGc->DiscardFont();
			iInternalStatus.iFontHandle = NULL;
			break;
		case EWsGcOpSetUnderlineStyle:
			if (iWin->Redraw()->OutputDevice())
				iBackedUpWinGc->SetUnderlineStyle(*pData.SetUnderlineStyle);
			iInternalStatus.iUnderline = *pData.SetUnderlineStyle;
			break;
		case EWsGcOpSetStrikethroughStyle:
			if (iWin->Redraw()->OutputDevice())
				iBackedUpWinGc->SetStrikethroughStyle(*pData.SetStrikethroughStyle);
			iInternalStatus.iStrikethrough = *pData.SetStrikethroughStyle;
			break;
		case EWsGcOpUseBrushPattern:
			if (iWin->Redraw()->OutputDevice())
				{
				TInt ret = iBackedUpWinGc->UseBrushPattern(*pData.handle);
				if (ret == KErrNoMemory)
					return;
				if (ret != KErrNone)
					GcOwnerPanic(EWservPanicBitmap);
				}
			else
				{
				// Make sure the bitmap handle is valid
				TInt ret = iScratchBitmap->Duplicate(*pData.handle);
				if (ret == KErrNoMemory)
					return;
				if (ret != KErrNone)
					GcOwnerPanic(EWservPanicBitmap);
				iScratchBitmap->Reset();
				}
			iInternalStatus.iBrushPatternHandle = *pData.handle;
			break;
		case EWsGcOpDiscardBrushPattern:
			if (iWin->Redraw()->OutputDevice())
				iBackedUpWinGc->DiscardBrushPattern();
			iInternalStatus.iBrushPatternHandle = NULL;
			if (iInternalStatus.iBrushStyle == CGraphicsContext::EPatternedBrush)
				iInternalStatus.iBrushStyle = CGraphicsContext::ENullBrush;
			break;
		case EWsGcOpSetBrushColor:
			if (iWin->Redraw()->OutputDevice())
				iBackedUpWinGc->SetBrushColor(*pData.rgb);
			iInternalStatus.iBrushColor = *pData.rgb; 
			break;
		case EWsGcOpSetPenColor:
			if (iWin->Redraw()->OutputDevice())
				iBackedUpWinGc->SetPenColor(*pData.rgb);
			iInternalStatus.iPenColor = *pData.rgb;
			break;
		case EWsGcOpSetPenStyle:
			iInternalStatus.iPenStyle = (CGraphicsContext::TPenStyle) (*pData.UInt);
			if (iWin->Redraw()->OutputDevice())
				iBackedUpWinGc->SetPenStyle(iInternalStatus.iPenStyle);
			break;
		case EWsGcOpSetPenSize:
			if (iWin->Redraw()->OutputDevice())
				iBackedUpWinGc->SetPenSize(*pData.Size);
			iInternalStatus.iPenSize = *pData.Size; 
			break;
		case EWsGcOpSetBrushStyle:
			if ((CGraphicsContext::TBrushStyle)*pData.UInt==CGraphicsContext::EPatternedBrush && !iInternalStatus.iBrushPatternHandle)
				GcOwnerPanic(EWservPanicNoBrush);
			iInternalStatus.iBrushStyle = (CGraphicsContext::TBrushStyle) (*pData.UInt);
			if (iWin->Redraw()->OutputDevice())
				iBackedUpWinGc->SetBrushStyle(iInternalStatus.iBrushStyle); 
			break;
		case EWsGcOpReset:
			CWsFontCache::Instance()->ReleaseFont(iFont);
			iBackedUpWinGc->Reset();
			iOrigin.SetXY(0,0);
			ResetClippingRect();
			iInternalStatus.ResetInternalStatus(iWin);
			if (iWin->Redraw()->OutputDevice())
				iBackedUpWinGc->SetBrushColor(iWin->BackColor());
			iInternalStatus.iBrushColor = iWin->BackColor();
			break;
		case EWsGcOpSetBrushOrigin:
			if (iWin->Redraw()->OutputDevice())
				iBackedUpWinGc->SetBrushOrigin(*pData.Point);
			iInternalStatus.iBrushOrigin = *pData.Point; 
			break;
		case EWsGcOpSetDitherOrigin:
			GcOwnerPanic(EWservPanicOpcode); //deprecated, the client should never generate this op
			break;
		case EWsGcOpSetWordJustification:
			if (iWin->Redraw()->OutputDevice())
				iBackedUpWinGc->SetWordJustification(pData.SetJustification->excessWidth, pData.SetJustification->numGaps);
			iInternalStatus.iWordExcessWidth = pData.SetJustification->excessWidth;
			iInternalStatus.iWordNumChars = pData.SetJustification->numGaps;
			break;
		case EWsGcOpSetCharJustification:
			if (iWin->Redraw()->OutputDevice())
				iBackedUpWinGc->SetCharJustification(pData.SetJustification->excessWidth, pData.SetJustification->numGaps);
			iInternalStatus.iCharExcessWidth = pData.SetJustification->excessWidth;
			iInternalStatus.iCharNumChars = pData.SetJustification->numGaps;
			break;
		case EWsGcOpSetOrigin:
			SetOrigin(*pData.Point);
			iInternalStatus.iOrigin = *pData.Point; 
			break;
		case EWsGcOpSetOpaque: // deprecated
			// do nothing
			break;
		case EWsGcOpSetShadowColor:
			if (iWin->Redraw()->OutputDevice())
				iBackedUpWinGc->SetShadowColor(*pData.rgb);
			iInternalStatus.iShadowColor = *pData.rgb; 
			break;
		}
	}

void CWsGc::DoDrawing0L(TWsGcOpcodes aOpcode, const TWsGcCmdUnion &pData)
	{
	if (iWin==NULL)
		{
		OwnerPanic(EWservPanicGcNotActive);
		return;
		}
	
	iWin->SetValidRedraw();

	switch(aOpcode)
		{
	case EWsGcOpStartSegmentedDrawPolygon:

		//tell Redraw Store about the drawing data, so that it is stored and CWsGc::ExternalizeL can be called if required
		if (iWin->Redraw()->DrawCommand(this,pData.any))
			StartSegmentedDrawPolygonL(pData.StartSegmentedDrawPolygon);
		return;
	case EWsGcOpSegmentedDrawPolygonData:
		//tell Redraw Store about the drawing data, so that it is stored and CWsGc::ExternalizeL can be called if required
		if (iWin->Redraw()->DrawCommand(this,pData.any))
			SegmentedDrawPolygonData(pData.SegmentedDrawPolygonData);
		return;
	case EWsGcOpSetClippingRegion:
		SetClippingRegionL(*pData.Int);
		break;
	case EWsGcOpSetClippingRect:
		SetClippingRect(*pData.Rect);
		break;
	case EWsGcOpCancelClippingRect:
		ResetClippingRect();
		break;
	case EWsGcOpCancelClippingRegion:
		CancelClippingRegion();
		break;
	case EWsGcOpSetFaded:
		if (iWin->Redraw()->OutputDevice())
			iBackedUpWinGc->SetFaded(*pData.Bool);
		break;
	case EWsGcOpSetFadeParams:
		if (iWin->Redraw()->OutputDevice())
			iBackedUpWinGc->SetFadingParameters(WservEncoding::ExtractFirst8BitValue(*pData.UInt),WservEncoding::ExtractSecond8BitValue(*pData.UInt));
		break;
	case EWsGcOpSetDrawMode:
	case EWsGcOpUseFont:
	case EWsGcOpDiscardFont:
	case EWsGcOpUseBrushPattern:
	case EWsGcOpDiscardBrushPattern:
	case EWsGcOpSetBrushColor:
	case EWsGcOpSetPenColor:
	case EWsGcOpSetPenStyle:
	case EWsGcOpSetPenSize:
	case EWsGcOpSetBrushStyle:
	case EWsGcOpReset:
	case EWsGcOpSetBrushOrigin:
	case EWsGcOpSetDitherOrigin:
	case EWsGcOpSetUnderlineStyle:
	case EWsGcOpSetStrikethroughStyle:
	case EWsGcOpSetWordJustification:
	case EWsGcOpSetCharJustification:
	case EWsGcOpSetOrigin:
	case EWsGcOpSetOpaque:
	case EWsGcOpSetShadowColor:
		{
		SetGcAttribute(aOpcode,pData);
		break;
		}
	case EWsGcOpDrawBoxText:	
	case EWsGcOpDrawBoxTextOptimised1:
	case EWsGcOpDrawBoxTextOptimised2:
	case EWsGcOpDrawBoxTextPtr:
	case EWsGcOpDrawBoxTextPtr1:
	case EWsGcOpDrawTextPtr:
	case EWsGcOpDrawTextPtr1:
	case EWsGcOpDrawText:
	case EWsGcOpDrawTextVertical:
	case EWsGcOpDrawTextVerticalPtr:
	case EWsGcOpDrawTextVerticalPtr1:
	case EWsGcOpDrawBoxTextVertical:
	case EWsGcOpDrawBoxTextVerticalPtr:
	case EWsGcOpDrawBoxTextVerticalPtr1:
	case EWsGcOpDrawTextLocal:
	case EWsGcOpDrawBoxTextLocal:
		{
		//Make sure a font is set before any text related opcodes are used.
		if (!iInternalStatus.iFontHandle)
			OwnerPanic(EWservPanicNoFont);
		//fall through
		}
	default:	// Assume remaining functions will draw
		{
		if (iWin->WinType()!=EWinTypeRoot)
			{
			if (!iWin->BaseParent())
				OwnerPanic(EWservPanicParentDeleted);
			if (iWin->WinType()!=EWinTypeClient)
				OwnerPanic(EWservPanicReadOnlyDrawable);
			}
		if (iWin->Redraw()->DrawCommand(this,pData.any))
			DoDrawing1(aOpcode,pData);
		return;
		}
		}
	iWin->Redraw()->GcAttributeChange(this,pData.any);
	}

void CWsGc::CommandL(TInt aOpcode, const TAny *aCmdData)
	{
	TWsGcOpcodes opcode = static_cast<TWsGcOpcodes>(aOpcode);

	TWsGcCmdUnion pData;
	pData.any=aCmdData;
	switch(opcode)
		{
		case EWsGcOpActivate:
			Activate(*pData.handle);
			break;
		case EWsGcOpDeactivate:
			Deactivate();
			break;
		case EWsGcOpFree:
			delete this;
			break;
		case EWsGcOpTestInvariant:
			break;
		default:
			DoDrawing0L(opcode,pData);
			break;
		}
	}

void CWsGc::SetOrigin(const TPoint &aOrigin)
	{
	iOrigin=aOrigin;
	}
	

/*------------------------------------------------------------------------------
  Description: Saves graphics context information into a given buffer from a
               given start position rather than just streaming data to the end.
               This variant allows for buffers that are not fully utilised.
 -----------------------------------------------------------------------------*/
TInt CWsGc::ExternalizeL(CBufBase& aBuffer, TInt aStartPos)
	{
	WS_ASSERT_DEBUG(!IsPolyPointData(), EWsPanicDrawCommandsInvalidState);

	// Open the stream used for the output from the given start position
	// in the buffer.
	RBufWriteStream bufWriteStream;
	bufWriteStream.Open(aBuffer, aStartPos);
	CleanupClosePushL(bufWriteStream);

	// Font/Bitmap Server data is serialised below in a call to 
	// ExternalizeGcAttributesL(). As this method does not return the amount of
	// the data externalised we use methods in the underlying stream to 
	// calculate it. We do this because we need to return an accurate count of
	// data serialised from this method so that the caller can update its 
	// buffer write counter.
	MStreamBuf* ptrToRawStream = bufWriteStream.Sink();	// This is the real stream

	// Position of read seek pointer before externalise
	TStreamPos size1 = ptrToRawStream->TellL(MStreamBuf::EWrite); 

	// Save the font/bitmap server data
	iInternalStatus.ExternalizeGcAttributesL(bufWriteStream);

	bufWriteStream.WriteInt32L(iOrigin.iX);
	bufWriteStream.WriteInt32L(iOrigin.iY);

	bufWriteStream.WriteInt8L(iClippingRectSet);

	// If there is a clipping rectangle output that too.
	if (iClippingRectSet)
		{
		bufWriteStream << iClippingRect;
		}
		
	// Save clipping region data.
	ExternalizeClippingRegionL(bufWriteStream);

	// Save the Alpha values for Brush and Pen colors.
	ExternalizeAlphaValueL(bufWriteStream);

	// Position of read seek pointer after externalise
	TStreamPos size2 = ptrToRawStream->TellL(MStreamBuf::EWrite);
	CleanupStack::PopAndDestroy(&bufWriteStream);

	// Return actual size of data serialized
	return (size2 - size1);
	}

/*------------------------------------------------------------------------------
  Description: Saves TRgb::alpha value information into a given buffer.
  ----------------------------------------------------------------------------*/
void CWsGc::ExternalizeAlphaValueL(RWriteStream& aWriteStream)
	{
	aWriteStream.WriteUint8L(iInternalStatus.iBrushColor.Alpha());
	aWriteStream.WriteUint8L(iInternalStatus.iPenColor.Alpha());
	}

/*------------------------------------------------------------------------------
  Description: Helper method to store clipping region data to a given
               write stream.
 -----------------------------------------------------------------------------*/
TInt CWsGc::ExternalizeClippingRegionL(RWriteStream& aWriteStream)
	{
	TBool clipRegion = (iUserDefinedClippingRegion != NULL);
	// Store flag to indicate if client has defined a clipping region
	aWriteStream.WriteInt8L(clipRegion);
	// Store client clipping region data if it exists
	if (clipRegion)
		{
		return ExternalizeRegionL(aWriteStream, *iUserDefinedClippingRegion) + sizeof(TInt8);
		}
	return sizeof(TInt8);
	}