windowing/windowserver/nga/CLIENT/RGC.CPP
changeset 0 5d03bc08d59c
child 18 57c618273d5c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/nga/CLIENT/RGC.CPP	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,2320 @@
+// 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:
+// Shells for window server graphics class
+// 
+//
+
+#include <e32std.h>
+#include <graphics/wsdrawresource.h>
+#include "../SERVER/w32cmd.h"
+#include "CLIENT.H"
+#include "w32comm.h"
+#include "graphicsresourcewrapper.h"
+#include <graphics/gdi/gdiconsts.h>
+#include <graphics/gdi/gdistructs.h>
+#include "graphics/windowserverconstants.h"
+
+#define KDefaultShadowColor KRgbGray
+enum {EPolygonMaxHeaderSize=sizeof(TWsCmdHeader)+sizeof(TWsGcCmdSegmentedDrawPolygonData)};
+
+//
+// class CWindowGc::CPimpl
+//
+
+NONSHARABLE_STRUCT(CWindowGc::CPimpl): public CBase, public MWsDrawResource
+/** @internalComponent @released */
+	{
+public:
+	enum TStateType
+	    {
+	    EStateBrushColor           = 1<<0,
+	    EStateBrushStyle           = 1<<1,
+	    EStatePenColor             = 1<<2,
+	    EStatePenStyle             = 1<<3,
+	    EStatePenSize              = 1<<4,           
+	    EStateDrawMode             = 1<<5,
+	    EStateClippingRect         = 1<<6,
+        EStateUnderlineStyle       = 1<<7,
+        EStateStrikethroughStyle   = 1<<8,
+        EStateWordJustification    = 1<<9,
+        EStateCharJustification    = 1<<10,
+	    };
+
+	CPimpl(CWindowGc& aGc);
+	void WriteAnyPendingStateChanges();
+	void ResetPendingState();
+	void StorePendingStateChange(TStateType aState, const TAny* aValue);
+	TUint32 GetState() const {return iPendingState;}
+	void CancelPendingClippingRect();
+	~CPimpl();
+public: //from MWsDrawResource
+	void DrawResource(const TPoint& aPos, const RWsDrawableSource& aSource, CWindowGc::TGraphicsRotation aRotation=CWindowGc::EGraphicsRotationNone)
+		{
+		iGc.DrawResource(aPos, aSource, aRotation);
+		}
+	void DrawResource(const TRect& aDestRect, const RWsDrawableSource& aSource, CWindowGc::TGraphicsRotation aRotation=CWindowGc::EGraphicsRotationNone)
+		{
+		iGc.DrawResource(aDestRect, aSource, aRotation);
+		}
+	void DrawResource(const TRect& aDestRect, const RWsDrawableSource& aSource, const TRect& aSrcRect, CWindowGc::TGraphicsRotation aRotation=CWindowGc::EGraphicsRotationNone)
+		{
+		iGc.DrawResource(aDestRect, aSource, aSrcRect, aRotation);
+		}
+	void DrawResource(const TRect& aDestRect, const RWsDrawableSource& aSource, const TDesC8& aParam)
+		{
+		iGc.DrawResource(aDestRect, aSource, aParam);
+		}
+public:
+	CWindowGc& iGc;
+	CFbsFont* iFont;
+	TRgb iShadowColor;
+    TBool iForceWrite;
+    TBool iClippingRectSet;
+        
+private:
+    TUint32 iPendingState;
+
+    // Pending state - used to store requested state changes not yet written to wserv
+    TRgb iPendingBrushColor;
+	TBrushStyle iPendingBrushStyle;
+    TRgb iPendingPenColor;
+    TPenStyle iPendingPenStyle;
+    TSize iPendingPenSize;
+    TDrawMode iPendingDrawMode;
+    TRect iPendingClippingRect;
+    TFontUnderline iPendingUnderlineStyle;
+    TFontStrikethrough iPendingStrikethroughStyle;
+    TWsGcCmdSetJustification iPendingWordJustification;
+    TWsGcCmdSetJustification iPendingCharJustification;
+
+    // Current state - values that have actually been written to wserv
+    TRgb iCurrentBrushColor;
+	TBrushStyle iCurrentBrushStyle;
+    TRgb iCurrentPenColor;
+    TPenStyle iCurrentPenStyle;
+    TSize iCurrentPenSize;
+    TDrawMode iCurrentDrawMode;
+    TFontUnderline iCurrentUnderlineStyle;
+    TFontStrikethrough iCurrentStrikethroughStyle;
+    TWsGcCmdSetJustification iCurrentWordJustification;
+    TWsGcCmdSetJustification iCurrentCharJustification;
+	};
+
+CWindowGc::CPimpl::CPimpl(CWindowGc& aGc)
+	: iGc(aGc), iFont(NULL), iShadowColor(KDefaultShadowColor)
+	{
+	ResetPendingState();
+	}
+
+CWindowGc::CPimpl::~CPimpl()
+	{
+	iFont = NULL;
+	}
+
+void CWindowGc::CPimpl::CancelPendingClippingRect()
+    {
+    iPendingState &= ~EStateClippingRect;
+    }
+
+void CWindowGc::CPimpl::WriteAnyPendingStateChanges()
+    {
+    if (iPendingState == 0)
+        return;
+    
+    if (iPendingState & EStateDrawMode)
+        {
+        if (iPendingDrawMode != iCurrentDrawMode)
+            {
+            iGc.WriteInt(iPendingDrawMode,EWsGcOpSetDrawMode);
+            iCurrentDrawMode = iPendingDrawMode;
+            }
+        }
+    
+    if (iPendingState & EStateBrushStyle)
+        {
+        if (iPendingBrushStyle != iCurrentBrushStyle)
+            {
+            iGc.WriteInt(iPendingBrushStyle,EWsGcOpSetBrushStyle);
+            iCurrentBrushStyle = iPendingBrushStyle;
+            }
+        }
+
+    if (iPendingState & EStateBrushColor)
+        {
+        // Brush colour optimisation more conservative (than for other state changes) because server-side code modifies it without client's knowledge
+        if (iPendingBrushColor != iCurrentBrushColor || iForceWrite)
+            {
+            iGc.WriteInt(iPendingBrushColor.Internal(),EWsGcOpSetBrushColor);
+            iCurrentBrushColor = iPendingBrushColor;
+            iForceWrite = EFalse;
+            }
+        }
+
+    if (iPendingState & EStatePenStyle)
+        {
+        if (iPendingPenStyle != iCurrentPenStyle)
+            {
+            iGc.WriteInt(iPendingPenStyle,EWsGcOpSetPenStyle);
+            iCurrentPenStyle = iPendingPenStyle;   
+            }
+        }
+        
+    if (iPendingState & EStatePenColor)
+        {
+        if (iPendingPenColor != iCurrentPenColor)
+            {
+            iGc.WriteInt(iPendingPenColor.Internal(),EWsGcOpSetPenColor);
+            iCurrentPenColor = iPendingPenColor;            
+            }
+        }
+    
+    if (iPendingState & EStateClippingRect)
+        {
+        iGc.WriteRect(iPendingClippingRect,EWsGcOpSetClippingRect);
+        iClippingRectSet = ETrue;
+        }
+
+    if (iPendingState & EStateUnderlineStyle)
+        {
+        if (iPendingUnderlineStyle != iCurrentUnderlineStyle)
+            {
+            iGc.WriteInt(iPendingUnderlineStyle,EWsGcOpSetUnderlineStyle);
+            iCurrentUnderlineStyle = iPendingUnderlineStyle;            
+            }
+        }
+    
+    if (iPendingState & EStateStrikethroughStyle)
+        {
+        if (iPendingStrikethroughStyle != iCurrentStrikethroughStyle)
+            {
+            iGc.WriteInt(iPendingStrikethroughStyle,EWsGcOpSetStrikethroughStyle);
+            iCurrentStrikethroughStyle = iPendingStrikethroughStyle;
+            }
+        }
+    
+    if (iPendingState & EStatePenSize)
+        {
+        if (iPendingPenSize != iCurrentPenSize)
+            {
+            iGc.WriteSize(iPendingPenSize,EWsGcOpSetPenSize);
+            iCurrentPenSize = iPendingPenSize;
+            }
+        }    
+
+    if (iPendingState & EStateWordJustification)
+        {
+        if (iPendingWordJustification.excessWidth != iCurrentWordJustification.excessWidth
+            || iPendingWordJustification.numGaps != iCurrentWordJustification.numGaps)
+            {
+            iGc.Write(&iPendingWordJustification,sizeof(iPendingWordJustification),EWsGcOpSetWordJustification);
+            iCurrentWordJustification = iPendingWordJustification;
+            }
+        }    
+
+    if (iPendingState & EStateCharJustification)
+        {
+        if (iPendingCharJustification.excessWidth != iCurrentCharJustification.excessWidth
+            || iPendingCharJustification.numGaps != iCurrentCharJustification.numGaps)
+            {
+            iGc.Write(&iPendingCharJustification,sizeof(iPendingCharJustification),EWsGcOpSetCharJustification);
+            iCurrentCharJustification = iPendingCharJustification;
+            }
+        }    
+    
+    iPendingState = 0;
+    }
+
+void CWindowGc::CPimpl::ResetPendingState()
+    {
+    // This function should only be called from CWindowGc::Reset()
+    iForceWrite = EFalse;
+    iPendingState = 0;
+
+    iClippingRectSet = EFalse;
+
+    // The following default values are the same as those used by CFbsBitGc::Reset()
+    iPendingBrushColor = KRgbWhite;
+    iPendingBrushStyle = CGraphicsContext::ENullBrush;
+    iPendingPenColor = KRgbBlack;
+    iPendingPenStyle = CGraphicsContext::ESolidPen;
+    iPendingPenSize = TSize(1,1);
+    iPendingDrawMode = CGraphicsContext::EDrawModePEN;
+    iPendingUnderlineStyle = EUnderlineOff;    
+    iPendingStrikethroughStyle = EStrikethroughOff;
+    iPendingWordJustification.excessWidth = 0;
+    iPendingWordJustification.numGaps = 0;
+    iPendingCharJustification.excessWidth = 0;
+    iPendingCharJustification.numGaps = 0;
+        
+    iCurrentBrushColor = iPendingBrushColor;
+    iCurrentBrushStyle = iPendingBrushStyle;
+    iCurrentPenColor = iPendingPenColor;
+    iCurrentPenStyle = iPendingPenStyle;
+    iCurrentPenSize = iPendingPenSize;    
+    iCurrentDrawMode = iPendingDrawMode;
+    iCurrentUnderlineStyle = iPendingUnderlineStyle;
+    iCurrentStrikethroughStyle = iPendingStrikethroughStyle;
+    iCurrentWordJustification.excessWidth = iPendingWordJustification.excessWidth;
+    iCurrentWordJustification.numGaps = iPendingWordJustification.numGaps;
+    iCurrentCharJustification.excessWidth = iPendingCharJustification.excessWidth;
+    iCurrentCharJustification.numGaps = iPendingCharJustification.numGaps;
+    }
+    
+void CWindowGc::CPimpl::StorePendingStateChange(TStateType aState, const TAny* aValue)
+    {
+    switch (aState)
+        {
+        case EStateBrushColor:
+            iPendingState |= EStateBrushColor;
+            iPendingBrushColor = *((TRgb*)(aValue));
+            break;
+        case EStateBrushStyle:
+            iPendingState|=EStateBrushStyle;
+            iPendingBrushStyle = *((TBrushStyle*)(aValue));
+            break;
+        case EStatePenColor:
+            iPendingState|=EStatePenColor;
+            iPendingPenColor = *((TRgb*)(aValue));
+            break;
+        case EStatePenStyle:
+            iPendingState|=EStatePenStyle;
+            iPendingPenStyle = *((TPenStyle*)(aValue));
+            break;
+        case EStateDrawMode:
+            iPendingState|=EStateDrawMode;
+            iPendingDrawMode = *((TDrawMode*)(aValue));
+            break;
+        case EStateClippingRect:
+            iPendingState|=EStateClippingRect;
+            iPendingClippingRect = *((TRect*)(aValue));
+            break;
+        case EStateUnderlineStyle:
+            iPendingState|=EStateUnderlineStyle;
+            iPendingUnderlineStyle = *((TFontUnderline*)(aValue));
+            break;
+        case EStateStrikethroughStyle:
+            iPendingState|=EStateStrikethroughStyle;
+            iPendingStrikethroughStyle= *((TFontStrikethrough*)(aValue));
+            break;
+        case EStatePenSize:
+            iPendingState|=EStatePenSize;
+            iPendingPenSize = *((TSize*)(aValue));
+            break;
+        case EStateWordJustification:
+            iPendingState|=EStateWordJustification;
+            iPendingWordJustification = *((TWsGcCmdSetJustification*)(aValue));
+            break;
+        case EStateCharJustification:
+            iPendingState|=EStateCharJustification;
+            iPendingCharJustification = *((TWsGcCmdSetJustification*)(aValue));
+            break;
+        default:
+            break;
+        }
+    }
+
+//
+// class CWindowGc
+//
+
+EXPORT_C CWindowGc::CWindowGc(CWsScreenDevice *aDevice) : MWsClientClass(aDevice->iBuffer), iPimpl(NULL), iDevice(aDevice)
+/** Constructor which creates, but does not initialise a graphics context. 
+
+@param aDevice Any screen device owned by the same session. Its life time 
+should be at least as long as the gc itself. 
+@see CWsScreenDevice::CreateContext() */
+	{}
+
+EXPORT_C CWindowGc::~CWindowGc()
+/** Destructor. */
+	{
+	if (iBuffer && iWsHandle)
+		Write(EWsGcOpFree);
+	delete iPimpl;
+	}
+
+void CWindowGc::WriteTextCommand(TAny *cmd, TInt len,const TDesC &aBuf,TInt opcode,TInt opcodePtr) const
+	{
+	if ((aBuf.Size()+len)>(TInt)(iBuffer->BufferSize()-sizeof(TWsCmdHeader)))
+		{
+		WriteReplyByProvidingRemoteReadAccess(cmd,len,&aBuf,opcodePtr);
+		}
+	else
+		{
+		Write(cmd,len,aBuf.Ptr(),aBuf.Size(),opcode);
+		}
+	}
+	
+void CWindowGc::WriteTextCommand(TAny *cmd, TInt len,const TDesC8 &aBuf,TInt opcode,TInt opcodePtr) const
+	{
+	if ((aBuf.Size()+len)>(TInt)(iBuffer->BufferSize()-sizeof(TWsCmdHeader)))
+		{
+		WriteReplyByProvidingRemoteReadAccess(cmd,len,&aBuf,opcodePtr);
+		}
+	else
+		{
+		Write(cmd,len,aBuf.Ptr(),aBuf.Size(),opcode);
+		}
+	}	
+	
+EXPORT_C TInt CWindowGc::Construct()
+/** Completes construction. 
+
+@return KErrNone if successful, otherwise a leave error. 
+@panic TW32Panic 17 in debug builds if called on an already constructed object.
+This function always causes a flush of the window server buffer. */
+	{
+	__ASSERT_DEBUG(iWsHandle == KNullHandle, Panic(EW32PanicGraphicDoubleConstruction));
+	iPimpl = new CPimpl(*this);
+	if (!iPimpl)
+		return KErrNoMemory;
+	TInt ret;
+	if ((ret=iBuffer->WriteReplyWs(EWsClOpCreateGc))<0)
+		return(ret);
+	iWsHandle=ret;
+	return(KErrNone);
+	}
+
+EXPORT_C void CWindowGc::Activate(RDrawableWindow &aDevice)
+/** Activates the context for a given window and updates iDevice with the pointer to the screen device of the screen on which aDevice is found.  
+
+When drawing is complete, the code using the context should call Deactivate(). 
+Draw methods invoked after an Activate() will affect the window specified. 
+A graphics context can only be active for one window at a time. A panic occurs 
+if a draw function is called before calling this function, or if Activate() 
+is called twice without an intervening Deactivate().
+
+@param aWindow The window for which the graphics context is to be activated. */
+	{
+	TUint devicePointer = WriteReplyInt(aDevice.WsHandle(),EWsGcOpActivate);
+	iDevice = (CWsScreenDevice*)devicePointer;
+	iPimpl->iForceWrite = ETrue; // needed because brush colour set to window background colour in CWsGc::Activate
+	}
+
+EXPORT_C void CWindowGc::Deactivate()
+/** Frees the graphics context to be used with another window. 
+
+This method should be called when the application has completed drawing to 
+the window. */
+	{
+	iPimpl->ResetPendingState(); // needed because server-side state is reset on deactivation
+	Write(EWsGcOpDeactivate);
+	iPimpl->iFont=NULL;
+	iPimpl->iShadowColor = KDefaultShadowColor;
+	}
+
+//====================Functions from GDI.H===============================
+
+EXPORT_C CGraphicsDevice* CWindowGc::Device() const
+/** Returns a pointer to the device, more specifically a CWsScreenDevice, for the screen that the WindowGc was last activated on.
+If the WindowGc has not been activated at all, it then returns the device that was passed to its constructor.
+
+The user should be careful when calling this function since it can return the screen device of any screen in the system.
+Hence, the return value of this function will be useful only if the user is aware of how the WindowGc was used before this function is called.
+@return A pointer to the device for the screen that the WindowGc was last activated on or the device passed at construction*/
+	{
+	return(iDevice);
+	}
+
+EXPORT_C void CWindowGc::SetOrigin(const TPoint &aPoint)
+/** Sets the position of the co-ordinate origin. 
+
+All subsequent drawing operations are then done relative to this origin. The 
+default origin is (0,0), the top left corner of the window.
+
+@param aPoint A point for the origin, default (0,0). 
+@see CGraphicsContext::SetOrigin() */
+	{
+	if ( iPimpl->GetState() & CPimpl::EStateClippingRect )
+	    {
+	    iPimpl->WriteAnyPendingStateChanges();
+	    }
+	WritePoint(aPoint,EWsGcOpSetOrigin);
+	}
+
+EXPORT_C void CWindowGc::SetClippingRect(const TRect& aRect)
+/** Sets a clipping rectangle.
+
+Graphics drawn to the window are clipped, so that only items which fall within 
+the rectangle are displayed. 
+
+Note that clipping is additive. If a clipping region has been set using SetClippingRegion() 
+then clipping will be to the intersection of that region and this rectangle.
+
+@param aRect The clipping rectangle in window co-ordinates. Note that this rectangle is 
+tranformed by the current drawing co-ordinate origin before it is used. 
+The co-ordinate origin is set using SetOrigin().
+ 
+@see SetClippingRegion() */
+	{
+    TRect rect(aRect);
+    iPimpl->StorePendingStateChange(CPimpl::EStateClippingRect, &rect);
+	}
+
+EXPORT_C void CWindowGc::CancelClippingRect()
+/** Cancels the clipping rectangle. 
+
+@see SetClippingRect() */
+	{
+	if (iPimpl->GetState() & CPimpl::EStateClippingRect)
+	    {
+	    iPimpl->CancelPendingClippingRect();
+	    }
+	
+	if (iPimpl->iClippingRectSet)
+	    {
+        Write(EWsGcOpCancelClippingRect);
+	    }
+
+	iPimpl->iClippingRectSet = EFalse;
+	}
+
+EXPORT_C TInt CWindowGc::SetClippingRegion(const TRegion &aRegion)
+/** Sets the clipping region.
+
+Drawing is always clipped to the visible area of a window. The region specified 
+by this function is in addition to that area.
+
+This function always causes a flush of the window server buffer.
+
+@param aRegion The new clipping region in window co-ordinates 
+as used in SetClippingRect(). The clipping region is transformed by the current 
+drawing origin before use.
+
+@return KErrNone if successful, KErrNoMemory if there is insufficient memory 
+to create the region on the server side, otherwise another error code. 
+
+@see SetClippingRect() */
+	{
+	const TInt regionCount=aRegion.Count();
+	TPtrC8 ptrRect(reinterpret_cast<const TUint8*>(aRegion.RectangleList()),regionCount*sizeof(TRect));
+	return(WriteReplyByProvidingRemoteReadAccess(&regionCount,sizeof(regionCount),&ptrRect,EWsGcOpSetClippingRegion));
+	}
+
+EXPORT_C void CWindowGc::CancelClippingRegion()
+/** Cancels the current clipping region. */
+	{
+	Write(EWsGcOpCancelClippingRegion);
+	}
+
+EXPORT_C void CWindowGc::SetDrawMode(TDrawMode aDrawingMode)
+/** Sets the drawing mode. 
+
+This affects the colour that is actually drawn, because it defines the way 
+that the current screen colour logically combines with the current pen colour 
+and brush colour. 
+
+There are 13 drawing modes (see CGraphicsContext::TDrawMode enum), each giving 
+different logical combinations of pen, brush and screen colours. Each mode 
+is produced by ORing together different combinations of seven drawing mode 
+components (see CGraphicsContext::TDrawModeComponents enum).
+
+The three most important modes are TDrawMode::EDrawModePEN, TDrawMode::EDrawModeNOTSCREEN 
+and TDrawMode::EDrawModeXOR. The default drawing mode is TDrawMode::EDrawModePEN.
+
+The drawing mode is over-ridden for line and shape drawing functions when 
+a wide pen line has been selected. It is forced to TDrawMode::EDrawModePEN. 
+This is to prevent undesired effects at line joins (vertexes).
+
+Notes:
+
+TDrawMode::EDrawModeAND gives a "colour filter" effect. For example:
+
+ANDing with white gives the original colour 
+
+ANDing with black gives black 
+
+TDrawMode::EDrawModeOR gives a "colour boost" effect. For example:
+
+ORing with black gives the original colour 
+
+ORing with white gives white 
+
+TDrawMode::EDrawModeXOR gives an "Exclusive OR" effect. For example:
+
+white XOR black gives white 
+
+white XOR white gives black 
+
+black XOR black gives black
+
+@param aDrawingMode A drawing mode. 
+@see CGraphicsContext::SetDrawMode() */
+	{
+    iPimpl->StorePendingStateChange(CPimpl::EStateDrawMode, &aDrawingMode);
+	}
+
+EXPORT_C void CWindowGc::UseFont(const CFont *aFont)
+/** Sets this context's font.
+
+The font is used for text drawing. If the font is already in the font and 
+bitmap server's memory the GDI will share that copy.
+
+Note that this function must be called prior to drawing text or the calling 
+thread will panic.
+
+@param aFont A device font. 
+@see CGraphicsContext::UseFont() */
+	{
+	if (iPimpl->iFont!=(CFbsFont *)aFont)
+		{
+		iPimpl->iFont=(CFbsFont *)aFont;
+		WriteInt(iPimpl->iFont->Handle(),EWsGcOpUseFont);
+		}
+	}
+
+EXPORT_C void CWindowGc::DiscardFont()
+/** Discards a font. 
+
+This frees up the memory used (if the font is not being shared with some other 
+process).
+
+Note that if no font is in use when this function is called, then there is no effect.
+
+@see CGraphicsContext::DiscardFont() */
+	{
+	Write(EWsGcOpDiscardFont);
+	iPimpl->iFont=NULL;
+	}
+
+EXPORT_C void CWindowGc::SetUnderlineStyle(TFontUnderline aUnderlineStyle)
+/** Sets the underline style for all subsequently drawn text.
+
+@param aUnderlineStyle The underline style: either on or off.
+@see CGraphicsContext::SetUnderlineStyle() */
+	{
+    iPimpl->StorePendingStateChange(CPimpl::EStateUnderlineStyle, &aUnderlineStyle);	
+	}
+
+EXPORT_C void CWindowGc::SetStrikethroughStyle(TFontStrikethrough aStrikethroughStyle)
+/** Sets the strikethrough style for all subsequently drawn text.
+
+@param aStrikethroughStyle The strikethrough style: either on or off. 
+@see CGraphicsContext::SetStrikethroughStyle() */
+	{
+	iPimpl->StorePendingStateChange(CPimpl::EStateStrikethroughStyle, &aStrikethroughStyle);
+	}
+
+void CWindowGc::SetJustification(TInt aExcessWidth,TInt aNumGaps, TInt aOpcode)
+	{
+	TWsGcCmdSetJustification justification;
+
+	justification.excessWidth=aExcessWidth;
+	justification.numGaps=aNumGaps;
+
+	if (aOpcode == EWsGcOpSetWordJustification)
+	    {
+        iPimpl->StorePendingStateChange(CPimpl::EStateWordJustification, &justification);
+	    }
+	else if (aOpcode == EWsGcOpSetCharJustification)
+	    {
+        iPimpl->StorePendingStateChange(CPimpl::EStateCharJustification, &justification);
+	    }
+	}
+
+EXPORT_C void CWindowGc::SetWordJustification(TInt aExcessWidth,TInt aNumGaps)
+/** Sets word justification.
+
+This function is particularly useful for doing WYSIWYG underlining or strikethrough, 
+as it ensures that the lines extend correctly into the gaps between words. It is not 
+intended for regular use by developers.
+
+@param aExcessWidth The excess width (in pixels) to be distributed between 
+the specified number of gaps (starting immediately) 
+@param aNumGaps The number of gaps between words 
+@see CGraphicsContext::SetWordJustification() */
+	{
+	SetJustification(aExcessWidth, aNumGaps, EWsGcOpSetWordJustification);
+	}
+
+EXPORT_C void CWindowGc::SetCharJustification(TInt aExcessWidth,TInt aNumChars)
+/** Sets the character justification.
+
+This function is used primarily to get accurate WYSIWYG, and is not intended 
+for regular use by developers.
+
+The text line that is to be justified has a certain number of characters (this 
+includes the spaces between the words). It also has a distance (in pixels) 
+between the end of the last word and the actual end of the line (right hand 
+margin, usually). These excess width pixels are distributed amongst all the 
+characters, increasing the gaps between them, to achieve full justification 
+of the text line.
+
+This function is particularly useful for WYSIWYG underlining or strikethrough, 
+as it ensures that the lines extend into the gaps between characters.
+
+See CGraphicsContext::SetCharJustification() for more information.
+
+@param aExcessWidth The excess width (in pixels) to be distributed between 
+the specified number of characters. 
+@param aNumChars The number of characters involved 
+@see CGraphicsContext::SetCharJustification() */
+	{
+	SetJustification(aExcessWidth, aNumChars, EWsGcOpSetCharJustification);
+	}
+
+EXPORT_C void CWindowGc::SetPenColor(const TRgb &aColor)
+/** Sets the pen colour.
+
+The effective pen colour depends on the drawing mode (see SetDrawMode()).
+
+The default pen colour is black.
+
+@param aColor The RGB colour for the pen. 
+@see CGraphicsContext::SetPenColor() */
+	{
+	TRgb color = aColor;
+    iPimpl->StorePendingStateChange(CPimpl::EStatePenColor, &color);
+	}
+
+EXPORT_C void CWindowGc::SetPenStyle(TPenStyle aPenStyle)
+/** Sets the line drawing style for the pen. 
+
+The pen is used when drawing lines and for the outline of filled shapes. There 
+are 6 pen styles (see CGraphicsContext::TPenStyle enum). If no pen style is 
+set, the default is TPenStyle::ESolidPen.
+
+To use a pen style, its full context must be given, e.g. for a null pen: CGraphicsContext::TPenStyle::ENullPen.
+
+@param aPenStyle A pen style. 
+@see CGraphicsContext::SetPenStyle() */
+	{
+	iPimpl->StorePendingStateChange(CPimpl::EStatePenStyle, &aPenStyle);
+	}
+
+EXPORT_C void CWindowGc::SetPenSize(const TSize& aSize)
+/** Sets the line drawing size for the pen.
+
+Lines of size greater than one pixel are drawn with rounded ends that extend 
+beyond the end points, (as if the line is drawn using a circular pen tip of 
+the specified size). Rounded ends of lines drawn with a wide pen are always 
+drawn in TDrawMode::EDrawModePEN mode, overriding whatever mode has been set 
+using SetDrawMode().
+
+@param aSize A line size, the default being 1 pixel. 
+@see CGraphicsContext::SetPenSize() */
+	{
+	TSize size(aSize);
+	iPimpl->StorePendingStateChange(CPimpl::EStatePenSize, &size);
+	}
+
+EXPORT_C void CWindowGc::SetBrushColor(const TRgb &aColor)
+/** Sets the brush colour. 
+
+The effective brush colour depends on the drawing mode (see SetDrawMode()). 
+If no brush colour has been set, it defaults to white. However the default 
+brush style is null, so when drawing to a window, the default appears to be 
+the window's background colour.
+
+@param aColor The RGB colour for the brush. 
+@see CGraphicsContext::SetBrushColor() */
+	{
+	TRgb color = aColor;
+    iPimpl->StorePendingStateChange(CPimpl::EStateBrushColor, &color);
+	}
+
+EXPORT_C void CWindowGc::SetBrushStyle(TBrushStyle aBrushStyle)
+/** Sets the line drawing style for the brush.
+
+The GDI provides ten brush styles, including six built-in hatching patterns 
+(see CGraphicsContext::TBrushStyle).
+
+Use TBrushStyle::ENullBrush to draw the outline of a fillable shape on its 
+own, without filling.
+
+If the TBrushStyle::EPatternedBrush style is set, but no bitmap pattern has 
+been selected using UseBrushPattern(), then the brush defaults to TBrushStyle::ENullBrush.
+
+Hatching lines are done in the current brush colour, set using SetBrushColor(). 
+Hatching can be overlaid on other graphics. The hatching pattern starts at 
+the brush origin, set using SetBrushOrigin().
+
+@param aBrushStyle The brush style. 
+@see CGraphicsContext::SetBrushStyle() */
+	{
+	iPimpl->StorePendingStateChange(CPimpl::EStateBrushStyle, &aBrushStyle);
+	}
+EXPORT_C void CWindowGc::SetBrushOrigin(const TPoint &aOrigin)
+/** Sets the brush pattern origin. 
+
+This specifies the position of the pixel in the top left corner of a reference 
+pattern tile, (in absolute device co-ordinates). Other copies of the pattern 
+tile are then drawn around the reference one. Thus the brush origin can be 
+set as the top left corner of a shape.
+
+The brush pattern may be a built-in style (see SetBrushStyle()), or a bitmap. 
+To use a bitmap, the brush must have a pattern set (see UseBrushPattern()) 
+and the brush style must be set to TBrushStyle::EPatternedBrush.
+
+Notes:
+
+If SetBrushOrigin() is not used, then the origin defaults to (0,0).
+
+This brush origin remains in effect for all fillable shapes drawn subsequently, 
+until a new brush origin is set. Shapes can thus be considered as windows 
+onto a continuous pattern field (covering the whole clipping region of a screen 
+device, or the whole device area of a printer).
+
+@param aOrigin The origin point for the brush. 
+@see CGraphicsContext::SetBrushOrigin() */
+	{
+	WritePoint(aOrigin,EWsGcOpSetBrushOrigin);
+	}
+
+EXPORT_C void CWindowGc::UseBrushPattern(const CFbsBitmap *aDevice)
+/** Sets the brush pattern to the specified bitmap. 
+
+For the brush to actually use the bitmap, TBrushStyle::EPatternedBrush must 
+be used to set the brush style (see SetBrushStyle()). When the brush pattern 
+is no longer required, use DiscardBrushPattern() to free up the memory used, 
+(if the bitmap is not being shared). If UseBrushPattern() is used again without 
+using DiscardBrushPattern() then the previous pattern is discarded automatically.
+
+Notes:
+
+When loading a bitmap, the GDI checks to see if the bitmap is already in memory. 
+If the bitmap is already there, then that copy is shared.
+
+The brush does not need to have a pattern set at all. There are several built-in 
+hatching patterns, which can be selected using SetBrushStyle().
+
+@param aDevice A bitmap pattern for the brush 
+@see CGraphicsContext::UseBrushPattern() */
+	{
+	WriteInt(aDevice->Handle(),EWsGcOpUseBrushPattern);
+	AddToBitmapArray(aDevice->Handle());
+	}
+
+EXPORT_C void CWindowGc::DiscardBrushPattern()
+/** Discards a non-built-in brush pattern. 
+
+This frees up the memory used for the bitmap, if it is not being shared by 
+another process.
+
+If no brush pattern has been set when this function is called, it has no effect.
+
+@see CGraphicsContext::DiscardBrushPattern() */
+	{
+	Write(EWsGcOpDiscardBrushPattern);
+	}
+
+EXPORT_C void CWindowGc::Plot(const TPoint &aPoint)
+/** Draws a single point. 
+
+The point is drawn with the current pen settings using the current drawing 
+mode.
+
+Note: if the pen size is greater than one pixel, a filled circle of the current 
+pen colour is drawn, with the pen size as the diameter and the plotted point 
+as the centre. If the pen size is an even number of pixels, the extra pixels 
+are drawn below and to the right of the centre. See SetPenSize().
+
+@param aPoint The point to be drawn. 
+@see CGraphicsContext::Plot() */
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	WritePoint(aPoint,EWsGcOpPlot);
+	}
+
+EXPORT_C void CWindowGc::DrawLine(const TPoint &aPoint1,const TPoint &aPoint2)
+/** Draws a straight line between two points.
+
+@param aPoint1 The point at the start of the line. 
+@param aPoint2 The point at the end of the line. 
+@see CGraphicsContext::DrawLine() */
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdDrawLine drawLine(aPoint1,aPoint2);
+	Write(&drawLine,sizeof(drawLine),EWsGcOpDrawLine);
+	}
+
+EXPORT_C void CWindowGc::MoveTo(const TPoint &aPoint)
+/** Moves the internal drawing position relative to the co-ordinate origin, without 
+drawing a line.
+
+A subsequent call to DrawLineTo() or DrawLineBy() will then use the new internal 
+drawing position as the start point for the line drawn.
+
+Notes:
+
+The operations DrawLine(), DrawLineTo(), DrawLineBy() and DrawPolyline() also 
+change the internal drawing position to the last point of the drawn line(s).
+
+The internal drawing position is set to the co-ordinate origin if no drawing 
+or moving operations have yet taken place.
+
+@param aPoint The point to move the internal drawing position to. 
+@see CGraphicsContext::MoveTo()
+@see CGraphicsContext::MoveBy() */
+	{
+	WritePoint(aPoint,EWsGcOpMoveTo);
+	}
+
+EXPORT_C void CWindowGc::MoveBy(const TPoint &aPoint)
+/** Moves the internal drawing position by a vector, without drawing a line.
+
+The internal drawing position is moved relative to its current co-ordinates.
+
+@param aPoint The vector to move the internal drawing position by. 
+@see CGraphicsContext::MoveBy()
+@see CGraphicsContext::MoveTo() */
+	{
+	WritePoint(aPoint,EWsGcOpMoveBy);
+	}
+
+EXPORT_C void CWindowGc::DrawLineTo(const TPoint &aPoint)
+/** Draws a straight line from the current internal drawing position to a point.
+
+@param aPoint The point at the end of the line. 
+@see CGraphicsContext::DrawLineTo() */
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	WritePoint(aPoint,EWsGcOpDrawTo);
+	}
+
+EXPORT_C void CWindowGc::DrawLineBy(const TPoint &aPoint)
+/** Draws a straight line relative to the current internal drawing position, using 
+a vector.
+
+The start point of the line is the current internal drawing position. The 
+vector aVector is added to the internal drawing position to give the end point 
+of the line
+
+@param aPoint The vector to add to the current internal drawing position, 
+giving the end point of the line. 
+@see CGraphicsContext::DrawLineBy() */
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	WritePoint(aPoint,EWsGcOpDrawBy);
+	}
+
+void CWindowGc::doDrawPolyLine(const CArrayFix<TPoint> *aPointArray, const TPoint* aPointList,TInt aNumPoints)
+	{
+	TWsGcOpcodes opcode=EWsGcOpDrawPolyLine;
+	TWsGcCmdDrawPolyLine polyLine;
+	TInt maxBufLen=(iBuffer->BufferSize()-sizeof(TWsCmdHeader)-sizeof(polyLine))/sizeof(TPoint);
+	TInt sent=0;
+	while(sent<aNumPoints)
+		{
+		TInt availableLen;
+		const TPoint *ptr;
+		if (aPointArray)
+			{
+			ptr=&(*aPointArray)[sent];
+			availableLen=aPointArray->End(sent)-ptr;
+			}
+		else
+			{
+			ptr=aPointList+sent;
+			availableLen=aNumPoints-sent;
+			}
+		polyLine.numPoints=Min(availableLen,maxBufLen);
+		sent+=polyLine.numPoints;
+		polyLine.more=(sent!=aNumPoints);
+		Write(&polyLine,sizeof(polyLine),ptr,polyLine.numPoints*sizeof(TPoint),opcode);
+		polyLine.last=ptr[polyLine.numPoints-1];
+		opcode=EWsGcOpDrawPolyLineContinued;
+		} 
+	}
+
+EXPORT_C void CWindowGc::DrawPolyLine(const TPoint* aPointList,TInt aNumPoints)
+/** Draws a polyline using points in a list. 
+
+A polyline is a series of concatenated straight lines joining a set of points.
+
+@param aPointList Pointer to a list of points on the polyline. 
+@param aNumPoints The number of points in the point list. 
+@see CGraphicsContext::DrawPolyLine() */
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	doDrawPolyLine(NULL,aPointList,aNumPoints);
+	}
+
+EXPORT_C void CWindowGc::DrawPolyLine(const CArrayFix<TPoint> *aPointArray)
+/** Draws a polyline using points in an array. 
+
+A polyline is a series of concatenated straight lines joining a set of points.
+
+@param aPointArray An array containing the points on the polyline. 
+@see CGraphicsContext::DrawPolyLine() */
+	{
+   	iPimpl->WriteAnyPendingStateChanges();
+	doDrawPolyLine(aPointArray,NULL,aPointArray->Count());
+	}
+
+TInt CWindowGc::doDrawPolygon(const CArrayFix<TPoint> *aPointArray,const TPoint* aPointList,TInt aNumPoints,TFillRule aFillRule)
+	{
+	if (aNumPoints<=0)
+		return(KErrNone);
+	TWsGcCmdSegmentedDrawPolygonData polyData;
+	polyData.index=0;
+	TInt maxBufLen=(iBuffer->BufferSize()-EPolygonMaxHeaderSize)/sizeof(TPoint);
+	FOREVER
+		{
+		const TPoint *ptr;
+		TInt availableLen;
+		if (aPointArray)
+			{
+			ptr=&(*aPointArray)[polyData.index];
+			availableLen=aPointArray->End(polyData.index)-ptr;
+			}
+		else
+			{
+			ptr=aPointList+polyData.index;
+			availableLen=aNumPoints-polyData.index;
+			}
+		polyData.numPoints=Min(availableLen,maxBufLen);
+		if (polyData.index==0)	// First time around
+			{
+			if (polyData.numPoints==aNumPoints)	// Can it be done in one go?
+				{
+				TWsGcCmdDrawPolygon drawPolygon;
+				drawPolygon.numPoints=aNumPoints;
+				drawPolygon.fillRule=aFillRule;
+				Write(&drawPolygon,sizeof(drawPolygon),ptr,aNumPoints*sizeof(TPoint),EWsGcOpDrawPolygon);
+				break;
+				}
+			TWsGcCmdStartSegmentedDrawPolygon start;
+			start.totalNumPoints=aNumPoints;
+			TInt err=WriteReply(&start,sizeof(start),EWsGcOpStartSegmentedDrawPolygon);
+			if (err!=KErrNone)
+				return(err);
+			}
+		Write(&polyData,sizeof(polyData),ptr,polyData.numPoints*sizeof(TPoint),EWsGcOpSegmentedDrawPolygonData);
+		polyData.index+=polyData.numPoints;
+		if (polyData.index==aNumPoints)
+			{
+			TWsGcCmdDrawSegmentedPolygon draw;
+			draw.fillRule=aFillRule;
+			Write(&draw,sizeof(draw),EWsGcOpDrawSegmentedPolygon);
+			break;
+			}
+		}
+	return(KErrNone);
+	}
+
+EXPORT_C TInt CWindowGc::DrawPolygon(const TPoint* aPointList,TInt aNumPoints,TFillRule aFillRule)
+/** Draws and fills a polygon using points defined in a list.
+
+The first TPoint in the list defines the start of the first side of the polygon. 
+The second TPoint defines the second vertex (the end point of the first side 
+and the start point of the second side) and so on. The final side of the polygon 
+is drawn using the last TPoint from the array or list, and the line drawn 
+to the start point of the first side.
+
+Self-crossing polygons can be filled according to one of two rules, TFillRule::EAlternate 
+(the default), or TFillRule::EWinding. To explain the difference between these 
+rules, the concept of a winding number needs to be introduced. The area outside 
+any of the loops of the polygon has a winding number of zero, and is never 
+filled. An inside a loop which is bounded by an area with winding number 0 
+has a winding number of 1. If an area is within a loop that is bounded by 
+an area with winding number 1, e.g. a loop within a loop, has a winding number 
+of 2, and so on.
+
+The filling of a polygon proceeds according to this algorithm:
+
+If aFillRule is TFillRule::EAlternate (default) and it has an odd winding 
+number, then fill the surrounding area.
+
+If aFillRule is TFillRule::EWinding and it has a winding number greater than 
+zero, then fill the surrounding area.
+
+This function always causes a flush of the window server buffer.
+
+@param aPointList Pointer to a list of points, specifying the vertices of 
+the polygon. 
+@param aNumPoints The number of points in the vertex list 
+@param aFillRule Either TFillRule::EAlternate (the default) or TFillRule::EWinding. 
+@return KErrNone if successful, otherwise another of the system-wide error 
+codes. 
+@see CGraphicsContext::DrawPolygon() */
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	return(doDrawPolygon(NULL,aPointList,aNumPoints,aFillRule));
+	}
+
+EXPORT_C TInt CWindowGc::DrawPolygon(const CArrayFix<TPoint> *aPointArray,TFillRule aFillRule)
+/** Draws and fills a polygon using points defined in an array.
+
+The first TPoint in the array defines the start of the first side of the polygon. 
+The second TPoint defines the second vertex (the end point of the first side 
+and the start point of the second side) and so on. The final side of the polygon 
+is drawn using the last TPoint from the array or list, and the line drawn 
+to the start point of the first side.
+
+Self-crossing polygons can be filled according to one of two rules, TFillRule::EAlternate 
+(the default), or TFillRule::EWinding. To explain the difference between these 
+rules, the concept of a winding number needs to be introduced. The area outside 
+any of the loops of the polygon has a winding number of zero, and is never 
+filled. An inside a loop which is bounded by an area with winding number 0 
+has a winding number of 1. If an area is within a loop that is bounded by 
+an area with winding number 1, e.g. a loop within a loop, has a winding number 
+of 2, and so on.
+
+The filling of a polygon proceeds according to this algorithm:
+
+If aFillRule is TFillRule::EAlternate (default) and it has an odd winding 
+number, then fill the surrounding area.
+
+If aFillRule is TFillRule::EWinding and it has a winding number greater than 
+zero, then fill the surrounding area.
+
+This function always causes a flush of the window server buffer.
+
+@param aPointArray An array of points, specifying the vertices of the polygon. 
+@param aFillRule Either TFillRule::EAlternate (the default) or TFillRule::EWinding. 
+@return KErrNone if successful, otherwise another of the system-wide error 
+codes. 
+@see CGraphicsContext::DrawPolygon() */
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	return(doDrawPolygon(aPointArray,NULL,aPointArray->Count(),aFillRule));
+	}
+
+void CWindowGc::DrawArcOrPie(const TRect &aRect,const TPoint &aStart,const TPoint &aEnd, TInt aOpcode)
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdDrawArcOrPie cmd(aRect,aStart,aEnd);
+	Write(&cmd,sizeof(cmd),aOpcode);
+	}
+
+EXPORT_C void CWindowGc::DrawArc(const TRect &aRect,const TPoint &aStart,const TPoint &aEnd)
+/** Draws an arc (a portion of an ellipse).
+
+The point aStart is used to define one end of a line from the geometric centre 
+of the ellipse. The point of intersection between this line and the ellipse 
+defines the start point of the arc. The point aEnd is used to define one end 
+of a second line from the geometric centre of the ellipse. The point of intersection 
+between this line and the ellipse defines the end point of the arc. The pixels 
+at both the start point and the end point are drawn.
+
+The arc itself is the segment of the ellipse in an anti-clockwise direction 
+from the start point to the end point.
+
+Notes
+
+A rectangle is used in the construction of the ellipse of which the arc is 
+a segment. This rectangle is passed as an argument of type TRect.
+
+A wide line arc is drawn with the pixels distributed either side of a true 
+ellipse, in such a way that the outer edge of the line would touch the edge 
+of the construction rectangle. In other words, the ellipse used to construct 
+it is slightly smaller than that for a single pixel line size.
+
+If aStart or aEnd are the ellipse centre then the line that defines the start/end 
+of the arc defaults to one extending vertically above the centre point.
+
+If aStart and aEnd are the same point, or points on the same line through 
+the ellipse centre then a complete unfilled ellipse is drawn.
+
+Line drawing is subject to pen colour, width and style and draw mode
+
+@param aRect The rectangle in which to draw the ellipse (of which the arc is 
+a segment).
+@param aStart A point to define the start of the arc.
+@param aEnd A point to define the end of the arc.
+@see CGraphicsContext::DrawArc() */
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	DrawArcOrPie(aRect,aStart,aEnd,EWsGcOpDrawArc);
+	}
+
+EXPORT_C void CWindowGc::DrawPie(const TRect &aRect,const TPoint &aStart,const TPoint &aEnd)
+/** Draws and fills a pie-shaped slice of an ellipse.
+
+Outlines are subject to the current pen colour, width, style and draw mode. 
+Set the pen to ENullPen for no outline. The fill is subject to brush style 
+(colour, hash or pattern), the origin and the current drawing mode. Set the 
+brush to ENullBrush for no fill.
+
+The point aStart is used to define one end of a line to the centre of the 
+ellipse. The point of intersection between this line and the ellipse defines 
+the start point of the arc bounding the pie slice. The point aEnd is used 
+to define one end of a second line to the centre of the ellipse. The point 
+of intersection between this line and the ellipse defines the end point of 
+the arc bounding the pie slice. The pixels at the end point are not drawn.
+
+The pie slice itself is the area bounded by: the arc of the ellipse in an 
+anticlockwise direction from the start point to the end point; the straight 
+line from the start point from the geometric centre of the ellipse; the 
+straight line from the end point from the geometric centre of the ellipse.
+
+The line drawn by the pen goes inside the rectangle given by the aRect argument.
+
+Notes:
+
+A rectangle is used in the construction of the pie slice. This rectangle is 
+passed as an argument of type TRect. The curved edge of the pie slice is an 
+arc of an ellipse constructed within the rectangle.
+
+A wide line edged pie slice has the arc drawn with the pixels distributed 
+either side of a true ellipse. This is done in such a way that the outer edge 
+of the line would touch the edge of the construction rectangle. In other words, 
+the ellipse used to construct it is slightly smaller than that for a single 
+pixel line size.
+
+If aStart or aEnd are the ellipse centre then the line that defines the start/end 
+of the arc defaults to one extending vertically above the centre point.
+
+If aStart and aEnd are the same point, or points on the same line through 
+the ellipse centre then a complete filled ellipse is drawn. A line is also 
+drawn from the edge to the ellipse centre.
+
+@param aRect A rectangle in which to draw the ellipse bounding the pie slice 
+@param aStart A point to define the start of the pie slice 
+@param aEnd A point to define the end of the pie slice 
+@see CGraphicsContext::DrawPie() */
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	DrawArcOrPie(aRect,aStart,aEnd,EWsGcOpDrawPie);
+	}
+
+EXPORT_C void CWindowGc::DrawEllipse(const TRect &aRect)
+/** Draws and fills an ellipse.
+
+The ellipse is drawn inside the rectangle defined by the aRect argument. Any 
+TRect that has odd pixel dimensions, has the bottom right corner trimmed to 
+give even pixel dimensions before the ellipse is constructed.
+
+The column and row of pixels containing the bottom right co-ordinate of the 
+aRect argument are not part of the rectangle.
+
+Note: a wide outline ellipse is drawn with the pixels distributed either side of 
+a true ellipse, in such a way that the outer edge of the line touches the 
+edge of the construction rectangle. In other words, the ellipse used to construct 
+it is smaller than that for a single pixel line size.
+
+@param aRect The rectangle in which to draw the ellipse 
+@see CGraphicsContext::DrawEllipse() */
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	WriteRect(aRect,EWsGcOpDrawEllipse);
+	}
+
+EXPORT_C void CWindowGc::DrawRect(const TRect &aRect)
+/** Draws and fills a rectangle. 
+
+The rectangle's border is drawn with the pen, and it is filled using the brush.
+
+@param aRect The rectangle to be drawn. 
+@see CGraphicsContext::DrawRect() */
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	WriteRect(aRect,EWsGcOpDrawRect);
+	}
+
+EXPORT_C void CWindowGc::DrawRoundRect(const TRect &aRect,const TSize &aEllipse)
+/** Draws and fills a rectangle with rounded corners.
+
+The rounded corners are each constructed as an arc of an ellipse. The dimensions 
+of each corner (corner size and corner height) are given by aEllipse. See 
+DrawArc() for a description of arc construction.
+
+The line drawn by the pen (if any) goes inside the rectangle given by the 
+TRect argument.
+
+Notes:
+
+Dotted and dashed pen styles cannot be used for the outline of a rounded rectangle.
+
+If either corner size dimension is greater than half the corresponding rectangle 
+length, the corner size dimension is reduced to half the rectangle size.
+
+@param aRect The rectangle to be drawn. 
+@param aEllipse The dimensions of each corner. 
+@see CGraphicsContext::DrawRoundRect() */
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdDrawRoundRect drawRoundRect(aRect,aEllipse);
+	Write(&drawRoundRect,sizeof(drawRoundRect),EWsGcOpDrawRoundRect);
+	}
+
+EXPORT_C void CWindowGc::DrawBitmap(const TPoint &aTopLeft, const CFbsBitmap *aDevice)
+/** Draws a bitmap at a specified point. 
+
+The function does a compress/stretch based on its internally stored size in 
+twips. Note that if the twips value of the bitmap is not set then nothing 
+is drawn (this is the default situation).
+
+Windows that store their redraw commands will only store drawing position and a handle to bitmaps 
+that are drawn in it. The bitmap handle is just a pointer to the bitmap in the FBSERV heap. 
+At some point later WSERV may need to draw that window again and it will just replay the 
+stored commands including the draw bitmap.  However, if the client has changed the content of the bitmap,
+WSERV will effectively draw a different bitmap when it replays the commands.
+
+Note: this member function uses the bitmap's size in twips and does a stretch/compress 
+blit using a linear DDA.
+
+@param aTopLeft The point where the top left pixel of the bitmap is to be 
+drawn 
+@param aDevice The source bitmap. 
+@see CGraphicsContext::DrawBitmap() */
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdDrawBitmap drawBitmap(aTopLeft,aDevice->Handle());
+	Write(&drawBitmap,sizeof(drawBitmap),EWsGcOpDrawBitmap);
+	AddToBitmapArray(aDevice->Handle());
+	}
+
+EXPORT_C void CWindowGc::DrawBitmap(const TRect &aDestRect, const CFbsBitmap *aDevice)
+/** Draws a bitmap in a rectangle.
+
+The bitmap is compressed/stretched to fit the specified rectangle. Note that 
+if the twips value of the bitmap is not set then nothing is drawn (this is 
+the default situation).
+
+Windows that store their redraw commands will only store drawing position and a handle to bitmaps 
+that are drawn in it. The bitmap handle is just a pointer to the bitmap in the FBSERV heap. 
+At some point later WSERV may need to draw that window again and it will just replay the 
+stored commands including the draw bitmap.  However, if the client has changed the content of the bitmap,
+WSERV will effectively draw a different bitmap when it replays the commands.
+
+Notes: this member function uses the bitmap's size in pixels and does a stretch/compress 
+blit using a linear DDA.
+
+@param aDestRect The rectangle within which the bitmap is to be drawn. 
+@param aDevice The source bitmap. 
+@see CGraphicsContext::DrawBitmap() */
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdDrawBitmap2 drawBitmap(aDestRect,aDevice->Handle());
+	Write(&drawBitmap,sizeof(drawBitmap),EWsGcOpDrawBitmap2);
+	AddToBitmapArray(aDevice->Handle());
+	}
+
+EXPORT_C void CWindowGc::DrawBitmap(const TRect &aDestRect, const CFbsBitmap *aDevice, const TRect &aSourceRect)
+/** Draws a specified rectangle from a bitmap into another rectangle.
+
+The function compresses/stretches the specified rectangle from the bitmap 
+to fit the destination rectangle. Note that if the twips value of the bitmap 
+is not set then nothing is drawn (this is the default situation).
+
+Windows that store their redraw commands will only store drawing position and a handle to bitmaps 
+that are drawn in it. The bitmap handle is just a pointer to the bitmap in the FBSERV heap. 
+At some point later WSERV may need to draw that window again and it will just replay the 
+stored commands including the draw bitmap. However, if the client has changed the content of the bitmap,
+WSERV will effectively draw a different bitmap when it replays the commands.
+
+Note: this member function uses rectangle sizes in pixels and does a stretch/compress 
+blit using a linear DDA.
+
+@param aDestRect The rectangle within which the bitmap is to be drawn. 
+@param aDevice A source bitmap. 
+@param aSourceRect The rectangle in the source bitmap that is copied to the 
+destination rectangle. 
+@see CGraphicsContext::DrawBitmap() */
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdDrawBitmap3 drawBitmap(aDestRect,aDevice->Handle(),aSourceRect);
+	Write(&drawBitmap,sizeof(drawBitmap),EWsGcOpDrawBitmap3);
+	AddToBitmapArray(aDevice->Handle());
+	}
+
+/** Draws a specified rectangle from a bitmap and its mask into another rectangle.
+
+The function compresses/stretches the specified rectangle from the bitmap 
+to fit the destination rectangle. 
+The mask bitmap can be used as either a positive or negative mask. Masked 
+pixels are not mapped to the destination rectangle.
+
+A black and white (binary) mask bitmap is used. With aInvertMask=EFalse, black 
+pixels in the mask bitmap stop corresponding pixels in the source bitmap from 
+being transferred to the destination rectangle. With aInvertMask=ETrue, white 
+pixels in the mask bitmap stop corresponding pixels in the source bitmap from 
+being transferred to the destination rectangle.
+
+If mask bitmap's display mode is EColor256, the function does AplhaBlending
+and ignores aInvertMask parameter.
+
+Windows that store their redraw commands will only store drawing position and a handle to bitmaps 
+that are drawn in it. The bitmap handle is just a pointer to the bitmap in the FBSERV heap. 
+At some point later WSERV may need to draw that window again and it will just replay the 
+stored commands including the draw bitmap.  However, if the client has changed the content of the bitmap,
+WSERV will effectively draw a different bitmap when it replays the commands.
+
+Note: this member function uses rectangle sizes in pixels and does a stretch/compress 
+blit using a linear DDA.
+
+@param aDestRect The rectangle within which the masked bitmap is to be drawn. 
+@param aBitmap A source bitmap. 
+@param aSourceRect The rectangle in the source bitmap that is copied to the 
+destination rectangle.
+@param aMaskBitmap A mask bitmap. 
+@param aInvertMask If false, a source pixel that is masked by a black pixel 
+is not transferred to the destination rectangle. If true, then a source pixel 
+that is masked by a white pixel is not transferred to the destination rectangle. */
+EXPORT_C void CWindowGc::DrawBitmapMasked(const TRect& aDestRect, const CFbsBitmap* aBitmap, const TRect& aSourceRect, const CFbsBitmap* aMaskBitmap, TBool aInvertMask)
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdDrawBitmapMasked drawBitmap(aDestRect,aBitmap->Handle(),aSourceRect,aMaskBitmap->Handle(),aInvertMask);
+	Write(&drawBitmap,sizeof(drawBitmap),EWsGcOpDrawBitmapMasked);
+	AddToBitmapArray(aBitmap->Handle());
+	AddToBitmapArray(aMaskBitmap->Handle());
+	}
+
+EXPORT_C void CWindowGc::DrawBitmapMasked(const TRect& aDestRect, const CWsBitmap* aBitmap, const TRect& aSourceRect, const CWsBitmap* aMaskBitmap, TBool aInvertMask)
+/** Draws a specified rectangle from a wserv bitmap and its mask into 
+another rectangle.
+
+The function compresses/stretches the specified rectangle from the bitmap 
+to fit the destination rectangle. 
+The mask bitmap can be used as either a positive or negative mask. Masked 
+pixels are not mapped to the destination rectangle.
+
+A black and white (binary) mask bitmap is used. With aInvertMask=EFalse, black 
+pixels in the mask bitmap stop corresponding pixels in the source bitmap from 
+being transferred to the destination rectangle. With aInvertMask=ETrue, white 
+pixels in the mask bitmap stop corresponding pixels in the source bitmap from 
+being transferred to the destination rectangle.
+
+If mask bitmap's display mode is EColor256, the function does AplhaBlending
+and ignores aInvertMask parameter.
+
+Windows that store their redraw commands will only store drawing position and a handle to bitmaps 
+that are drawn in it. The bitmap handle is just a pointer to the bitmap in the FBSERV heap. 
+At some point later WSERV may need to draw that window again and it will just replay the 
+stored commands including the draw bitmap.  However, if the client has changed the content of the bitmap,
+WSERV will effectively draw a different bitmap when it replays the commands.
+
+Note: this member function uses rectangle sizes in pixels and does a stretch/compress 
+blit using a linear DDA.
+
+@param aDestRect The rectangle within which the masked bitmap is to be drawn. 
+@param aBitmap A source wserv bitmap. 
+@param aSourceRect The rectangle in the source bitmap that is copied to the 
+destination rectangle.
+@param aMaskBitmap A mask wserv bitmap. 
+@param aInvertMask If false, a source pixel that is masked by a black pixel 
+is not transferred to the destination rectangle. If true, then a source pixel 
+that is masked by a white pixel is not transferred to the destination rectangle. */
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdDrawBitmapMasked drawBitmap(aDestRect,aBitmap->WsHandle(),aSourceRect,aMaskBitmap->WsHandle(),aInvertMask);
+	Write(&drawBitmap,sizeof(drawBitmap),EWsGcOpWsDrawBitmapMasked);
+	AddToBitmapArray(aBitmap->Handle());
+	AddToBitmapArray(aMaskBitmap->Handle());
+	}
+EXPORT_C void CWindowGc::DrawText(const TDesC &aBuf, const TPoint &aPos)
+/** Draws horizontal text with no surrounding box. 
+
+The appearance of the text is subject to the drawing mode, the font, pen colour, 
+word justification and character justification. 
+
+A panic occurs if this function is called when there is no font: see UseFont().
+
+@param aBuf The string to write. 
+@param aPos The point specifying the position of the baseline at the left 
+end of the text.
+@see CGraphicsContext::DrawText() */
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdDrawText printText(aPos,aBuf.Length());
+	WriteTextCommand(&printText,sizeof(printText),aBuf,EWsGcOpDrawText,EWsGcOpDrawTextPtr);
+	}
+
+EXPORT_C void CWindowGc::DrawText(const TDesC &aBuf,const TRect &aBox,TInt aBaselineOffset,TTextAlign aHoriz,TInt aLeftMrg)
+/** Draws horizontal text within a cleared box.
+
+The appearance of the text is subject to the drawing mode, the font, pen colour, 
+word justification and character justification. It is also subject to the 
+background brush (set brush to ENullBrush for no effect on background).
+
+A panic occurs if this function is called when there is no font: see UseFont().
+
+Note: the text is clipped to the box. You must ensure that the specified string 
+is not too large.
+
+@param aBuf The text to write.
+@param aBox The box to draw the text in. 
+@param aBaselineOffset An offset from the top of the box to the text baseline. 
+Note that the baseline is the line on which letters sit, for instance below r, s, t, and 
+above the tail of q, and y. 
+@param aHoriz The text alignment mode (default is left, rather than centre 
+or right). 
+@param aLeftMrg The left margin for left-aligned text, or the right margin 
+for right-aligned text (default is zero). 
+@see CGraphicsContext::DrawText() */
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	if (aBuf.Size()<(TInt)(iBuffer->BufferSize()-sizeof(TWsCmdHeader)-sizeof(TWsGcCmdBoxTextOptimised2))) 
+		{
+		if (aHoriz==ELeft && aLeftMrg==0)
+			{
+			TWsGcCmdBoxTextOptimised1 boxTextOpt1(aBox,aBaselineOffset,aBuf.Length());
+			Write(&boxTextOpt1,sizeof(boxTextOpt1),aBuf.Ptr(),aBuf.Size(),EWsGcOpDrawBoxTextOptimised1);
+			}
+		else
+			{
+			TWsGcCmdBoxTextOptimised2 boxTextOpt2(aBox,aBaselineOffset,aHoriz,aLeftMrg,aBuf.Length());
+			Write(&boxTextOpt2,sizeof(boxTextOpt2),aBuf.Ptr(),aBuf.Size(),EWsGcOpDrawBoxTextOptimised2);
+			}
+		}
+	else
+		{
+		TWsGcCmdBoxText boxText(aBox,aBaselineOffset,aHoriz,aLeftMrg,aBuf.Length(),iPimpl->iFont->TextWidthInPixels(aBuf));
+		WriteTextCommand(&boxText,sizeof(boxText),aBuf,EWsGcOpDrawBoxText,EWsGcOpDrawBoxTextPtr);
+		}
+	}
+
+TInt CWindowGc::APIExDrawText(const TDesC& aBuf,const TTextParameters* aParam,const TPoint& aPos)
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdDrawTextInContext printTextInContext(aPos,aBuf.Length(),aParam->iStart,aParam->iEnd);
+	WriteTextCommand(&printTextInContext,sizeof(printTextInContext),aBuf,EWsGcOpDrawTextInContext,EWsGcOpDrawTextInContextPtr);
+	return KErrNone;
+	}
+	
+TInt CWindowGc::APIExDrawText(const TDesC& aBuf,const TTextParameters* aParam,const TRect& aBox,TInt aBaselineOffset,TTextAlign aHoriz,TInt aLeftMrg)
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	if (aBuf.Size()<(TInt)(iBuffer->BufferSize()-sizeof(TWsCmdHeader)-sizeof(TWsGcCmdBoxTextInContextOptimised2))) 
+		{
+		if (aHoriz==ELeft && aLeftMrg==0)
+			{
+			TWsGcCmdBoxTextInContextOptimised1 boxTextOpt1(aBox,aBaselineOffset,aBuf.Length(),aParam->iStart,aParam->iEnd);
+			Write(&boxTextOpt1,sizeof(boxTextOpt1),aBuf.Ptr(),aBuf.Size(),EWsGcOpDrawBoxTextInContextOptimised1);
+			}
+		else
+			{
+			TWsGcCmdBoxTextInContextOptimised2 boxTextOpt2(aBox,aBaselineOffset,aHoriz,aLeftMrg,aBuf.Length(),aParam->iStart,aParam->iEnd);
+			Write(&boxTextOpt2,sizeof(boxTextOpt2),aBuf.Ptr(),aBuf.Size(),EWsGcOpDrawBoxTextInContextOptimised2);
+			}
+		}
+	else
+		{
+		TWsGcCmdBoxTextInContext boxText(aBox,aBaselineOffset,aHoriz,aLeftMrg,aBuf.Length(),iPimpl->iFont->TextWidthInPixels(aBuf),aParam->iStart,aParam->iEnd);
+		WriteTextCommand(&boxText,sizeof(boxText),aBuf,EWsGcOpDrawBoxTextInContext,EWsGcOpDrawBoxTextInContextPtr);
+		}
+	return KErrNone;
+	}
+EXPORT_C void CWindowGc::DrawTextVertical(const TDesC& aText,const TPoint& aPos,TBool aUp)
+/** Draws vertical text in the specified direction.
+
+A panic occurs if this function is called when there is no font: see UseFont().
+
+@param aText The text to be drawn. 
+@param aPos Point of origin of the text baseline. 
+@param aUp Direction. ETrue for up, EFalse for down. */
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdDrawTextVertical printText(aPos,aText.Length(),aUp);
+	WriteTextCommand(&printText,sizeof(printText),aText,EWsGcOpDrawTextVertical,EWsGcOpDrawTextVerticalPtr);
+	}
+
+EXPORT_C void CWindowGc::DrawTextVertical(const TDesC& aText,const TRect& aBox,TInt aBaselineOffset,TBool aUp,TTextAlign aVert,TInt aMargin)
+/** Draws text vertically in the specified direction, within a box of the specified 
+size.
+
+A panic occurs if this function is called when there is no font: see UseFont().
+
+@param aText The text to be drawn. 
+@param aBox The bounding box within which the text should be drawn, and which 
+it is clipped to.
+@param aBaselineOffset The height of the top of the characters from their text 
+baseline. 
+@param aUp The direction. ETrue for up, EFalse for down.
+@param aVert The text alignment. 
+@param aMargin The margin. */
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdBoxTextVertical boxText(aBox);
+	boxText.baselineOffset=aBaselineOffset;
+	boxText.up=aUp;
+	boxText.vert=aVert;
+	boxText.margin=aMargin;
+	boxText.length=aText.Length();
+	boxText.width=iPimpl->iFont->TextWidthInPixels(aText);
+	WriteTextCommand(&boxText,sizeof(boxText),aText,EWsGcOpDrawBoxTextVertical,EWsGcOpDrawBoxTextVerticalPtr);
+	}
+
+TInt CWindowGc::APIExDrawTextVertical(const TDesC& aText,const TTextParameters* aParam,const TPoint& aPos,TBool aUp)
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdDrawTextInContextVertical printText(aPos,aText.Length(),aUp,aParam->iStart,aParam->iEnd);
+	WriteTextCommand(&printText,sizeof(printText),aText,EWsGcOpDrawTextInContextVertical,EWsGcOpDrawTextInContextVerticalPtr);
+	return KErrNone;
+	}
+
+TInt CWindowGc::APIExDrawTextVertical(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox,TInt aBaselineOffset,TBool aUp,TTextAlign aVert,TInt aMargin)
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdBoxTextInContextVertical boxText(aBox);
+	boxText.baselineOffset=aBaselineOffset;
+	boxText.up=aUp;
+	boxText.vert=aVert;
+	boxText.margin=aMargin;
+	boxText.length=aText.Length();
+	boxText.width=iPimpl->iFont->TextWidthInPixels(aText);
+	boxText.start = aParam->iStart;
+	boxText.end = aParam->iEnd;
+	WriteTextCommand(&boxText,sizeof(boxText),aText,EWsGcOpDrawBoxTextInContextVertical,EWsGcOpDrawBoxTextInContextVerticalPtr);
+	return KErrNone;
+	}
+
+//========================Extra functions============================
+
+EXPORT_C void CWindowGc::CopyRect(const TPoint &anOffset,const TRect &aRect)
+/** Copies a rectangle from any part of the screen into the window that the gc 
+is active on.
+
+The copy part of the operation applies to the whole rectangle, irrespective 
+of whether or not it within the window, however the "paste" is clipped to 
+the drawing area.
+
+The rectangle is specified in window coordinates (if the top-left of the rectangle 
+is (0,0) then the area of the screen it specifies has its top-left at the 
+top left corner of the window, if it is (-10,-10) then it starts 10 pixels 
+above and to the left of the window). 
+
+Note: shadows in the source rectangle will be copied. None of the area drawn to 
+will gain shadowing (even if the window is already in shadow).
+
+This version of this function is only really suitable for testing.
+
+@param anOffset The offset from the original position to the point where the 
+rectangle is copied. 
+@param aRect The rectangular area to be copied. This is in window co-ordinates, 
+e.g. the top left corner of the window is position (0,0) with respect to the 
+rectangle.
+@see CBitmapContext::CopyRect() */
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdCopyRect copyRect(anOffset,aRect);
+	Write(&copyRect,sizeof(copyRect),EWsGcOpCopyRect);
+	}
+
+EXPORT_C void CWindowGc::BitBlt(const TPoint &aPoint, const CFbsBitmap *aBitmap)
+/** Performs a bitmap block transfer.
+
+Windows that store their redraw commands will only store drawing position and a handle to bitmaps 
+that are drawn in it. The bitmap handle is just a pointer to the bitmap in the FBSERV heap. 
+At some point later WSERV may need to draw that window again and it will just replay the 
+stored commands including the draw bitmap. However, if the client has changed the content of the bitmap,
+WSERV will effectively draw a different bitmap when it replays the commands.
+
+@param aPoint The position for the top left corner of the bitmap. 
+@param aBitmap A memory-resident bitmap. 
+@see CBitmapContext::BitBlt() */
+	{
+	if (aBitmap == NULL || !aBitmap->Handle())
+		return; 
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdGdiBlt2 gdiBlit(aPoint,aBitmap->Handle());
+	Write(&gdiBlit,sizeof(gdiBlit),EWsGcOpGdiBlt2);
+	AddToBitmapArray(aBitmap->Handle());
+	}
+
+EXPORT_C void CWindowGc::BitBlt(const TPoint &aDestination,const CFbsBitmap *aBitmap,const TRect &aSource)
+/** Performs a bitmap block transfer of a rectangular piece of a bitmap.
+
+Windows that store their redraw commands will only store drawing position and a handle to bitmaps 
+that are drawn in it. The bitmap handle is just a pointer to the bitmap in the FBSERV heap. 
+At some point later WSERV may need to draw that window again and it will just replay the 
+stored commands including the draw bitmap.  However, if the client has changed the content of the bitmap,
+WSERV will effectively draw a different bitmap when it replays the commands.
+
+Note: if the rectangle aSource is larger than the bitmap then the bitmap will be padded 
+with white.
+
+@param aDestination The position for the top left corner of the bitmap. 
+@param aBitmap A memory-resident bitmap 
+@param aSource A rectangle defining the piece of the bitmap to be drawn, with 
+co-ordinates relative to the top left corner of the bitmap 
+@see CBitmapContext::BitBlt() */
+	{
+	if (aBitmap == NULL || !aBitmap->Handle())
+		return; 
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdGdiBlt3 gdiBlit(aDestination,aBitmap->Handle(),aSource);
+	Write(&gdiBlit,sizeof(gdiBlit),EWsGcOpGdiBlt3);
+	AddToBitmapArray(aBitmap->Handle());
+	}
+
+EXPORT_C void CWindowGc::BitBltMasked(const TPoint& aPoint,const CFbsBitmap* aBitmap,const TRect& aSourceRect,const CFbsBitmap* aMaskBitmap,TBool aInvertMask)
+/** Performs a masked bitmap block transfer of a memory resident source bitmap.
+
+The mask bitmap can be used as either a positive or negative mask. Masked 
+pixels are not mapped to the destination rectangle.
+
+A black and white (binary) mask bitmap is used. With aInvertMask=EFalse, black 
+pixels in the mask bitmap stop corresponding pixels in the source bitmap from 
+being transferred to the destination rectangle. With aInvertMask=ETrue, white 
+pixels in the mask bitmap stop corresponding pixels in the source bitmap from 
+being transferred to the destination rectangle.
+
+Windows that store their redraw commands will only store drawing position and a handle to bitmaps 
+that are drawn in it. The bitmap handle is just a pointer to the bitmap in the FBSERV heap. 
+At some point later WSERV may need to draw that window again and it will just replay the 
+stored commands including the draw bitmap.  However, if the client has changed the content of the bitmap,
+WSERV will effectively draw a different bitmap when it replays the commands.
+
+@param aPoint A position for the top left corner of the bitmap. 
+@param aBitmap A memory-resident source bitmap. 
+@param aSourceRect A rectangle defining the piece of the bitmap to be drawn, 
+with co-ordinates relative to the top left corner of the bitmap 
+@param aMaskBitmap A mask bitmap. 
+@param aInvertMask If false, a source pixel that is masked by a black pixel 
+is not transferred to the destination rectangle. If true, then a source pixel 
+that is masked by a white pixel is not transferred to the destination rectangle. 
+
+@see CBitmapContext::BitBltMasked() */
+	{
+	if (aBitmap == NULL || !aBitmap->Handle() || aMaskBitmap == NULL || !aMaskBitmap->Handle())
+		return; 
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdBltMasked gdiBlitMasked(aPoint,aBitmap->Handle(),aSourceRect,aMaskBitmap->Handle(),aInvertMask);
+	Write(&gdiBlitMasked,sizeof(gdiBlitMasked),EWsGcOpGdiBltMasked);
+	AddToBitmapArray(aBitmap->Handle());
+	AddToBitmapArray(aMaskBitmap->Handle());
+	}
+
+EXPORT_C void CWindowGc::BitBlt(const TPoint &aPoint, const CWsBitmap *aBitmap)
+/** Performs a bitmap block transfer on a bitmap to which the window server already 
+has a handle.
+
+Windows that store their redraw commands will only store drawing position and a handle to bitmaps 
+that are drawn in it. The bitmap handle is just a pointer to the bitmap in the FBSERV heap. 
+At some point later WSERV may need to draw that window again and it will just replay the 
+stored commands including the draw bitmap.  However, if the client has changed the content of the bitmap,
+WSERV will effectively draw a different bitmap when it replays the commands.
+
+This function should be used in preference to the CFbsBitmap overload if the 
+bitmap is to be used more than once, as it is a lot quicker.
+
+@param aPoint The position for the top left corner of the bitmap. 
+@param aBitmap A window server bitmap. 
+@see CBitmapContext::BitBlt() */
+	{
+	if (aBitmap == NULL || !aBitmap->Handle())
+		return; 
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdGdiBlt2 gdiBlit(aPoint,aBitmap->WsHandle());
+	Write(&gdiBlit,sizeof(gdiBlit),EWsGcOpGdiWsBlt2);
+	AddToBitmapArray(aBitmap->Handle());
+	}
+
+EXPORT_C void CWindowGc::BitBlt(const TPoint &aDestination,const CWsBitmap  *aBitmap,const TRect &aSource)
+/** Performs a bitmap block transfer of a rectangular piece of a bitmap to which 
+the window server already has a handle.
+
+Windows that store their redraw commands will only store drawing position and a handle to bitmaps 
+that are drawn in it. The bitmap handle is just a pointer to the bitmap in the FBSERV heap. 
+At some point later WSERV may need to draw that window again and it will just replay the 
+stored commands including the draw bitmap.  However, if the client has changed the content of the bitmap,
+WSERV will effectively draw a different bitmap when it replays the commands.
+
+This function should be used in preference to the CFbsBitmap overload if the 
+bitmap is to be used more than once, as it is a lot quicker.
+
+Note: if the rectangle aSource is larger than the bitmap then the bitmap will be padded 
+with white.
+	
+@param aDestination The position for the top left corner of the bitmap. 
+@param aBitmap A window server bitmap. 
+@param aSource A rectangle defining the piece of the bitmap to be drawn, with 
+co-ordinates relative to the top left corner of the bitmap 
+@see CBitmapContext::BitBlt() */
+	{
+	if (aBitmap == NULL || !aBitmap->Handle())
+		return; 
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdGdiBlt3 gdiBlit(aDestination,aBitmap->WsHandle(),aSource);
+	Write(&gdiBlit,sizeof(gdiBlit),EWsGcOpGdiWsBlt3);
+	AddToBitmapArray(aBitmap->Handle());
+	}
+
+EXPORT_C void CWindowGc::BitBltMasked(const TPoint& aPoint,const CWsBitmap * aBitmap,const TRect& aSourceRect,const CWsBitmap * aMaskBitmap,TBool aInvertMask)
+/** Performs a masked bitmap block transfer of a window server bitmap.
+
+The mask bitmap can be used as either a positive or negative mask. Masked 
+pixels are not mapped to the destination rectangle.
+
+A black and white (binary) mask bitmap is used. With aInvertMask=EFalse, black 
+pixels in the mask bitmap stop corresponding pixels in the source bitmap from 
+being transferred to the destination rectangle. With aInvertMask=ETrue, white 
+pixels in the mask bitmap stop corresponding pixels in the source bitmap from 
+being transferred to the destination rectangle.
+
+This function should be used in preference to the CFbsBitmap overload if the 
+bitmap is to be used more than once, as it is a lot quicker.
+
+Windows that store their redraw commands will only store drawing position and a handle to bitmaps 
+that are drawn in it. The bitmap handle is just a pointer to the bitmap in the FBSERV heap. 
+At some point later WSERV may need to draw that window again and it will just replay the 
+stored commands including the draw bitmap.  However, if the client has changed the content of the bitmap,
+WSERV will effectively draw a different bitmap when it replays the commands.
+
+@param aPoint A position for the top left corner of the bitmap. 
+@param aBitmap A window server bitmap. 
+@param aSourceRect A rectangle defining the piece of the bitmap to be drawn, 
+with co-ordinates relative to the top left corner of the bitmap. 
+@param aMaskBitmap A window server mask bitmap. 
+@param aInvertMask If false, a source pixel that is masked by a black pixel 
+is not transferred to the destination rectangle. If true, then a source pixel 
+that is masked by a white pixel is not transferred to the destination rectangle. 
+
+@see CBitmapContext::BitBltMasked() */
+	{
+	if (aBitmap == NULL || !aBitmap->Handle() || aMaskBitmap == NULL || !aMaskBitmap->Handle())
+		return;
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdBltMasked gdiBlitMasked(aPoint,aBitmap->WsHandle(),aSourceRect,aMaskBitmap->WsHandle(),aInvertMask);
+	Write(&gdiBlitMasked,sizeof(gdiBlitMasked),EWsGcOpGdiWsBltMasked);
+	AddToBitmapArray(aBitmap->Handle());
+	AddToBitmapArray(aMaskBitmap->Handle()); 
+	}
+
+/**
+This method has been deprecated. It is no longer possible to re-map pixel colours
+within a rectangle. Calling it has no effect.
+@param aRect Ignored.
+@param aColors Ignored.
+@param aNumPairs Ignored.
+@param aMapForwards Ignored.
+@deprecated
+*/
+EXPORT_C void CWindowGc::MapColors(const TRect& /*aRect*/, const TRgb* /*aColors*/, TInt /*aNumPairs*/, TBool /*aMapForwards*/)
+	{
+	}
+
+EXPORT_C void CWindowGc::Clear(const TRect &aRect)
+/** Clears a rectangular area of a window.
+
+The cleared area is filled with the current brush colour.
+
+@param aRect The rectangle to clear. 
+@see CBitmapContext::Clear() */
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	WriteRect(aRect,EWsGcOpClearRect);
+	}
+
+EXPORT_C void CWindowGc::Clear()
+/** Clears the whole window.
+
+The cleared area is filled with the current brush colour.
+
+@see CBitmapContext::Clear() */
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	Write(EWsGcOpClear);
+	}
+
+EXPORT_C void CWindowGc::Reset()
+/** Resets the graphics context to its default settings.
+
+The drawing mode is set to TDrawMode::EDrawModePen (pen and brush colours used as 
+they are); there is no clipping rectangle; the pen settings are black, 
+solid, single pixel size; the brush style is null; no text font is selected.
+
+@see CGraphicsContext::Reset() */
+	{
+	Write(EWsGcOpReset);
+	iPimpl->iFont=NULL;
+	iPimpl->iShadowColor = KDefaultShadowColor;
+    iPimpl->ResetPendingState();
+    iPimpl->iForceWrite = ETrue; // needed because brush colour set to window background colour in CPlaybackGc::CommandL and CWsGc::SetGcAttribute
+	}
+
+/**
+This method has been deprecated. Dithering is no longer supported. Calling it
+has no effect.
+@param aPoint Ignored.
+@deprecated
+*/
+EXPORT_C void CWindowGc::SetDitherOrigin(const TPoint& /*aPoint*/)
+	{
+	}
+
+EXPORT_C void CWindowGc::SetFaded(TBool aFaded)
+/** Sets whether the graphics context is faded.
+
+Fading is used to make a window appear less colourful so that other windows 
+stand out. For example, a window would be faded when a dialogue is displayed 
+in front of it.
+
+@param aFaded ETrue to fade the graphics context, EFalse to unfade it. */
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	WriteInt(aFaded,EWsGcOpSetFaded);
+	}
+
+EXPORT_C void CWindowGc::SetFadingParameters(TUint8 aBlackMap,TUint8 aWhiteMap)
+/** Sets the fading parameters.
+
+This function allows you to override the map used when drawing with a faded 
+graphics context. However if you draw to a faded window with a faded graphics 
+context, then fading on the graphics context is ignored and it will use the 
+fading of the window.
+
+Fading is used to make a window appear less colourful so that other windows stand 
+out. For example, a window would be faded when a dialogue is displayed 
+in front of it. 
+
+You can either make a faded window closer to white or closer to black. 
+The fading map allows you to over-ride the default fading parameters set in 
+RWsSession::SetDefaultFadingParameters(). 
+
+Fading re-maps colours to fall between the specified black and white map values. 
+If aBlackMap=0 and aWhiteMap=255 then the colours are mapped unchanged. As the 
+values converge, the colours are mapped to a smaller range, so the differences 
+between colours in the faded graphics context decrease. If the values are reversed 
+then the colours are inverted (i.e. where the gc would be black, it is now white). 
+
+@param aBlackMap Black map fading parameter. Unfaded this is 0. 
+@param aWhiteMap White map fading parameter. Unfaded this is 255. 
+@see RWsSession::SetDefaultFadingParameters()
+@see RWindowTreeNode::SetFaded() */
+	{
+	WriteInt(WservEncoding::Encode8BitValues(aBlackMap,aWhiteMap),EWsGcOpSetFadeParams);
+	}
+
+EXPORT_C TInt CWindowGc::AlphaBlendBitmaps(const TPoint& aDestPt, const CFbsBitmap* aSrcBmp, const TRect& aSrcRect,const CFbsBitmap* aAlphaBmp, const TPoint& aAlphaPt)
+/**
+Performs an alpha blending of the source data, aSrcBmp, with the window, using
+the data from aAlphaBmp as an alpha blending factor.
+The formula used is:
+(S * A + W * (255 - A)) / 255, where:
+- S - a pixel from aSrcBmp;
+- W - a pixel from the window;
+- A - a pixel from aAlphaBmp;
+The contents of source and alpha bitmap are preserved.
+The calculated alpha blended pixels are written to the destination - the window image.
+
+Windows that store their redraw commands will only store drawing position and a handle to bitmaps 
+that are drawn in it. The bitmap handle is just a pointer to the bitmap in the FBSERV heap. 
+At some point later WSERV may need to draw that window again and it will just replay the 
+stored commands including the draw bitmap.  However, if the client has changed the content of the bitmap,
+WSERV will effectively draw a different bitmap when it replays the commands.
+
+This method is supported from version 8.1
+@param aDestPt Position in the target the result should be drawn to.
+@param aSrcBmp A pointer to the source bitmap.
+@param aSrcRect The part of the source bitmap that should be used.
+@param aAlphaBmp A pointer to the bitmap used as an alpha blending factor.
+@param aAlphaPt Position of the first pixel in the alpha bitmap that should be used as a source 
+                for the alpha blending. The size of the area is the same as the 
+                source bitmap area - aSrcRect parameter.
+@see CFbsBitGc::AlphaBlendBitmaps()
+*/
+	{
+   	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdAlphaBlendBitmaps alphaBlend(aDestPt, aSrcBmp->Handle(), aSrcRect, aAlphaBmp->Handle(), aAlphaPt);
+	Write(&alphaBlend,sizeof(alphaBlend),EWsGcOpGdiAlphaBlendBitmaps);
+	AddToBitmapArray(aSrcBmp->Handle());
+	AddToBitmapArray(aAlphaBmp->Handle());
+	return KErrNone;
+	}
+
+EXPORT_C TInt CWindowGc::AlphaBlendBitmaps(const TPoint& aDestPt, const CWsBitmap* aSrcBmp, const TRect& aSrcRect,const CWsBitmap* aAlphaBmp, const TPoint& aAlphaPt)
+/**
+The method performs an alpha blending of the source data, aSrcBmp, with the window, using
+the data from aAlphaBmp as an alpha blending factor.
+For information on how this function works, see the other overload.
+
+Windows that store their redraw commands will only store drawing position and a handle to bitmaps 
+that are drawn in it. The bitmap handle is just a pointer to the bitmap in the FBSERV heap. 
+At some point later WSERV may need to draw that window again and it will just replay the 
+stored commands including the draw bitmap. However, if the client has changed the content of the bitmap,
+WSERV will effectively draw a different bitmap when it replays the commands.
+
+This method is supported from version 8.1
+@param aDestPt Position in the target the result should be drawn to.
+@param aSrcBmp A pointer to the source bitmap.
+@param aSrcRect The part of the source bitmap that should be used.
+@param aAlphaBmp A pointer to the bitmap used as an alpha blending factor.
+@param aAlphaPt Position of the first pixel in the alpha bitmap that should be used as a source 
+                for the alpha blending. The size of the area is the same as the 
+                source bitmap area - aSrcRect parameter.
+@see CFbsBitGc::AlphaBlendBitmaps()
+*/
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdAlphaBlendBitmaps alphaBlend(aDestPt, aSrcBmp->WsHandle(), aSrcRect, aAlphaBmp->WsHandle(), aAlphaPt);
+	Write(&alphaBlend,sizeof(alphaBlend),EWsGcOpGdiWsAlphaBlendBitmaps);
+	AddToBitmapArray(aSrcBmp->Handle());
+	AddToBitmapArray(aAlphaBmp->Handle());
+	return KErrNone;
+	}
+
+/**
+This method has been deprecated. Calling it has no effect.
+@param aDrawOpaque Ignored.
+@deprecated
+*/
+EXPORT_C void CWindowGc::SetOpaque(TBool aDrawOpaque)
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	WriteInt(aDrawOpaque, EWsGcOpSetOpaque);
+	}
+
+/** APIExtension can contain as many additional methods as is required by 
+CGraphicsContext after its original conception. It takes 3 parameters.
+Function is exported due to constrains of retaining BC with earlier versions.
+This is not used directly by external methods, instead it is called by a named 
+method in CGraphicsContext which passes the relivant arguements including an 
+unique identifier for the required action.
+@param aUid The unique identifier for the method that is required. Selected 
+internally by a series of "if" statements. 
+@see Valid Uid identifiers are listed in header gdi.h
+@see CGraphicsContext
+@param aOutput is a TAny pointer to a reference. Used to output data as the structure
+does not need to be instantiated before the function call this adds greater 
+flexibility.
+@param aInput is a TAny pointer used to input data.
+*/	
+EXPORT_C TInt CWindowGc::APIExtension(TUid aUid, TAny*& aOutput, TAny* aInput)
+	{
+	if (aUid == KGetUnderlineMetrics)
+		{		
+		return APIExGetUnderlineMetrics(aOutput);
+		}
+	else if (aUid == KSetShadowColor)
+		{
+		return APIExSetShadowColor(aInput);
+		}
+	else if (aUid == KGetShadowColor)
+		{
+		return APIExGetShadowColor(aOutput);
+		}
+	else if (aUid == KDrawTextInContextUid)
+		{
+		TDrawTextInContextInternal* contextParam = (TDrawTextInContextInternal*)aInput;
+		return APIExDrawText(contextParam->iText, &contextParam->iParam, contextParam->iPosition);
+		}
+	else if (aUid == KDrawBoxTextInContextUid)
+		{
+		TDrawTextInContextInternal* contextParam = (TDrawTextInContextInternal*)aInput;
+		return APIExDrawText(contextParam->iText,&contextParam->iParam,contextParam->iBox,contextParam->iBaselineOffset,contextParam->iAlign,contextParam->iMargin);
+		}
+	else if (aUid == KDrawTextInContextVerticalUid)
+		{
+		TDrawTextInContextInternal* contextParam = (TDrawTextInContextInternal*)aInput;
+		return APIExDrawTextVertical(contextParam->iText, &contextParam->iParam, contextParam->iPosition,contextParam->iUp);
+		}
+	else if (aUid == KDrawBoxTextInContextVerticalUid)
+		{
+		TDrawTextInContextInternal* contextParam = (TDrawTextInContextInternal*)aInput;
+		return APIExDrawTextVertical(contextParam->iText,&contextParam->iParam,contextParam->iBox,contextParam->iBaselineOffset,contextParam->iUp,contextParam->iAlign,contextParam->iMargin);
+		}
+	else if (aUid == KApiExtensionInterfaceUid)
+		{
+		return APIExInterface(aOutput, *static_cast<TUid*>(aInput));
+		}
+	/* Future cases may be placed here later.*/
+	else
+		return CBitmapContext::APIExtension(aUid, aOutput, aInput);
+	}
+
+//The methods listed above in APIExtension follow here with the prefix APIEx.
+TInt CWindowGc::APIExGetUnderlineMetrics(TAny*& aOutput)
+	{
+	const TInt width = Max(iPimpl->iFont->HeightInPixels() / 10,1);
+	TTwoTInt* ptr = (TTwoTInt*)aOutput;
+	ptr->iTop = 1 + width / 2;
+	ptr->iBottom = (ptr->iTop) + width;
+	return KErrNone;
+	}
+
+TInt CWindowGc::APIExSetShadowColor(TAny* aShadowColor)
+	{
+	const TRgb shadowColor = *(reinterpret_cast<TRgb*> (aShadowColor));
+	WriteInt(shadowColor.Internal(), EWsGcOpSetShadowColor);
+	iPimpl->iShadowColor = shadowColor;
+	return KErrNone;
+	}
+
+TInt CWindowGc::APIExGetShadowColor(TAny*& aOutput)
+	{
+	TRgb* ptr = (TRgb*)aOutput;
+	ptr->SetInternal(iPimpl->iShadowColor.Internal());
+	return KErrNone;
+	}
+
+//Default implementation of reserved virtual
+EXPORT_C void CWindowGc::Reserved_CGraphicsContext_2()
+	{
+	CBitmapContext::Reserved_CGraphicsContext_2();
+	}
+
+//Default implementation of reserved virtual
+EXPORT_C void CWindowGc::Reserved_CBitmapContext_1()
+	{
+	CBitmapContext::Reserved_CBitmapContext_1();
+	}
+
+//Default implementation of reserved virtual
+EXPORT_C void CWindowGc::Reserved_CBitmapContext_2()
+	{
+	CBitmapContext::Reserved_CBitmapContext_2();
+	}
+
+//Default implementation of reserved virtual
+EXPORT_C void CWindowGc::Reserved_CBitmapContext_3()
+	{
+	CBitmapContext::Reserved_CBitmapContext_3();
+	}
+	
+// was Reserved_CWindowGc_1
+EXPORT_C void CWindowGc::DrawWsGraphic(const TWsGraphicId& aId,const TRect& aDestRect)
+/** Draws an abstract artwork.
+It does nothing if aDestRect values fall outside the window area.
+
+@param aId the identifier for the artwork
+@param aDestRect the destination rect within the active window for this artwork
+
+@since 9.2
+@released
+*/
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdDrawWsGraphic drawWsGraphic(aId,aDestRect);
+	Write(&drawWsGraphic,sizeof(drawWsGraphic),EWsGcOpDrawWsGraphic);
+	}
+
+// Reserved_CWindowGc_2
+EXPORT_C void CWindowGc::DrawWsGraphic(const TWsGraphicId& aId,const TRect& aDestRect,const TDesC8& aData)
+/** Draws an abstract artwork.
+It does nothing if aDestRect values fall outside the window area.
+
+@param aId the identifier for the artwork
+@param aDestRect the destination rect within the active window for this artwork
+@param aData opaque datagram to associate with this occasion of drawing.  The format is dependent upon the artwork
+
+@since 9.2
+@released
+*/
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdDrawWsGraphic drawWsGraphic(aId,aDestRect);
+	drawWsGraphic.iDataLen = aData.Size();
+	WriteTextCommand(&drawWsGraphic, sizeof(drawWsGraphic),	aData, EWsGcOpDrawWsGraphic, EWsGcOpDrawWsGraphicPtr);	
+	}
+
+/**
+Gets an extension interface specified by the supplied UID, or NULL if it isn't supported.
+
+@param aInterfaceId The UID of the requested interface
+@return A pointer to the interface, or NULL if the interface isn't supported
+@publishedPartner
+@prototype
+*/
+EXPORT_C TAny* CWindowGc::Interface(TUid aInterfaceId)
+	{
+	TAny* interface = NULL;
+	if(KErrNone == APIExtension(KApiExtensionInterfaceUid, interface, &aInterfaceId))
+		return interface;
+	return NULL;
+	}
+
+/**
+Gets an extension interface specified by the supplied UID, or NULL if it isn't supported.
+
+@param aInterfaceId The UID of the requested interface
+@return A pointer to the interface, or NULL if the interface isn't supported
+@publishedPartner
+@prototype
+*/
+EXPORT_C const TAny* CWindowGc::Interface(TUid aInterfaceId) const
+	{
+	return const_cast<CWindowGc*>(this)->Interface(aInterfaceId);
+	}
+
+TInt CWindowGc::APIExInterface(TAny*& aInterface, TUid aInterfaceId)
+	{
+	if(aInterfaceId == KMWsDrawResourceInterfaceUid)
+		{
+		aInterface = static_cast<MWsDrawResource*>(iPimpl);
+		return KErrNone;
+		}
+	return KErrNotSupported;
+	}
+
+void CWindowGc::DrawResource(const TPoint& aPos, const RWsDrawableSource& aSource, TGraphicsRotation aRotation)
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdDrawResourceToPos drawWsResource(aSource.WsHandle(), aPos, aRotation);
+	Write(&drawWsResource, sizeof(drawWsResource), EWsGcOpDrawResourceToPos);
+	}
+
+void CWindowGc::DrawResource(const TRect& aDestRect, const RWsDrawableSource& aSource, TGraphicsRotation aRotation)
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdDrawResourceToRect drawWsResource(aSource.WsHandle(), aDestRect, aRotation);
+	Write(&drawWsResource, sizeof(drawWsResource), EWsGcOpDrawResourceToRect);
+	}
+
+void CWindowGc::DrawResource(const TRect& aDestRect, const RWsDrawableSource& aSource, const TRect& aSrcRect, TGraphicsRotation aRotation)
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdDrawResourceFromRectToRect drawWsResource(aSource.WsHandle(), aDestRect, aSrcRect, aRotation);
+	Write(&drawWsResource, sizeof(drawWsResource), EWsGcOpDrawResourceFromRectToRect);
+	}
+
+void CWindowGc::DrawResource(const TRect& aDestRect, const RWsDrawableSource& aSource, const TDesC8& aParam)
+	{
+	iPimpl->WriteAnyPendingStateChanges();
+	TWsGcCmdDrawResourceWithData drawWsResource(aSource.WsHandle(), aDestRect, &aParam);
+	Write(&drawWsResource, sizeof(drawWsResource),EWsGcOpDrawResourceWithData);
+	}
+
+//Default implementation of reserved virtual
+EXPORT_C void CWindowGc::Reserved_CWindowGc_3()
+	{
+	}
+
+//Default implementation of reserved virtual
+EXPORT_C void CWindowGc::Reserved_CWindowGc_4()
+	{
+	}
+
+//Default implementation of reserved virtual
+EXPORT_C void CWindowGc::Reserved_CWindowGc_5()
+	{
+	}
+
+/**
+Default constructor. 
+Only for embedding instances of RWsDrawableSource into other classes as data members. 
+Before a RWsDrawableSource can be used the other constructor must be called. 
+ */
+EXPORT_C RWsDrawableSource::RWsDrawableSource()
+	: iDrawableId(KSgNullDrawableId), iScreenNumber(KSgScreenIdMain)
+	{
+	}
+
+/**
+Constructor.
+@param aWs Session to the window server
+ 
+@pre Connection to the window server is established
+ */
+EXPORT_C RWsDrawableSource::RWsDrawableSource(RWsSession &aWs)
+	: MWsClientClass(aWs.iBuffer), iDrawableId(KSgNullDrawableId), iScreenNumber(KSgScreenIdMain)
+	{
+	}
+
+/**
+Create window server object for resource drawing operation via window server.
+
+This object will be identified by a unique handle and will be associated with drawable resource which is passed as a parameter.
+
+This object will be created for drawing onto the default screen only.
+ 
+@see CWindowGc
+@param  aDrawable Drawable resource.
+ 
+@post Drawable source is created and can be used by window server. The reference counter of the underlying
+		image resource is incremented. 
+
+@return KErrNone if successful, KErrArgument if the image resource is not valid,
+		KErrAlreadyExists if this handle is already associated with a 
+		specific resource,  otherwise one of the system-wide error codes.
+ */
+EXPORT_C TInt RWsDrawableSource::Create(const RSgDrawable& aDrawable)
+	{
+	return Create(aDrawable, KSgScreenIdMain);
+	}
+
+/**
+Create window server object for resource drawing operation via window server.
+
+This object will be identified by  unique handle and will be associated with drawable resource which is passed as a parameter.
+
+This object will be created for drawing onto the specified screen only.
+
+@see CWindowGc
+@param  aDrawable Drawable resource.
+@param  aScreenNumber The screen onto which this drawable resource can be drawn.
+ 
+@post Drawable source is created and can be used by window server. The reference counter of the underlying
+		image resource is incremented. 
+
+@return KErrNone if successful, KErrArgument if the image resource is not valid
+		or if the specified screen is invalid, KErrAlreadyExists if this handle
+		is already associated with a specific resource, otherwise one of the
+		system-wide error codes.
+ */
+EXPORT_C TInt RWsDrawableSource::Create(const RSgDrawable& aDrawable, TInt aScreenNumber)
+	{
+	if (iWsHandle)
+		{
+		return KErrAlreadyExists;
+		}
+	CGraphicsResourceWrapperFactory* grwFactory = new CGraphicsResourceWrapperFactory();
+	if (!grwFactory)
+		return KErrNoMemory;
+	CGraphicsResourceWrapper* graphicsResource = grwFactory->NewGraphicsResourceWrapper();
+	if(!graphicsResource)
+		{
+		delete grwFactory;
+		return KErrNotSupported;
+		}
+	if (graphicsResource->IsNull(aDrawable) || aScreenNumber < 0)
+		{
+		delete graphicsResource;
+		delete grwFactory;
+		return KErrArgument;
+		}
+	TWsClCmdCreateDrawableSource create(graphicsResource->Id(aDrawable), aScreenNumber);
+	TInt ret;
+	if ((ret = iBuffer->WriteReplyWs(&create, sizeof(TWsClCmdCreateDrawableSource), EWsClOpCreateDrawableSource)) < 0)
+		{
+		delete graphicsResource;
+		delete grwFactory;
+		return ret;
+		}
+	iWsHandle = ret;
+	iDrawableId = graphicsResource->Id(aDrawable);
+	iScreenNumber = aScreenNumber;
+	delete graphicsResource;
+	delete grwFactory;
+	return KErrNone;
+	}
+
+/**
+Destroy the window server drawable source. 
+Calling this method on a object that is not associated with any RSgDrawable 
+resource will have no effect. Once Close() is called, this drawable source object can be reused.
+
+@post	The window server drawable object is destroyed. The instance is no longer associated
+		with a RSgDrawable specific resource. The reference counter of the underlying
+		image resource is decremented. 
+*/
+EXPORT_C void RWsDrawableSource::Close()
+	{
+	if (iWsHandle)
+		{
+		Write(EWsDrawableSourceOpFree);
+		iWsHandle = 0;
+		iDrawableId = KSgNullDrawableId;
+		iScreenNumber = KSgScreenIdMain;
+		}
+	}
+
+/**
+ Get the unique ID of the associated drawable resource.
+ */
+EXPORT_C const TSgDrawableId& RWsDrawableSource::DrawableId() const
+	{
+	return iDrawableId;
+	}
+
+/**
+ Get the screen number of the drawable source.
+ */
+EXPORT_C TInt RWsDrawableSource::ScreenNumber() const
+	{
+	return iScreenNumber;
+	}